* make FPC RTL again compatible to OS/2 2.x (avoid using DosAllocThreadAlloc/FreeMemory if not available while keeping to use them if possible)

git-svn-id: trunk@28979 -
This commit is contained in:
Tomas Hajny 2014-11-03 21:05:32 +00:00
parent 7c34dc51a1
commit 9419073608
2 changed files with 123 additions and 20 deletions

View File

@ -1241,8 +1241,27 @@ begin
end;
end;
end;
end;
if RC <> 0 then
if RC <> 0 then
OSErrorWatch (RC);
RC := DosQueryProcAddr (DosCallsHandle, OrdDosAllocThreadLocalMemory,
nil, P);
if RC = 0 then
begin
DosAllocThreadLocalMemory := TDosAllocThreadLocalMemory (P);
RC := DosQueryProcAddr (DosCallsHandle, OrdDosAllocThreadLocalMemory,
nil, P);
if RC = 0 then
begin
DosFreeThreadLocalMemory := TDosFreeThreadLocalMemory (P);
TLSAPISupported := true;
end
else
OSErrorWatch (RC);
end
else
OSErrorWatch (RC);
end
else
OSErrorWatch (RC);
{ ... and exceptions }

View File

@ -1,6 +1,6 @@
{
This file is part of the Free Pascal run time library.
Copyright (c) 2002-2011 by Tomas Hajny,
Copyright (c) 2002-2014 by Tomas Hajny,
member of the Free Pascal development team.
OS/2 threading support implementation
@ -18,6 +18,9 @@
Local Api imports
*****************************************************************************}
var
OS2ThreadManager: TThreadManager;
const
pag_Read = 1;
pag_Write = 2;
@ -98,12 +101,27 @@ type
PFSRec: pointer;
end;
TDosAllocThreadLocalMemory = function (Count: cardinal; var P: pointer):
cardinal; cdecl;
TDosFreeThreadLocalMemory = function (P: pointer): cardinal; cdecl;
const
DosAllocThreadLocalMemory: TDosAllocThreadLocalMemory = nil;
DosFreeThreadLocalMemory: TDosFreeThreadLocalMemory = nil;
OrdDosAllocThreadLocalMemory = 454;
OrdDosFreeThreadLocalMemory = 455;
TLSAPISupported: boolean = false;
{ import the necessary stuff from the OS }
(*
function DosAllocThreadLocalMemory (Count: cardinal; var P: pointer): cardinal;
cdecl; external 'DOSCALLS' index 454;
function DosFreeThreadLocalMemory (P: pointer): cardinal; cdecl;
external 'DOSCALLS' index 455;
*)
function DosCreateThread (var TID: cardinal; Address: pointer;
(* TThreadFunc *)
@ -177,16 +195,24 @@ function DosQuerySysState (EntityList, EntityLevel, PID, TID: cardinal;
*****************************************************************************}
const
ThreadVarBlockSize: dword = 0;
ThreadVarBlockSize: dword = 0;
const
(* Pointer to an allocated dword space within the local thread *)
(* memory area. Pointer to the real memory block allocated for *)
(* thread vars in this block is then stored in this dword. *)
DataIndex: PPointer = nil;
DataIndex: PPointer = nil;
type
(* If Thread Local Memory Area (TLMA) and the respective API functions are *)
(* not available (OS/2 version 2.x) then handle the memory using array *)
(* of pointers indexed by Thread ID - pointer to this array is then stored *)
(* in DataIndex (typecasted using the following types). *)
TTLSPointers = array [0..4095] of pointer;
PTLSPointers = ^TTLSPointers;
procedure SysInitThreadvar (var Offset: dword; Size: dword);
begin
Offset := ThreadVarBlockSize;
@ -203,8 +229,20 @@ begin
{ exceptions which use threadvars but }
{ these aren't allocated yet ... }
{ allocate room on the heap for the thread vars }
RC := DosAllocMem (DataIndex^, ThreadVarBlockSize, pag_Read or pag_Write
or pag_Commit);
if TLSAPISupported then
RC := DosAllocMem (DataIndex^, ThreadVarBlockSize, pag_Read or pag_Write
or pag_Commit)
else
begin
if PTLSPointers (DataIndex)^ [ThreadID] <> nil then
begin
RC := DosFreeMem (PTLSPointers (DataIndex)^ [ThreadID]);
if RC <> 0 then
OSErrorWatch (RC);
end;
RC := DosAllocMem (PTLSPointers (DataIndex)^ [ThreadID], ThreadVarBlockSize,
pag_Read or pag_Write or pag_Commit);
end;
if RC <> 0 then
begin
OSErrorWatch (RC);
@ -215,22 +253,35 @@ begin
FillChar (DataIndex^^, 0, ThreadVarBlockSize);
end;
function SysRelocateThreadVar (Offset: dword): pointer;
begin
{ DataIndex itself not checked for not being nil - expected that this should }
{ not be necessary because the equivalent check (i.e. TlsKey not being set) }
{ is note performed by the Windows implementation. }
{ is not performed by the Windows implementation. }
if PTLSPointers (DataIndex)^ [ThreadID] = nil then
begin
SysAllocateThreadVars;
InitThread ($1000000);
end;
SysRelocateThreadVar := PTLSPointers (DataIndex)^ [ThreadID] + Offset;
end;
function OS2RelocateThreadVar (Offset: dword): pointer;
begin
{ DataIndex itself not checked for not being nil - expected that this should }
{ not be necessary because the equivalent check (i.e. TlsKey not being set) }
{ is not performed by the Windows implementation. }
if DataIndex^ = nil then
begin
SysAllocateThreadVars;
InitThread ($1000000);
end;
SysRelocateThreadVar := DataIndex^ + Offset;
OS2RelocateThreadVar := DataIndex^ + Offset;
end;
procedure SysInitMultithreading;
var
RC: cardinal;
begin
{ do not check IsMultiThread, as program could have altered it, out of Delphi habit }
@ -238,8 +289,30 @@ begin
if DataIndex = nil then
begin
{ We're still running in single thread mode, setup the TLS }
if DosAllocThreadLocalMemory (1, DataIndex) <> 0 then RunError (8);
InitThreadVars (@SysRelocateThreadvar);
RC := DosAllocThreadLocalMemory (1, DataIndex);
if RC = 0 then
begin
(* Avoid the need for checking TLSAPISupported on every call *)
(* to RelocateThreadVar - ensure using the right version. *)
OS2ThreadManager.RelocateThreadVar := @OS2RelocateThreadVar;
CurrentTM.RelocateThreadVar := @OS2RelocateThreadVar;
InitThreadVars (@OS2RelocateThreadvar);
end
else
begin
OSErrorWatch (RC);
(* We can still try using the internal solution for older OS/2 versions... *)
TLSAPISupported := false;
RC := DosAllocMem (DataIndex, SizeOf (TTLSPointers),
pag_Read or pag_Write or pag_Commit);
if RC = 0 then
InitThreadVars (@SysRelocateThreadvar)
else
begin
OSErrorWatch (RC);
RunError (8);
end;
end;
IsMultiThread := true;
end;
end;
@ -251,7 +324,10 @@ var
begin
if IsMultiThread then
begin
RC := DosFreeThreadLocalMemory (DataIndex);
if TLSAPISupported then
RC := DosFreeThreadLocalMemory (DataIndex)
else
RC := DosFreeMem (DataIndex);
if RC <> 0 then
begin
{??? What to do if releasing fails?}
@ -265,11 +341,23 @@ end;
procedure SysReleaseThreadVars;
var
RC: cardinal;
(* TID serves for storing ThreadID before freeing the memory allocated *)
(* to threadvars to avoid accessing a threadvar ThreadID afterwards. *)
TID: cardinal;
begin
RC := DosFreeMem (DataIndex^);
if TLSAPISupported then
begin
RC := DosFreeMem (DataIndex^);
DataIndex^ := nil;
end
else
begin
TID := ThreadID;
RC := DosFreeMem (PTLSPointers (DataIndex)^ [TID]);
PTLSPointers (DataIndex)^ [TID] := nil;
end;
if RC <> 0 then
OSErrorWatch (RC);
DataIndex^ := nil;
end;
@ -837,10 +925,6 @@ begin
end;
var
OS2ThreadManager: TThreadManager;
procedure InitSystemThreads;
begin
with OS2ThreadManager do