mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 00:08:12 +02:00
+ support for tlsm_general on i386-linux
git-svn-id: trunk@40281 -
This commit is contained in:
parent
6d78637441
commit
72416edcc4
@ -399,7 +399,7 @@ begin
|
||||
begin
|
||||
if (base = NR_NO) and
|
||||
(index <> NR_NO) and
|
||||
(scalefactor in [0,1]) then
|
||||
(scalefactor in [0,1]) and (refaddr<>addr_tlsgd) then
|
||||
begin
|
||||
base := index;
|
||||
index := NR_NO
|
||||
|
@ -95,11 +95,18 @@ unit cpupi;
|
||||
para_stack_size := 0;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcpuprocinfo.allocate_got_register(list: tasmlist);
|
||||
begin
|
||||
if (cs_create_pic in current_settings.moduleswitches) then
|
||||
begin
|
||||
got := cg.getaddressregister(list);
|
||||
if pi_uses_threadvar in flags then
|
||||
begin
|
||||
cg.getcpuregister(list,NR_EBX);
|
||||
got := NR_EBX;
|
||||
end
|
||||
else
|
||||
got := cg.getaddressregister(list);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -1901,7 +1901,10 @@ implementation
|
||||
{ Switching index to base position gives shorter assembler instructions.
|
||||
Converting index*2 to base+index also gives shorter instructions. }
|
||||
if (ref.base=NR_NO) and (ref.index<>NR_NO) and (ref.scalefactor<=2) and
|
||||
(ss_equals_ds or (ref.segment<>NR_NO) or (ref.index<>NR_EBP)) then
|
||||
(ss_equals_ds or (ref.segment<>NR_NO) or (ref.index<>NR_EBP))
|
||||
{ do not mess with tls references, they have the (,reg,1) format on purpose
|
||||
else the linker cannot resolve/replace them }
|
||||
{$ifdef i386} and (ref.refaddr<>addr_tlsgd) {$endif i386} then
|
||||
begin
|
||||
ref.base:=ref.index;
|
||||
if ref.scalefactor=2 then
|
||||
|
@ -182,6 +182,8 @@ interface
|
||||
{$ifdef i386}
|
||||
addr_ntpoff:
|
||||
owner.writer.AsmWrite('@ntpoff');
|
||||
addr_tlsgd:
|
||||
owner.writer.AsmWrite('@tlsgd');
|
||||
{$endif i386}
|
||||
end;
|
||||
|
||||
@ -229,7 +231,7 @@ interface
|
||||
else
|
||||
owner.writer.AsmWrite(gas_regname(o.reg));
|
||||
top_ref :
|
||||
if o.ref^.refaddr in [addr_no,addr_pic,addr_pic_no_got{$ifdef i386},addr_ntpoff{$endif i386}] then
|
||||
if o.ref^.refaddr in [addr_no,addr_pic,addr_pic_no_got{$ifdef i386},addr_ntpoff,addr_tlsgd{$endif i386}] then
|
||||
WriteReference(o.ref^)
|
||||
else
|
||||
begin
|
||||
|
@ -40,10 +40,11 @@ implementation
|
||||
uses
|
||||
globals,
|
||||
cutils,verbose,systems,
|
||||
aasmbase,aasmtai,aasmdata,
|
||||
aasmbase,aasmtai,aasmdata,aasmcpu,
|
||||
cgutils,cgobj,
|
||||
symconst,symdef,symtable,
|
||||
cgbase,cpubase,parabase,paramgr;
|
||||
cgbase,cpubase,parabase,paramgr,
|
||||
procinfo;
|
||||
|
||||
{*****************************************************************************
|
||||
TX86LOADNODE
|
||||
@ -91,10 +92,29 @@ implementation
|
||||
case target_info.system of
|
||||
system_i386_linux,system_i386_android:
|
||||
begin
|
||||
location.reference.segment:=NR_GS;
|
||||
case current_settings.tlsmodel of
|
||||
tlsm_local:
|
||||
location.reference.refaddr:=addr_ntpoff;
|
||||
begin
|
||||
location.reference.segment:=NR_GS;
|
||||
location.reference.refaddr:=addr_ntpoff;
|
||||
end;
|
||||
tlsm_general:
|
||||
begin
|
||||
if not(cs_create_pic in current_settings.moduleswitches) then
|
||||
Internalerror(2018110701);
|
||||
reference_reset(href,0,[]);
|
||||
location.reference.index:=current_procinfo.got;
|
||||
location.reference.scalefactor:=1;
|
||||
location.reference.refaddr:=addr_tlsgd;
|
||||
cg.getcpuregister(current_asmdata.CurrAsmList,NR_EAX);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_LEA,S_L,location.reference,NR_EAX));
|
||||
cg.g_call(current_asmdata.CurrAsmList,'___tls_get_addr');
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_EAX,hregister);
|
||||
reference_reset(location.reference,location.reference.alignment,location.reference.volatility);
|
||||
location.reference.base:=hregister;
|
||||
end;
|
||||
else
|
||||
Internalerror(2018110401);
|
||||
end;
|
||||
|
@ -1577,10 +1577,8 @@ end;
|
||||
{ Generic threadmanager }
|
||||
{$i thread.inc}
|
||||
|
||||
{$ifndef FPC_SECTION_THREADVARS}
|
||||
{ Generic threadvar support }
|
||||
{$i threadvr.inc}
|
||||
{$endif FPC_SECTION_THREADVARS}
|
||||
|
||||
{$ifdef DISABLE_NO_THREAD_MANAGER}
|
||||
{ OS Dependent implementation }
|
||||
|
@ -110,10 +110,11 @@ Function SetThreadManager(Const NewTM : TThreadManager; Var OldTM : TThreadManag
|
||||
Function SetThreadManager(Const NewTM : TThreadManager) : Boolean;
|
||||
{$ifndef DISABLE_NO_THREAD_MANAGER}
|
||||
{$endif DISABLE_NO_THREAD_MANAGER}
|
||||
// Needs to be exported, so the manager can call it.
|
||||
{$ifndef FPC_SECTION_THREADVARS}
|
||||
{ Needs to be exported, so the manager can call it.
|
||||
It needs to be exported even if FPC_SECTION_THREADVARS is set as it relocates also the
|
||||
heap
|
||||
}
|
||||
procedure InitThreadVars(RelocProc : TRelocateThreadVarHandler);
|
||||
{$endif FPC_SECTION_THREADVARS}
|
||||
procedure InitThread(stklen:SizeUInt);
|
||||
procedure DoneThread;
|
||||
|
||||
|
@ -47,6 +47,13 @@ function fpc_geteipasebxlocal : pointer; [external name 'fpc_geteipasebx'];
|
||||
|
||||
procedure InitTLS; [external name 'FPC_INITTLS'];
|
||||
|
||||
|
||||
{ so far, I found no case where this is actually called, so it is a dummy so far (FK) }
|
||||
function ___tls_get_addr(p : pointer) : pointer; public name '___tls_get_addr';
|
||||
begin
|
||||
end;
|
||||
|
||||
|
||||
procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
|
||||
asm
|
||||
{ First locate the start of the environment variables }
|
||||
|
@ -496,6 +496,7 @@ end;
|
||||
procedure InitTLS; [public,alias:'FPC_INITTLS'];
|
||||
const
|
||||
PT_TLS = 7;
|
||||
PT_DYNAMIC = 2;
|
||||
|
||||
type
|
||||
tphdr = record
|
||||
@ -536,18 +537,30 @@ procedure InitTLS; [public,alias:'FPC_INITTLS'];
|
||||
inc(auxp,2);
|
||||
end;
|
||||
found:=false;
|
||||
size:=0;
|
||||
for i:=1 to phnum do
|
||||
begin
|
||||
if phdr^.p_type=PT_TLS then
|
||||
begin
|
||||
found:=true;
|
||||
break;
|
||||
end;
|
||||
case phdr^.p_type of
|
||||
PT_TLS:
|
||||
begin
|
||||
found:=true;
|
||||
inc(size,phdr^.p_memsz);
|
||||
size:=Align(size,phdr^.p_align);
|
||||
end;
|
||||
PT_DYNAMIC:
|
||||
{ if the program header contains a dynamic section, the program
|
||||
is linked dynamically so the dynamic linker takes care of the
|
||||
allocation of the TLS segment.
|
||||
|
||||
We cannot allocate it by ourself anyways as PT_TLS provides only
|
||||
the size of TLS data of the executable itself
|
||||
}
|
||||
exit;
|
||||
end;
|
||||
inc(phdr);
|
||||
end;
|
||||
if found then
|
||||
begin
|
||||
size:=phdr^.p_memsz;
|
||||
{$ifdef CPUI386}
|
||||
{ threadvars should start at a page boundary,
|
||||
add extra space for the TCB }
|
||||
|
@ -233,7 +233,9 @@ Type PINTRTLEvent = ^TINTRTLEvent;
|
||||
|
||||
procedure CReleaseThreadVars;
|
||||
begin
|
||||
{$ifndef FPC_SECTION_THREADVARS}
|
||||
Fpmunmap(pointer(pthread_getspecific(tlskey)),threadvarblocksize);
|
||||
{$endif FPC_SECTION_THREADVARS}
|
||||
end;
|
||||
|
||||
{ Include OS independent Threadvar initialization }
|
||||
@ -300,9 +302,11 @@ Type PINTRTLEvent = ^TINTRTLEvent;
|
||||
fpwrite(0,s[1],length(s));
|
||||
{$endif DEBUG_MT}
|
||||
ti:=pthreadinfo(param)^;
|
||||
dispose(pthreadinfo(param));
|
||||
|
||||
{ Initialize thread }
|
||||
InitThread(ti.stklen);
|
||||
|
||||
dispose(pthreadinfo(param));
|
||||
{ Start thread function }
|
||||
{$ifdef DEBUG_MT}
|
||||
writeln('Jumping to thread function');
|
||||
@ -323,9 +327,7 @@ Type PINTRTLEvent = ^TINTRTLEvent;
|
||||
begin
|
||||
{ We're still running in single thread mode, setup the TLS }
|
||||
pthread_key_create(@TLSKey,nil);
|
||||
{$ifndef FPC_SECTION_THREADVARS}
|
||||
InitThreadVars(@CRelocateThreadvar);
|
||||
{$endif FPC_SECTION_THREADVARS}
|
||||
{ used to clean up threads that we did not create ourselves:
|
||||
a) the default value for a key (and hence also this one) in
|
||||
new threads is NULL, and if it's still like that when the
|
||||
|
Loading…
Reference in New Issue
Block a user