tthread.inc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by Peter Vreman
  5. Linux TThread implementation
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. type
  13. PThreadRec=^TThreadRec;
  14. TThreadRec=record
  15. thread : TThread;
  16. next : PThreadRec;
  17. end;
  18. var
  19. ThreadRoot : PThreadRec;
  20. ThreadsInited : boolean;
  21. // MainThreadID: longint;
  22. Const
  23. ThreadCount: longint = 0;
  24. function ThreadSelf:TThread;
  25. var
  26. hp : PThreadRec;
  27. sp : Pointer;
  28. begin
  29. sp:=SPtr;
  30. hp:=ThreadRoot;
  31. while assigned(hp) do
  32. begin
  33. if (sp<=hp^.Thread.FStackPointer) and
  34. (sp>(hp^.Thread.FStackPointer-hp^.Thread.FStackSize)) then
  35. begin
  36. Result:=hp^.Thread;
  37. exit;
  38. end;
  39. hp:=hp^.next;
  40. end;
  41. Result:=nil;
  42. end;
  43. //function SIGCHLDHandler(Sig: longint): longint; cdecl;//this is std linux C declaration as function
  44. procedure SIGCHLDHandler(Sig: longint); cdecl;
  45. begin
  46. fpwaitpid(-1, nil, WNOHANG);
  47. end;
  48. const zeroset :sigset = (0,0,0,0);
  49. procedure InitThreads;
  50. var
  51. Act, OldAct: PSigActionRec;
  52. begin
  53. ThreadRoot:=nil;
  54. ThreadsInited:=true;
  55. // This will install SIGCHLD signal handler
  56. // signal() installs "one-shot" handler,
  57. // so it is better to install and set up handler with sigaction()
  58. GetMem(Act, SizeOf(SigActionRec));
  59. GetMem(OldAct, SizeOf(SigActionRec));
  60. signalhandler(Act^.sa_handler) := @SIGCHLDHandler;
  61. fillchar(Act^.sa_mask,sizeof(sigset_t),#0);
  62. Act^.sa_flags := SA_NOCLDSTOP {or SA_NOMASK or SA_RESTART};
  63. //Do not block all signals ??. Don't need if SA_NOMASK in flags
  64. fpsigaction(SIGCHLD, @Act, @OldAct);
  65. FreeMem(Act, SizeOf(SigActionRec));
  66. FreeMem(OldAct, SizeOf(SigActionRec));
  67. end;
  68. procedure DoneThreads;
  69. var
  70. hp : PThreadRec;
  71. begin
  72. while assigned(ThreadRoot) do
  73. begin
  74. ThreadRoot^.Thread.Destroy;
  75. hp:=ThreadRoot;
  76. ThreadRoot:=ThreadRoot^.Next;
  77. dispose(hp);
  78. end;
  79. ThreadsInited:=false;
  80. end;
  81. procedure AddThread(t:TThread);
  82. var
  83. hp : PThreadRec;
  84. begin
  85. { Need to initialize threads ? }
  86. if not ThreadsInited then
  87. InitThreads;
  88. { Put thread in the linked list }
  89. new(hp);
  90. hp^.Thread:=t;
  91. hp^.next:=ThreadRoot;
  92. ThreadRoot:=hp;
  93. inc(ThreadCount, 1);
  94. end;
  95. procedure RemoveThread(t:TThread);
  96. var
  97. lasthp,hp : PThreadRec;
  98. begin
  99. hp:=ThreadRoot;
  100. lasthp:=nil;
  101. while assigned(hp) do
  102. begin
  103. if hp^.Thread=t then
  104. begin
  105. if assigned(lasthp) then
  106. lasthp^.next:=hp^.next
  107. else
  108. ThreadRoot:=hp^.next;
  109. dispose(hp);
  110. exit;
  111. end;
  112. lasthp:=hp;
  113. hp:=hp^.next;
  114. end;
  115. Dec(ThreadCount, 1);
  116. if ThreadCount = 0 then DoneThreads;
  117. end;
  118. { TThread }
  119. function ThreadProc(args:pointer): Integer;cdecl;
  120. var
  121. FreeThread: Boolean;
  122. Thread : TThread absolute args;
  123. begin
  124. try
  125. Thread.Execute;
  126. except
  127. Thread.FFatalException := TObject(AcquireExceptionObject);
  128. end;
  129. FreeThread := Thread.FFreeOnTerminate;
  130. Result := Thread.FReturnValue;
  131. Thread.FFinished := True;
  132. Thread.DoTerminate;
  133. if FreeThread then
  134. Thread.Free;
  135. fpExit(Result);
  136. end;
  137. constructor TThread.Create(CreateSuspended: Boolean);
  138. var
  139. Flags: Integer;
  140. begin
  141. inherited Create;
  142. AddThread(self);
  143. FSuspended := CreateSuspended;
  144. Flags := CLONE_VM + CLONE_FS + CLONE_FILES + CLONE_SIGHAND + SIGCHLD;
  145. { Setup 16k of stack }
  146. FStackSize:=16384;
  147. Getmem(pointer(FStackPointer),FStackSize);
  148. inc(FStackPointer,FStackSize);
  149. FCallExitProcess:=false;
  150. { Clone }
  151. FHandle:= Clone(@ThreadProc,pointer(FStackPointer),Flags,self);
  152. if FSuspended then Suspend;
  153. FThreadID := FHandle;
  154. IsMultiThread := TRUE;
  155. FFatalException := nil;
  156. end;
  157. destructor TThread.Destroy;
  158. begin
  159. if not FFinished and not Suspended then
  160. begin
  161. Terminate;
  162. WaitFor;
  163. end;
  164. if FHandle <> -1 then
  165. fpkill(FHandle, SIGKILL);
  166. dec(FStackPointer,FStackSize);
  167. Freemem(pointer(FStackPointer),FStackSize);
  168. FFatalException.Free;
  169. FFatalException := nil;
  170. inherited Destroy;
  171. RemoveThread(self);
  172. end;
  173. procedure TThread.CallOnTerminate;
  174. begin
  175. FOnTerminate(Self);
  176. end;
  177. procedure TThread.DoTerminate;
  178. begin
  179. if Assigned(FOnTerminate) then
  180. Synchronize(@CallOnTerminate);
  181. end;
  182. const
  183. { I Don't know idle or timecritical, value is also 20, so the largest other
  184. possibility is 19 (PFV) }
  185. Priorities: array [TThreadPriority] of Integer =
  186. (-20,-19,-10,9,10,19,20);
  187. function TThread.GetPriority: TThreadPriority;
  188. var
  189. P: Integer;
  190. I: TThreadPriority;
  191. begin
  192. P :=
  193. Unix.fpGetPriority (Prio_Process,FHandle);
  194. Result := tpNormal;
  195. for I := Low(TThreadPriority) to High(TThreadPriority) do
  196. if Priorities[I] = P then
  197. Result := I;
  198. end;
  199. procedure TThread.SetPriority(Value: TThreadPriority);
  200. begin
  201. Unix.fpSetPriority
  202. (Prio_Process,FHandle, Priorities[Value]);
  203. end;
  204. procedure TThread.Synchronize(Method: TThreadMethod);
  205. begin
  206. FSynchronizeException := nil;
  207. FMethod := Method;
  208. { SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self)); }
  209. if Assigned(FSynchronizeException) then
  210. raise FSynchronizeException;
  211. end;
  212. procedure TThread.SetSuspended(Value: Boolean);
  213. begin
  214. if Value <> FSuspended then
  215. if Value then
  216. Suspend
  217. else
  218. Resume;
  219. end;
  220. procedure TThread.Suspend;
  221. begin
  222. fpkill(FHandle, SIGSTOP);
  223. FSuspended := true;
  224. end;
  225. procedure TThread.Resume;
  226. begin
  227. fpkill(FHandle, SIGCONT);
  228. FSuspended := False;
  229. end;
  230. procedure TThread.Terminate;
  231. begin
  232. FTerminated := True;
  233. end;
  234. function TThread.WaitFor: Integer;
  235. var
  236. status : longint;
  237. begin
  238. if FThreadID = MainThreadID then
  239. fpWaitPid(0,@status,0)
  240. else
  241. fpWaitPid(FHandle,@status,0);
  242. Result:=status;
  243. end;
  244. {
  245. $Log$
  246. Revision 1.4 2003-11-03 09:42:27 marco
  247. * Peter's Cardinal<->Longint fixes patch
  248. Revision 1.3 2003/10/27 17:12:45 marco
  249. * fixes for signal handling.
  250. Revision 1.2 2003/10/09 10:55:20 marco
  251. * fix for moving classes to rtl while cycling with 1.0 start
  252. Revision 1.1 2003/10/06 21:01:06 peter
  253. * moved classes unit to rtl
  254. Revision 1.12 2003/10/06 17:06:55 florian
  255. * applied Johannes Berg's patch for exception handling in threads
  256. Revision 1.11 2003/09/20 14:51:42 marco
  257. * small v1_0 fix
  258. Revision 1.10 2003/09/20 12:38:29 marco
  259. * FCL now compiles for FreeBSD with new 1.1. Now Linux.
  260. Revision 1.9 2003/01/17 19:01:07 marco
  261. * small fix
  262. Revision 1.8 2002/11/17 21:09:44 marco
  263. * 16byte sigset
  264. Revision 1.7 2002/10/24 12:47:54 marco
  265. * Fix emptying sa_mask
  266. Revision 1.6 2002/09/07 15:15:24 peter
  267. * old logs removed and tabs fixed
  268. }