thread.inc 13 KB

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