systhrds.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  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. Linux (pthreads) 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. {$ifndef BSD}
  17. {$linklib c}
  18. {$linklib pthread}
  19. {$else}
  20. // Link reentrant libc with pthreads
  21. {$linklib c_r}
  22. {$endif}
  23. type
  24. PRTLCriticalSection = ^TRTLCriticalSection;
  25. TRTLCriticalSection = record
  26. m_spinlock : longint;
  27. m_count : longint;
  28. m_owner : pointer {pthread_t};
  29. m_kind : longint;
  30. m_waiting : record
  31. head,tail : pointer;
  32. end; {_pthread_queue}
  33. end;
  34. { Include generic thread interface }
  35. {$i threadh.inc}
  36. implementation
  37. {*****************************************************************************
  38. Generic overloaded
  39. *****************************************************************************}
  40. { Include generic overloaded routines }
  41. {$i thread.inc}
  42. {$ifndef BSD}
  43. {$i pthread.inc}
  44. {$else}
  45. {$i ptypes.inc}
  46. CONST PTHREAD_EXPLICIT_SCHED = 0;
  47. PTHREAD_CREATE_DETACHED = 1;
  48. PTHREAD_SCOPE_PROCESS = 0;
  49. TYPE
  50. pthread_t = pointer;
  51. ppthread_t = ^pthread_t;
  52. pthread_key_t = cint;
  53. ppthread_key_t = ^pthread_key_t;
  54. pthread_mutex_t = pointer;
  55. ppthread_mutex_t= ^pthread_mutex_t;
  56. pthread_attr_t = pointer; // opague
  57. ppthread_attr_t = ^pthread_attr_t; // opague
  58. __destr_func_t = procedure (p :pointer);cdecl;
  59. __startroutine_t= function (p :pointer):pointer;cdecl;
  60. pthread_mutex_attr_t = pointer;
  61. ppthread_mutex_attr_t = ^pthread_mutex_t;
  62. function pthread_getspecific (t : pthread_key_t):pointer; cdecl; external;
  63. function pthread_setspecific (t : pthread_key_t;p:pointer):cint; cdecl; external;
  64. function pthread_key_create (p : ppthread_key_t;f: __destr_func_t):cint; cdecl;external;
  65. function pthread_attr_init (p : ppthread_key_t):cint; cdecl; external;
  66. function pthread_attr_setinheritsched(p : ppthread_attr_t;i:cint):cint; cdecl; external;
  67. function pthread_attr_setscope (p : ppthread_attr_t;i:cint):cint;cdecl;external;
  68. function pthread_attr_setdetachstate (p : ppthread_attr_t;i:cint):cint;cdecl;external;
  69. function pthread_create ( p: ppthread_t;attr : ppthread_attr_t;f:__startroutine_t;arg:pointer):cint;cdecl;external;
  70. procedure pthread_exit ( p: pointer); cdecl;external;
  71. function pthread_mutex_init (p:ppthread_mutex_t;o:ppthread_mutex_attr_t):cint; cdecl;external;
  72. function pthread_mutex_destroy (p:ppthread_mutex_attr_t):cint; cdecl;external;
  73. function pthread_mutex_lock (p:ppthread_mutex_attr_t):cint; cdecl;external;
  74. function pthread_mutex_unlock (p:ppthread_mutex_attr_t):cint; cdecl;external;
  75. {$endif}
  76. {*****************************************************************************
  77. System dependent memory allocation
  78. *****************************************************************************}
  79. {$ifndef BSD}
  80. const
  81. syscall_nr_mmap = 90;
  82. syscall_nr_munmap = 91;
  83. { Constansts for MMAP }
  84. MAP_PRIVATE =2;
  85. MAP_ANONYMOUS =$20;
  86. type
  87. SysCallRegs=record
  88. reg1,reg2,reg3,reg4,reg5,reg6 : longint;
  89. end;
  90. var
  91. Errno : longint;
  92. { Include syscall itself }
  93. {$i syscallo.inc}
  94. Function Fpmmap(adr,len,prot,flags,fdes,off:longint):longint;
  95. type
  96. tmmapargs=packed record
  97. address : longint;
  98. size : longint;
  99. prot : longint;
  100. flags : longint;
  101. fd : longint;
  102. offset : longint;
  103. end;
  104. var
  105. t : syscallregs;
  106. mmapargs : tmmapargs;
  107. begin
  108. mmapargs.address:=adr;
  109. mmapargs.size:=len;
  110. mmapargs.prot:=prot;
  111. mmapargs.flags:=flags;
  112. mmapargs.fd:=fdes;
  113. mmapargs.offset:=off;
  114. t.reg2:=longint(@mmapargs);
  115. Fpmmap:=syscall(syscall_nr_mmap,t);
  116. end;
  117. Function Fpmunmap(adr,len:longint):longint;
  118. var
  119. t : syscallregs;
  120. begin
  121. t.reg2:=adr;
  122. t.reg3:=len;
  123. Fpmunmap:=syscall(syscall_nr_munmap,t);
  124. end;
  125. {$else}
  126. CONST
  127. { Constansts for MMAP. These are still private for *BSD }
  128. MAP_PRIVATE =2;
  129. MAP_ANONYMOUS =$1000;
  130. // include some non posix internal types.
  131. {$i ostypes.inc}
  132. // *BSD POSIX. Include headers to syscalls.
  133. {$I ossysch.inc}
  134. {$endif}
  135. {*****************************************************************************
  136. Threadvar support
  137. *****************************************************************************}
  138. {$ifdef HASTHREADVAR}
  139. const
  140. threadvarblocksize : dword = 0;
  141. var
  142. TLSKey : pthread_key_t;
  143. procedure SysInitThreadvar(var offset : dword;size : dword);
  144. begin
  145. offset:=threadvarblocksize;
  146. inc(threadvarblocksize,size);
  147. end;
  148. function SysRelocateThreadvar(offset : dword) : pointer;
  149. begin
  150. SysRelocateThreadvar:=pthread_getspecific(tlskey)+Offset;
  151. end;
  152. procedure SysAllocateThreadVars;
  153. var
  154. dataindex : pointer;
  155. begin
  156. { we've to allocate the memory from system }
  157. { because the FPC heap management uses }
  158. { exceptions which use threadvars but }
  159. { these aren't allocated yet ... }
  160. { allocate room on the heap for the thread vars }
  161. DataIndex:=Pointer(Fpmmap(0,threadvarblocksize,3,MAP_PRIVATE+MAP_ANONYMOUS,-1,0));
  162. FillChar(DataIndex^,threadvarblocksize,0);
  163. pthread_setspecific(tlskey,dataindex);
  164. end;
  165. procedure SysReleaseThreadVars;
  166. begin
  167. Fpmunmap(longint(pthread_getspecific(tlskey)),threadvarblocksize);
  168. end;
  169. { Include OS independent Threadvar initialization }
  170. {$i threadvr.inc}
  171. {$endif HASTHREADVAR}
  172. {*****************************************************************************
  173. Thread starting
  174. *****************************************************************************}
  175. type
  176. pthreadinfo = ^tthreadinfo;
  177. tthreadinfo = record
  178. f : tthreadfunc;
  179. p : pointer;
  180. stklen : cardinal;
  181. end;
  182. procedure DoneThread;
  183. begin
  184. { Release Threadvars }
  185. {$ifdef HASTHREADVAR}
  186. SysReleaseThreadVars;
  187. {$endif HASTHREADVAR}
  188. end;
  189. function ThreadMain(param : pointer) : pointer;cdecl;
  190. var
  191. ti : tthreadinfo;
  192. begin
  193. {$ifdef HASTHREADVAR}
  194. { Allocate local thread vars, this must be the first thing,
  195. because the exception management and io depends on threadvars }
  196. SysAllocateThreadVars;
  197. {$endif HASTHREADVAR}
  198. { Copy parameter to local data }
  199. {$ifdef DEBUG_MT}
  200. writeln('New thread started, initialising ...');
  201. {$endif DEBUG_MT}
  202. ti:=pthreadinfo(param)^;
  203. dispose(pthreadinfo(param));
  204. { Initialize thread }
  205. InitThread(ti.stklen);
  206. { Start thread function }
  207. {$ifdef DEBUG_MT}
  208. writeln('Jumping to thread function');
  209. {$endif DEBUG_MT}
  210. ThreadMain:=pointer(ti.f(ti.p));
  211. end;
  212. function BeginThread(sa : Pointer;stacksize : dword;
  213. ThreadFunction : tthreadfunc;p : pointer;
  214. creationFlags : dword; var ThreadId : DWord) : DWord;
  215. var
  216. ti : pthreadinfo;
  217. thread_attr : pthread_attr_t;
  218. begin
  219. {$ifdef DEBUG_MT}
  220. writeln('Creating new thread');
  221. {$endif DEBUG_MT}
  222. { Initialize multithreading if not done }
  223. if not IsMultiThread then
  224. begin
  225. {$ifdef HASTHREADVAR}
  226. { We're still running in single thread mode, setup the TLS }
  227. pthread_key_create(@TLSKey,nil);
  228. InitThreadVars(@SysRelocateThreadvar);
  229. {$endif HASTHREADVAR}
  230. IsMultiThread:=true;
  231. end;
  232. { the only way to pass data to the newly created thread
  233. in a MT safe way, is to use the heap }
  234. new(ti);
  235. ti^.f:=ThreadFunction;
  236. ti^.p:=p;
  237. ti^.stklen:=stacksize;
  238. { call pthread_create }
  239. {$ifdef DEBUG_MT}
  240. writeln('Starting new thread');
  241. {$endif DEBUG_MT}
  242. pthread_attr_init(@thread_attr);
  243. pthread_attr_setinheritsched(@thread_attr, PTHREAD_EXPLICIT_SCHED);
  244. pthread_attr_setscope(@thread_attr, PTHREAD_SCOPE_PROCESS);
  245. pthread_attr_setdetachstate(@thread_attr, PTHREAD_CREATE_DETACHED);
  246. pthread_create(@threadid, @thread_attr, @ThreadMain,ti);
  247. BeginThread:=threadid;
  248. end;
  249. procedure EndThread(ExitCode : DWord);
  250. begin
  251. DoneThread;
  252. pthread_exit(pointer(ExitCode));
  253. end;
  254. function SuspendThread (threadHandle : dword) : dword;
  255. begin
  256. {$Warning SuspendThread needs to be implemented}
  257. end;
  258. function ResumeThread (threadHandle : dword) : dword;
  259. begin
  260. {$Warning ResumeThread needs to be implemented}
  261. end;
  262. procedure ThreadSwitch; {give time to other threads}
  263. begin
  264. {extern int pthread_yield (void) __THROW;}
  265. {$Warning ThreadSwitch needs to be implemented}
  266. end;
  267. function KillThread (threadHandle : dword) : dword;
  268. begin
  269. {$Warning KillThread needs to be implemented}
  270. end;
  271. function WaitForThreadTerminate (threadHandle : dword; TimeoutMs : longint) : dword; {0=no timeout}
  272. begin
  273. {$Warning WaitForThreadTerminate needs to be implemented}
  274. end;
  275. function ThreadSetPriority (threadHandle : dword; Prio: longint): boolean; {-15..+15, 0=normal}
  276. begin
  277. {$Warning ThreadSetPriority needs to be implemented}
  278. end;
  279. function ThreadGetPriority (threadHandle : dword): Integer;
  280. begin
  281. {$Warning ThreadGetPriority needs to be implemented}
  282. end;
  283. function GetCurrentThreadHandle : dword;
  284. begin
  285. {$Warning ThreadGetPriority needs to be implemented}
  286. end;
  287. {*****************************************************************************
  288. Delphi/Win32 compatibility
  289. *****************************************************************************}
  290. procedure InitCriticalSection(var CS:TRTLCriticalSection);
  291. begin
  292. cs.m_spinlock:=0;
  293. cs.m_count:=0;
  294. cs.m_owner:=0;
  295. cs.m_kind:=1;
  296. cs.m_waiting.head:=0;
  297. cs.m_waiting.tail:=0;
  298. pthread_mutex_init(@CS,NIL);
  299. end;
  300. procedure EnterCriticalSection(var CS:TRTLCriticalSection);
  301. begin
  302. pthread_mutex_lock(@CS);
  303. end;
  304. procedure LeaveCriticalSection(var CS:TRTLCriticalSection);
  305. begin
  306. pthread_mutex_unlock(@CS);
  307. end;
  308. procedure DoneCriticalSection(var CS:TRTLCriticalSection);
  309. begin
  310. pthread_mutex_destroy(@CS);
  311. end;
  312. {*****************************************************************************
  313. Heap Mutex Protection
  314. *****************************************************************************}
  315. var
  316. HeapMutex : pthread_mutex_t;
  317. procedure PThreadHeapMutexInit;
  318. begin
  319. pthread_mutex_init(@heapmutex,nil);
  320. end;
  321. procedure PThreadHeapMutexDone;
  322. begin
  323. pthread_mutex_destroy(@heapmutex);
  324. end;
  325. procedure PThreadHeapMutexLock;
  326. begin
  327. pthread_mutex_lock(@heapmutex);
  328. end;
  329. procedure PThreadHeapMutexUnlock;
  330. begin
  331. pthread_mutex_unlock(@heapmutex);
  332. end;
  333. const
  334. PThreadMemoryMutexManager : TMemoryMutexManager = (
  335. MutexInit : @PThreadHeapMutexInit;
  336. MutexDone : @PThreadHeapMutexDone;
  337. MutexLock : @PThreadHeapMutexLock;
  338. MutexUnlock : @PThreadHeapMutexUnlock;
  339. );
  340. procedure InitHeapMutexes;
  341. begin
  342. SetMemoryMutexManager(PThreadMemoryMutexManager);
  343. end;
  344. initialization
  345. InitHeapMutexes;
  346. end.
  347. {
  348. $Log$
  349. Revision 1.8 2003-03-27 17:14:27 armin
  350. * more platform independent thread routines, needs to be implemented for unix
  351. Revision 1.7 2003/01/05 19:11:32 marco
  352. * small changes originating from introduction of Baseunix to FreeBSD
  353. Revision 1.6 2002/11/11 21:41:06 marco
  354. * syscall.inc -> syscallo.inc
  355. Revision 1.5 2002/10/31 13:45:21 carl
  356. * threadvar.inc -> threadvr.inc
  357. Revision 1.4 2002/10/26 18:27:52 marco
  358. * First series POSIX calls commits. Including getcwd.
  359. Revision 1.3 2002/10/18 18:05:06 marco
  360. * $I pthread.inc instead of pthreads.inc
  361. Revision 1.2 2002/10/18 12:19:59 marco
  362. * Fixes to get the generic *BSD RTL compiling again + fixes for thread
  363. support. Still problems left in fexpand. (inoutres?) Therefore fixed
  364. sysposix not yet commited
  365. Revision 1.1 2002/10/16 06:22:56 michael
  366. Threads renamed from threads to systhrds
  367. Revision 1.1 2002/10/14 19:39:17 peter
  368. * threads unit added for thread support
  369. }