thread.inc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. {
  2. $Id$
  3. Linux TThread implementation
  4. }
  5. { Thread management routines }
  6. const
  7. Sig_Cancel = SIGUSR2;
  8. type
  9. PThreadRec=^TThreadRec;
  10. TThreadRec=record
  11. thread : TThread;
  12. next : PThreadRec;
  13. end;
  14. var
  15. ThreadRoot : PThreadRec;
  16. ThreadsInited : boolean;
  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. procedure ThreadCancelHandler(Sig:integer);cdecl;
  37. var
  38. p : TThread;
  39. begin
  40. p:=ThreadSelf;
  41. if assigned(p) and (p.FCallExitProcess) then
  42. ExitProcess(p.FReturnValue);
  43. end;
  44. procedure InitThreads;
  45. begin
  46. ThreadRoot:=nil;
  47. ThreadsInited:=true;
  48. { Install sig_cancel handler }
  49. Signal(Sig_Cancel,@ThreadCancelHandler);
  50. end;
  51. procedure DoneThreads;
  52. var
  53. hp : PThreadRec;
  54. begin
  55. while assigned(ThreadRoot) do
  56. begin
  57. ThreadRoot^.Thread.Destroy;
  58. hp:=ThreadRoot;
  59. ThreadRoot:=ThreadRoot^.Next;
  60. dispose(hp);
  61. end;
  62. ThreadsInited:=false;
  63. end;
  64. procedure AddThread(t:TThread);
  65. var
  66. hp : PThreadRec;
  67. begin
  68. { Need to initialize threads ? }
  69. if not ThreadsInited then
  70. InitThreads;
  71. { Put thread in the linked list }
  72. new(hp);
  73. hp^.Thread:=t;
  74. hp^.next:=ThreadRoot;
  75. ThreadRoot:=hp;
  76. end;
  77. procedure RemoveThread(t:TThread);
  78. var
  79. lasthp,hp : PThreadRec;
  80. begin
  81. hp:=ThreadRoot;
  82. lasthp:=nil;
  83. while assigned(hp) do
  84. begin
  85. if hp^.Thread=t then
  86. begin
  87. if assigned(lasthp) then
  88. lasthp^.next:=hp^.next
  89. else
  90. ThreadRoot:=hp^.next;
  91. dispose(hp);
  92. exit;
  93. end;
  94. lasthp:=hp;
  95. hp:=hp^.next;
  96. end;
  97. end;
  98. { TThread }
  99. function ThreadProc(Thread: TThread): Integer;cdecl;
  100. var
  101. FreeThread: Boolean;
  102. begin
  103. Thread.Execute;
  104. FreeThread := Thread.FFreeOnTerminate;
  105. Result := Thread.FReturnValue;
  106. Thread.FFinished := True;
  107. Thread.DoTerminate;
  108. if FreeThread then
  109. Thread.Free;
  110. ExitProcess(Result);
  111. end;
  112. constructor TThread.Create(CreateSuspended: Boolean);
  113. var
  114. Flags: Integer;
  115. begin
  116. inherited Create;
  117. AddThread(self);
  118. FSuspended := CreateSuspended;
  119. Flags:=CLONE_VM+CLONE_FS+CLONE_FILES+CLONE_SIGHAND;
  120. { Setup 16k of stack }
  121. FStackSize:=16384;
  122. Getmem(pointer(FStackPointer),FStackSize);
  123. inc(FStackPointer,FStackSize);
  124. FCallExitProcess:=false;
  125. { Clone }
  126. FHandle:= Clone(@ThreadProc,pointer(FStackPointer),Flags,self);
  127. FThreadID := FHandle;
  128. end;
  129. destructor TThread.Destroy;
  130. begin
  131. if not FFinished and not Suspended then
  132. begin
  133. Terminate;
  134. WaitFor;
  135. end;
  136. { Remove stack }
  137. dec(FStackPointer,FStackSize);
  138. Freemem(pointer(FStackPointer),FStackSize);
  139. inherited Destroy;
  140. RemoveThread(self);
  141. end;
  142. procedure TThread.CallOnTerminate;
  143. begin
  144. FOnTerminate(Self);
  145. end;
  146. procedure TThread.DoTerminate;
  147. begin
  148. if Assigned(FOnTerminate) then
  149. Synchronize(@CallOnTerminate);
  150. end;
  151. const
  152. { I Don't know idle or timecritical, value is also 20, so the largest other
  153. possibility is 19 (PFV) }
  154. Priorities: array [TThreadPriority] of Integer =
  155. (-20,-19,-10,9,10,19,20);
  156. function TThread.GetPriority: TThreadPriority;
  157. var
  158. P: Integer;
  159. I: TThreadPriority;
  160. begin
  161. P := Linux.GetPriority(Prio_Process,FHandle);
  162. Result := tpNormal;
  163. for I := Low(TThreadPriority) to High(TThreadPriority) do
  164. if Priorities[I] = P then
  165. Result := I;
  166. end;
  167. procedure TThread.SetPriority(Value: TThreadPriority);
  168. begin
  169. Linux.SetPriority(Prio_Process,FHandle, Priorities[Value]);
  170. end;
  171. procedure TThread.Synchronize(Method: TThreadMethod);
  172. begin
  173. FSynchronizeException := nil;
  174. FMethod := Method;
  175. { SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self)); }
  176. if Assigned(FSynchronizeException) then
  177. raise FSynchronizeException;
  178. end;
  179. procedure TThread.SetSuspended(Value: Boolean);
  180. begin
  181. if Value <> FSuspended then
  182. if Value then
  183. Suspend
  184. else
  185. Resume;
  186. end;
  187. procedure TThread.Suspend;
  188. begin
  189. FSuspended := True;
  190. { SuspendThread(FHandle); }
  191. end;
  192. procedure TThread.Resume;
  193. begin
  194. { if ResumeThread(FHandle) = 1 then }
  195. FSuspended := False;
  196. end;
  197. procedure TThread.Terminate;
  198. begin
  199. { Set the flag for this tthread, so the sighandler knows which tthread
  200. needs termination }
  201. FCallExitProcess:=true;
  202. Kill(FHandle,Sig_Cancel);
  203. FTerminated := True;
  204. end;
  205. function TThread.WaitFor: Integer;
  206. var
  207. status : longint;
  208. begin
  209. if FThreadID = MainThreadID then
  210. WaitPid(0,@status,0)
  211. else
  212. WaitPid(FHandle,@status,0);
  213. Result:=status;
  214. end;
  215. {
  216. $Log$
  217. Revision 1.2 1999-05-31 12:47:59 peter
  218. * classes unit to unitobjects
  219. Revision 1.1 1999/05/30 10:46:42 peter
  220. * start of tthread for linux,win32
  221. }