thread.inc 12 KB

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