systhrds.pp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2002 by Peter Vreman,
  5. member of the Free Pascal development team.
  6. Win32 threading support implementation
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit systhrds;
  14. interface
  15. {$S-}
  16. type
  17. { the fields of this record are os dependent }
  18. { and they shouldn't be used in a program }
  19. { only the type TCriticalSection is important }
  20. PRTLCriticalSection = ^TRTLCriticalSection;
  21. TRTLCriticalSection = packed record
  22. DebugInfo : pointer;
  23. LockCount : longint;
  24. RecursionCount : longint;
  25. OwningThread : DWord;
  26. LockSemaphore : DWord;
  27. Reserved : DWord;
  28. end;
  29. { Include generic thread interface }
  30. {$i threadh.inc}
  31. implementation
  32. {*****************************************************************************
  33. Generic overloaded
  34. *****************************************************************************}
  35. { Include generic overloaded routines }
  36. {$i thread.inc}
  37. {*****************************************************************************
  38. Local WINApi imports
  39. *****************************************************************************}
  40. const
  41. { GlobalAlloc, GlobalFlags }
  42. GMEM_FIXED = 0;
  43. GMEM_ZEROINIT = 64;
  44. function TlsAlloc : DWord;
  45. external 'kernel32' name 'TlsAlloc';
  46. function TlsGetValue(dwTlsIndex : DWord) : pointer;
  47. external 'kernel32' name 'TlsGetValue';
  48. function TlsSetValue(dwTlsIndex : DWord;lpTlsValue : pointer) : LongBool;
  49. external 'kernel32' name 'TlsSetValue';
  50. function TlsFree(dwTlsIndex : DWord) : LongBool;
  51. external 'kernel32' name 'TlsFree';
  52. function CreateThread(lpThreadAttributes : pointer;
  53. dwStackSize : DWord; lpStartAddress : pointer;lpParameter : pointer;
  54. dwCreationFlags : DWord;var lpThreadId : DWord) : Dword;
  55. external 'kernel32' name 'CreateThread';
  56. procedure ExitThread(dwExitCode : DWord);
  57. external 'kernel32' name 'ExitThread';
  58. function GlobalAlloc(uFlags:DWord; dwBytes:DWORD):Pointer;
  59. external 'kernel32' name 'GlobalAlloc';
  60. function GlobalFree(hMem : Pointer):Pointer; external 'kernel32' name 'GlobalFree';
  61. {*****************************************************************************
  62. Threadvar support
  63. *****************************************************************************}
  64. {$ifdef HASTHREADVAR}
  65. const
  66. threadvarblocksize : dword = 0;
  67. var
  68. TLSKey : Dword;
  69. procedure SysInitThreadvar(var offset : dword;size : dword);
  70. begin
  71. offset:=threadvarblocksize;
  72. inc(threadvarblocksize,size);
  73. end;
  74. function SysRelocateThreadvar(offset : dword) : pointer;
  75. begin
  76. SysRelocateThreadvar:=TlsGetValue(tlskey)+Offset;
  77. end;
  78. procedure SysAllocateThreadVars;
  79. var
  80. dataindex : pointer;
  81. begin
  82. { we've to allocate the memory from system }
  83. { because the FPC heap management uses }
  84. { exceptions which use threadvars but }
  85. { these aren't allocated yet ... }
  86. { allocate room on the heap for the thread vars }
  87. dataindex:=pointer(GlobalAlloc(GMEM_FIXED or GMEM_ZEROINIT,threadvarblocksize));
  88. TlsSetValue(tlskey,dataindex);
  89. end;
  90. procedure SysReleaseThreadVars;
  91. begin
  92. GlobalFree(TlsGetValue(tlskey));
  93. end;
  94. { Include OS independent Threadvar initialization }
  95. {$i threadvr.inc}
  96. {$endif HASTHREADVAR}
  97. {*****************************************************************************
  98. Thread starting
  99. *****************************************************************************}
  100. type
  101. pthreadinfo = ^tthreadinfo;
  102. tthreadinfo = record
  103. f : tthreadfunc;
  104. p : pointer;
  105. stklen : cardinal;
  106. end;
  107. procedure DoneThread;
  108. begin
  109. { Release Threadvars }
  110. {$ifdef HASTHREADVAR}
  111. SysReleaseThreadVars;
  112. {$endif HASTHREADVAR}
  113. end;
  114. function ThreadMain(param : pointer) : pointer;cdecl;
  115. var
  116. ti : tthreadinfo;
  117. begin
  118. {$ifdef HASTHREADVAR}
  119. { Allocate local thread vars, this must be the first thing,
  120. because the exception management and io depends on threadvars }
  121. SysAllocateThreadVars;
  122. {$endif HASTHREADVAR}
  123. { Copy parameter to local data }
  124. {$ifdef DEBUG_MT}
  125. writeln('New thread started, initialising ...');
  126. {$endif DEBUG_MT}
  127. ti:=pthreadinfo(param)^;
  128. dispose(pthreadinfo(param));
  129. { Initialize thread }
  130. InitThread(ti.stklen);
  131. { Start thread function }
  132. {$ifdef DEBUG_MT}
  133. writeln('Jumping to thread function');
  134. {$endif DEBUG_MT}
  135. ThreadMain:=pointer(ti.f(ti.p));
  136. end;
  137. function BeginThread(sa : Pointer;stacksize : dword;
  138. ThreadFunction : tthreadfunc;p : pointer;
  139. creationFlags : dword; var ThreadId : DWord) : DWord;
  140. var
  141. ti : pthreadinfo;
  142. begin
  143. {$ifdef DEBUG_MT}
  144. writeln('Creating new thread');
  145. {$endif DEBUG_MT}
  146. { Initialize multithreading if not done }
  147. if not IsMultiThread then
  148. begin
  149. {$ifdef HASTHREADVAR}
  150. { We're still running in single thread mode, setup the TLS }
  151. TLSKey:=TlsAlloc;
  152. InitThreadVars(@SysRelocateThreadvar);
  153. {$endif HASTHREADVAR}
  154. IsMultiThread:=true;
  155. end;
  156. { the only way to pass data to the newly created thread
  157. in a MT safe way, is to use the heap }
  158. new(ti);
  159. ti^.f:=ThreadFunction;
  160. ti^.p:=p;
  161. ti^.stklen:=stacksize;
  162. { call pthread_create }
  163. {$ifdef DEBUG_MT}
  164. writeln('Starting new thread');
  165. {$endif DEBUG_MT}
  166. BeginThread:=CreateThread(sa,stacksize,@ThreadMain,ti,creationflags,threadid);
  167. BeginThread:=threadid;
  168. end;
  169. procedure EndThread(ExitCode : DWord);
  170. begin
  171. DoneThread;
  172. ExitThread(ExitCode);
  173. end;
  174. {*****************************************************************************
  175. Delphi/Win32 compatibility
  176. *****************************************************************************}
  177. { we implement these procedures for win32 by importing them }
  178. { directly from windows }
  179. procedure InitCriticalSection(var cs : TRTLCriticalSection);
  180. external 'kernel32' name 'InitializeCriticalSection';
  181. procedure DoneCriticalSection(var cs : TRTLCriticalSection);
  182. external 'kernel32' name 'DeleteCriticalSection';
  183. procedure EnterCriticalSection(var cs : TRTLCriticalSection);
  184. external 'kernel32' name 'EnterCriticalSection';
  185. procedure LeaveCriticalSection(var cs : TRTLCriticalSection);
  186. external 'kernel32' name 'LeaveCriticalSection';
  187. {*****************************************************************************
  188. Heap Mutex Protection
  189. *****************************************************************************}
  190. var
  191. HeapMutex : TRTLCriticalSection;
  192. procedure Win32HeapMutexInit;
  193. begin
  194. InitCriticalSection(heapmutex);
  195. end;
  196. procedure Win32HeapMutexDone;
  197. begin
  198. DoneCriticalSection(heapmutex);
  199. end;
  200. procedure Win32HeapMutexLock;
  201. begin
  202. EnterCriticalSection(heapmutex);
  203. end;
  204. procedure Win32HeapMutexUnlock;
  205. begin
  206. LeaveCriticalSection(heapmutex);
  207. end;
  208. const
  209. Win32MemoryMutexManager : TMemoryMutexManager = (
  210. MutexInit : @Win32HeapMutexInit;
  211. MutexDone : @Win32HeapMutexDone;
  212. MutexLock : @Win32HeapMutexLock;
  213. MutexUnlock : @Win32HeapMutexUnlock;
  214. );
  215. procedure InitHeapMutexes;
  216. begin
  217. SetMemoryMutexManager(Win32MemoryMutexManager);
  218. end;
  219. initialization
  220. InitHeapMutexes;
  221. end.
  222. {
  223. $Log$
  224. Revision 1.2 2002-10-31 13:45:44 carl
  225. * threadvar.inc -> threadvr.inc
  226. Revision 1.1 2002/10/16 06:27:30 michael
  227. + Renamed thread unit to systhrds
  228. Revision 1.1 2002/10/14 19:39:18 peter
  229. * threads unit added for thread support
  230. }