thread.inc 13 KB

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