thread.inc 12 KB

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