thread.inc 12 KB

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