thread.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. {
  2. This file is part of the Free Pascal Run time library.
  3. Copyright (c) 2000 by the Free Pascal development team
  4. OS independent thread functions/overloads
  5. See the File COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. Var
  12. fCurrentTM : TThreadManager; public;
  13. Procedure InitSystemThreads; forward;
  14. function CurrentTM : TThreadManager;
  15. begin
  16. if not Assigned(fCurrentTM.BeginThread) then
  17. InitSystemThreads;
  18. Result:=fCurrentTM;
  19. end;
  20. {*****************************************************************************
  21. Threadvar initialization
  22. *****************************************************************************}
  23. procedure InitThread(stklen:SizeUInt);
  24. begin
  25. SysResetFPU;
  26. SysInitFPU;
  27. {$ifndef HAS_MEMORYMANAGER}
  28. { initialize this thread's heap }
  29. InitHeapThread;
  30. {$endif HAS_MEMORYMANAGER}
  31. if MemoryManager.InitThread <> nil then
  32. MemoryManager.InitThread();
  33. {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
  34. if assigned(widestringmanager.ThreadInitProc) then
  35. widestringmanager.ThreadInitProc;
  36. {$endif FPC_HAS_FEATURE_WIDESTRINGS}
  37. { ExceptAddrStack and ExceptObjectStack are threadvars }
  38. { so every thread has its on exception handling capabilities }
  39. SysInitExceptions;
  40. { Open all stdio fds again }
  41. SysInitStdio;
  42. InOutRes:=0;
  43. // ErrNo:=0;
  44. { Stack checking }
  45. StackLength:= CheckInitialStkLen(stkLen);
  46. StackBottom:=Sptr - StackLength;
  47. ThreadID := CurrentTM.GetCurrentThreadID();
  48. end;
  49. procedure DoneThread;
  50. begin
  51. {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
  52. if assigned(widestringmanager.ThreadFiniProc) then
  53. widestringmanager.ThreadFiniProc;
  54. {$endif FPC_HAS_FEATURE_WIDESTRINGS}
  55. {$ifndef HAS_MEMORYMANAGER}
  56. FinalizeHeap;
  57. {$endif HAS_MEMORYMANAGER}
  58. if MemoryManager.DoneThread <> nil then
  59. MemoryManager.DoneThread();
  60. CurrentTM.ReleaseThreadVars;
  61. end;
  62. {*****************************************************************************
  63. Overloaded functions
  64. *****************************************************************************}
  65. function BeginThread(ThreadFunction : tthreadfunc) : TThreadID;
  66. var
  67. dummy : TThreadID;
  68. begin
  69. BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,nil,0,dummy);
  70. end;
  71. function BeginThread(ThreadFunction : tthreadfunc;p : pointer) : TThreadID;
  72. var
  73. dummy : TThreadID;
  74. begin
  75. BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,dummy);
  76. end;
  77. function BeginThread(ThreadFunction : tthreadfunc;p : pointer;var ThreadId : TThreadID) : TThreadID;
  78. begin
  79. BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,ThreadId);
  80. end;
  81. function BeginThread(ThreadFunction : tthreadfunc;p : pointer;
  82. var ThreadId : TThreadID; const stacksize: SizeUInt) : TThreadID;
  83. begin
  84. BeginThread:=BeginThread(nil,stacksize,ThreadFunction,p,0,ThreadId);
  85. end;
  86. procedure EndThread;
  87. begin
  88. EndThread(0);
  89. end;
  90. function BeginThread(sa : Pointer;stacksize : SizeUInt; ThreadFunction : tthreadfunc;p : pointer;creationFlags : dword; var ThreadId : TThreadID) : TThreadID;
  91. begin
  92. Result:=CurrentTM.BeginThread(sa,stacksize,threadfunction,P,creationflags,ThreadID);
  93. end;
  94. procedure FlushThread;
  95. begin
  96. {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
  97. { Make sure that all output is written to the redirected file }
  98. Flush(Output);
  99. Flush(ErrOutput);
  100. Flush(StdOut);
  101. Flush(StdErr);
  102. {$endif FPC_HAS_FEATURE_CONSOLEIO}
  103. end;
  104. procedure EndThread(ExitCode : DWord);
  105. begin
  106. FlushThread;
  107. CurrentTM.EndThread(ExitCode);
  108. end;
  109. function SuspendThread (threadHandle : TThreadID) : dword;
  110. begin
  111. Result:=CurrentTM.SuspendThread(ThreadHandle);
  112. end;
  113. function ResumeThread (threadHandle : TThreadID) : dword;
  114. begin
  115. Result:=CurrentTM.ResumeThread(ThreadHandle);
  116. end;
  117. procedure ThreadSwitch;
  118. begin
  119. CurrentTM.ThreadSwitch;
  120. end;
  121. function KillThread (threadHandle : TThreadID) : dword;
  122. begin
  123. Result:=CurrentTM.KillThread(ThreadHandle);
  124. end;
  125. function WaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword;
  126. begin
  127. Result:=CurrentTM.WaitForThreadTerminate(ThreadHandle,TimeOutMS);
  128. end;
  129. function ThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean;
  130. begin
  131. Result:=CurrentTM.ThreadSetPriority(ThreadHandle,Prio);
  132. end;
  133. function ThreadGetPriority (threadHandle : TThreadID): longint;
  134. begin
  135. Result:=CurrentTM.ThreadGetPriority(ThreadHandle);
  136. end;
  137. function GetCurrentThreadId : TThreadID;
  138. begin
  139. Result:=CurrentTM.GetCurrentThreadID();
  140. end;
  141. procedure InitCriticalSection(var cs : TRTLCriticalSection);
  142. begin
  143. CurrentTM.InitCriticalSection(cs);
  144. end;
  145. procedure DoneCriticalsection(var cs : TRTLCriticalSection);
  146. begin
  147. CurrentTM.DoneCriticalSection(cs);
  148. end;
  149. procedure EnterCriticalsection(var cs : TRTLCriticalSection);
  150. begin
  151. CurrentTM.EnterCriticalSection(cs);
  152. end;
  153. procedure LeaveCriticalsection(var cs : TRTLCriticalSection);
  154. begin
  155. CurrentTM.LeaveCriticalSection(cs);
  156. end;
  157. Function GetThreadManager(Var TM : TThreadManager) : Boolean;
  158. begin
  159. TM:=CurrentTM;
  160. Result:=True;
  161. end;
  162. Function SetThreadManager(Const NewTM : TThreadManager; Var OldTM : TThreadManager) : Boolean;
  163. begin
  164. GetThreadManager(OldTM);
  165. Result:=SetThreadManager(NewTM);
  166. end;
  167. Function SetThreadManager(Const NewTM : TThreadManager) : Boolean;
  168. begin
  169. Result:=True;
  170. If Assigned(fCurrentTM.DoneManager) then
  171. Result:=fCurrentTM.DoneManager();
  172. If Result then
  173. begin
  174. fCurrentTM:=NewTM;
  175. If Assigned(fCurrentTM.InitManager) then
  176. Result:=fCurrentTM.InitManager();
  177. end;
  178. end;
  179. function BasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;
  180. begin
  181. result:=currenttm.BasicEventCreate(EventAttributes,AManualReset,InitialState, Name);
  182. end;
  183. procedure basiceventdestroy(state:peventstate);
  184. begin
  185. currenttm.basiceventdestroy(state);
  186. end;
  187. procedure basiceventResetEvent(state:peventstate);
  188. begin
  189. currenttm.basiceventResetEvent(state);
  190. end;
  191. procedure basiceventSetEvent(state:peventstate);
  192. begin
  193. currenttm.basiceventSetEvent(state);
  194. end;
  195. function basiceventWaitFor(Timeout : Cardinal;state:peventstate) : longint;
  196. begin
  197. result:=currenttm.basiceventWaitFor(Timeout,state);
  198. end;
  199. function RTLEventCreate :PRTLEvent;
  200. begin
  201. result:=currenttm.rtleventcreate();
  202. end;
  203. procedure RTLeventdestroy(state:pRTLEvent);
  204. begin
  205. currenttm.rtleventdestroy(state);
  206. end;
  207. procedure RTLeventSetEvent(state:pRTLEvent);
  208. begin
  209. currenttm.rtleventsetEvent(state);
  210. end;
  211. procedure RTLeventResetEvent(state:pRTLEvent);
  212. begin
  213. currenttm.rtleventResetEvent(state);
  214. end;
  215. procedure RTLeventWaitFor(state:pRTLEvent);
  216. begin
  217. currenttm.rtleventWaitFor(state);
  218. end;
  219. procedure RTLeventWaitFor(state:pRTLEvent;timeout : longint);
  220. begin
  221. currenttm.rtleventWaitForTimeout(state,timeout);
  222. end;
  223. procedure RTLeventsync(m:trtlmethod;p:tprocedure);
  224. begin
  225. currenttm.rtleventsync(m,p);
  226. end;
  227. { ---------------------------------------------------------------------
  228. ThreadManager which gives run-time error. Use if no thread support.
  229. ---------------------------------------------------------------------}
  230. {$ifndef DISABLE_NO_THREAD_MANAGER}
  231. { resourcestrings are not supported by the system unit,
  232. they are in the objpas unit and not available for fpc/tp modes }
  233. const
  234. SNoThreads = 'This binary has no thread support compiled in.';
  235. SRecompileWithThreads = 'Recompile the application with a thread-driver in the program uses clause before other units using thread.';
  236. Procedure NoThreadError;
  237. begin
  238. {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
  239. If IsConsole then
  240. begin
  241. Writeln(StdErr,SNoThreads);
  242. Writeln(StdErr,SRecompileWithThreads);
  243. end;
  244. {$endif FPC_HAS_FEATURE_CONSOLEIO}
  245. RunError(232)
  246. end;
  247. function NoBeginThread(sa : Pointer;stacksize : PtrUInt;
  248. ThreadFunction : tthreadfunc;p : pointer;
  249. creationFlags : dword; var ThreadId : TThreadID) : TThreadID;
  250. begin
  251. NoThreadError;
  252. end;
  253. procedure NoEndThread(ExitCode : DWord);
  254. begin
  255. NoThreadError;
  256. end;
  257. function NoThreadHandler (threadHandle : TThreadID) : dword;
  258. begin
  259. NoThreadError;
  260. end;
  261. procedure NoThreadSwitch; {give time to other threads}
  262. begin
  263. NoThreadError;
  264. end;
  265. function NoWaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword; {0=no timeout}
  266. begin
  267. NoThreadError;
  268. end;
  269. function NoThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean; {-15..+15, 0=normal}
  270. begin
  271. NoThreadError;
  272. end;
  273. function NoThreadGetPriority (threadHandle : TThreadID): longint;
  274. begin
  275. NoThreadError;
  276. end;
  277. function NoGetCurrentThreadId : TThreadID;
  278. begin
  279. if IsMultiThread then
  280. NoThreadError
  281. else
  282. ThreadingAlreadyUsed:=true;
  283. result:=ThreadID;
  284. end;
  285. procedure NoCriticalSection(var CS);
  286. begin
  287. if IsMultiThread then
  288. NoThreadError
  289. else
  290. ThreadingAlreadyUsed:=true;
  291. end;
  292. procedure NoInitThreadvar(var offset : dword;size : dword);
  293. begin
  294. NoThreadError;
  295. end;
  296. function NoRelocateThreadvar(offset : dword) : pointer;
  297. begin
  298. NoThreadError;
  299. end;
  300. procedure NoAllocateThreadVars;
  301. begin
  302. NoThreadError;
  303. end;
  304. procedure NoReleaseThreadVars;
  305. begin
  306. NoThreadError;
  307. end;
  308. function noBasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;
  309. begin
  310. NoThreadError;
  311. end;
  312. procedure nobasiceventdestroy(state:peventstate);
  313. begin
  314. NoThreadError;
  315. end;
  316. procedure nobasiceventResetEvent(state:peventstate);
  317. begin
  318. NoThreadError;
  319. end;
  320. procedure nobasiceventSetEvent(state:peventstate);
  321. begin
  322. NoThreadError;
  323. end;
  324. function nobasiceventWaitFor(Timeout : Cardinal;state:peventstate) : longint;
  325. begin
  326. NoThreadError;
  327. end;
  328. function NORTLEventCreate :PRTLEvent;
  329. begin
  330. if IsMultiThread then
  331. NoThreadError
  332. else
  333. ThreadingAlreadyUsed:=true
  334. end;
  335. procedure NORTLeventdestroy(state:pRTLEvent);
  336. begin
  337. if IsMultiThread then
  338. NoThreadError
  339. else
  340. ThreadingAlreadyUsed:=true
  341. end;
  342. procedure NORTLeventSetEvent(state:pRTLEvent);
  343. begin
  344. NoThreadError;
  345. end;
  346. procedure NORTLeventWaitFor(state:pRTLEvent);
  347. begin
  348. NoThreadError;
  349. end;
  350. procedure NORTLeventWaitForTimeout(state:pRTLEvent;timeout : longint);
  351. begin
  352. NoThreadError;
  353. end;
  354. procedure NORTLeventsync(m:trtlmethod;p:tprocedure);
  355. begin
  356. NoThreadError;
  357. end;
  358. function NoSemaphoreInit: Pointer;
  359. begin
  360. NoThreadError;
  361. end;
  362. procedure NoSemaphoreWait(const FSem: Pointer);
  363. begin
  364. NoThreadError;
  365. end;
  366. procedure NoSemaphorePost(const FSem: Pointer);
  367. begin
  368. NoThreadError;
  369. end;
  370. procedure NoSemaphoreDestroy(const FSem: Pointer);
  371. begin
  372. NoThreadError;
  373. end;
  374. Var
  375. NoThreadManager : TThreadManager;
  376. Procedure SetNoThreadManager;
  377. begin
  378. With NoThreadManager do
  379. begin
  380. InitManager :=Nil;
  381. DoneManager :=Nil;
  382. BeginThread :=@NoBeginThread;
  383. EndThread :=@NoEndThread;
  384. SuspendThread :=@NoThreadHandler;
  385. ResumeThread :=@NoThreadHandler;
  386. KillThread :=@NoThreadHandler;
  387. ThreadSwitch :=@NoThreadSwitch;
  388. WaitForThreadTerminate :=@NoWaitForThreadTerminate;
  389. ThreadSetPriority :=@NoThreadSetPriority;
  390. ThreadGetPriority :=@NoThreadGetPriority;
  391. GetCurrentThreadId :=@NoGetCurrentThreadId;
  392. InitCriticalSection :=@NoCriticalSection;
  393. DoneCriticalSection :=@NoCriticalSection;
  394. EnterCriticalSection :=@NoCriticalSection;
  395. LeaveCriticalSection :=@NoCriticalSection;
  396. InitThreadVar :=@NoInitThreadVar;
  397. RelocateThreadVar :=@NoRelocateThreadVar;
  398. AllocateThreadVars :=@NoAllocateThreadVars;
  399. ReleaseThreadVars :=@NoReleaseThreadVars;
  400. BasicEventCreate :=@NoBasicEventCreate;
  401. basiceventdestroy :=@Nobasiceventdestroy;
  402. basiceventResetEvent :=@NobasiceventResetEvent;
  403. basiceventSetEvent :=@NobasiceventSetEvent;
  404. basiceventWaitFor :=@NobasiceventWaitFor;
  405. rtlEventCreate :=@NortlEventCreate;
  406. rtleventdestroy :=@Nortleventdestroy;
  407. rtleventSetEvent :=@NortleventSetEvent;
  408. rtleventWaitFor :=@NortleventWaitFor;
  409. rtleventsync :=@Nortleventsync;
  410. rtleventwaitfortimeout :=@NortleventWaitForTimeout;
  411. // semaphores stuff
  412. SemaphoreInit :=@NoSemaphoreInit;
  413. SemaphoreDestroy :=@NoSemaphoreDestroy;
  414. SemaphoreWait :=@NoSemaphoreWait;
  415. SemaphorePost :=@NoSemaphorePost;
  416. end;
  417. SetThreadManager(NoThreadManager);
  418. end;
  419. {$endif DISABLE_NO_THREAD_MANAGER}