[Top][All Lists]
[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;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnet/support hb_gc.c,1.18,1.19 thread.c,1.12,1.13,
Thong Nguyen <address@hidden> <=
- Prev by Date:
[Dotgnu-pnet-commits] CVS: pnet ChangeLog,1.2529,1.2530
- Next by Date:
[Dotgnu-pnet-commits] CVS: pnet/engine heap.c,1.18,1.19 engine.h,1.80,1.81 process.c,1.50,1.51
- Previous by thread:
[Dotgnu-pnet-commits] CVS: pnet ChangeLog,1.2529,1.2530
- Next by thread:
[Dotgnu-pnet-commits] CVS: pnet/engine heap.c,1.18,1.19 engine.h,1.80,1.81 process.c,1.50,1.51
- Index(es):