thread.inc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. {
  2. $Id$
  3. Linux TThread implementation
  4. }
  5. type
  6. PThreadRec=^TThreadRec;
  7. TThreadRec=record
  8. thread : TThread;
  9. next : PThreadRec;
  10. end;
  11. var
  12. ThreadRoot : PThreadRec;
  13. ThreadsInited : boolean;
  14. // MainThreadID: longint;
  15. Const
  16. ThreadCount: longint = 0;
  17. function ThreadSelf:TThread;
  18. var
  19. hp : PThreadRec;
  20. sp : longint;
  21. begin
  22. sp:=SPtr;
  23. hp:=ThreadRoot;
  24. while assigned(hp) do
  25. begin
  26. if (sp<=hp^.Thread.FStackPointer) and
  27. (sp>(hp^.Thread.FStackPointer-hp^.Thread.FStackSize)) then
  28. begin
  29. Result:=hp^.Thread;
  30. exit;
  31. end;
  32. hp:=hp^.next;
  33. end;
  34. Result:=nil;
  35. end;
  36. //function SIGCHLDHandler(Sig: longint): longint; cdecl;//this is std linux C declaration as function
  37. procedure SIGCHLDHandler(Sig: longint); cdecl;
  38. begin
  39. waitpid(-1, nil, WNOHANG);
  40. end;
  41. procedure InitThreads;
  42. var
  43. Act, OldAct: PSigActionRec;
  44. begin
  45. ThreadRoot:=nil;
  46. ThreadsInited:=true;
  47. // This will install SIGCHLD signal handler
  48. // signal() installs "one-shot" handler,
  49. // so it is better to install and set up handler with sigaction()
  50. GetMem(Act, SizeOf(SigActionRec));
  51. GetMem(OldAct, SizeOf(SigActionRec));
  52. Act^.sa_handler := @SIGCHLDHandler;
  53. Act^.sa_flags := SA_NOCLDSTOP {or SA_NOMASK or SA_RESTART};
  54. Act^.sa_mask := 0; //Do not block all signals ??. Don't need if SA_NOMASK in flags
  55. SigAction(SIGCHLD, Act, OldAct);
  56. FreeMem(Act, SizeOf(SigActionRec));
  57. FreeMem(OldAct, SizeOf(SigActionRec));
  58. end;
  59. procedure DoneThreads;
  60. var
  61. hp : PThreadRec;
  62. begin
  63. while assigned(ThreadRoot) do
  64. begin
  65. ThreadRoot^.Thread.Destroy;
  66. hp:=ThreadRoot;
  67. ThreadRoot:=ThreadRoot^.Next;
  68. dispose(hp);
  69. end;
  70. ThreadsInited:=false;
  71. end;
  72. procedure AddThread(t:TThread);
  73. var
  74. hp : PThreadRec;
  75. begin
  76. { Need to initialize threads ? }
  77. if not ThreadsInited then
  78. InitThreads;
  79. { Put thread in the linked list }
  80. new(hp);
  81. hp^.Thread:=t;
  82. hp^.next:=ThreadRoot;
  83. ThreadRoot:=hp;
  84. inc(ThreadCount, 1);
  85. end;
  86. procedure RemoveThread(t:TThread);
  87. var
  88. lasthp,hp : PThreadRec;
  89. begin
  90. hp:=ThreadRoot;
  91. lasthp:=nil;
  92. while assigned(hp) do
  93. begin
  94. if hp^.Thread=t then
  95. begin
  96. if assigned(lasthp) then
  97. lasthp^.next:=hp^.next
  98. else
  99. ThreadRoot:=hp^.next;
  100. dispose(hp);
  101. exit;
  102. end;
  103. lasthp:=hp;
  104. hp:=hp^.next;
  105. end;
  106. Dec(ThreadCount, 1);
  107. if ThreadCount = 0 then DoneThreads;
  108. end;
  109. { TThread }
  110. function ThreadProc(Thread: TThread): Integer;cdecl;
  111. var
  112. FreeThread: Boolean;
  113. begin
  114. Thread.Execute;
  115. FreeThread := Thread.FFreeOnTerminate;
  116. Result := Thread.FReturnValue;
  117. Thread.FFinished := True;
  118. Thread.DoTerminate;
  119. if FreeThread then
  120. Thread.Free;
  121. ExitProcess(Result);
  122. end;
  123. constructor TThread.Create(CreateSuspended: Boolean);
  124. var
  125. Flags: Integer;
  126. begin
  127. inherited Create;
  128. AddThread(self);
  129. FSuspended := CreateSuspended;
  130. Flags := CLONE_VM + CLONE_FS + CLONE_FILES + CLONE_SIGHAND + SIGCHLD;
  131. { Setup 16k of stack }
  132. FStackSize:=16384;
  133. Getmem(pointer(FStackPointer),FStackSize);
  134. inc(FStackPointer,FStackSize);
  135. FCallExitProcess:=false;
  136. { Clone }
  137. FHandle:= Clone(@ThreadProc,pointer(FStackPointer),Flags,self);
  138. if FSuspended then Suspend;
  139. FThreadID := FHandle;
  140. end;
  141. destructor TThread.Destroy;
  142. begin
  143. if not FFinished and not Suspended then
  144. begin
  145. Terminate;
  146. WaitFor;
  147. end;
  148. if FHandle <> -1 then
  149. Kill(FHandle, SIGKILL);
  150. dec(FStackPointer,FStackSize);
  151. Freemem(pointer(FStackPointer),FStackSize);
  152. inherited Destroy;
  153. RemoveThread(self);
  154. end;
  155. procedure TThread.CallOnTerminate;
  156. begin
  157. FOnTerminate(Self);
  158. end;
  159. procedure TThread.DoTerminate;
  160. begin
  161. if Assigned(FOnTerminate) then
  162. Synchronize(@CallOnTerminate);
  163. end;
  164. const
  165. { I Don't know idle or timecritical, value is also 20, so the largest other
  166. possibility is 19 (PFV) }
  167. Priorities: array [TThreadPriority] of Integer =
  168. (-20,-19,-10,9,10,19,20);
  169. function TThread.GetPriority: TThreadPriority;
  170. var
  171. P: Integer;
  172. I: TThreadPriority;
  173. begin
  174. P := Linux.GetPriority(Prio_Process,FHandle);
  175. Result := tpNormal;
  176. for I := Low(TThreadPriority) to High(TThreadPriority) do
  177. if Priorities[I] = P then
  178. Result := I;
  179. end;
  180. procedure TThread.SetPriority(Value: TThreadPriority);
  181. begin
  182. Linux.SetPriority(Prio_Process,FHandle, Priorities[Value]);
  183. end;
  184. procedure TThread.Synchronize(Method: TThreadMethod);
  185. begin
  186. FSynchronizeException := nil;
  187. FMethod := Method;
  188. { SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self)); }
  189. if Assigned(FSynchronizeException) then
  190. raise FSynchronizeException;
  191. end;
  192. procedure TThread.SetSuspended(Value: Boolean);
  193. begin
  194. if Value <> FSuspended then
  195. if Value then
  196. Suspend
  197. else
  198. Resume;
  199. end;
  200. procedure TThread.Suspend;
  201. begin
  202. Kill(FHandle, SIGSTOP);
  203. FSuspended := true;
  204. end;
  205. procedure TThread.Resume;
  206. begin
  207. Kill(FHandle, SIGCONT);
  208. FSuspended := False;
  209. end;
  210. procedure TThread.Terminate;
  211. begin
  212. FTerminated := True;
  213. end;
  214. function TThread.WaitFor: Integer;
  215. var
  216. status : longint;
  217. begin
  218. if FThreadID = MainThreadID then
  219. WaitPid(0,@status,0)
  220. else
  221. WaitPid(FHandle,@status,0);
  222. Result:=status;
  223. end;
  224. {
  225. $Log$
  226. Revision 1.4 1999-08-28 09:32:26 peter
  227. * readded header/log
  228. Revision 1.2 1999/05/31 12:47:59 peter
  229. * classes unit to unitobjects
  230. Revision 1.1 1999/05/30 10:46:42 peter
  231. * start of tthread for linux,win32
  232. }