systhrds.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2002 by the Free Pascal development team.
  5. OS/2 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. unit systhrds;
  13. interface
  14. {$S-}
  15. type
  16. { the fields of this record are os dependent }
  17. { and they shouldn't be used in a program }
  18. { only the type TCriticalSection is important }
  19. PRTLCriticalSection = ^TRTLCriticalSection;
  20. TRTLCriticalSection = packed record
  21. DebugInfo : pointer;
  22. LockCount : longint;
  23. RecursionCount : longint;
  24. OwningThread : DWord;
  25. LockSemaphore : DWord;
  26. Reserved : DWord;
  27. end;
  28. { Include generic thread interface }
  29. {$i threadh.inc}
  30. implementation
  31. {*****************************************************************************
  32. Local Api imports
  33. *****************************************************************************}
  34. const
  35. pag_Read = 1;
  36. pag_Write = 2;
  37. pag_Execute = 4;
  38. pag_Guard = 8;
  39. pag_Commit = $10;
  40. obj_Tile = $40;
  41. sem_Indefinite_Wait = -1;
  42. dtSuspended = 1;
  43. dtStack_Commited = 2;
  44. type
  45. TByteArray = array [0..$ffff] of byte;
  46. PByteArray = ^TByteArray;
  47. TSysThreadIB = record
  48. TID,
  49. Priority,
  50. Version: cardinal;
  51. MCCount,
  52. MCForceFlag: word;
  53. end;
  54. PSysThreadIB = ^TSysThreadIB;
  55. TThreadInfoBlock = record
  56. PExChain,
  57. Stack,
  58. StackLimit: pointer;
  59. TIB2: PSysThreadIB;
  60. Version,
  61. Ordinal: cardinal;
  62. end;
  63. PThreadInfoBlock = ^TThreadInfoBlock;
  64. PPThreadInfoBlock = ^PThreadInfoBlock;
  65. TProcessInfoBlock = record
  66. PID,
  67. ParentPid,
  68. Handle: cardinal;
  69. Cmd,
  70. Env: PByteArray;
  71. Status,
  72. ProcType: cardinal;
  73. end;
  74. PProcessInfoBlock = ^TProcessInfoBlock;
  75. PPProcessInfoBlock = ^PProcessInfoBlock;
  76. { import the necessary stuff from the OS }
  77. function DosAllocThreadLocalMemory (Count: cardinal; var P: pointer): cardinal;
  78. cdecl; external 'DOSCALLS' index 454;
  79. function DosFreeThreadLocalMemory (P: pointer): cardinal; cdecl;
  80. external 'DOSCALLS' index 455;
  81. function DosCreateThread (var TID: cardinal; Address: pointer;
  82. (* TThreadFunc *)
  83. aParam: pointer; Flags: cardinal; StackSize: cardinal): cardinal; cdecl;
  84. external 'DOSCALLS' index 311;
  85. procedure DosExit (Action, Result: cardinal); cdecl;
  86. external 'DOSCALLS' index 234;
  87. function DosCreateMutExSem (Name: PChar; var Handle: longint; Attr: cardinal;
  88. State: boolean): cardinal; cdecl; external 'DOSCALLS' index 331;
  89. function DosCloseMutExSem (Handle: longint): cardinal; cdecl;
  90. external 'DOSCALLS' index 333;
  91. function DosQueryMutExSem (Handle: longint; var PID, TID, Count: cardinal):
  92. cardinal; cdecl; external 'DOSCALLS' index 336;
  93. function DosRequestMutExSem (Handle:longint; Timeout: cardinal): cardinal; cdecl;
  94. external 'DOSCALLS' index 334;
  95. function DosReleaseMutExSem (Handle: longint): cardinal; cdecl;
  96. external 'DOSCALLS' index 335;
  97. function DosAllocMem (var P: pointer; Size, Flag: cardinal): cardinal; cdecl;
  98. external 'DOSCALLS' index 299;
  99. function DosFreeMem (P: pointer): cardinal; cdecl;
  100. external 'DOSCALLS' index 304;
  101. function DosEnterCritSec:cardinal; cdecl; external 'DOSCALLS' index 232;
  102. function DosExitCritSec:cardinal; cdecl; external 'DOSCALLS' index 233;
  103. procedure DosGetInfoBlocks (PATIB: PPThreadInfoBlock;
  104. PAPIB: PPProcessInfoBlock); cdecl;
  105. external 'DOSCALLS' index 312;
  106. {*****************************************************************************
  107. Threadvar support
  108. *****************************************************************************}
  109. {$ifdef HASTHREADVAR}
  110. const
  111. ThreadVarBlockSize: dword = 0;
  112. var
  113. (* Pointer to an allocated dword space within the local thread *)
  114. (* memory area. Pointer to the real memory block allocated for *)
  115. (* thread vars in this block is then stored in this dword. *)
  116. DataIndex: PPointer;
  117. procedure SysInitThreadvar (var Offset: dword; Size: dword);
  118. begin
  119. Offset := ThreadVarBlockSize;
  120. Inc (ThreadVarBlockSize, Size);
  121. end;
  122. function SysRelocateThreadVar (Offset: dword): pointer;
  123. begin
  124. SysRelocateThreadVar := DataIndex^ + Offset;
  125. end;
  126. procedure SysAllocateThreadVars;
  127. begin
  128. { we've to allocate the memory from the OS }
  129. { because the FPC heap management uses }
  130. { exceptions which use threadvars but }
  131. { these aren't allocated yet ... }
  132. { allocate room on the heap for the thread vars }
  133. if DosAllocMem (DataIndex^, ThreadVarBlockSize, pag_Read or pag_Write
  134. or pag_Commit) <> 0 then HandleError (8);
  135. end;
  136. procedure SysReleaseThreadVars;
  137. begin
  138. { release thread vars }
  139. DosFreeMem (DataIndex^);
  140. end;
  141. { Include OS independent Threadvar initialization }
  142. {$i threadvar.inc}
  143. procedure InitThreadVars;
  144. begin
  145. { allocate one ThreadVar entry from the OS, we use this entry }
  146. { for a pointer to our threadvars }
  147. if DosAllocThreadLocalMemory (1, DataIndex) <> 0 then HandleError (8);
  148. { initialize threadvars }
  149. init_all_unit_threadvars;
  150. { allocate mem for main thread threadvars }
  151. SysAllocateThreadVars;
  152. { copy main thread threadvars }
  153. copy_all_unit_threadvars;
  154. { install threadvar handler }
  155. fpc_threadvar_relocate_proc := @SysRelocateThreadvar;
  156. end;
  157. {$endif HASTHREADVAR}
  158. {*****************************************************************************
  159. Thread starting
  160. *****************************************************************************}
  161. const
  162. DefaultStackSize = 32768; { including 16384 margin for stackchecking }
  163. type
  164. pthreadinfo = ^tthreadinfo;
  165. tthreadinfo = record
  166. f : tthreadfunc;
  167. p : pointer;
  168. stklen : cardinal;
  169. end;
  170. procedure InitThread(stklen:cardinal);
  171. begin
  172. SysResetFPU;
  173. { ExceptAddrStack and ExceptObjectStack are threadvars }
  174. { so every thread has its on exception handling capabilities }
  175. SysInitExceptions;
  176. { Open all stdio fds again }
  177. SysInitStdio;
  178. InOutRes:=0;
  179. // ErrNo:=0;
  180. { Stack checking }
  181. StackLength:=stklen;
  182. StackBottom:=Sptr - StackLength;
  183. end;
  184. procedure DoneThread;
  185. begin
  186. { Release Threadvars }
  187. {$ifdef HASTHREADVAR}
  188. SysReleaseThreadVars;
  189. {$endif HASTHREADVAR}
  190. end;
  191. function ThreadMain(param : pointer) : pointer;cdecl;
  192. var
  193. ti : tthreadinfo;
  194. begin
  195. {$ifdef HASTHREADVAR}
  196. { Allocate local thread vars, this must be the first thing,
  197. because the exception management and io depends on threadvars }
  198. SysAllocateThreadVars;
  199. {$endif HASTHREADVAR}
  200. { Copy parameter to local data }
  201. {$ifdef DEBUG_MT}
  202. writeln('New thread started, initialising ...');
  203. {$endif DEBUG_MT}
  204. ti:=pthreadinfo(param)^;
  205. dispose(pthreadinfo(param));
  206. { Initialize thread }
  207. InitThread(ti.stklen);
  208. { Start thread function }
  209. {$ifdef DEBUG_MT}
  210. writeln('Jumping to thread function');
  211. {$endif DEBUG_MT}
  212. ThreadMain:=pointer(ti.f(ti.p));
  213. end;
  214. function BeginThread(sa : Pointer;stacksize : dword;
  215. ThreadFunction : tthreadfunc;p : pointer;
  216. creationFlags : dword; var ThreadId : DWord) : DWord;
  217. var
  218. ti : pthreadinfo;
  219. begin
  220. {$ifdef DEBUG_MT}
  221. writeln('Creating new thread');
  222. {$endif DEBUG_MT}
  223. { Initialize multithreading if not done }
  224. if not IsMultiThread then
  225. begin
  226. {$ifdef HASTHREADVAR}
  227. InitThreadVars;
  228. {$endif HASTHREADVAR}
  229. IsMultiThread:=true;
  230. end;
  231. { the only way to pass data to the newly created thread
  232. in a MT safe way, is to use the heap }
  233. new(ti);
  234. ti^.f:=ThreadFunction;
  235. ti^.p:=p;
  236. ti^.stklen:=stacksize;
  237. { call pthread_create }
  238. {$ifdef DEBUG_MT}
  239. writeln('Starting new thread');
  240. {$endif DEBUG_MT}
  241. BeginThread:=CreateThread(sa,stacksize,@ThreadMain,ti,creationflags,threadid);
  242. BeginThread:=threadid;
  243. end;
  244. procedure EndThread(ExitCode : DWord);
  245. begin
  246. DoneThread;
  247. ExitThread(ExitCode);
  248. end;
  249. {*****************************************************************************
  250. Delphi/Win32 compatibility
  251. *****************************************************************************}
  252. { we implement these procedures for win32 by importing them }
  253. { directly from windows }
  254. procedure InitCriticalSection(var cs : TRTLCriticalSection);
  255. external 'kernel32' name 'InitializeCriticalSection';
  256. procedure DoneCriticalSection(var cs : TRTLCriticalSection);
  257. external 'kernel32' name 'DeleteCriticalSection';
  258. procedure EnterCriticalSection(var cs : TRTLCriticalSection);
  259. external 'kernel32' name 'EnterCriticalSection';
  260. procedure LeaveCriticalSection(var cs : TRTLCriticalSection);
  261. external 'kernel32' name 'LeaveCriticalSection';
  262. {*****************************************************************************
  263. Heap Mutex Protection
  264. *****************************************************************************}
  265. var
  266. HeapMutex : TRTLCriticalSection;
  267. procedure OS2HeapMutexInit;
  268. begin
  269. InitCriticalSection(heapmutex);
  270. end;
  271. procedure OS2HeapMutexDone;
  272. begin
  273. DoneCriticalSection(heapmutex);
  274. end;
  275. procedure OS2HeapMutexLock;
  276. begin
  277. EnterCriticalSection(heapmutex);
  278. end;
  279. procedure OS2HeapMutexUnlock;
  280. begin
  281. LeaveCriticalSection(heapmutex);
  282. end;
  283. const
  284. OS2MemoryMutexManager : TMemoryMutexManager = (
  285. MutexInit : @OS2HeapMutexInit;
  286. MutexDone : @OS2HeapMutexDone;
  287. MutexLock : @OS2HeapMutexLock;
  288. MutexUnlock : @OS2HeapMutexUnlock;
  289. );
  290. procedure InitHeapMutexes;
  291. begin
  292. SetMemoryMutexManager(Win32MemoryMutexManager);
  293. end;
  294. {*****************************************************************************
  295. Generic overloaded
  296. *****************************************************************************}
  297. { Include generic overloaded routines }
  298. {$i thread.inc}
  299. finalization
  300. DosFreeThreadLocalMemory (DataIndex);
  301. end;
  302. initialization
  303. InitHeapMutexes;
  304. end.
  305. {
  306. $Log$
  307. Revision 1.2 2003-10-13 21:17:31 hajny
  308. * longint to cardinal corrections
  309. Revision 1.1 2002/11/17 22:31:46 hajny
  310. + first (incomplete) version of systhrds
  311. Revision 1.1 2002/10/14 19:39:18 peter
  312. * threads unit added for thread support
  313. }