Răsfoiți Sursa

amicommon: more AThreads work
- in WaitForThreadTerminate, do not try to wait if the thread already exited
- when debug mode enabled, release the threadvars later, so AnsiString debug messages still work
- do not call DoneThread in EndThread. the threadfunc will call it when exited.

git-svn-id: trunk@30913 -

Károly Balogh 10 ani în urmă
părinte
comite
45ce4538fa
1 a modificat fișierele cu 41 adăugiri și 8 ștergeri
  1. 41 8
      rtl/amicommon/athreads.pp

+ 41 - 8
rtl/amicommon/athreads.pp

@@ -136,9 +136,23 @@ begin
       tmpNext:=p^.nextThread;
       if not p^.mainthread and p^.exited then
         begin
+{$IFDEF DEBUG_MT}
+          SysDebugLn('FPC AThreads: Releasing resources for thread ID:'+hexStr(Pointer(threadID)));
+{$ENDIF}
           while GetMsg(p^.replyPort) <> nil do begin end;
           DeleteMsgPort(p^.replyPort);
           dispose(p^.replyMsg);
+{$ifdef DEBUG_MT}
+          { When debug mode enabled, release the threadvars here, later, because the "normal" location }
+          { is too early, because debug messages on the thread might still use the heap manager (KB) }
+{$ifdef AMIGA}
+          ObtainSemaphore(ASYS_heapSemaphore);
+{$endif}
+          FreePooled(ASYS_heapPool,p^.threadVars,p^.threadVarsSize);
+{$ifdef AMIGA}
+          ReleaseSemaphore(ASYS_heapSemaphore);
+{$endif}
+{$endif}
           dispose(p);
           if pprev <> nil then
             pprev^.nextThread:=tmpNext;
@@ -313,13 +327,20 @@ begin
   p:=PThreadInfo(PProcess(FindTask(nil))^.pr_Task.tc_UserData);
   if (p <> nil) and (p^.threadVars <> nil) then
     begin
+{$ifndef DEBUG_MT}
+      { When debug mode is enabled, do not release threadvars here, because }
+      { Debug messages later might still need the heapmanager, which depends }
+      { on the threadvar (KB) }
 {$ifdef AMIGA}
       ObtainSemaphore(ASYS_heapSemaphore);
 {$endif}
       FreePooled(ASYS_heapPool,p^.threadVars,p^.threadVarsSize);
+      p^.threadVars:=nil;
+      p^.threadVarsSize:=0;
 {$ifdef AMIGA}
       ReleaseSemaphore(ASYS_heapSemaphore);
 {$endif}
+{$endif DEBUG_MT}
     end
   else
     begin
@@ -529,7 +550,7 @@ end;
 
 procedure AEndThread(ExitCode : DWord);
 begin
-  DoneThread;
+  { Do not call DoneThread here. It will be called by the threadfunction, when it exits. }
 end;
 
 
@@ -615,16 +636,28 @@ begin
   p:=GetThreadInfo(AThreadList,threadHandle);
   if (p <> nil) then
     begin
+      if not p^.exited then
+        begin
 {$ifdef DEBUG_MT}
-      SysDebugLn('FPC AThreads: Waiting for thread to exit, ID:'+hexStr(Pointer(threadHandle)));
+          SysDebugLn('FPC AThreads: Waiting for thread to exit, ID:'+hexStr(Pointer(threadHandle)));
 {$endif}
-      { WaitPort in SendMessageToThread will break the Forbid() state... }
-      if p^.suspended then
-        SendMessageToThread(m,p,toExit,true);
+          { WaitPort in SendMessageToThread will break the Forbid() state... }
+          if p^.suspended then
+            begin
+              SendMessageToThread(m,p,toExit,true);
+{$ifdef DEBUG_MT}
+              SysDebugLn('FPC AThreads: Signaled suspended thread to exit, ID:'+hexStr(Pointer(threadHandle)));
+{$endif}
+            end;
 
-      { WaitPort will break the Forbid() state... }
-      WaitPort(p^.replyPort);
-      GetMsg(p^.replyPort);
+          { WaitPort will break the Forbid() state... }
+          WaitPort(p^.replyPort);
+          GetMsg(p^.replyPort);
+        end
+      else
+{$ifdef DEBUG_MT}
+        SysDebugLn('FPC AThreads: Thread already exited, ID:'+hexStr(Pointer(threadHandle)));
+{$endif}
       AWaitForThreadTerminate:=DWord(p^.exitCode);
     end
   else