dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dotgnu-pnet-commits] CVS: pnet/support hb_gc.c,1.18,1.19 thread.c,1.12


From: Thong Nguyen <address@hidden>
Subject: [Dotgnu-pnet-commits] CVS: pnet/support hb_gc.c,1.18,1.19 thread.c,1.12,1.13
Date: Tue, 08 Jul 2003 08:05:20 -0400

Update of /cvsroot/dotgnu-pnet/pnet/support
In directory subversions:/tmp/cvs-serv7886/support

Modified Files:
        hb_gc.c thread.c 
Log Message:
GC & finalizer improvements.  Support for thread cleanup handlers.
 


Index: hb_gc.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/hb_gc.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -r1.18 -r1.19
*** hb_gc.c     6 Jul 2003 05:29:14 -0000       1.18
--- hb_gc.c     8 Jul 2003 12:05:17 -0000       1.19
***************
*** 34,37 ****
--- 34,39 ----
  #endif
  
+ /* #define GC_TRACE_ENABLE */
+ 
  /*
   * Set to non-zero if finalization has been temporarily disabled.
***************
*** 39,48 ****
  static int volatile FinalizersDisabled = 0;
  
! static volatile int g_Deinit = 0;
! static ILThread *g_FinalizerThread = 0;
! static ILWaitHandle *g_FinalizerSignal = 0;
! static ILWaitHandle *g_FinalizerResponse = 0;
! static ILMutex *g_GcLock = 0;
  
  #ifdef GC_TRACE_ENABLE
        #define GC_TRACE(a, b)          printf(a, b)
--- 41,78 ----
  static int volatile FinalizersDisabled = 0;
  
! /*
!  *    Lock used by the finalizer.
!  */
! static _ILMutex _FinalizerLock;
! 
! /*
!  *    Tells the finalizer to stop spinning.
!  * Note:  You need to signal the finalizer first.
!  */
! static volatile int _FinalizerStopFlag = 0;
! 
! /*
!  *    The finalizer thread.
!  */
! static ILThread * volatile _FinalizerThread = 0;
! 
! /*
!  *    Flag that determines whether the finalizer has started or not.
!  */
! static volatile int _FinalizerThreadStarted = 0;
! 
! /*
!  *    WaitEvent that wakes up the finalizer thread.
!  */
! static ILWaitHandle *_FinalizerSignal = 0;
  
+ /*
+  *    WaitEvent that wakes up threads waiting on finalizers.
+  */
+ static ILWaitHandle *_FinalizerResponse = 0;
+ 
+ /*
+  *    Tracing macros for the GC.
+  */
  #ifdef GC_TRACE_ENABLE
        #define GC_TRACE(a, b)          printf(a, b)
***************
*** 54,92 ****
   *    Main entry point for the finalizer thread.
   */
