systhrd.inc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2002 by Peter Vreman,
  4. member of the Free Pascal development team.
  5. Linux (pthreads) threading support implementation
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {*****************************************************************************
  13. Local WINApi imports
  14. *****************************************************************************}
  15. const
  16. { LocalAlloc flags }
  17. LMEM_FIXED = 0;
  18. LMEM_ZEROINIT = 64;
  19. {$ifndef WINCE}
  20. function TlsAlloc : DWord;
  21. stdcall;external KernelDLL name 'TlsAlloc';
  22. function TlsFree(dwTlsIndex : DWord) : LongBool;
  23. stdcall;external KernelDLL name 'TlsFree';
  24. {$endif WINCE}
  25. function TlsGetValue(dwTlsIndex : DWord) : pointer;
  26. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'TlsGetValue';
  27. function TlsSetValue(dwTlsIndex : DWord;lpTlsValue : pointer) : LongBool;
  28. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'TlsSetValue';
  29. function CreateThread(lpThreadAttributes : pointer;
  30. dwStackSize : SIZE_T; lpStartAddress : pointer;lpParameter : pointer;
  31. dwCreationFlags : DWord;var lpThreadId : DWord) : THandle;
  32. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'CreateThread';
  33. procedure ExitThread(dwExitCode : DWord);
  34. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'ExitThread';
  35. function LocalAlloc(uFlags:DWord; dwBytes:SIZE_T):Pointer;
  36. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'LocalAlloc';
  37. function LocalFree(hMem : Pointer):Pointer; {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'LocalFree';
  38. procedure Sleep(dwMilliseconds: DWord); {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'Sleep';
  39. function WinSuspendThread (threadHandle : THandle) : dword; {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'SuspendThread';
  40. function WinResumeThread (threadHandle : THandle) : dword; {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'ResumeThread';
  41. function WinCloseHandle (threadHandle : THandle) : dword; {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'CloseHandle';
  42. function TerminateThread (threadHandle : THandle; var exitCode : dword) : boolean; {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'TerminateThread';
  43. function WaitForSingleObject (hHandle : THandle;Milliseconds: dword): dword; {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'WaitForSingleObject';
  44. function WinThreadSetPriority (threadHandle : THandle; Prio: longint): boolean; {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'SetThreadPriority';
  45. function WinThreadGetPriority (threadHandle : THandle): LongInt; {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'GetThreadPriority';
  46. {$ifndef WINCE}
  47. function WinGetCurrentThread: THandle; stdcall; external KernelDLL name 'GetCurrentThread';
  48. function WinOpenThread(dwDesiredAccess: DWord; bInheritHandle: Boolean; dwThreadId: DWord): THandle; stdcall; external KernelDLL name 'OpenThread';
  49. function WinIsDebuggerPresent: Boolean; stdcall; external KernelDLL name 'IsDebuggerPresent';
  50. type
  51. TSetThreadDescription = function(threadHandle: THandle; lpThreadDescription: PWideChar): HResult; stdcall;
  52. var
  53. WinSetThreadDescription: TSetThreadDescription;
  54. function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle; stdcall; external KernelDLL name 'CreateEventA';
  55. function ResetEvent(hEvent:THandle):LONGBOOL; stdcall; external KernelDLL name 'ResetEvent';
  56. function SetEvent(hEvent:THandle):LONGBOOL; stdcall; external KernelDLL name 'SetEvent';
  57. {$endif WINCE}
  58. procedure WinInitCriticalSection(var cs : TRTLCriticalSection);
  59. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'InitializeCriticalSection';
  60. procedure WinDoneCriticalSection(var cs : TRTLCriticalSection);
  61. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'DeleteCriticalSection';
  62. procedure WinEnterCriticalSection(var cs : TRTLCriticalSection);
  63. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'EnterCriticalSection';
  64. procedure WinLeaveCriticalSection(var cs : TRTLCriticalSection);
  65. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'LeaveCriticalSection';
  66. CONST
  67. WAIT_OBJECT_0 = 0;
  68. WAIT_ABANDONED_0 = $80;
  69. WAIT_TIMEOUT = $102;
  70. WAIT_IO_COMPLETION = $c0;
  71. WAIT_ABANDONED = $80;
  72. WAIT_FAILED = $ffffffff;
  73. {$ifndef SUPPORT_WIN95}
  74. function WinTryEnterCriticalSection(var cs : TRTLCriticalSection):longint;
  75. {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'TryEnterCriticalSection';
  76. {$else SUPPORT_WIN95}
  77. type
  78. TTryEnterCriticalSection = function(var cs : TRTLCriticalSection):longint; stdcall;
  79. var
  80. WinTryEnterCriticalSection : TTryEnterCriticalSection;
  81. {$endif SUPPORT_WIN95}
  82. {*****************************************************************************
  83. Threadvar support
  84. *****************************************************************************}
  85. var
  86. // public names are used by heaptrc unit
  87. threadvarblocksize : dword; public name '_FPC_TlsSize';
  88. {$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
  89. TLSKey : PDword = nil; public name '_FPC_TlsKey';
  90. {$else FPC_HAS_INDIRECT_ENTRY_INFORMATION}
  91. TLSKeyVar : DWord = $ffffffff;
  92. TLSKey : PDWord = @TLSKeyVar; public name '_FPC_TlsKey';
  93. {$endif FPC_HAS_INDIRECT_ENTRY_INFORMATION}
  94. var
  95. MainThreadIdWin32 : DWORD;
  96. procedure SysInitThreadvar(var offset : dword;size : dword);
  97. begin
  98. offset:=threadvarblocksize;
  99. {$ifdef CPUARM}
  100. // Data must be allocated at 4 bytes boundary for ARM
  101. size:=(size + 3) and not dword(3);
  102. {$endif CPUARM}
  103. inc(threadvarblocksize,size);
  104. end;
  105. procedure SysAllocateThreadVars; public name '_FPC_SysAllocateThreadVars';
  106. var
  107. dataindex : pointer;
  108. errorsave : dword;
  109. begin
  110. { we've to allocate the memory from system }
  111. { because the FPC heap management uses }
  112. { exceptions which use threadvars but }
  113. { these aren't allocated yet ... }
  114. { allocate room on the heap for the thread vars }
  115. errorsave:=GetLastError;
  116. if tlskey^=$ffffffff then
  117. RunError(226);
  118. dataindex:=TlsGetValue(tlskey^);
  119. if dataindex=nil then
  120. begin
  121. dataindex:=pointer(LocalAlloc(LMEM_FIXED or LMEM_ZEROINIT,threadvarblocksize));
  122. if dataindex=nil then
  123. RunError(226);
  124. TlsSetValue(tlskey^,dataindex);
  125. end;
  126. SetLastError(errorsave);
  127. end;
  128. function SysRelocateThreadvar(offset : dword) : pointer; forward;
  129. procedure SysInitTLS;
  130. begin
  131. { do not check IsMultiThread, as program could have altered it, out of Delphi habit }
  132. { the thread attach/detach code uses locks to avoid multiple calls of this }
  133. if TLSKey^=$ffffffff then
  134. begin
  135. { We're still running in single thread mode, setup the TLS }
  136. TLSKey^:=TlsAlloc;
  137. InitThreadVars(@SysRelocateThreadvar);
  138. end;
  139. end;
  140. procedure SysFiniMultithreading;
  141. begin
  142. if TLSKey^<>$ffffffff then
  143. TlsFree(TLSKey^);
  144. TLSKey^:=$ffffffff;
  145. end;
  146. function SysRelocateThreadvar(offset : dword) : pointer;
  147. var
  148. dataindex : pointer;
  149. errorsave : dword;
  150. begin
  151. errorsave:=GetLastError;
  152. dataindex:=TlsGetValue(tlskey^);
  153. if dataindex=nil then
  154. begin
  155. SysAllocateThreadVars;
  156. dataindex:=TlsGetValue(tlskey^);
  157. InitThread($1000000);
  158. end;
  159. SetLastError(errorsave);
  160. SysRelocateThreadvar:=DataIndex+Offset;
  161. end;
  162. procedure SysReleaseThreadVars;
  163. var
  164. p: pointer;
  165. begin
  166. if TLSKey^<>$ffffffff then
  167. begin
  168. p:=TlsGetValue(tlskey^);
  169. if Assigned(p) then
  170. LocalFree(p);
  171. TlsSetValue(tlskey^, nil);
  172. end;
  173. end;
  174. {*****************************************************************************
  175. Thread starting
  176. *****************************************************************************}
  177. type
  178. pthreadinfo = ^tthreadinfo;
  179. tthreadinfo = record
  180. f : tthreadfunc;
  181. p : pointer;
  182. stklen : ptruint;
  183. end;
  184. function ThreadMain(param : pointer) : Longint; {$ifdef wince}cdecl{$else}stdcall{$endif};
  185. var
  186. ti : tthreadinfo;
  187. begin
  188. { Copy parameter to local data }
  189. ti:=pthreadinfo(param)^;
  190. { Handle all possible threadvar models:
  191. - dynamic threadvars: initialized either in DllMain,
  192. or upon accessing the threadvar ThreadID;
  193. - static threadvars+TLS callback: initialized in TLS callback;
  194. - static threadvars, no callback: ThreadID remains 0 and
  195. initialization happens here. }
  196. if ThreadID=TThreadID(0) then
  197. InitThread(ti.stklen);
  198. dispose(pthreadinfo(param));
  199. { Start thread function }
  200. {$ifdef DEBUG_MT}
  201. writeln('Jumping to thread function of thread ',Win32GetCurrentThreadId);
  202. {$endif DEBUG_MT}
  203. {$if defined(FPC_USE_WIN64_SEH) or defined(FPC_USE_WIN32_SEH)}
  204. { use special 'top-level' exception handler around the thread function }
  205. ThreadMain:=main_wrapper(ti.p,pointer(ti.f));
  206. {$else FPC_USE_WIN64_SEH}
  207. ThreadMain:=ti.f(ti.p);
  208. {$endif FPC_USE_WIN64_SEH or FPC_USE_WIN32_SEH}
  209. end;
  210. function SysBeginThread(sa : Pointer;stacksize : ptruint;
  211. ThreadFunction : tthreadfunc;p : pointer;
  212. creationFlags : dword;var ThreadId : TThreadID) : TThreadID;
  213. var
  214. ti : pthreadinfo;
  215. _threadid : dword;
  216. begin
  217. {$ifdef DEBUG_MT}
  218. writeln('Creating new thread');
  219. {$endif DEBUG_MT}
  220. { Initialize multithreading if not done }
  221. SysInitTLS;
  222. IsMultiThread:=true;
  223. { the only way to pass data to the newly created thread
  224. in a MT safe way, is to use the heap }
  225. new(ti);
  226. ti^.f:=ThreadFunction;
  227. ti^.p:=p;
  228. ti^.stklen:=stacksize;
  229. {$ifdef DEBUG_MT}
  230. writeln('Starting new thread');
  231. {$endif DEBUG_MT}
  232. _threadid:=0;
  233. SysBeginThread:=CreateThread(sa,stacksize,@ThreadMain,ti,creationflags,_threadid);
  234. { creation failed? if yes, we dispose the parameter record }
  235. if SysBeginThread=0 then
  236. begin
  237. {$ifdef DEBUG_MT}
  238. writeln('Thread creation failed');
  239. {$endif DEBUG_MT}
  240. dispose(ti);
  241. end;
  242. ThreadID:=_threadid;
  243. end;
  244. procedure SysEndThread(ExitCode : DWord);
  245. begin
  246. DoneThread;
  247. ExitThread(ExitCode);
  248. end;
  249. procedure SysThreadSwitch;
  250. begin
  251. Sleep(0);
  252. end;
  253. function SysSuspendThread (threadHandle : TThreadID) : dword;
  254. begin
  255. SysSuspendThread:=WinSuspendThread(threadHandle);
  256. end;
  257. function SysResumeThread (threadHandle : TThreadID) : dword;
  258. begin
  259. SysResumeThread:=WinResumeThread(threadHandle);
  260. end;
  261. function SysKillThread (threadHandle : TThreadID) : dword;
  262. var exitCode : dword;
  263. begin
  264. if not TerminateThread (threadHandle, exitCode) then
  265. SysKillThread := GetLastError
  266. else
  267. SysKillThread := 0;
  268. end;
  269. function SysCloseThread (threadHandle : TThreadID) : dword;
  270. begin
  271. SysCloseThread:=winCloseHandle(threadHandle);
  272. end;
  273. function SysWaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword;
  274. begin
  275. if timeoutMs = 0 then dec (timeoutMs); // $ffffffff is INFINITE
  276. SysWaitForThreadTerminate := WaitForSingleObject(threadHandle, TimeoutMs);
  277. end;
  278. function SysThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean; {-15..+15, 0=normal}
  279. begin
  280. SysThreadSetPriority:=WinThreadSetPriority(threadHandle,Prio);
  281. end;
  282. function SysThreadGetPriority (threadHandle : TThreadID): longint;
  283. begin
  284. SysThreadGetPriority:=WinThreadGetPriority(threadHandle);
  285. end;
  286. function SysGetCurrentThreadId : TThreadID;
  287. begin
  288. SysGetCurrentThreadId:=Win32GetCurrentThreadId;
  289. end;
  290. {$ifndef WINCE}
  291. { following method is supported on older Windows versions AND currently only supported method by GDB }
  292. procedure RaiseMSVCExceptionMethod(threadHandle: TThreadID; const ThreadName: AnsiString);
  293. const
  294. MS_VC_EXCEPTION: DWord = $406D1388;
  295. type
  296. THREADNAME_INFO = record
  297. dwType: DWord; // Must be 0x1000.
  298. szName: PAnsiChar; // Pointer to name (in user addr space).
  299. dwThreadID: DWord; // Thread ID (-1=caller thread).
  300. dwFlags: DWord; // Reserved for future use, must be zero.
  301. end;
  302. var
  303. thrdinfo: THREADNAME_INFO;
  304. begin
  305. thrdinfo.dwType:=$1000;
  306. thrdinfo.szName:=@ThreadName[1];
  307. thrdinfo.dwThreadID:=threadHandle;
  308. thrdinfo.dwFlags:=0;
  309. try
  310. RaiseException(MS_VC_EXCEPTION, 0, SizeOf(thrdinfo) div SizeOf(DWord), @thrdinfo);
  311. except
  312. {do nothing}
  313. end;
  314. end;
  315. { following method needs at least Windows 10 version 1607 or Windows Server 2016 }
  316. procedure SetThreadDescriptionMethod(threadHandle: TThreadID; const ThreadName: UnicodeString);
  317. var
  318. thrdhandle: THandle;
  319. ClosingNeeded: Boolean;
  320. begin
  321. if threadHandle=TThreadID(-1) then
  322. begin
  323. thrdhandle:=WinGetCurrentThread;
  324. ClosingNeeded:=False;
  325. end
  326. else
  327. begin
  328. thrdhandle:=WinOpenThread($0400, False, threadHandle);
  329. ClosingNeeded:=True;
  330. end;
  331. WinSetThreadDescription(thrdhandle, @ThreadName[1]);
  332. if ClosingNeeded then
  333. begin
  334. CloseHandle(thrdhandle);
  335. end;
  336. end;
  337. {$endif WINCE}
  338. procedure SysSetThreadDebugNameA(threadHandle: TThreadID; const ThreadName: AnsiString);
  339. begin
  340. {$ifndef WINCE}
  341. if ThreadName = '' then
  342. Exit;
  343. if WinIsDebuggerPresent then
  344. begin
  345. RaiseMSVCExceptionMethod(threadHandle, ThreadName);
  346. end;
  347. if Assigned(WinSetThreadDescription) then
  348. begin
  349. SetThreadDescriptionMethod(threadHandle, UnicodeString(ThreadName));
  350. end;
  351. {$else WINCE}
  352. {$Warning SetThreadDebugNameA needs to be implemented}
  353. {$endif WINCE}
  354. end;
  355. procedure SysSetThreadDebugNameU(threadHandle: TThreadID; const ThreadName: UnicodeString);
  356. begin
  357. {$ifndef WINCE}
  358. if ThreadName = '' then
  359. Exit;
  360. if WinIsDebuggerPresent then
  361. begin
  362. RaiseMSVCExceptionMethod(threadHandle, AnsiString(ThreadName));
  363. end;
  364. if Assigned(WinSetThreadDescription) then
  365. begin
  366. SetThreadDescriptionMethod(threadHandle, ThreadName);
  367. end;
  368. {$else WINCE}
  369. {$Warning SetThreadDebugNameU needs to be implemented}
  370. {$endif WINCE}
  371. end;
  372. {*****************************************************************************
  373. Delphi/Win32 compatibility
  374. *****************************************************************************}
  375. procedure SySInitCriticalSection(var cs);
  376. begin
  377. WinInitCriticalSection(PRTLCriticalSection(@cs)^);
  378. end;
  379. procedure SysDoneCriticalSection(var cs);
  380. begin
  381. WinDoneCriticalSection(PRTLCriticalSection(@cs)^);
  382. end;
  383. procedure SysEnterCriticalSection(var cs);
  384. begin
  385. WinEnterCriticalSection(PRTLCriticalSection(@cs)^);
  386. end;
  387. {$ifdef SUPPORT_WIN95}
  388. function Win95TryEnterCriticalSection(var cs : TRTLCriticalSection):longint;stdcall;
  389. var
  390. MyThreadID : DWORD;
  391. begin
  392. MyThreadId:=GetCurrentThreadId();
  393. if InterlockedIncrement(cs.LockCount)=0 then
  394. begin
  395. cs.OwningThread:=MyThreadId;
  396. cs.RecursionCount:=1;
  397. result:=1;
  398. end
  399. else
  400. begin
  401. if cs.OwningThread=MyThreadId then
  402. begin
  403. InterlockedDecrement(cs.LockCount);
  404. InterlockedIncrement(cs.RecursionCount);
  405. result:=1;
  406. end
  407. else
  408. begin
  409. InterlockedDecrement(cs.LockCount);
  410. result:=0;
  411. end;
  412. end;
  413. end;
  414. {$endif SUPPORT_WIN95}
  415. function SysTryEnterCriticalSection(var cs):longint;
  416. begin
  417. result:=WinTryEnterCriticalSection(PRTLCriticalSection(@cs)^);
  418. end;
  419. procedure SySLeaveCriticalSection(var cs);
  420. begin
  421. WinLeaveCriticalSection(PRTLCriticalSection(@cs)^);
  422. end;
  423. Const
  424. wrSignaled = 0;
  425. wrTimeout = 1;
  426. wrAbandoned= 2;
  427. wrError = 3;
  428. type Tbasiceventstate=record
  429. fhandle : THandle;
  430. flasterror : longint;
  431. end;
  432. plocaleventrec= ^tbasiceventstate;
  433. function intBasicEventCreate(EventAttributes : Pointer;
  434. AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;
  435. var
  436. n : PChar;
  437. begin
  438. new(plocaleventrec(result));
  439. if Length(Name) = 0 then
  440. n := Nil
  441. else
  442. n := PChar(Name);
  443. plocaleventrec(result)^.FHandle := CreateEvent(EventAttributes, AManualReset, InitialState,n);
  444. end;
  445. procedure intbasiceventdestroy(state:peventstate);
  446. begin
  447. closehandle(plocaleventrec(state)^.fhandle);
  448. dispose(plocaleventrec(state));
  449. end;
  450. procedure intbasiceventResetEvent(state:peventstate);
  451. begin
  452. ResetEvent(plocaleventrec(state)^.FHandle)
  453. end;
  454. procedure intbasiceventSetEvent(state:peventstate);
  455. begin
  456. SetEvent(plocaleventrec(state)^.FHandle);
  457. end;
  458. function intbasiceventWaitFor(Timeout : Cardinal;state:peventstate) : longint;
  459. begin
  460. case WaitForSingleObject(plocaleventrec(state)^.fHandle, Timeout) of
  461. WAIT_ABANDONED: Result := wrAbandoned;
  462. WAIT_OBJECT_0: Result := wrSignaled;
  463. WAIT_TIMEOUT: Result := wrTimeout;
  464. WAIT_FAILED:
  465. begin
  466. Result := wrError;
  467. plocaleventrec(state)^.FLastError := GetLastError;
  468. end;
  469. else
  470. Result := wrError;
  471. end;
  472. end;
  473. function intRTLEventCreate: PRTLEvent;
  474. begin
  475. Result := PRTLEVENT(CreateEvent(nil, false, false, nil));
  476. end;
  477. procedure intRTLEventDestroy(AEvent: PRTLEvent);
  478. begin
  479. CloseHandle(THANDLE(AEvent));
  480. end;
  481. procedure intRTLEventSetEvent(AEvent: PRTLEvent);
  482. begin
  483. SetEvent(THANDLE(AEvent));
  484. end;
  485. procedure intRTLEventResetEvent(AEvent: PRTLEvent);
  486. begin
  487. ResetEvent(THANDLE(AEvent));
  488. end;
  489. procedure intRTLEventWaitFor(AEvent: PRTLEvent);
  490. const
  491. INFINITE=dword(-1);
  492. begin
  493. WaitForSingleObject(THANDLE(AEvent), INFINITE);
  494. end;
  495. procedure intRTLEventWaitForTimeout(AEvent: PRTLEvent;timeout : longint);
  496. begin
  497. WaitForSingleObject(THANDLE(AEvent), timeout);
  498. end;
  499. Var
  500. WinThreadManager : TThreadManager;
  501. Procedure InitSystemThreads;public name '_FPC_InitSystemThreads';
  502. {$ifndef WINCE}
  503. var
  504. KernelHandle : THandle;
  505. {$endif}
  506. begin
  507. With WinThreadManager do
  508. begin
  509. InitManager :=Nil;
  510. DoneManager :=Nil;
  511. BeginThread :=@SysBeginThread;
  512. EndThread :=@SysEndThread;
  513. SuspendThread :=@SysSuspendThread;
  514. ResumeThread :=@SysResumeThread;
  515. KillThread :=@SysKillThread;
  516. ThreadSwitch :=@SysThreadSwitch;
  517. CloseThread :=@SysCloseThread;
  518. WaitForThreadTerminate :=@SysWaitForThreadTerminate;
  519. ThreadSetPriority :=@SysThreadSetPriority;
  520. ThreadGetPriority :=@SysThreadGetPriority;
  521. GetCurrentThreadId :=@SysGetCurrentThreadId;
  522. SetThreadDebugNameA :=@SysSetThreadDebugNameA;
  523. SetThreadDebugNameU :=@SysSetThreadDebugNameU;
  524. InitCriticalSection :=@SysInitCriticalSection;
  525. DoneCriticalSection :=@SysDoneCriticalSection;
  526. EnterCriticalSection :=@SysEnterCriticalSection;
  527. TryEnterCriticalSection:=@SysTryEnterCriticalSection;
  528. LeaveCriticalSection :=@SysLeaveCriticalSection;
  529. InitThreadVar :=@SysInitThreadVar;
  530. RelocateThreadVar :=@SysRelocateThreadVar;
  531. AllocateThreadVars :=@SysAllocateThreadVars;
  532. ReleaseThreadVars :=@SysReleaseThreadVars;
  533. BasicEventCreate :=@intBasicEventCreate;
  534. BasicEventDestroy :=@intBasicEventDestroy;
  535. BasicEventResetEvent :=@intBasicEventResetEvent;
  536. BasicEventSetEvent :=@intBasicEventSetEvent;
  537. BasiceventWaitFor :=@intBasiceventWaitFor;
  538. RTLEventCreate :=@intRTLEventCreate;
  539. RTLEventDestroy :=@intRTLEventDestroy;
  540. RTLEventSetEvent :=@intRTLEventSetEvent;
  541. RTLEventResetEvent :=@intRTLEventResetEvent;
  542. RTLEventWaitFor :=@intRTLEventWaitFor;
  543. RTLEventWaitForTimeout :=@intRTLEventWaitForTimeout;
  544. end;
  545. SetThreadManager(WinThreadManager);
  546. ThreadID := GetCurrentThreadID;
  547. {$ifndef FPC_USE_TLS_DIRECTORY}
  548. if IsLibrary then
  549. {$endif}
  550. SysInitTLS;
  551. {$ifndef WINCE}
  552. KernelHandle:=GetModuleHandle(KernelDLL);
  553. {$endif}
  554. {$IFDEF SUPPORT_WIN95}
  555. { Try to find TryEnterCriticalSection function }
  556. if KernelHandle<>0 then
  557. WinTryEnterCriticalSection:=TTryEnterCriticalSection(WinGetProcAddress(KernelHandle,'TryEnterCriticalSection'));
  558. if not assigned(WinTryEnterCriticalSection) then
  559. WinTryEnterCriticalSection:=@Win95TryEnterCriticalSection;
  560. {$ENDIF SUPPORT_WIN95}
  561. {$ifndef WINCE}
  562. if KernelHandle<>0 then
  563. begin
  564. WinSetThreadDescription:=TSetThreadDescription(WinGetProcAddress(KernelHandle, 'SetThreadDescription'));
  565. end;
  566. {$endif WINCE}
  567. end;