+ support for tlsm_general on i386-linux

git-svn-id: trunk@40281 -
This commit is contained in:
florian 2018-11-11 17:32:20 +00:00
parent 6d78637441
commit 72416edcc4
10 changed files with 75 additions and 22 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 }

View File

@ -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;

View File

@ -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 }

View File

@ -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 }

View File

@ -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