Freeman пишет:У Delphi есть 4 функции для работы с TLS в System:
В модуле SysInit есть функции для работы с TLS
▼Для Windows:
{$IFDEF MSWINDOWS}
................................................
function TlsAlloc: Integer; stdcall;
external kernel name 'TlsAlloc';
function TlsFree(TlsIndex: Integer): Boolean; stdcall;
external kernel name 'TlsFree';
function TlsGetValue(TlsIndex: Integer): Pointer; stdcall;
external kernel name 'TlsGetValue';
function TlsSetValue(TlsIndex: Integer; TlsValue: Pointer): Boolean; stdcall;
external kernel name 'TlsSetValue';
................................................
const
tlsArray = $2C; { offset of tls array from FS: }
LMEM_ZEROINIT = $40;
function AllocTlsBuffer(Size: Integer): Pointer;
begin
Result := LocalAlloc(LMEM_ZEROINIT, Size);
end;
var
tlsBuffer: Pointer; // RTM32 DOS support
{$ENDIF}
▼Для Linux:
{$IFDEF LINUX}
................................................
function TlsGetValue(Key: Integer): Pointer; cdecl;
external libpthreadmodulename name 'pthread_getspecific';
function TlsSetValue(Key: Integer; Ptr: Pointer): Integer; cdecl;
external libpthreadmodulename name 'pthread_setspecific';
function AllocTlsBuffer(Size: Cardinal): Pointer;
begin
// The C++ rtl handles all tls in a C++ module
if ModuleIsCpp then
RunError(226);
Result := malloc(Size);
if Result <> nil then
FillChar(Result^, Size, 0);
end;
procedure FreeTLSBuffer(ValueInKey: Pointer); export cdecl;
begin
// The C++ rtl handles all tls in a C++ module
if ModuleIsCpp then
RunError(226);
free(ValueInKey);
end;
procedure AllocTlsIndex; cdecl export;
begin
// guaranteed to reach here only once per process
// The C++ rtl handles all tls in a C++ module
if ModuleIsCpp then
RunError(226);
if pthread_key_create(TlsIndex, FreeTLSBuffer) <> 0 then
begin
TlsIndex := -1;
RunError(226);
end;
end;
{$ENDIF}
▼и вот ещё это:
function GetTlsSize: Integer;
{$IFDEF LINUX}
asm
MOV EAX, offset TlsLast
end;
{$ENDIF}
{$IFDEF MSWINDOWS}
begin
Result := Integer(@TlsLast);
end;
{$ENDIF}
procedure InitThreadTLS;
var
p: Pointer;
tlsSize: Integer;
begin
tlsSize := GetTlsSize;
if tlsSize = 0 then Exit;
{$IFDEF LINUX}
pthread_once(InitOnceSemaphore, AllocTlsIndex);
{$ENDIF}
if TlsIndex = -1 then RunError(226);
p := AllocTlsBuffer(tlsSize);
if p = nil then
RunError(226)
else
TlsSetValue(TlsIndex, p);
end;
{$IFDEF MSWINDOWS}
procedure InitProcessTLS;
begin
if @TlsLast = nil then
Exit;
TlsIndex := TlsAlloc;
InitThreadTLS;
tlsBuffer := TlsGetValue(TlsIndex); // RTM32 DOS support
end;
procedure ExitThreadTLS;
var
p: Pointer;
begin
if @TlsLast = nil then
Exit;
if TlsIndex <> -1 then begin
p := TlsGetValue(TlsIndex);
if p <> nil then
LocalFree(p);
end;
end;
procedure ExitProcessTLS;
begin
if @TlsLast = nil then
Exit;
ExitThreadTLS;
if TlsIndex <> -1 then
TlsFree(TlsIndex);
end;
{$ENDIF}
................................................
function _GetTls: Pointer;
{$IFDEF LINUX}
begin
Result := TlsGetValue(TlsIndex);
if Result = nil then
begin
InitThreadTLS;
Result := TlsGetValue(TlsIndex);
end;
end;
{$ENDIF}
{$IFDEF MSWINDOWS}
asm
MOV CL,ModuleIsLib
MOV EAX,TlsIndex
TEST CL,CL
JNE @@isDll
MOV EDX,FS:tlsArray
MOV EAX,[EDX+EAX*4]
RET
@@initTls:
CALL InitThreadTLS
MOV EAX,TlsIndex
PUSH EAX
CALL TlsGetValue
TEST EAX,EAX
JE @@RTM32
RET
@@RTM32:
MOV EAX, tlsBuffer
RET
@@isDll:
PUSH EAX
CALL TlsGetValue
TEST EAX,EAX
JE @@initTls
end;
const
TlsProc: array [DLL_PROCESS_DETACH..DLL_THREAD_DETACH] of procedure =
(ExitProcessTLS,InitProcessTLS,InitThreadTLS,ExitThreadTLS);
{$ENDIF}
Freeman пишет:Под KolibriOS реализация будет в самом System, я правильно понимаю? Тогда их можно сделать register, думаю.
Да, я думаю, что вполне можно в System реализовать.
И, так как под разные ОС используются разные соглашения вызова(Windows — stdcall; Linux — cdecl), то и под KolibriOS можно сделать удобным для нас способом.
Добавлено 2020-12-13 в 23:59
На SVN в newlib есть ещё вот это:
tls_init, tls_free, tls_alloc
tls_get, tls_set