thread.inc 13 KB

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