thread.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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. procedure ThreadSwitch;
  119. begin
  120. CurrentTM.ThreadSwitch;
  121. end;
  122. function KillThread (threadHandle : TThreadID) : dword;
  123. begin
  124. Result:=CurrentTM.KillThread(ThreadHandle);
  125. end;
  126. function WaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword;
  127. begin
  128. Result:=CurrentTM.WaitForThreadTerminate(ThreadHandle,TimeOutMS);
  129. end;
  130. function ThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean;
  131. begin
  132. Result:=CurrentTM.ThreadSetPriority(ThreadHandle,Prio);
  133. end;
  134. function ThreadGetPriority (threadHandle : TThreadID): longint;
  135. begin
  136. Result:=CurrentTM.ThreadGetPriority(ThreadHandle);
  137. end;
  138. function GetCurrentThreadId : TThreadID;
  139. begin
  140. Result:=CurrentTM.GetCurrentThreadID();
  141. end;
  142. procedure InitCriticalSection(var cs : TRTLCriticalSection);
  143. begin
  144. CurrentTM.InitCriticalSection(cs);
  145. end;
  146. procedure DoneCriticalsection(var cs : TRTLCriticalSection);
  147. begin
  148. CurrentTM.DoneCriticalSection(cs);
  149. end;
  150. procedure EnterCriticalsection(var cs : TRTLCriticalSection);
  151. begin
  152. CurrentTM.EnterCriticalSection(cs);
  153. end;
  154. procedure LeaveCriticalsection(var cs : TRTLCriticalSection);
  155. begin
  156. CurrentTM.LeaveCriticalSection(cs);
  157. end;
  158. Function GetThreadManager(Var TM : TThreadManager) : Boolean;
  159. begin
  160. TM:=CurrentTM;
  161. Result:=True;
  162. end;
  163. Function SetThreadManager(Const NewTM : TThreadManager; Var OldTM : TThreadManager) : Boolean;
  164. begin
  165. GetThreadManager(OldTM);
  166. Result:=SetThreadManager(NewTM);
  167. end;
  168. Function SetThreadManager(Const NewTM : TThreadManager) : Boolean;
  169. begin
  170. Result:=True;
  171. If Assigned(CurrentTM.DoneManager) then
  172. Result:=CurrentTM.DoneManager();
  173. If Result then
  174. begin
  175. CurrentTM:=NewTM;
  176. If Assigned(CurrentTM.InitManager) then
  177. Result:=CurrentTM.InitManager();
  178. end;
  179. end;
  180. function BasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;
  181. begin
  182. result:=currenttm.BasicEventCreate(EventAttributes,AManualReset,InitialState, Name);
  183. end;
  184. procedure basiceventdestroy(state:peventstate);
  185. begin
  186. currenttm.basiceventdestroy(state);
  187. end;
  188. procedure basiceventResetEvent(state:peventstate);
  189. begin
  190. currenttm.basiceventResetEvent(state);
  191. end;
  192. procedure basiceventSetEvent(state:peventstate);
  193. begin
  194. currenttm.basiceventSetEvent(state);
  195. end;
  196. function basiceventWaitFor(Timeout : Cardinal;state:peventstate) : longint;
  197. begin
  198. result:=currenttm.basiceventWaitFor(Timeout,state);
  199. end;
  200. function RTLEventCreate :PRTLEvent;
  201. begin
  202. result:=currenttm.rtleventcreate();
  203. end;
  204. procedure RTLeventdestroy(state:pRTLEvent);
  205. begin
  206. currenttm.rtleventdestroy(state);
  207. end;
  208. procedure RTLeventSetEvent(state:pRTLEvent);
  209. begin
  210. currenttm.rtleventsetEvent(state);
  211. end;
  212. procedure RTLeventResetEvent(state:pRTLEvent);
  213. begin
  214. currenttm.rtleventResetEvent(state);
  215. end;
  216. procedure RTLeventWaitFor(state:pRTLEvent);
  217. begin
  218. currenttm.rtleventWaitFor(state);
  219. end;
  220. procedure RTLeventWaitFor(state:pRTLEvent;timeout : longint);
  221. begin
  222. currenttm.rtleventWaitForTimeout(state,timeout);
  223. end;
  224. procedure RTLeventsync(m:trtlmethod;p:tprocedure);
  225. begin
  226. currenttm.rtleventsync(m,p);
  227. end;
  228. { ---------------------------------------------------------------------
  229. ThreadManager which gives run-time error. Use if no thread support.
  230. ---------------------------------------------------------------------}
  231. {$ifndef DISABLE_NO_THREAD_MANAGER}
  232. { resourcestrings are not supported by the system unit,
  233. they are in the objpas unit and not available for fpc/tp modes }
  234. const
  235. SNoThreads = 'This binary has no thread support compiled in.';
  236. SRecompileWithThreads = 'Recompile the application with a thread-driver in the program uses clause before other units using thread.';
  237. Procedure NoThreadError;
  238. begin
  239. {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
  240. If IsConsole then
  241. begin
  242. Writeln(StdErr,SNoThreads);
  243. Writeln(StdErr,SRecompileWithThreads);
  244. end;
  245. {$endif FPC_HAS_FEATURE_CONSOLEIO}
  246. RunError(232)
  247. end;
  248. function NoBeginThread(sa : Pointer;stacksize : PtrUInt;
  249. ThreadFunction : tthreadfunc;p : pointer;
  250. creationFlags : dword; var ThreadId : TThreadID) : TThreadID;
  251. begin
  252. NoThreadError;
  253. end;
  254. procedure NoEndThread(ExitCode : DWord);
  255. begin
  256. NoThreadError;
  257. end;
  258. function NoThreadHandler (threadHandle : TThreadID) : dword;
  259. begin
  260. NoThreadError;
  261. end;
  262. procedure NoThreadSwitch; {give time to other threads}
  263. begin
  264. NoThreadError;
  265. end;
  266. function NoWaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword; {0=no timeout}
  267. begin
  268. NoThreadError;
  269. end;
  270. function NoThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean; {-15..+15, 0=normal}
  271. begin
  272. NoThreadError;
  273. end;
  274. function NoThreadGetPriority (threadHandle : TThreadID): longint;
  275. begin
  276. NoThreadError;
  277. end;
  278. function NoGetCurrentThreadId : TThreadID;
  279. begin
  280. if IsMultiThread then
  281. NoThreadError
  282. else
  283. ThreadingAlreadyUsed:=true;
  284. result:=ThreadID;
  285. end;
  286. procedure NoCriticalSection(var CS);
  287. begin
  288. if IsMultiThread then
  289. NoThreadError
  290. else
  291. ThreadingAlreadyUsed:=true;
  292. end;
  293. procedure NoInitThreadvar(var offset : dword;size : dword);
  294. begin
  295. NoThreadError;
  296. end;
  297. function NoRelocateThreadvar(offset : dword) : pointer;
  298. begin
  299. NoThreadError;
  300. end;
  301. procedure NoAllocateThreadVars;
  302. begin
  303. NoThreadError;
  304. end;
  305. procedure NoReleaseThreadVars;
  306. begin
  307. NoThreadError;
  308. end;
  309. function noBasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;
  310. begin
  311. NoThreadError;
  312. end;
  313. procedure nobasiceventdestroy(state:peventstate);
  314. begin
  315. NoThreadError;
  316. end;
  317. procedure nobasiceventResetEvent(state:peventstate);
  318. begin
  319. NoThreadError;
  320. end;
  321. procedure nobasiceventSetEvent(state:peventstate);
  322. begin
  323. NoThreadError;
  324. end;
  325. function nobasiceventWaitFor(Timeout : Cardinal;state:peventstate) : longint;
  326. begin
  327. NoThreadError;
  328. end;
  329. function NORTLEventCreate :PRTLEvent;
  330. begin
  331. if IsMultiThread then
  332. NoThreadError
  333. else
  334. ThreadingAlreadyUsed:=true
  335. end;
  336. procedure NORTLeventdestroy(state:pRTLEvent);
  337. begin
  338. if IsMultiThread then
  339. NoThreadError
  340. else
  341. ThreadingAlreadyUsed:=true
  342. end;
  343. procedure NORTLeventSetEvent(state:pRTLEvent);
  344. begin
  345. NoThreadError;
  346. end;
  347. procedure NORTLeventWaitFor(state:pRTLEvent);
  348. begin
  349. NoThreadError;
  350. end;
  351. procedure NORTLeventWaitForTimeout(state:pRTLEvent;timeout : longint);
  352. begin
  353. NoThreadError;
  354. end;
  355. procedure NORTLeventsync(m:trtlmethod;p:tprocedure);
  356. begin
  357. NoThreadError;
  358. end;
  359. function NoSemaphoreInit: Pointer;
  360. begin
  361. NoThreadError;
  362. end;
  363. procedure NoSemaphoreWait(const FSem: Pointer);
  364. begin
  365. NoThreadError;
  366. end;
  367. procedure NoSemaphorePost(const FSem: Pointer);
  368. begin
  369. NoThreadError;
  370. end;
  371. procedure NoSemaphoreDestroy(const FSem: Pointer);
  372. begin
  373. NoThreadError;
  374. end;
  375. Var
  376. NoThreadManager : TThreadManager;
  377. Procedure SetNoThreadManager;
  378. begin
  379. With NoThreadManager do
  380. begin
  381. InitManager :=Nil;
  382. DoneManager :=Nil;
  383. BeginThread :=@NoBeginThread;
  384. EndThread :=@NoEndThread;
  385. SuspendThread :=@NoThreadHandler;
  386. ResumeThread :=@NoThreadHandler;
  387. KillThread :=@NoThreadHandler;
  388. ThreadSwitch :=@NoThreadSwitch;
  389. WaitForThreadTerminate :=@NoWaitForThreadTerminate;
  390. ThreadSetPriority :=@NoThreadSetPriority;
  391. ThreadGetPriority :=@NoThreadGetPriority;
  392. GetCurrentThreadId :=@NoGetCurrentThreadId;
  393. InitCriticalSection :=@NoCriticalSection;
  394. DoneCriticalSection :=@NoCriticalSection;
  395. EnterCriticalSection :=@NoCriticalSection;
  396. LeaveCriticalSection :=@NoCriticalSection;
  397. InitThreadVar :=@NoInitThreadVar;
  398. RelocateThreadVar :=@NoRelocateThreadVar;
  399. AllocateThreadVars :=@NoAllocateThreadVars;
  400. ReleaseThreadVars :=@NoReleaseThreadVars;
  401. BasicEventCreate :=@NoBasicEventCreate;
  402. basiceventdestroy :=@Nobasiceventdestroy;
  403. basiceventResetEvent :=@NobasiceventResetEvent;
  404. basiceventSetEvent :=@NobasiceventSetEvent;
  405. basiceventWaitFor :=@NobasiceventWaitFor;
  406. rtlEventCreate :=@NortlEventCreate;
  407. rtleventdestroy :=@Nortleventdestroy;
  408. rtleventSetEvent :=@NortleventSetEvent;
  409. rtleventWaitFor :=@NortleventWaitFor;
  410. rtleventsync :=@Nortleventsync;
  411. rtleventwaitfortimeout :=@NortleventWaitForTimeout;
  412. // semaphores stuff
  413. SemaphoreInit :=@NoSemaphoreInit;
  414. SemaphoreDestroy :=@NoSemaphoreDestroy;
  415. SemaphoreWait :=@NoSemaphoreWait;
  416. SemaphorePost :=@NoSemaphorePost;
  417. end;
  418. SetThreadManager(NoThreadManager);
  419. end;
  420. Procedure InitSystemThreads;
  421. begin
  422. { This should be changed to a real value during
  423. thread driver initialization if appropriate. }
  424. ThreadID := TThreadID(1);
  425. SetNoThreadManager;
  426. end;
  427. {$endif DISABLE_NO_THREAD_MANAGER}