[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] CVS: pnet/engine engine.h, 1.82, 1.83 heap.c, 1.19
From: |
Thong Nguyen <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] CVS: pnet/engine engine.h, 1.82, 1.83 heap.c, 1.19, 1.20 ilrun.c, 1.36, 1.37 lib_thread.c, 1.18, 1.19 monitor.c, 1.3, 1.4 process.c, 1.53, 1.54 thread.c, 1.21, 1.22 throw.c, 1.6, 1.7 |
Date: |
Tue, 15 Jul 2003 18:17:35 -0400 |
Update of /cvsroot/dotgnu-pnet/pnet/engine
In directory subversions:/tmp/cvs-serv24211/engine
Modified Files:
engine.h heap.c ilrun.c lib_thread.c monitor.c process.c
thread.c throw.c
Log Message:
Various updates to threading & finalization
Index: engine.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/engine.h,v
retrieving revision 1.82
retrieving revision 1.83
diff -C2 -r1.82 -r1.83
*** engine.h 13 Jul 2003 12:41:01 -0000 1.82
--- engine.h 15 Jul 2003 22:17:33 -0000 1.83
***************
*** 85,88 ****
--- 85,102 ----
/*
+ * Passed to objects when they are finalized. Objects being finalized
should
+ * verify the information in the context valid before continuuing finalization
+ * because it is possible for objects to be finalized *long* after their owner
+ * process has been destroyed.
+ */
+ typedef struct __tagILFinalizationContext ILFinalizationContext;
+ struct __tagILFinalizationContext
+ {
+ /* The process that created the object and registered the finalizer or 0
+ if that process has been destroyed. */
+ ILExecProcess *volatile process;
+ };
+
+ /*
* Execution control context for a process.
*/
***************
*** 98,101 ****
--- 112,118 ----
ILExecThread *mainThread;
+ /* The finalizer thread for the process */
+ ILExecThread *finalizerThread;
+
/* Default stack size for new threads */
ILUInt32 stackSize;
***************
*** 119,122 ****
--- 136,140 ----
ILClass *exceptionClass;
ILClass *clrTypeClass;
+ ILClass *threadAbortClass;
/* The object to throw when the system runs out of memory */
***************
*** 138,141 ****
--- 156,162 ----
#endif
+ /* Finalization context used by this process */
+ ILFinalizationContext *finalizationContext;
+
/* Hash table that maps program items to reflection objects */
void *reflectionHash;
***************
*** 228,231 ****
--- 249,255 ----
ILObject *thrownException;
+ /* Indicates if an abort is in progress */
+ int aborting;
+
/* Security manager in use by this thread */
ILObject *securityManager;
***************
*** 652,655 ****
--- 676,699 ----
*/
ILObject *_ILGetCurrentClrThread(ILExecThread *thread);
+
+ /*
+ * Makes the given support thread execute in the context of the given
engine thread.
+ */
+ void _ILThreadExecuteOn(ILThread *thread, ILExecThread *execThread);
+
+ /*
+ * Throws a thread abort exception on the given thread.
+ */
+ void _ILExecThreadThrowThreadAbortException(ILExecThread *thread, ILObject
*stateInfo);
+
+ /*
+ * Aborts the current thread.
+ */
+ void _ILAbortThread(ILExecThread *thread);
+
+ /*
+ * Handles thread aborts & interruption.
+ */
+ void _ILHandleWaitResult(ILExecThread *thread, int result);
/*
Index: heap.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/heap.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -r1.19 -r1.20
*** heap.c 8 Jul 2003 12:05:17 -0000 1.19
--- heap.c 15 Jul 2003 22:17:33 -0000 1.20
***************
*** 26,32 ****
#endif
- /* TODO: Design a better way to access the main executing process */
- static ILExecProcess *mainProcess;
-
/*
* Initialize a class.
--- 26,29 ----
***************
*** 34,40 ****
static int InitializeClass(ILExecThread *thread, ILClass *classInfo)
{
- /* Cache the main process needed by finalizers */
- mainProcess = thread->process;
-
/* Quick check to see if the class is already laid out,
to avoid acquiring the metadata lock if possible */
--- 31,34 ----
***************
*** 68,80 ****
}
! /*
! * Cleanup handler that is attached to the finalizer thread so that it
unregisters
! * itself upon closing.
! */
! static void DeregisterFinalizerThreadForManagedExecution(ILThread *thread)
! {
! ILThreadUnregisterForManagedExecution(thread);
! }
!
void _ILFinalizeObject(void *block, void *data)
{
--- 62,66 ----
}
! /* This method assumes there is only one finalizer thread for the entire os
process */
void _ILFinalizeObject(void *block, void *data)
{
***************
*** 83,128 ****
ILMethod *method;
ILType *signature;
ILExecThread *execThread;
/* Skip the object header within the block */
object = GetObjectFromGcBase(block);
! /* Get the object's class and locate the "Finalize" method */
! classInfo = GetObjectClass(object);
!
! execThread = ILExecThreadCurrent();
! if (execThread == 0)
{
! ILThread *thread;
! /* The thread the finalizer isn't registered for managed
execution */
! /* Register the thread to execute managed code */
! thread = ILThreadSelf();
! if (!mainProcess)
! {
! /* Impossible state */
! /* Finalizer on an object called before an object was
allocated */
! return;
! }
! if ((execThread =
ILThreadRegisterForManagedExecution(mainProcess, thread)) == 0)
{
- /* Registering for managed execution failed */
-
return;
}
! /* Register a cleanup handler that will deregister the thread
from the engine
! when it finishes */
! ILThreadRegisterCleanup(thread,
DeregisterFinalizerThreadForManagedExecution);
!
! /* Mark the thread as a finalizer thread */
! execThread->isFinalizerThread = 1;
}
!
while(classInfo != 0)
{
--- 69,121 ----
ILMethod *method;
ILType *signature;
+ ILThread *thread;
+ ILExecProcess *process;
ILExecThread *execThread;
+ ILFinalizationContext *finalizationContext;
+ /* Get the finalization context */
+ finalizationContext = (ILFinalizationContext *)data;
+
/* Skip the object header within the block */
object = GetObjectFromGcBase(block);
! /* Get the process that created the object */
! process = finalizationContext->process;
! /* Make sure the process is still alive */
! if (process == 0)
{
! /* Our owner process died. We're orphaned and can't finalize */
! return;
! }
! /* Get the engine thread to execute the finalizer on */
! execThread = process->finalizerThread;
! /* Get the finalizer thread instance */
! thread = ILThreadSelf();
! if (execThread == 0)
! {
! /* Create a new engine thread for the finalizers of this
process to run on */
! execThread = _ILExecThreadCreate(process);
! if (execThread == 0)
{
return;
}
! execThread->supportThread = thread;
! process->finalizerThread = execThread;
}
!
! /* Make the finalizer thread execute in the context of the object's
process's
! finalizer thread */
! _ILThreadExecuteOn(thread, execThread);
!
! /* Get the object's class and locate the "Finalize" method */
! classInfo = GetObjectClass(object);
!
while(classInfo != 0)
{
***************
*** 150,153 ****
--- 143,151 ----
classInfo = ILClassGetParent(classInfo);
}
+
+ execThread->supportThread = 0;
+
+ /* Make sure the finalizer thread can no longer execute managed code */
+ _ILThreadExecuteOn(thread, 0);
}
***************
*** 190,194 ****
((ILClassPrivate *)(classInfo->userData))->hasFinalizer)
{
! ILGCRegisterFinalizer(ptr, _ILFinalizeObject, 0);
}
--- 188,192 ----
((ILClassPrivate *)(classInfo->userData))->hasFinalizer)
{
! ILGCRegisterFinalizer(ptr, _ILFinalizeObject,
thread->process->finalizationContext);
}
***************
*** 235,239 ****
((ILClassPrivate *)(classInfo->userData))->hasFinalizer)
{
! ILGCRegisterFinalizer(ptr, _ILFinalizeObject, 0);
}
--- 233,237 ----
((ILClassPrivate *)(classInfo->userData))->hasFinalizer)
{
! ILGCRegisterFinalizer(ptr, _ILFinalizeObject,
thread->process->finalizationContext);
}
Index: ilrun.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/ilrun.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -r1.36 -r1.37
*** ilrun.c 8 Jul 2003 04:11:14 -0000 1.36
--- ilrun.c 15 Jul 2003 22:17:33 -0000 1.37
***************
*** 442,448 ****
}
! /* Wait for all other foreground threads to finish */
ILThreadWaitForForegroundThreads(-1);
!
#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
/* Print profile information if requested */
--- 442,448 ----
}
! /* Wait for all foreground threads to finish */
ILThreadWaitForForegroundThreads(-1);
!
#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
/* Print profile information if requested */
***************
*** 489,492 ****
--- 489,493 ----
error = ILExecProcessGetStatus(process);
ILExecProcessDestroy(process);
+ ILExecDeinit();
return (int)retval;
Index: lib_thread.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/lib_thread.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -r1.18 -r1.19
*** lib_thread.c 7 Jul 2003 16:00:59 -0000 1.18
--- lib_thread.c 15 Jul 2003 22:17:33 -0000 1.19
***************
*** 1,3 ****
-
/*
* lib_thread.c - Internalcall methods for "System.Threading.*".
--- 1,2 ----
***************
*** 40,44 ****
* Timeout value the managed WaitHandle uses.
*/
! #define WIN32_WAIT_TIMEOUT (258L)
/*
--- 39,43 ----
* Timeout value the managed WaitHandle uses.
*/
! #define IL_CLR_WAIT_TIMEOUT (258L)
/*
***************
*** 48,61 ****
/*
- * Cache of the System.Threading.ThreadStart.Invoke() method.
- */
- static ILMethod *c_ThreadStartInvokeMethod = NULL;
-
- /*
- * Predeclartion of code that handles thread aborts & interruption.
- */
- static void HandleWaitResult(ILExecThread *thread, int result);
-
- /*
* public static void Enter(Object obj);
*/
--- 47,50 ----
***************
*** 80,84 ****
{
break;
! }
}
}
--- 69,73 ----
{
break;
! }
}
}
***************
*** 103,108 ****
* lockword.
*/
! static int _IL_Monitor_CheckAndReturnMonitorToFreeList(ILExecThread *thread,
ILExecMonitor *monitor, volatile ILObject *obj)
! {
if(monitor->waiters == 0 &&
ILWaitMonitorCanClose(monitor->supportMonitor))
{
--- 92,103 ----
* lockword.
*/
! static void _IL_Monitor_CheckAndReturnMonitorToFreeList(ILExecThread *thread,
ILExecMonitor *monitor, volatile ILObject *obj)
! {
! if (monitor == 0)
! {
! /* The monitor has already been claimed by another thread */
! return;
! }
!
if(monitor->waiters == 0 &&
ILWaitMonitorCanClose(monitor->supportMonitor))
{
***************
*** 111,115 ****
/* Remove the monitor from the object if the object hasn't been
assigned
a new monitor */
! current = CompareAndExchangeObjectLockWord(thread, obj, 0,
IL_LW_MARK(monitor));
if(current == IL_LW_MARK(monitor))
--- 106,110 ----
/* Remove the monitor from the object if the object hasn't been
assigned
a new monitor */
! current = CompareAndExchangeObjectLockWord(thread, obj,
IL_LW_MARK(0), IL_LW_MARK(monitor));
if(current == IL_LW_MARK(monitor))
***************
*** 129,137 ****
has already been claimed as as free by another
thread */
}
-
- return 1;
}
-
- return 0;
}
--- 124,128 ----
***************
*** 221,227 ****
monitor->next = thread->freeMonitor;
thread->freeMonitor = monitor;
! }
! HandleWaitResult(thread, result);
return 0;
--- 212,218 ----
monitor->next = thread->freeMonitor;
thread->freeMonitor = monitor;
! }
! _ILHandleWaitResult(thread, result);
return 0;
***************
*** 234,238 ****
/* Finally allow other threads to enter the monitor */
_IL_ObjectLockword_Unmark(thread, obj);
!
return 1;
}
--- 225,229 ----
/* Finally allow other threads to enter the monitor */
_IL_ObjectLockword_Unmark(thread, obj);
!
return 1;
}
***************
*** 255,261 ****
disassociate the monitor with the object. */
if (IL_LW_MARKED(lockword))
! {
/* Spin */
-
goto retry;
}
--- 246,256 ----
disassociate the monitor with the object. */
if (IL_LW_MARKED(lockword))
! {
! /* Yeld CPU time while spinning. This appears to speed up
monitors
! but may cause us to never enter the object's monitor, so
threads releasing
! the same monitor will sleep too */
! ILThreadSleep(0);
!
/* Spin */
goto retry;
}
***************
*** 285,288 ****
--- 280,284 ----
_IL_ObjectLockword_Unmark(thread, obj);
+ /* Spin */
goto retry;
}
***************
*** 293,299 ****
/* Try entering the monitor */
result = ILWaitMonitorTryEnter(monitor->supportMonitor, timeout);
!
! _IL_Interlocked_Decrement_Ri(thread, (ILInt32 *)&monitor->waiters);
!
/* Failed or timed out somehow */
if (result != 0)
--- 289,293 ----
/* Try entering the monitor */
result = ILWaitMonitorTryEnter(monitor->supportMonitor, timeout);
!
/* Failed or timed out somehow */
if (result != 0)
***************
*** 311,315 ****
/* Handle ThreadAbort etc */
! HandleWaitResult(thread, result);
}
--- 305,313 ----
/* Handle ThreadAbort etc */
! _ILHandleWaitResult(thread, result);
! }
! else
! {
! _IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
}
***************
*** 322,325 ****
--- 320,324 ----
void _IL_Monitor_Exit(ILExecThread *thread, ILObject *objnv)
{
+ int result;
ILLockWord lockword;
ILExecMonitor *monitor;
***************
*** 335,339 ****
return;
}
!
/* Make sure noone is allowed to change the object's monitor */
_IL_ObjectLockword_WaitAndMark(thread, obj);
--- 334,338 ----
return;
}
!
/* Make sure noone is allowed to change the object's monitor */
_IL_ObjectLockword_WaitAndMark(thread, obj);
***************
*** 349,357 ****
/* Hmm. Can't call Monitor.Exit before Monitor.Enter */
ILExecThreadThrowSystem
(
! thread,
! "System.Threading.SynchronizationLockException",
! "Exception_ThreadNeedsLock"
);
--- 348,358 ----
/* Hmm. Can't call Monitor.Exit before Monitor.Enter */
+ _IL_ObjectLockword_Unmark(thread, obj);
+
ILExecThreadThrowSystem
(
! thread,
!
"System.Threading.SynchronizationLockException",
! "Exception_ThreadNeedsLock"
);
***************
*** 359,381 ****
}
! if (ILWaitMonitorSpeculativeLeave(monitor->supportMonitor) == 1
/* Note: No need to check for aborts on call to leave */)
! {
! if (!_IL_Monitor_CheckAndReturnMonitorToFreeList(thread,
monitor, obj))
{
! /* There are waiters. Unmark the lockword */
! _IL_ObjectLockword_Unmark(thread, obj);
! }
! else
! {
! /* The object's lockword has been cleared. This
implicitly unmarks it */
! }
! ILWaitMonitorCompleteLeave(monitor->supportMonitor);
}
else
{
! /* We don't own the monitor */
!
ILExecThreadThrowSystem
(
--- 360,388 ----
}
! if ((result = ILWaitMonitorSpeculativeLeave(monitor->supportMonitor)) > 0
/* Note: No need to check for aborts on call to leave */)
! {
! _IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
!
! /* There are waiters. Unmark the lockword */
! _IL_ObjectLockword_Unmark(thread, obj);
!
! /* Notify waiting monitors */
! ILWaitMonitorCompleteLeave(monitor->supportMonitor);
!
! if (result != IL_WAIT_LEAVE_STILL_OWNS)
{
! /* If we no longer own the monitor then give up some
CPU time to prevent
! monitor hogging */
! ILThreadSleep(0);
! }
}
else
{
! /* Unmark the lockword */
! _IL_ObjectLockword_Unmark(thread, obj);
!
! /* We don't own the monitor */
ILExecThreadThrowSystem
(
***************
*** 384,390 ****
"Exception_ThreadNeedsLock"
);
-
- /* Unmark the lockword */
- _IL_ObjectLockword_Unmark(thread, obj);
}
}
--- 391,394 ----
***************
*** 419,422 ****
--- 423,427 ----
if (IL_LW_MARKED(lockword))
{
+
/* Spin */
goto retry;
***************
*** 521,524 ****
--- 526,530 ----
_IL_ObjectLockword_Unmark(thread, obj);
+ /* Spin */
goto retry;
}
***************
*** 549,553 ****
--- 555,568 ----
/* Thread doesn't currently own lock */
+ /* Mark the object's lockword */
+ _IL_ObjectLockword_WaitAndMark(thread, obj);
+
+ /* The current thread has exclusive access to the object's
lockword */
+
_IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
+ _IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
+
+ /* Unmark the object's lockword */
+ _IL_ObjectLockword_Unmark(thread, obj);
ILExecThreadThrowSystem
***************
*** 564,568 ****
--- 579,592 ----
/* Successfully waited */
+ /* Mark the object's lockword */
+ _IL_ObjectLockword_WaitAndMark(thread, obj);
+
+ /* The current thread has exclusive access to the object's
lockword */
+
_IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
+ _IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
+
+ /* Unmark the object's lockword */
+ _IL_ObjectLockword_Unmark(thread, obj);
return 1;
***************
*** 573,579 ****
--- 597,611 ----
/* Timed out */
+ /* Mark the object's lockword */
+ _IL_ObjectLockword_WaitAndMark(thread, obj);
+
+ /* The current thread has exclusive access to the object's
lockword */
+
_IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
_IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
+ /* Unmark the object's lockword */
+ _IL_ObjectLockword_Unmark(thread, obj);
+
return 0;
***************
*** 582,588 ****
/* Handle ThreadAbort etc */
_IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
! HandleWaitResult(thread, result);
return 0;
--- 614,629 ----
/* Handle ThreadAbort etc */
+ /* Mark the object's lockword */
+ _IL_ObjectLockword_WaitAndMark(thread, obj);
+
+ /* The current thread has exclusive access to the object's
lockword */
+
_IL_Interlocked_Decrement_Ri(thread, (ILInt32
*)&monitor->waiters);
+ _IL_Monitor_CheckAndReturnMonitorToFreeList(thread, monitor,
obj);
! /* Unmark the object's lockword */
! _IL_ObjectLockword_Unmark(thread, obj);
!
! _ILHandleWaitResult(thread, result);
return 0;
***************
*** 641,645 ****
/* Handle ThreadAbort etc */
! HandleWaitResult(thread, result);
return;
--- 682,686 ----
/* Handle ThreadAbort etc */
! _ILHandleWaitResult(thread, result);
return;
***************
*** 703,707 ****
/* Handle ThreadAbort etc */
! HandleWaitResult(thread, result);
return;
--- 744,748 ----
/* Handle ThreadAbort etc */
! _ILHandleWaitResult(thread, result);
return;
***************
*** 882,897 ****
/* Get the ThreadStart.Invoke method */
!
! if (c_ThreadStartInvokeMethod == NULL)
! {
! method = ILExecThreadLookupMethod(thread,
! "System.Threading.ThreadStart", "Invoke", "(T)V");
!
! c_ThreadStartInvokeMethod = method;
! }
! else
! {
! method = c_ThreadStartInvokeMethod;
! }
/* Invoke the ThreadStart delegate */
--- 923,927 ----
/* Get the ThreadStart.Invoke method */
! method = ILExecThreadLookupMethod(thread,
"System.Threading.ThreadStart", "Invoke", "(T)V");
/* Invoke the ThreadStart delegate */
***************
*** 903,908 ****
ILExecThreadPrintException(thread);
}
-
- ILThreadUnregisterForManagedExecution(thread->supportThread);
}
--- 933,936 ----
***************
*** 970,974 ****
*/
void _IL_Thread_Abort(ILExecThread *thread, ILObject *_this)
! {
ILThreadAbort(((System_Thread *)_this)->privateData);
}
--- 998,1002 ----
*/
void _IL_Thread_Abort(ILExecThread *thread, ILObject *_this)
! {
ILThreadAbort(((System_Thread *)_this)->privateData);
}
***************
*** 1039,1048 ****
case IL_JOIN_ABORTED:
! ILExecThreadThrowSystem
! (
! thread,
! "System.Threading.ThreadAbortException",
! (const char *)0
! );
return 0;
--- 1067,1071 ----
case IL_JOIN_ABORTED:
! _ILAbortThread(thread);
return 0;
***************
*** 1074,1078 ****
void _IL_Thread_ResetAbort(ILExecThread *thread)
{
! if ((ILThreadGetState(thread->supportThread) & IL_TS_ABORT_REQUESTED)
!= 0)
{
/* No abort has been requested */
--- 1097,1101 ----
void _IL_Thread_ResetAbort(ILExecThread *thread)
{
! if (!thread->aborting)
{
/* No abort has been requested */
***************
*** 1084,1088 ****
}
! ILThreadAbortReset();
}
--- 1107,1111 ----
}
! thread->aborting = 0;
}
***************
*** 1152,1161 ****
if (ILThreadStart(supportThread) == 0)
{
! /* Start unsuccessful. Destroy the support & engine
threads */
- ((System_Thread *)_this)->privateData = 0;
ILThreadUnregisterForManagedExecution(supportThread);
! ILThreadDestroy(supportThread);
!
/* Throw an OutOfMemoryException */
--- 1175,1183 ----
if (ILThreadStart(supportThread) == 0)
{
! /* Start unsuccessful. Destroy the engine thread */
! /* The support thread will linger as long as the CLR
thread does */
ILThreadUnregisterForManagedExecution(supportThread);
!
/* Throw an OutOfMemoryException */
***************
*** 1181,1184 ****
--- 1203,1213 ----
ILObject *_this, ILBool value)
{
+ if (ILThreadGetState(((System_Thread *)_this)->privateData) ==
IL_TS_STOPPED)
+ {
+ ILExecThreadThrowSystem(thread,
"System.Threading.ThreadStateException", (const char *)0);
+
+ return;
+ }
+
ILThreadSetBackground(((System_Thread *)_this)->privateData, value);
}
***************
*** 1198,1207 ****
ILExecThreadThrowSystem(thread,
"System.Threading.ThreadStateException", (const char *)0);
! return 1;
}
-
- /* TODO */
! return 2; /* Normal */
}
--- 1227,1234 ----
ILExecThreadThrowSystem(thread,
"System.Threading.ThreadStateException", (const char *)0);
! return 0;
}
! return ILThreadGetPriority(supportThread);
}
***************
*** 1223,1226 ****
--- 1250,1255 ----
return;
}
+
+ ILThreadSetPriority(supportThread, priority);
}
***************
*** 1563,1595 ****
}
/*
* Handle the result from an "ILWait*" function call.
*/
! static void HandleWaitResult(ILExecThread *thread, int result)
{
! if(result == IL_WAIT_INTERRUPTED)
{
! ILExecThreadThrowSystem
! (thread, "System.Threading.ThreadInterruptedException",
! (const char *)0);
! }
! else if(result == IL_WAIT_ABORTED)
! {
! /* Determine if we currently have an abort in progress,
! or if we need to throw a new abort exception */
! if(ILThreadIsAborting())
{
! if(ILThreadAbort(ILThreadSelf()))
! {
! /* Allocate an instance of
"ThreadAbortException" and throw */
! /* TODO */
!
! ILExecThreadThrowSystem
! (
! thread,
!
"System.Threading.ThreadAbortException",
! (const char *)0
! );
! }
}
}
--- 1592,1642 ----
}
+ void _ILAbortThread(ILExecThread *thread)
+ {
+ /* Determine if we currently have an abort in progress,
+ or if we need to throw a new abort exception */
+ if(ILThreadIsAborting())
+ {
+ if(ILThreadAbort(ILThreadSelf()))
+ {
+ /* Allocate an instance of "ThreadAbortException" and
throw */
+
+ ILThreadAbortReset();
+ thread->aborting = 1;
+ _ILExecThreadThrowThreadAbortException(thread, 0);
+ }
+ }
+ }
+
/*
* Handle the result from an "ILWait*" function call.
*/
! void _ILHandleWaitResult(ILExecThread *thread, int result)
{
! switch (result)
{
! case IL_WAIT_INTERRUPTED:
{
! ILExecThreadThrowSystem
! (
! thread,
!
"System.Threading.ThreadInterruptedException",
! (const char *)0
! );
! }
! break;
! case IL_WAIT_ABORTED:
! {
! _ILAbortThread(thread);
! }
! break;
! case IL_WAIT_FAILED:
! {
! ILExecThreadThrowSystem
! (
! thread,
! "System.Threading.SystemException",
! (const char *)0
! );
}
}
***************
*** 1646,1650 ****
if(!(waitHandles->length))
{
! return 1;
}
--- 1693,1697 ----
if(!(waitHandles->length))
{
! return 0;
}
***************
*** 1657,1662 ****
/* Perform the wait */
result = ILWaitAll(handles, (ILUInt32)(waitHandles->length), timeout);
! HandleWaitResult(_thread, result);
! return (result == 0);
}
--- 1704,1722 ----
/* Perform the wait */
result = ILWaitAll(handles, (ILUInt32)(waitHandles->length), timeout);
!
! if (result == IL_WAIT_TIMEOUT)
! {
! return exitContext;
! }
! else if (result < 0)
! {
! _ILHandleWaitResult(_thread, result);
!
! return 0;
! }
! else
! {
! return exitContext;
! }
}
***************
*** 1686,1701 ****
/* Perform the wait */
result = ILWaitAny(handles, (ILUInt32)(waitHandles->length), timeout);
- HandleWaitResult(_thread, result);
- /*return (result == 0);*/
-
- /* Now returns index of the handle that was set and proper timeout
value */
if (result == IL_WAIT_TIMEOUT)
{
! result = WIN32_WAIT_TIMEOUT;
}
else if (result < 0)
{
! /* TODO: FIXME: Docs don't state how to report an error! */
}
--- 1746,1759 ----
/* Perform the wait */
result = ILWaitAny(handles, (ILUInt32)(waitHandles->length), timeout);
if (result == IL_WAIT_TIMEOUT)
{
! result = IL_CLR_WAIT_TIMEOUT;
}
else if (result < 0)
{
! _ILHandleWaitResult(_thread, result);
!
! result = 0;
}
***************
*** 1713,1717 ****
{
int result = ILWaitOne((ILWaitHandle *)privateData, timeout);
! HandleWaitResult(_thread, result);
return (result == 0);
}
--- 1771,1775 ----
{
int result = ILWaitOne((ILWaitHandle *)privateData, timeout);
! _ILHandleWaitResult(_thread, result);
return (result == 0);
}
Index: monitor.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/monitor.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** monitor.c 26 Jun 2003 22:23:35 -0000 1.3
--- monitor.c 15 Jul 2003 22:17:33 -0000 1.4
***************
*** 41,44 ****
--- 41,46 ----
if((monitor->supportMonitor = ILWaitMonitorCreate()) == 0)
{
+ ILFree(monitor);
+
return 0;
}
Index: process.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/process.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -C2 -r1.53 -r1.54
*** process.c 13 Jul 2003 12:41:01 -0000 1.53
--- process.c 15 Jul 2003 22:17:33 -0000 1.54
***************
*** 4,7 ****
--- 4,9 ----
* Copyright (C) 2001 Southern Storm Software, Pty Ltd.
*
+ * Contributions by Thong Nguyen (address@hidden)
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
***************
*** 28,33 ****
void ILExecInit(unsigned long maxSize)
{
- /* Tum changed init order because the GC needs threading support */
-
/* Initialize the thread routines */
ILThreadInit();
--- 30,33 ----
***************
*** 37,40 ****
--- 37,49 ----
}
+ void ILExecDeinit()
+ {
+ /* Deinitialize the global garbage collector */
+ ILGCDeinit();
+
+ /* Deinitialize the thread routines */
+ ILThreadDeinit();
+ }
+
ILExecProcess *ILExecProcessCreate(unsigned long stackSize, unsigned long
cachePageSize)
{
***************
*** 51,54 ****
--- 60,64 ----
process->firstThread = 0;
process->mainThread = 0;
+ process->finalizerThread = 0;
#ifdef USE_HASHING_MONITORS
process->monitorHash = 0;
***************
*** 65,70 ****
process->exceptionClass = 0;
process->clrTypeClass = 0;
! process->outOfMemoryObject = 0;
process->commandLineObject = 0;
ILGetCurrTime(&(process->startTime));
process->internHash = 0;
--- 75,81 ----
process->exceptionClass = 0;
process->clrTypeClass = 0;
! process->outOfMemoryObject = 0;
process->commandLineObject = 0;
+ process->threadAbortClass = 0;
ILGetCurrTime(&(process->startTime));
process->internHash = 0;
***************
*** 95,98 ****
--- 106,112 ----
}
+ /* Associate the process with the context */
+ ILContextSetUserData(process->context, process);
+
/* Initialize the CVM coder */
process->coder = ILCoderCreate(&_ILCVMCoderClass, 100000,
cachePageSize);
***************
*** 121,124 ****
--- 135,148 ----
#endif
+ /* Initialize the finalization context */
+ process->finalizationContext = (ILFinalizationContext
*)ILGCAlloc(sizeof(ILFinalizationContext));
+ if (!process->finalizationContext)
+ {
+ ILExecProcessDestroy(process);
+ return 0;
+ }
+
+ process->finalizationContext->process = process;
+
/* Initialize the metadata lock */
process->metadataLock = ILRWLockCreate();
***************
*** 137,140 ****
--- 161,170 ----
return 0;
}
+
+ /* If threading isn't supported, then the main thread is the finalizer
thread */
+ if (!ILHasThreads())
+ {
+ process->finalizerThread = process->mainThread;
+ }
/* Initialize the random seed pool lock */
***************
*** 150,222 ****
}
void ILExecProcessDestroy(ILExecProcess *process)
{
! ILExecThread *thread, *next;
! ILExecThread *firstFinalizerThread;
! /* Note: All non-finalizer threads have to be destroyed *before*
GCDeinit
! is called so the GC can reclaim & finalize everything on those
threads'
! stacks - Tum */
! /* Wait for all foreground threads to finish */
! ILThreadWaitForForegroundThreads(-1);
!
! /* Delete all non-finalizer threads */
! firstFinalizerThread = 0;
! thread = process->firstThread;
! while (thread)
! {
! next = thread->nextThread;
! /* Add the thread to the finalizer threads list if it is a
finalizer thread */
! if (thread->isFinalizerThread)
{
! if (firstFinalizerThread)
{
! firstFinalizerThread->nextThread = thread;
}
else
{
! firstFinalizerThread = thread;
}
}
- else
- {
- /* The thread isn't a finalizer thread so destroy it to
free up its stack space
- so the finalizer can reclaim everything
- Note: This is threadsafe. There's no way the
finalizer could run on the
- CLR thread while we still hold a reference to
it */
! if (thread->clrThread)
{
! /* Null out the privateData field so the thread
doesn't try to destroy
! the ILThread twice when it finalizes */
! ((System_Thread
*)thread->clrThread)->privateData = 0;
! }
! /* Destroy the support thread */
! ILThreadDestroy(thread->supportThread);
! /* Destroy the engine thread */
! _ILExecThreadDestroy(thread);
}
! thread = next;
}
! /* The only threads left in the process are finalizer threads */
! process->firstThread = firstFinalizerThread;
! /* Tell the GC we're history */
! /* This performs a final collect and finalizer run and also destroy any
finalizer threads */
! ILGCDeinit();
! /* All threads should be destroyed now */
! /* Destroy the CVM coder instance */
! ILCoderDestroy(process->coder);
/* Destroy the metadata lock */
--- 180,373 ----
}
+ typedef struct _tagThreadListEntry ThreadListEntry;
+ struct _tagThreadListEntry
+ {
+ ILThread *thread;
+ ThreadListEntry *next;
+ };
+
void ILExecProcessDestroy(ILExecProcess *process)
{
! int result;
! int mainIsFinalizer = 0;
! ILThread *mainSupportThread;
! ILExecThread *thread, *nextThread;
! ThreadListEntry *firstEntry, *entry, *next;
! if (process->mainThread)
! {
! /* TODO: Stack still contains last frame */
! ILMemZero(process->mainThread->stackBase, sizeof(int));
! }
! /* Delete all managed threads so the objects they used can be
finalizerd */
! /* Keeps deleting managed threads until they're all gone just in case
! threads spawn new threads when they exit */
! for (;;)
! {
! firstEntry = 0;
! /* Lock down the process */
! ILMutexLock(process->lock);
! /* Walk all the threads */
! thread = process->firstThread;
! while (thread)
{
! if (thread != process->finalizerThread &&
! /* Make sure its a managed thread */
! (thread->clrThread || thread ==
process->mainThread)
! && thread->supportThread != ILThreadSelf())
{
! /*
! * Instead of aborting and then waiting on each
thread, we abort all
! * threads and then wait for them all at the
bottom. This prevents us from
! * deadlocking on a thread that's waiting
on another (not yet aborted) thread.
! */
!
! nextThread = thread->nextThread;
!
! entry = ILMalloc(sizeof(ThreadListEntry));
!
! if (!entry)
! {
!
ILExecThreadThrowOutOfMemory(ILExecThreadCurrent());
!
! return;
! }
!
! entry->thread = thread->supportThread;
!
! if (!firstEntry)
! {
! entry->next = 0;
! firstEntry = entry;
! }
! else
! {
! entry->next = firstEntry;
! firstEntry = entry;
! }
!
! /* Abort the thread */
! ILThreadAbort(thread->supportThread);
!
! thread = nextThread;
!
! /* Note: The CLR thread (and thus the support
thread) might still be used
! by another thread so the support thread
is left to be destroyed by the
! CLR thread's finalizer */
}
else
{
! /* Move onto the next thread */
! thread = thread->nextThread;
}
}
! /* Unlock the process */
! ILMutexUnlock(process->lock);
!
! entry = firstEntry;
!
! /*
! * Wait for the threads that have been aborted.
! */
!
! if (entry)
! {
! while (entry)
{
! next = entry->next;
! result = ILThreadJoin(entry->thread, -1);
!
! ILFree(entry);
!
! if (result != 0)
! {
! /* The thread might be aborted while
trying to exit */
!
! entry = next;
! while (entry)
! {
! next = entry->next;
! ILFree(entry);
! entry = next;
! }
!
_ILHandleWaitResult(ILExecThreadCurrent(), result);
!
! return;
! }
!
! entry = next;
! }
}
+ else
+ {
+ break;
+ }
+ }
+
+ mainIsFinalizer = process->mainThread == process->finalizerThread;
+ mainSupportThread = process->mainThread->supportThread;
! /* Destory the engine thread for the main thread if it isn't needed
anymore.
! This isn't strictly necessary but may help remove stray pointers on
the CVM stack */
! /* If the main thread is the finalizer thread, then the engine thread
will be automatically
! destroyed when main thread is destroyed */
! if (!mainIsFinalizer)
! {
!
ILThreadUnregisterForManagedExecution(process->mainThread->supportThread);
}
+
+ /* Invoke the finalizers -- hopefully finalizes all objects left in the
process being destroyed */
+ /* Any objects left lingering (because of a stray or fake pointer) are
orphans */
+ ILGCCollect();
+ ILGCInvokeFinalizers();
+
+ /* We must ensure that objects created and then orphaned by this
process won't
+ finalize themselves from this point on (because the process will no
longer be valid).
+ Objects can be orphaned if we're using a conservative GC like
the Boehm GC */
+
+ /* Disable finalizers to ensure no finalizers are running until we
reenable them */
+ ILGCDisableFinalizers();
+
+ /* Mark the process as dead in the finalization context. This prevents
orphans from
+ finalizing */
+ process->finalizationContext->process = 0;
! /* Reenable finalizers */
! ILGCEnableFinalizers();
! /* Destroy the main thread if we aren't the main thread or the
finalizer thread*/
! if (!mainIsFinalizer && ILThreadSelf() != mainSupportThread)
! {
! /* Abort the thread */
! ILThreadAbort(mainSupportThread);
! /* Wait for the thread to be aborted */
! ILThreadJoin(mainSupportThread, -1);
! /* Destroy the thread object */
! ILThreadDestroy(mainSupportThread);
! }
!
! /* Destroy the finalizer thread */
! if (process->finalizerThread)
! {
! /* Only destroy the engine thread. The support thread is
shared by other
! engine processes and is destroyed when the engine is
deinitialized */
! _ILExecThreadDestroy(process->finalizerThread);
! }
!
! if (process->coder)
! {
! /* Destroy the CVM coder instance */
! ILCoderDestroy(process->coder);
! }
/* Destroy the metadata lock */
***************
*** 232,242 ****
}
! /* Destroy the main part of the intern'ed hash table.
! The rest will be cleaned up by the garbage collector */
! ILGCFreePersistent(process->internHash);
!
! /* Destroy the main part of the reflection hash table.
! The rest will be cleaned up by the garbage collector */
! ILGCFreePersistent(process->reflectionHash);
#ifdef IL_CONFIG_PINVOKE
--- 383,399 ----
}
! if (process->internHash)
! {
! /* Destroy the main part of the intern'ed hash table.
! The rest will be cleaned up by the garbage collector */
! ILGCFreePersistent(process->internHash);
! }
!
! if (process->reflectionHash)
! {
! /* Destroy the main part of the reflection hash table.
! The rest will be cleaned up by the garbage collector */
! ILGCFreePersistent(process->reflectionHash);
! }
#ifdef IL_CONFIG_PINVOKE
***************
*** 282,288 ****
#endif
! /* Destroy the random seed pool */
! ILMutexDestroy(process->randomLock);
! ILMemZero(process->randomPool, sizeof(process->randomPool));
#ifdef USE_HASHING_MONITORS
--- 439,452 ----
#endif
! if (process->randomLock)
! {
! /* Destroy the random seed pool */
! ILMutexDestroy(process->randomLock);
! }
!
! if (process->randomPool)
! {
! ILMemZero(process->randomPool, sizeof(process->randomPool));
! }
#ifdef USE_HASHING_MONITORS
***************
*** 291,302 ****
#endif
! /* Destroy the object lock */
! ILMutexDestroy(process->lock);
/* Free the process block itself */
ILGCFreePersistent(process);
-
- /* Cleanup the threading subsystem */
- ILThreadDeinit();
}
--- 455,466 ----
#endif
! if (process->lock)
! {
! /* Destroy the object lock */
! ILMutexDestroy(process->lock);
! }
/* Free the process block itself */
ILGCFreePersistent(process);
}
***************
*** 328,346 ****
{
/* If this image caused "OutOfMemoryException" to be
! loaded, then create an object based upon it. We must
! allocate this object ahead of time because we won't be
! able to when the system actually runs out of memory */
classInfo = ILClassLookupGlobal(ILImageToContext(image),
!
"OutOfMemoryException", "System");
if(classInfo)
{
/* We don't call the "OutOfMemoryException" constructor,
! to avoid various circularity problems at this stage
! of the loading process */
process->outOfMemoryObject =
_ILEngineAllocObject(process->mainThread,
classInfo);
}
}
!
/* Look for "System.Object" */
if(!(process->objectClass))
--- 492,510 ----
{
/* If this image caused "OutOfMemoryException" to be
! loaded, then create an object based upon it. We must
! allocate this object ahead of time because we won't be
! able to when the system actually runs out of memory */
classInfo = ILClassLookupGlobal(ILImageToContext(image),
! "OutOfMemoryException", "System");
if(classInfo)
{
/* We don't call the "OutOfMemoryException" constructor,
! to avoid various circularity problems at this stage
! of the loading process */
process->outOfMemoryObject =
_ILEngineAllocObject(process->mainThread,
classInfo);
}
}
!
/* Look for "System.Object" */
if(!(process->objectClass))
***************
*** 369,372 ****
--- 533,543 ----
process->clrTypeClass =
ILClassLookupGlobal(ILImageToContext(image),
"ClrType", "System.Reflection");
+ }
+
+ /* Look for "System.Threading.ThreadAbortException" */
+ if(!(process->threadAbortClass))
+ {
+ process->threadAbortClass =
ILClassLookupGlobal(ILImageToContext(image),
+ "ThreadAbortException", "System.Threading");
}
}
Index: thread.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/thread.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -r1.21 -r1.22
*** thread.c 9 Jul 2003 06:58:23 -0000 1.21
--- thread.c 15 Jul 2003 22:17:33 -0000 1.22
***************
*** 70,73 ****
--- 70,89 ----
/*
+ * Makes the given support thread execute in the context of the given
engine thread.
+ */
+ void _ILThreadExecuteOn(ILThread *thread, ILExecThread *execThread)
+ {
+ ILThreadSetObject(thread, execThread);
+ }
+
+ /*
+ * Cleanup handler for threads that have been registered for managed
execution.
+ */
+ static void ILExecThreadCleanup(ILThread *thread)
+ {
+ ILThreadUnregisterForManagedExecution(thread);
+ }
+
+ /*
* Registers a thread for managed execution
*/
***************
*** 76,88 ****
ILExecThread *execThread;
/* Create a new engine-level thread */
! execThread = _ILExecThreadCreate(process);
/* Associate the new engine-level thread with the OS-level thread */
! ILThreadSetObject(thread, execThread);
/* Associate the OS-level thread with the new engine-level thread */
execThread->supportThread = thread;
return execThread;
}
--- 92,116 ----
ILExecThread *execThread;
+ /* If the thread has already been registerered then return the existing
engine thread */
+ if ((execThread = ILThreadGetObject(thread)) != 0)
+ {
+ return execThread;
+ }
+
/* Create a new engine-level thread */
! if ((execThread = _ILExecThreadCreate(process)) == 0)
! {
! return 0;
! }
/* Associate the new engine-level thread with the OS-level thread */
! _ILThreadExecuteOn(thread, execThread);
/* Associate the OS-level thread with the new engine-level thread */
execThread->supportThread = thread;
+ /* Register a cleanup handler for the thread */
+ ILThreadRegisterCleanup(thread, ILExecThreadCleanup);
+
return execThread;
}
***************
*** 95,100 ****
--- 123,142 ----
ILExecThread *execThread;
+ /* Get the engine thread from the support thread */
execThread = ILThreadGetObject(thread);
+ if (execThread == 0)
+ {
+ /* Already unregistered */
+ return;
+ }
+
+ /* Unregister the cleanup handler */
+ ILThreadUnregisterCleanup(thread, ILExecThreadCleanup);
+
+ /* Disassociate the engine thread with the support thread */
+ _ILThreadExecuteOn(thread, 0);
+
+ /* Destroy the engine thread */
_ILExecThreadDestroy(execThread);
}
***************
*** 134,137 ****
--- 176,180 ----
/* Initialize the thread state */
thread->supportThread = 0;
+ thread->aborting = 0;
thread->clrThread = 0;
thread->freeMonitor = 0;
***************
*** 141,145 ****
thread->stackTop = thread->stackBase;
thread->method = 0;
! thread->thrownException = 0;
thread->securityManager = 0;
thread->threadStaticSlots = 0;
--- 184,188 ----
thread->stackTop = thread->stackBase;
thread->method = 0;
! thread->thrownException = 0;
thread->securityManager = 0;
thread->threadStaticSlots = 0;
***************
*** 175,178 ****
--- 218,226 ----
{
process->mainThread = 0;
+ }
+
+ if (process->finalizerThread == thread)
+ {
+ process->finalizerThread = 0;
}
Index: throw.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/throw.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** throw.c 26 Jun 2003 10:34:51 -0000 1.6
--- throw.c 15 Jul 2003 22:17:33 -0000 1.7
***************
*** 191,195 ****
}
}
-
void ILExecThreadThrowOutOfMemory(ILExecThread *thread)
{
--- 191,194 ----
***************
*** 200,203 ****
--- 199,222 ----
}
+ void _ILExecThreadThrowThreadAbortException(ILExecThread *thread, ILObject
*stateInfo)
+ {
+ ILObject *object;
+
+ /* Bail out if there already is a pending exception */
+ if(ILExecThreadHasException(thread))
+ {
+ return;
+ }
+
+ object = ILExecThreadNew(thread,
"System.Threading.ThreadAbortException",
+ "(ToSystem.Object;)V",
stateInfo);
+
+ _ILSetExceptionStackTrace(thread, object);
+ if(!ILExecThreadHasException(thread))
+ {
+ ILExecThreadSetException(thread, object);
+ }
+ }
+
void ILExecThreadPrintException(ILExecThread *thread)
{
***************
*** 229,235 ****
}
/* Attempt to use "ToString" to format the exception, but not
if we know that the exception is reporting out of memory */
! if(exception != thread->process->outOfMemoryObject)
{
str = ILObjectToString(thread, exception);
--- 248,263 ----
}
+ /*
+ * Don't print out ThreadAbortExceptions.
+ */
+
+ if (GetObjectClass(exception) == thread->process->threadAbortClass)
+ {
+ return;
+ }
+
/* Attempt to use "ToString" to format the exception, but not
if we know that the exception is reporting out of memory */
! if(exception != thread->process->outOfMemoryObject)
{
str = ILObjectToString(thread, exception);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnet/engine engine.h, 1.82, 1.83 heap.c, 1.19, 1.20 ilrun.c, 1.36, 1.37 lib_thread.c, 1.18, 1.19 monitor.c, 1.3, 1.4 process.c, 1.53, 1.54 thread.c, 1.21, 1.22 throw.c, 1.6, 1.7,
Thong Nguyen <address@hidden> <=
- Prev by Date:
[Dotgnu-pnet-commits] CVS: pnet/include il_engine.h, 1.40, 1.41 il_image.h, 1.20, 1.21 il_thread.h, 1.15, 1.16
- Next by Date:
[Dotgnu-pnet-commits] CVS: pnet/image context.c, 1.13, 1.14 image.h, 1.29, 1.30
- Previous by thread:
[Dotgnu-pnet-commits] CVS: pnet/include il_engine.h, 1.40, 1.41 il_image.h, 1.20, 1.21 il_thread.h, 1.15, 1.16
- Next by thread:
[Dotgnu-pnet-commits] CVS: pnet/image context.c, 1.13, 1.14 image.h, 1.29, 1.30
- Index(es):