2
0

thread.inc 12 KB

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