! static void FinalizerThreadFunc(void *data)
  {
!       GC_TRACE("GC:FinalizerThread: Finalizer thread started [thread:%d]\n", 
(int)ILThreadSelf());
  
        for (;;)
        {
!               ILWaitOne(g_FinalizerSignal, -1);
  
!               GC_TRACE("GC:FinalizerThread: Signal [thread:%d]\n", 
(int)ILThreadSelf());
  
                if (GC_should_invoke_finalizers())
                {
!                       GC_TRACE("GC:FinalizerThread: Finalizers running 
[thread:%d]\n", (int)ILThreadSelf());
  
                        GC_invoke_finalizers();
  
!                       GC_TRACE("GC:FinalizerThread: Finalizers finished 
[thread:%d]\n", (int)ILThreadSelf());
                }
                
!               if (g_Deinit)
                {
                        /* Exit finalizer thread after having invoked 
finalizers one last time */
  
!                       GC_TRACE("GC:FinalizerThread: Finalizer thread finished 
[thread:%d]\n", (int)ILThreadSelf());
  
!                       ILWaitEventReset(g_FinalizerSignal);
!                       ILWaitEventSet(g_FinalizerResponse);
                        
                        return;
                }
  
!               GC_TRACE("GC:FinalizerThread: Response [thread:%d]\n", 
(int)ILThreadSelf());
  
!               ILWaitEventReset(g_FinalizerSignal);
!               ILWaitEventSet(g_FinalizerResponse);
        }
  }
--- 84,152 ----
   *    Main entry point for the finalizer thread.
   */
! static void _FinalizerThreadFunc(void *data)
  {
!       GC_TRACE("GC:_FinalizerThread: Finalizer thread started [thread:%d]\n", 
(int)ILThreadSelf());
  
        for (;;)
        {
!               ILWaitOne(_FinalizerSignal, -1);
  
!               GC_TRACE("GC:_FinalizerThread: Signal [thread:%d]\n", 
(int)ILThreadSelf());
  
                if (GC_should_invoke_finalizers())
                {
!                       GC_TRACE("GC:_FinalizerThread: Finalizers running 
[thread:%d]\n", (int)ILThreadSelf());
  
                        GC_invoke_finalizers();
  
!                       GC_TRACE("GC:_FinalizerThread: Finalizers finished 
[thread:%d]\n", (int)ILThreadSelf());
                }
                
!               if (_FinalizerStopFlag)
                {
                        /* Exit finalizer thread after having invoked 
finalizers one last time */
  
!                       GC_TRACE("GC:_FinalizerThread: Finalizer thread 
finished [thread:%d]\n", (int)ILThreadSelf());
  
!                       ILWaitEventReset(_FinalizerSignal);
!                       ILWaitEventSet(_FinalizerResponse);
                        
                        return;
                }
  
!               GC_TRACE("GC:_FinalizerThread: Response [thread:%d]\n", 
(int)ILThreadSelf());
! 
!               ILWaitEventReset(_FinalizerSignal);
!               ILWaitEventSet(_FinalizerResponse);
!       }
! }
! 
! /*
!  *    Resolves the situation where a finalizer thread can't be created or 
started.
!  * Returns 0 if the situation couldn't be resolved.
!  */
! static int Resolve_FinalizerThreadCantRun()
! {
!       long fg, bg;
! 
!       ILThreadGetCounts(&fg, &bg);
! 
!       if (fg + bg > 1)
!       {
!               /* Threads are supported and there are other threads active */
!               /* Can't be resolved without potentially causing a deadlock 
down the road */
! 
!               return 0;
!       }
!       else
!       {
!               /* Threads are supported and there are no other threads active
!                   Can invoke the finalizers synchronously.
!                       Note: Since this is the only thread, no other threads 
can be started
!                       so safety is assured */
! 
!               GC_invoke_finalizers();
  
!               return 1;
        }
  }
***************
*** 97,114 ****
  static int PrivateGCNotifyFinalize(int timeout)
  {
!       ILExecThread *thread;
! 
!       if (FinalizersDisabled || g_FinalizerThread == 0)
        {
                return 0;
        }
        
!       if (!ILHasThreads())
        {
                GC_invoke_finalizers();
                return 1;
        }
        
!       if (ILThreadSelf() == g_FinalizerThread)
        {
                /* Finalizer thread can't recursively call finalizers */
--- 157,181 ----
  static int PrivateGCNotifyFinalize(int timeout)
  {
!       if (FinalizersDisabled)
        {
                return 0;
        }
        
!       /* If threading isn't supported then invoke the finalizers 
synchronously */
! 
!       if (!ILHasThreads() || _FinalizerThread == 0)
        {
                GC_invoke_finalizers();
+ 
                return 1;
        }
+ 
+       /* Threads are supported but there is no finalizer thread! */
+       if (_FinalizerThread == 0)
+       {
+               return Resolve_FinalizerThreadCantRun();                
+       }
        
!       if (ILThreadSelf() == _FinalizerThread)
        {
                /* Finalizer thread can't recursively call finalizers */
***************
*** 117,151 ****
        }
  
!       /* Register the finalizer thread for managed code execution */
!       ILThreadAtomicStart();
  
!       if (ILThreadGetObject(g_FinalizerThread) == 0)
!       {                       
!               /* Make sure the the finalizer thread is registered for managed 
execution. */
!               /* This can't be done in ILGCInit cause the runtime isn't fully 
initialized in that function */
! 
!               thread = (ILExecThread *)ILThreadGetObject(ILThreadSelf());
                
!               if (thread != 0)
                {
!                       
ILThreadRegisterForManagedExecution(ILExecThreadGetProcess(thread), 
g_FinalizerThread);
!               }
!               else
!               {
!                       /* The thread calling finalize isn't managed */
!                       /* Finalizers for managed objects won't work properly */
                }
-       }
  
!       ILThreadAtomicEnd();
  
        /* Signal the finalizer thread */
  
!       ILWaitEventSet(g_FinalizerSignal);
  
        GC_TRACE("ILGCInvokeFinalizers: Invoked finalizers and waiting [thread: 
%d]\n", (int)ILThreadSelf());
                
        /* Wait until finalizers have finished */
!       ILWaitOne(g_FinalizerResponse, timeout);
        
        GC_TRACE("ILGCInvokeFinalizers: Finalizers finished[thread: %d]\n", 
(int)ILThreadSelf());
--- 184,220 ----
        }
  
!       /* Start the finalizer thread if it hasn't been started */
  
!       if (!_FinalizerThreadStarted)
!       {
!               _ILMutexLock(&_FinalizerLock);
                
!               if (!_FinalizerThreadStarted)
                {
!                       if (ILThreadStart(_FinalizerThread) == 0)
!                       {
!                               /* Couldn't create the finalizer thread */
! 
!                               GC_TRACE("ILGCInvokeFinalizers: Couldn't start 
finalizer thread [thread: %d]\n", (int)ILThreadSelf());
!                               
!                               _ILMutexUnlock(&_FinalizerLock);
! 
!                               return Resolve_FinalizerThreadCantRun();
!                       }
! 
!                       _FinalizerThreadStarted = 1;
                }
  
!               _ILMutexUnlock(&_FinalizerLock);
!       }
  
        /* Signal the finalizer thread */
  
!       ILWaitEventSet(_FinalizerSignal);
  
        GC_TRACE("ILGCInvokeFinalizers: Invoked finalizers and waiting [thread: 
%d]\n", (int)ILThreadSelf());
                
        /* Wait until finalizers have finished */
!       ILWaitOne(_FinalizerResponse, timeout);
        
        GC_TRACE("ILGCInvokeFinalizers: Finalizers finished[thread: %d]\n", 
(int)ILThreadSelf());
***************
*** 154,157 ****
--- 223,229 ----
  }
  
+ /*
+  *    Called by the GC when it needs to run finalizers.
+  */
  static void GCNotifyFinalize(void)
  {
***************
*** 171,186 ****
        FinalizersDisabled = 0;
  
        /* Create the finalizer thread */
!       g_Deinit = 0;
!       g_GcLock = ILMutexCreate();
!       g_FinalizerThread = ILThreadCreate(FinalizerThreadFunc, 0);
        
!       if (g_FinalizerThread)
        {
!               g_FinalizerSignal = ILWaitEventCreate(1, 0);
!               g_FinalizerResponse = ILWaitEventCreate(1, 0);
  
!               ILThreadStart(g_FinalizerThread);
!               ILThreadSetBackground(g_FinalizerThread, 1);
        }
  }
--- 243,262 ----
        FinalizersDisabled = 0;
  
+       _ILMutexCreate(&_FinalizerLock);
+ 
        /* Create the finalizer thread */
!       _FinalizerStopFlag = 0; 
!       _FinalizerThread = ILThreadCreate(_FinalizerThreadFunc, 0);
        
!       if (_FinalizerThread)
        {
!               _FinalizerSignal = ILWaitEventCreate(1, 0);
!               _FinalizerResponse = ILWaitEventCreate(1, 0);
  
!               /* Make the thread a background thread */
!               ILThreadSetBackground(_FinalizerThread, 1);
! 
!               /* To speed up simple command line apps, the finalizer thread 
doesn't start
!                   until it is first needed */
        }
  }
***************
*** 188,192 ****
  void ILGCDeinit()
  {
!       g_Deinit = 1;
  
        GC_TRACE("ILGCDeinit: Performing final GC [thread:%d]\n", 
(int)ILThreadSelf());
--- 264,268 ----
  void ILGCDeinit()
  {
!       _FinalizerStopFlag = 1;
  
        GC_TRACE("ILGCDeinit: Performing final GC [thread:%d]\n", 
(int)ILThreadSelf());
***************
*** 198,215 ****
  
        /* Wait up to 10 seconds for the finalizers to run */           
!       PrivateGCNotifyFinalize(10000);
! 
        /* Cleanup the finalizer thread */
!       if (g_FinalizerThread)
        {
                GC_TRACE("ILGCDeinit: Waiting for finalizer thread to end 
[thread:%d]\n", (int)ILThreadSelf());
  
                /* Unregister and destroy the finalizer thread if it's 
responding */
!               if (ILThreadJoin(g_FinalizerThread, 1000))
                {
!                       GC_TRACE("ILGCDeinit: Finalizer thread finished 
[thread:%d]\n", (int)ILThreadSelf());
! 
!                       
ILThreadUnregisterForManagedExecution(g_FinalizerThread);
!                       ILThreadDestroy(g_FinalizerThread);                     
                }
                else
--- 274,291 ----
  
        /* Wait up to 10 seconds for the finalizers to run */           
!       if (GC_should_invoke_finalizers())
!       {
!               PrivateGCNotifyFinalize(10000);
!       }
!       
        /* Cleanup the finalizer thread */
!       if (_FinalizerThread && _FinalizerThreadStarted)
        {
                GC_TRACE("ILGCDeinit: Waiting for finalizer thread to end 
[thread:%d]\n", (int)ILThreadSelf());
  
                /* Unregister and destroy the finalizer thread if it's 
responding */
!               if (ILThreadJoin(_FinalizerThread, 1000))
                {
!                       GC_TRACE("ILGCDeinit: Finalizer thread finished 
[thread:%d]\n", (int)ILThreadSelf());                   
                }
                else
***************
*** 217,223 ****
                        GC_TRACE("ILGCDeinit: Finalizer thread not responding 
[thread:%d]\n", (int)ILThreadSelf());
                }
        }
  
!       ILMutexDestroy(g_GcLock);
  }
  
--- 293,301 ----
                        GC_TRACE("ILGCDeinit: Finalizer thread not responding 
[thread:%d]\n", (int)ILThreadSelf());
                }
+ 
+               ILThreadDestroy(_FinalizerThread);                      
        }
  
!       _ILMutexDestroy(&_FinalizerLock);
  }
  

Index: thread.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/thread.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -r1.12 -r1.13
*** thread.c    7 Jul 2003 19:44:05 -0000       1.12
--- thread.c    8 Jul 2003 12:05:17 -0000       1.13
***************
*** 96,100 ****
  void ThreadDeinit(void)
  {
!       if (foregroundThreadsFinished != 0)
        {
                ILWaitHandleClose(foregroundThreadsFinished);
--- 96,100 ----
  void ThreadDeinit(void)
  {
!       if(foregroundThreadsFinished != 0)
        {
                ILWaitHandleClose(foregroundThreadsFinished);
***************
*** 115,118 ****
--- 115,119 ----
  {
        int isbg;
+       ILThreadCleanupEntry *entry, *next;
  
        /* If we still have a startup function, then execute it.
***************
*** 131,134 ****
--- 132,151 ----
        _ILMutexUnlock(&(thread->lock));
  
+       /* Notify and remove the cleanup handlers */
+ 
+       entry = thread->firstCleanupEntry;
+ 
+       while (entry)
+       {
+               /* Call the cleanup function */
+               entry->cleanup(thread);
+               next = entry->next;
+ 
+               /* Free the entry */
+               ILFree(entry);
+ 
+               entry = next;
+       }
+ 
        /* Update the thread counts */
        _ILMutexLock(&threadLockAll);
***************
*** 169,172 ****
--- 186,191 ----
        thread->suspendRequested = 0;
        thread->numLocksHeld = 0;
+       thread->firstCleanupEntry = 0;
+       thread->lastCleanupEntry = 0;
        _ILSemaphoreCreate(&(thread->resumeAck));
        _ILSemaphoreCreate(&(thread->suspendAck));
***************
*** 214,218 ****
                                setting it again (which normally happens at the 
end of _ILThreadRun) */
  
!                       if (((thread->state & IL_TS_BACKGROUND) == 0))
                        {
                                ILWaitEventReset(foregroundThreadsFinished);
--- 233,237 ----
                                setting it again (which normally happens at the 
end of _ILThreadRun) */
  
!                       if(((thread->state & IL_TS_BACKGROUND) == 0))
                        {
                                ILWaitEventReset(foregroundThreadsFinished);
***************
*** 254,258 ****
  
                /* Only terminate the system thread if one was created */
!               if ((thread->state & IL_TS_UNSTARTED) == 0)
                {
                        _ILThreadTerminate(thread);
--- 273,277 ----
  
                /* Only terminate the system thread if one was created */
!               if((thread->state & IL_TS_UNSTARTED) == 0)
                {
                        _ILThreadTerminate(thread);
***************
*** 267,271 ****
  
        /* Only destroy the system thread if one was created */
!       if ((thread->state & IL_TS_UNSTARTED) == 0)
        {
                _ILThreadDestroy(thread);
--- 286,290 ----
  
        /* Only destroy the system thread if one was created */
!       if((thread->state & IL_TS_UNSTARTED) == 0)
        {
                _ILThreadDestroy(thread);
***************
*** 291,295 ****
        /* If there are no more foreground threads (except the main one) then 
set
                the event that signals that state */
!       if (numThreads - numBackgroundThreads == 1)
        {
                ILWaitEventSet(foregroundThreadsFinished);
--- 310,314 ----
        /* If there are no more foreground threads (except the main one) then 
set
                the event that signals that state */
!       if(numThreads - numBackgroundThreads == 1)
        {
                ILWaitEventSet(foregroundThreadsFinished);
***************
*** 705,709 ****
        /* If there are no more foreground threads (except the main one) then 
set
                the event that signals that state */
!       if (numThreads - numBackgroundThreads == 1)
        {
                ILWaitEventSet(foregroundThreadsFinished);
--- 724,728 ----
        /* If there are no more foreground threads (except the main one) then 
set
                the event that signals that state */
!       if(numThreads - numBackgroundThreads == 1)
        {
                ILWaitEventSet(foregroundThreadsFinished);
***************
*** 834,837 ****
--- 853,980 ----
        ILWaitOne(foregroundThreadsFinished, timeout);
  #endif
+ }
+ 
+ int ILThreadRegisterCleanup(ILThread *thread, ILThreadCleanupFunc func)
+ {
+       ILThreadCleanupEntry *entry;
+ 
+       _ILMutexLock(&(thread->lock));
+ 
+       if((thread->state & IL_TS_STOPPED))
+       {
+               /* Thread has stopped */
+ 
+               _ILMutexUnlock(&(thread->lock));
+ 
+               return -1;
+       }
+ 
+       entry = thread->firstCleanupEntry;
+ 
+       while(entry)
+       {
+               if(entry->cleanup == func)
+               {
+                       /* Function already registered */
+ 
+                       _ILMutexUnlock(&(thread->lock));
+ 
+                       return -1;
+               }
+       }
+ 
+       if((entry = (ILThreadCleanupEntry 
*)ILMalloc(sizeof(ILThreadCleanupEntry))) == 0)
+       {
+               /* Out of memory */
+ 
+               _ILMutexUnlock(&(thread->lock));
+ 
+               return -1;
+       }
+ 
+       entry->cleanup = func;
+       entry->next = 0;
+ 
+       /* Add the entry to the end up the cleanup list */
+ 
+       if(thread->lastCleanupEntry)
+       {
+               thread->lastCleanupEntry->next = entry;
+               thread->lastCleanupEntry = entry;
+       }
+       else
+       {
+               thread->firstCleanupEntry = thread->lastCleanupEntry = entry;
+       }
+ 
+       _ILMutexUnlock(&(thread->lock));
+       
+       return 0;
+ }
+ 
+ int ILThreadUnregisterCleanup(ILThread *thread, ILThreadCleanupFunc func)
+ {
+       ILThreadCleanupEntry *entry, *prev;
+ 
+       _ILMutexLock(&(thread->lock));
+ 
+       if((thread->state & IL_TS_STOPPED))
+       {
+               /* Thread has stopped */
+ 
+               _ILMutexUnlock(&(thread->lock));
+ 
+               return -1;
+       }
+ 
+       /* Walk the list and remove the cleanup function */
+ 
+       prev = 0;
+       entry = thread->firstCleanupEntry;
+ 
+       while(entry)
+       {
+               if(entry->cleanup == func)
+               {
+                       /* Remove the entry from the list */
+ 
+                       if(prev)
+                       {
+                               /* Entry is in the tail of the list */
+ 
+                               prev->next = entry->next;
+ 
+                               if(prev->next == 0)
+                               {
+                                       thread->lastCleanupEntry = prev;
+                               }
+ 
+                               ILFree(entry);
+                       }
+                       else
+                       {
+                               /* Entry is in the head of the list */
+ 
+                               thread->firstCleanupEntry = entry->next;
+                               
+                               if(thread->firstCleanupEntry == 0)
+                               {
+                                       thread->lastCleanupEntry = 0;
+                               }
+                       }
+ 
+                       _ILMutexUnlock(&(thread->lock));
+ 
+                       /* Found and removed */
+ 
+                       return 0;
+               }
+       }
+ 
+       _ILMutexUnlock(&(thread->lock));
+ 
+       /* Not found */
+ 
+       return -1;
  }
  





reply via email to

[Prev in Thread] Current Thread [Next in Thread]