thread.inc 14 KB

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