thread.inc 12 KB

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