thread.inc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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(args:pointer): Integer;cdecl;
  111. var
  112. FreeThread: Boolean;
  113. Thread : TThread absolute args;
  114. begin
  115. Thread.Execute;
  116. FreeThread := Thread.FFreeOnTerminate;
  117. Result := Thread.FReturnValue;
  118. Thread.FFinished := True;
  119. Thread.DoTerminate;
  120. if FreeThread then
  121. Thread.Free;
  122. ExitProcess(Result);
  123. end;
  124. constructor TThread.Create(CreateSuspended: Boolean);
  125. var
  126. Flags: Integer;
  127. begin
  128. inherited Create;
  129. AddThread(self);
  130. FSuspended := CreateSuspended;
  131. Flags := CLONE_VM + CLONE_FS + CLONE_FILES + CLONE_SIGHAND + SIGCHLD;
  132. { Setup 16k of stack }
  133. FStackSize:=16384;
  134. Getmem(pointer(FStackPointer),FStackSize);
  135. inc(FStackPointer,FStackSize);
  136. FCallExitProcess:=false;
  137. { Clone }
  138. FHandle:= Clone(@ThreadProc,pointer(FStackPointer),Flags,self);
  139. if FSuspended then Suspend;
  140. FThreadID := FHandle;
  141. end;
  142. destructor TThread.Destroy;
  143. begin
  144. if not FFinished and not Suspended then
  145. begin
  146. Terminate;
  147. WaitFor;
  148. end;
  149. if FHandle <> -1 then
  150. Kill(FHandle, SIGKILL);
  151. dec(FStackPointer,FStackSize);
  152. Freemem(pointer(FStackPointer),FStackSize);
  153. inherited Destroy;
  154. RemoveThread(self);
  155. end;
  156. procedure TThread.CallOnTerminate;
  157. begin
  158. FOnTerminate(Self);
  159. end;
  160. procedure TThread.DoTerminate;
  161. begin
  162. if Assigned(FOnTerminate) then
  163. Synchronize(@CallOnTerminate);
  164. end;
  165. const
  166. { I Don't know idle or timecritical, value is also 20, so the largest other
  167. possibility is 19 (PFV) }
  168. Priorities: array [TThreadPriority] of Integer =
  169. (-20,-19,-10,9,10,19,20);
  170. function TThread.GetPriority: TThreadPriority;
  171. var
  172. P: Integer;
  173. I: TThreadPriority;
  174. begin
  175. P := Linux.GetPriority(Prio_Process,FHandle);
  176. Result := tpNormal;
  177. for I := Low(TThreadPriority) to High(TThreadPriority) do
  178. if Priorities[I] = P then
  179. Result := I;
  180. end;
  181. procedure TThread.SetPriority(Value: TThreadPriority);
  182. begin
  183. Linux.SetPriority(Prio_Process,FHandle, Priorities[Value]);
  184. end;
  185. procedure TThread.Synchronize(Method: TThreadMethod);
  186. begin
  187. FSynchronizeException := nil;
  188. FMethod := Method;
  189. { SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self)); }
  190. if Assigned(FSynchronizeException) then
  191. raise FSynchronizeException;
  192. end;
  193. procedure TThread.SetSuspended(Value: Boolean);
  194. begin
  195. if Value <> FSuspended then
  196. if Value then
  197. Suspend
  198. else
  199. Resume;
  200. end;
  201. procedure TThread.Suspend;
  202. begin
  203. Kill(FHandle, SIGSTOP);
  204. FSuspended := true;
  205. end;
  206. procedure TThread.Resume;
  207. begin
  208. Kill(FHandle, SIGCONT);
  209. FSuspended := False;
  210. end;
  211. procedure TThread.Terminate;
  212. begin
  213. FTerminated := True;
  214. end;
  215. function TThread.WaitFor: Integer;
  216. var
  217. status : longint;
  218. begin
  219. if FThreadID = MainThreadID then
  220. WaitPid(0,@status,0)
  221. else
  222. WaitPid(FHandle,@status,0);
  223. Result:=status;
  224. end;
  225. {
  226. $Log$
  227. Revision 1.5 1999-10-27 10:40:30 peter
  228. * fixed threadproc decl
  229. Revision 1.4 1999/08/28 09:32:26 peter
  230. * readded header/log
  231. Revision 1.2 1999/05/31 12:47:59 peter
  232. * classes unit to unitobjects
  233. Revision 1.1 1999/05/30 10:46:42 peter
  234. * start of tthread for linux,win32
  235. }