# Patch created by kt # Date: Mon Oct 3 17:18:11 2005 # Repository: pnet # Comments: # #### End of Preamble #### #### Patch data follows #### Index: engine/engine.h =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/engine/engine.h,v retrieving revision 1.105 diff -c -r1.105 engine.h *** engine/engine.h 23 Aug 2005 10:45:52 -0000 1.105 --- engine/engine.h 3 Oct 2005 15:18:37 -0000 *************** *** 166,171 **** --- 166,194 ---- ILExecProcess *volatile process; }; + #ifdef IL_CONFIG_APPDOMAINS + /* + * Structure to save the old execution context of an ILExecThread + * when a process switch occures. + */ + typedef struct _tagILExecContext ILExecContext; + struct _tagILExecContext + { + /* Pointer to the previous exec context */ + ILExecContext *prevContext; + + /* Back-pointer to the process this thread belongs to */ + ILExecProcess *process; + + /* System.Threading.Thread object */ + ILObject *clrThread; + + /* Thread-static values for this thread */ + void **threadStaticSlots; + ILUInt32 threadStaticSlotsUsed; + }; + #endif + /* class private data */ typedef struct _tagILClassPrivate ILClassPrivate; *************** *** 393,398 **** --- 416,427 ---- int profilingEnabled; #endif + #ifdef IL_CONFIG_APPDOMAINS + /* Keep track of the process switches for this thread */ + /* Needed to clean them up when the thread is destroyed. */ + ILExecContext *prevContext; + #endif + #if defined(IL_INTERRUPT_SUPPORTS_ILLEGAL_MEMORY_ACCESS) /* Context for the current interrupt */ ILInterruptContext interruptContext; *************** *** 489,494 **** --- 518,571 ---- * Returns the ILExecEngine or 0 if the function fails. */ ILExecEngine *ILExecEngineCreate(); + + /* + * Let the thread return from an other ILExecProcess and restore the saved + * state. + * Returns 0 on failure. + */ + int ILExecThreadReturnToProcess(ILExecThread *thread, ILExecContext *context); + + /* + * Let the thread join an other ILExecProcess and save the current state + * in context. + * Returns 0 on failure. + */ + int ILExecThreadSwitchToProcess(ILExecThread *thread, + ILExecProcess *process, + ILExecContext *context); + + #define IL_BEGIN_EXECPROCESS_SWITCH(thread, process) \ + { \ + int __processSwitched = 0; \ + int __error = 0; \ + ILExecContext __context; \ + if((thread)->process != (process)) \ + { \ + __processSwitched = ILExecThreadSwitchToProcess((thread), \ + (process), \ + &__context); \ + } \ + if(!__error) \ + { + #define IL_END_EXECPROCESS_SWITCH(thread) \ + if(__processSwitched) \ + { \ + if(!ILExecThreadReturnToProcess((thread), &__context)) \ + { \ + \ + } \ + } \ + } \ + else \ + { \ + } \ + } + #else + #define IL_BEGIN_EXECPROCESS_SWITCH(thread, process) \ + { + #define IL_END_EXECPROCESS_SWITCH(thread) \ + } #endif /* *************** *** 824,829 **** --- 901,912 ---- ILObject *_ILCustomToObject(ILExecThread *thread, void *ptr, const char *customName, int customNameLen, const char *customCookie, int customCookieLen); + + /* + * Get an ILExecThread from the given support thread. + */ + #define _ILExecThreadFromThread(thread) \ + ((ILExecThread *)(ILThreadGetObject(thread))) /* * Gets the managed thread object from an engine thread. Index: engine/pinvoke.c =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/engine/pinvoke.c,v retrieving revision 1.29 diff -c -r1.29 pinvoke.c *** engine/pinvoke.c 1 Oct 2005 18:36:54 -0000 1.29 --- engine/pinvoke.c 3 Oct 2005 15:18:50 -0000 *************** *** 20,25 **** --- 20,26 ---- #include "engine.h" #include "lib_defs.h" + #include "../support/thr_defs.h" #if defined(IL_WIN32_PLATFORM) #include #endif *************** *** 942,987 **** } } /* ! * Invoke a delegate from a closure. */ ! static void DelegateInvoke(ffi_cif *cif, void *result, ! void **args, void *delegate) { - ILExecThread *thread = ILExecThreadCurrent(); ILMethod *method; ILType *type; ILUInt32 size; PackDelegateUserData userData; /* If this is a multicast delegate, then execute "prev" first */ ! if(((System_Delegate *)delegate)->prev) { ! DelegateInvoke(cif, result, args, ! ((System_Delegate *)delegate)->prev); ! if(ILExecThreadHasException(thread)) { return; } } /* Extract the method from the delegate */ ! method = ((System_Delegate *)delegate)->methodInfo; if(!method) { ! ILExecThreadThrowSystem(thread, "System.MissingMethodException", (const char *)0); return; } /* Call the method */ ! userData.args = args; userData.pinvokeInfo = (ILMethod *)ILTypeGetDelegateMethod ! (ILType_FromClass(GetObjectClass(delegate))); userData.needThis = 0; ! if(_ILCallMethod(thread, method, ! UnpackDelegateResult, result, ! 0, ((System_Delegate *)delegate)->target, PackDelegateParams, &userData)) { /* An exception occurred, which is already stored in the thread */ --- 943,1001 ---- } } + typedef struct { + ILExecThread *thread; + ffi_cif *cif; + void *result; + void **args; + System_Delegate *delegate; + } ILDelegateInvokeParams; + /* ! * Do the real delegate invokation. */ ! static void _DelegateInvoke(ILDelegateInvokeParams *params) { ILMethod *method; ILType *type; ILUInt32 size; PackDelegateUserData userData; /* If this is a multicast delegate, then execute "prev" first */ ! if(params->delegate->prev) { ! ILDelegateInvokeParams prevParams; ! ! prevParams.thread = params->thread; ! prevParams.cif = params->cif; ! prevParams.result = params->result; ! prevParams.args = params->args; ! prevParams.delegate = (System_Delegate *)(params->delegate->prev); ! ; ! _DelegateInvoke(&prevParams); ! if(ILExecThreadHasException(params->thread)) { return; } } /* Extract the method from the delegate */ ! method = params->delegate->methodInfo; if(!method) { ! ILExecThreadThrowSystem(params->thread, "System.MissingMethodException", (const char *)0); return; } /* Call the method */ ! userData.args = params->args; userData.pinvokeInfo = (ILMethod *)ILTypeGetDelegateMethod ! (ILType_FromClass(GetObjectClass(params->delegate))); userData.needThis = 0; ! if(_ILCallMethod(params->thread, method, ! UnpackDelegateResult, params->result, ! 0, params->delegate->target, PackDelegateParams, &userData)) { /* An exception occurred, which is already stored in the thread */ *************** *** 991,998 **** { /* Clear the native return value, because we cannot assume that the native caller knows how to handle exceptions */ ! size = ILSizeOfType(thread, type); ! ILMemZero(result, size); } } } --- 1005,1084 ---- { /* Clear the native return value, because we cannot assume that the native caller knows how to handle exceptions */ ! size = ILSizeOfType(params->thread, type); ! ILMemZero(params->result, size); ! } ! } ! } ! ! /* ! * Invoke the delegate from a new thread. ! */ ! static void _DelegateInvokeFromNewThread(void *params) ! { ! ILThread *thread = ILThreadSelf(); ! ILClassPrivate *classPrivate = GetObjectClassPrivate(((ILDelegateInvokeParams *)params)->delegate); ! ILExecProcess *process = classPrivate->process; ! ! if((((ILDelegateInvokeParams *)params)->thread = ILThreadRegisterForManagedExecution(process, thread))) ! { ! _DelegateInvoke((ILDelegateInvokeParams *)params); ! ILThreadUnregisterForManagedExecution(thread); ! } ! } ! ! /* ! * Invoke a delegate from a closure. ! */ ! static void DelegateInvoke(ffi_cif *cif, void *result, ! void **args, void *delegate) ! { ! ILThread *thread = ILThreadSelf(); ! ILClassPrivate *classPrivate = GetObjectClassPrivate(delegate); ! ILExecProcess *process = classPrivate->process; ! ILDelegateInvokeParams params; ! ! params.thread = 0; ! params.cif = cif; ! params.result = result; ! params.args = args; ! params.delegate = (System_Delegate *)delegate; ! if(!thread) ! { ! /* callback was invoked by a non pnet thread. */ ! ! ILThread *callingThread = _ILThreadCreateSelf(); ! ! if(callingThread) ! { ! if((thread = ILThreadCreate(_DelegateInvokeFromNewThread, ¶ms))) ! { ! ILThreadStart(thread); ! ILThreadJoin(thread, -1); ! ILThreadDestroy(thread); ! } ! _ILThreadDestroySelf(callingThread); ! } ! } ! else ! { ! params.thread = _ILExecThreadFromThread(thread); ! ! if(params.thread) ! { ! IL_BEGIN_EXECPROCESS_SWITCH(params.thread, process) ! _DelegateInvoke(¶ms); ! IL_END_EXECPROCESS_SWITCH(params.thread) ! } ! else ! { ! /* thread is not registerd for managed execution */ ! if((params.thread = ILThreadRegisterForManagedExecution(process, thread))) ! { ! ! _DelegateInvoke(¶ms); ! ILThreadUnregisterForManagedExecution(thread); ! } } } } Index: engine/thread.c =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/engine/thread.c,v retrieving revision 1.39 diff -c -r1.39 thread.c *** engine/thread.c 5 May 2005 10:16:16 -0000 1.39 --- engine/thread.c 3 Oct 2005 15:19:00 -0000 *************** *** 29,47 **** #endif /* - * Get an ILExecThread from the given support thread. - */ - static ILExecThread *_ILExecThreadFromThread(ILThread *thread) - { - return (ILExecThread *)(ILThreadGetObject(thread)); - } - - /* * Gets the currently ILExecThread. */ ILExecThread *ILExecThreadCurrent() { ! return _ILExecThreadFromThread(ILThreadSelf()); } /* --- 29,48 ---- #endif /* * Gets the currently ILExecThread. */ ILExecThread *ILExecThreadCurrent() { ! ILThread *thread = ILThreadSelf(); ! ! if(thread) ! { ! return _ILExecThreadFromThread(thread); ! } ! else ! { ! return 0; ! } } /* *************** *** 544,549 **** --- 545,590 ---- return result; } + /* + * Join an ILExecProcess for normal execution. + * The caller has to handle the thread safety and to make sure + * that the process is not unloaded. + */ + static IL_INLINE void ILExecThreadJoinProcess(ILExecThread *thread, ILExecProcess *process) + { + _ILExecThreadProcess(thread) = process; + thread->nextThread = process->firstThread; + thread->prevThread = 0; + if(process->firstThread) + { + process->firstThread->prevThread = thread; + } + process->firstThread = thread; + + } + + /* + * Detach from the ILExecProcess. + * The caller has to handle the thread safety. + */ + static IL_INLINE void ILExecThreadDetachFromProcess(ILExecThread *thread) + { + if(thread->nextThread) + { + thread->nextThread->prevThread = thread->prevThread; + } + if(thread->prevThread) + { + thread->prevThread->nextThread = thread->nextThread; + } + else + { + _ILExecThreadProcess(thread)->firstThread = thread->nextThread; + } + _ILExecThreadProcess(thread) = 0; + thread->nextThread = thread->prevThread = 0; + } + ILExecThread *_ILExecThreadCreate(ILExecProcess *process, int ignoreProcessState) { ILExecThread *thread; *************** *** 626,639 **** return 0; } ! thread->process = process; ! thread->nextThread = process->firstThread; ! thread->prevThread = 0; ! if(process->firstThread) ! { ! process->firstThread->prevThread = thread; ! } ! process->firstThread = thread; ILMutexUnlock(process->lock); --- 667,676 ---- return 0; } ! #ifdef IL_CONFIG_APPDOMAINS ! thread->prevContext = 0; ! #endif ! ILExecThreadJoinProcess(thread, process); ILMutexUnlock(process->lock); *************** *** 643,649 **** void _ILExecThreadDestroy(ILExecThread *thread) { ! ILExecProcess *process = thread->process; /* Lock down the process */ ILMutexLock(process->lock); --- 680,686 ---- void _ILExecThreadDestroy(ILExecThread *thread) { ! ILExecProcess *process = _ILExecThreadProcess(thread); /* Lock down the process */ ILMutexLock(process->lock); *************** *** 660,677 **** } /* Detach the thread from its process */ ! if(thread->nextThread) ! { ! thread->nextThread->prevThread = thread->prevThread; ! } ! if(thread->prevThread) ! { ! thread->prevThread->nextThread = thread->nextThread; ! } ! else ! { ! process->firstThread = thread->nextThread; ! } /* Remove associations between ILExecThread and ILThread if they haven't already been removed */ --- 697,703 ---- } /* Detach the thread from its process */ ! ILExecThreadDetachFromProcess(thread); /* Remove associations between ILExecThread and ILThread if they haven't already been removed */ *************** *** 696,702 **** ILExecProcess *ILExecThreadGetProcess(ILExecThread *thread) { ! return thread->process; } ILCallFrame *_ILGetCallFrame(ILExecThread *thread, ILInt32 n) --- 722,728 ---- ILExecProcess *ILExecThreadGetProcess(ILExecThread *thread) { ! return _ILExecThreadProcess(thread); } ILCallFrame *_ILGetCallFrame(ILExecThread *thread, ILInt32 n) *************** *** 753,758 **** --- 779,979 ---- return 0; } } + + #ifdef IL_CONFIG_APPDOMAINS + /* Copy the process dependant data to the ILExecContext */ + static IL_INLINE void ILExecThreadSaveExecContext(ILExecThread *thread, ILExecContext *context) + { + context->prevContext = thread->prevContext; + context->clrThread = thread->clrThread; + context->process = _ILExecThreadProcess(thread); + context->threadStaticSlots = thread->threadStaticSlots; + context->threadStaticSlotsUsed = thread->threadStaticSlotsUsed; + } + + /* Clean up an ILExecContext */ + static IL_INLINE void ILExecThreadClearExecContext(ILExecContext *context) + { + context->prevContext = 0; + context->process = 0; + context->clrThread = 0; + context->threadStaticSlots = 0; + context->threadStaticSlotsUsed = 0; + } + + /* Copy the process dependant data to the ILExecContext */ + static IL_INLINE void ILExecThreadRestoreExecContext(ILExecThread *thread, ILExecContext *context) + { + thread->prevContext = context->prevContext; + thread->clrThread = context->clrThread; + _ILExecThreadProcess(thread) = context->process; + thread->threadStaticSlots = context->threadStaticSlots; + thread->threadStaticSlotsUsed = context->threadStaticSlotsUsed; + } + + /* + * Let the thread return from an other ILExecProcess and restore the saved state. + * Returns 0 on failure. + */ + int ILExecThreadReturnToProcess(ILExecThread *thread, ILExecContext *context) + { + if(context->process != _ILExecThreadProcess(thread)) + { + int result = 1; + ILExecProcess *returnProcess = context->process; + ILExecProcess *leavingProcess = _ILExecThreadProcess(thread); + /* perform a real return */ + + /* do this so that the locks are always in the same order to avoid a deadlock */ + if(returnProcess < leavingProcess) + { + if(returnProcess) + { + ILMutexLock(returnProcess->lock); + } + if(leavingProcess) + { + ILMutexLock(leavingProcess->lock); + } + } + else + { + if(leavingProcess) + { + ILMutexLock(leavingProcess->lock); + } + if(returnProcess) + { + ILMutexLock(returnProcess->lock); + } + } + if(leavingProcess) + { + ILExecThreadDetachFromProcess(thread); + } + /* restore the previous state */ + thread->prevContext = context->prevContext; + thread->clrThread = context->clrThread; + _ILExecThreadProcess(thread) = context->process; + thread->threadStaticSlots = context->threadStaticSlots; + thread->threadStaticSlotsUsed = context->threadStaticSlotsUsed; + /* check if the new process can't be entered */ + if(returnProcess->state >= _IL_PROCESS_STATE_UNLOADING) + { + /* process is unloaded */ + result = 0; + /* i'm not sure what to do */ + /* abort the thread */ + } + else + { + if(returnProcess) + { + ILExecThreadJoinProcess(thread, returnProcess); + } + } + if(returnProcess) + { + ILMutexUnlock(returnProcess->lock); + } + if(leavingProcess) + { + ILMutexUnlock(leavingProcess->lock); + } + return result; + } + else + { + /* just clean up the context */ + ILExecThreadClearExecContext(context); + } + return 1; + } + + /* + * Let the thread join an other ILExecProcess and save the current state in context. + * Returns 0 on failure. + */ + int ILExecThreadSwitchToProcess(ILExecThread *thread, ILExecProcess *process, ILExecContext *context) + { + ILExecProcess *prevProcess = _ILExecThreadProcess(thread); + + if(prevProcess != process) + { + int result = 1; + + /* do this so that the locks are always in the same order to avoid a deadlock */ + if(prevProcess < process) + { + if(prevProcess) + { + ILMutexLock(prevProcess->lock); + } + if(process) + { + ILMutexLock(process->lock); + } + } + else + { + if(process) + { + ILMutexLock(process->lock); + } + if(prevProcess) + { + ILMutexLock(prevProcess->lock); + } + } + /* check if the new process can't be entered */ + if(process->state >= _IL_PROCESS_STATE_UNLOADING) + { + /* process is unloaded */ + result = 0; + if(prevProcess) + { + ILExecThreadThrowSystem(thread, "System.AppDomainUnloadedException", 0); + } + } + else + { + ILExecThreadSaveExecContext(thread, context); + if(prevProcess) + { + ILExecThreadDetachFromProcess(thread); + } + if(process) + { + ILExecThreadJoinProcess(thread, process); + } + else + { + _ILExecThreadProcess(thread) = 0; + } + thread->prevContext = context; + thread->clrThread = 0; + thread->threadStaticSlots = 0; + thread->threadStaticSlotsUsed = 0; + } + if(process) + { + ILMutexUnlock(process->lock); + } + if(prevProcess) + { + ILMutexUnlock(prevProcess->lock); + } + return result; + } + else + { + /* save the old context anyways */ + ILExecThreadSaveExecContext(thread, context); + thread->prevContext = context; + } + return 1; + } + #endif #ifdef __cplusplus }; Index: libgc/include/gc.h =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/libgc/include/gc.h,v retrieving revision 1.10 diff -c -r1.10 gc.h *** libgc/include/gc.h 23 Jul 2005 14:59:34 -0000 1.10 --- libgc/include/gc.h 3 Oct 2005 15:19:11 -0000 *************** *** 891,896 **** --- 891,911 ---- /* in returned list. */ extern void GC_thr_init(); /* Needed for Solaris/X86 */ + # if defined(GC_PTHREADS) + /* + * Register a thread in the gc that was not created through the gc routines + * (for example by a thrid party library that does a callback). + * This is a null op when the gc is created as a dll (not on cygwin) because + * the thread will be registerd through DllMain. + */ + GC_API void GC_register_current_thread(); + + /* + * Unregister a thread that was registered through GC_register_current_thread. + */ + GC_API void GC_unregister_current_thread(); + # endif + #endif /* THREADS && !SRC_M3 */ #if defined(GC_WIN32_THREADS) *************** *** 928,933 **** --- 943,961 ---- # define CreateThread GC_CreateThread # endif # endif /* defined(_WIN32_WCE) */ + + /* + * Register a thread in the gc that was not created through the gc routines + * (for example by a thrid party library that does a callback). + * This is a null op when the gc is created as a dll (not on cygwin) because + * the thread will be registerd through DllMain. + */ + GC_API void GC_register_current_thread(); + + /* + * Unregister a thread that was registered through GC_register_current_thread. + */ + GC_API void GC_unregister_current_thread(); #endif /* defined(GC_WIN32_THREADS) && !cygwin */ Index: libgc/pthread_support.c =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/libgc/pthread_support.c,v retrieving revision 1.3 diff -c -r1.3 pthread_support.c *** libgc/pthread_support.c 17 Sep 2005 16:54:39 -0000 1.3 --- libgc/pthread_support.c 3 Oct 2005 15:19:25 -0000 *************** *** 1593,1597 **** --- 1593,1677 ---- #endif /* PARALLEL_MARK */ + /* + * Register a thread that was not created by the gc routines. + * Thread was created either by a third party library or a timer or ... + */ + void + GC_register_current_thread(void) + { + + int dummy; + GC_thread me; + pthread_t my_pthread; + + my_pthread = pthread_self(); + # ifdef DEBUG_THREADS + GC_printf1("Registering thread 0x%lx\n", my_pthread); + GC_printf1("pid = %ld\n", (long) getpid()); + # endif + LOCK(); + GC_in_thread_creation = TRUE; + me = GC_new_thread(my_pthread); + GC_in_thread_creation = FALSE; + #ifdef GC_DARWIN_THREADS + me -> stop_info.mach_thread = mach_thread_self(); + #else + me -> stop_info.stack_ptr = 0; + #endif + me -> flags = DETACHED; + /* me -> stack_end = GC_linux_stack_base(); -- currently (11/99) */ + /* doesn't work because the stack base in /proc/self/stat is the */ + /* one for the main thread. There is a strong argument that that's */ + /* a kernel bug, but a pervasive one. */ + # ifdef STACK_GROWS_DOWN + me -> stack_end = (ptr_t)(((word)(&dummy) + (GC_page_size - 1)) + & ~(GC_page_size - 1)); + # ifndef GC_DARWIN_THREADS + me -> stop_info.stack_ptr = me -> stack_end - 0x10; + # endif + /* Needs to be plausible, since an asynchronous stack mark */ + /* should not crash. */ + # else + me -> stack_end = (ptr_t)((word)(&dummy) & ~(GC_page_size - 1)); + me -> stop_info.stack_ptr = me -> stack_end + 0x10; + # endif + /* This is dubious, since we may be more than a page into the stack, */ + /* and hence skip some of it, though it's not clear that matters. */ + # ifdef IA64 + me -> backing_store_end = (ptr_t) + (GC_save_regs_in_stack() & ~(GC_page_size - 1)); + /* This is also < 100% convincing. We should also read this */ + /* from /proc, but the hook to do so isn't there yet. */ + # endif /* IA64 */ + GC_init_thread_local(me); + UNLOCK(); + } + + /* + * Unregister a thread that was registered with GC_register_current_thread. + */ + void + GC_unregister_current_thread(void) + { + GC_thread me; + + LOCK(); + me = GC_lookup_thread(pthread_self()); + GC_destroy_thread_local(me); + if (me -> flags & DETACHED) { + GC_delete_thread(pthread_self()); + } else { + me -> flags |= FINISHED; + } + # if defined(THREAD_LOCAL_ALLOC) && !defined(USE_PTHREAD_SPECIFIC) \ + && !defined(USE_COMPILER_TLS) && !defined(DBG_HDRS_ALL) + GC_remove_specific(GC_thread_key); + # endif + /* The following may run the GC from "nonexistent" thread. */ + GC_wait_for_gc_completion(FALSE); + UNLOCK(); + } + # endif /* GC_LINUX_THREADS and friends */ Index: libgc/win32_threads.c =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/libgc/win32_threads.c,v retrieving revision 1.15 diff -c -r1.15 win32_threads.c *** libgc/win32_threads.c 17 Sep 2005 16:54:39 -0000 1.15 --- libgc/win32_threads.c 3 Oct 2005 15:19:35 -0000 *************** *** 953,956 **** --- 953,979 ---- # endif /* !MSWINCE */ + void + GC_register_current_thread(void) + { + #if defined(GC_DLL) && !defined(CYGWIN32) + /* we have nothing to do here because the thread is registered through DllMain */ + #else + GC_ASSERT(GC_thr_initialized); + if (GC_main_thread != GetCurrentThreadId()) { + GC_new_thread(); + } /* o.w. we already did it during GC_thr_init(), called by GC_init() */ + #endif + } + + void + GC_unregister_current_thread(void) + { + #if defined(GC_DLL) && !defined(CYGWIN32) + /* we have nothing to do here because the thread is registered through DllMain */ + #else + GC_delete_thread(GetCurrentThreadId()); + #endif + } + #endif /* GC_WIN32_THREADS */ Index: support/no_defs.c =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/support/no_defs.c,v retrieving revision 1.3 diff -c -r1.3 no_defs.c *** support/no_defs.c 15 Jul 2003 22:17:33 -0000 1.3 --- support/no_defs.c 3 Oct 2005 15:19:43 -0000 *************** *** 29,34 **** --- 29,44 ---- extern "C" { #endif + /* + * This function is only used for initializing an ILThread + * structure for threads not created by pnet. + * This Thread MUST NOT BE USED to run managed code or create + * managed objects because this thread is not controled by the GC. + */ + void _ILThreadInitHandleSelf(ILThread *thread) + { + } + void _ILThreadInitSystem(ILThread *mainThread) { mainThread->handle = 0; Index: support/pt_defs.c =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/support/pt_defs.c,v retrieving revision 1.7 diff -c -r1.7 pt_defs.c *** support/pt_defs.c 15 Jul 2003 22:17:33 -0000 1.7 --- support/pt_defs.c 3 Oct 2005 15:19:51 -0000 *************** *** 119,124 **** --- 119,148 ---- to force system calls to exit with EINTR */ } + /* + * This function is only used for initializing an ILThread + * structure for threads not created by pnet. + * This Thread MUST NOT BE USED to run managed code or create + * managed objects because this thread is not controled by the GC. + */ + void _ILThreadInitHandleSelf(ILThread *thread) + { + #if GC_LINUX_THREADS + /* register the thread with the gc */ + GC_register_current_thread(); + #endif + /* Set the thread handle and identifier for the thread */ + thread->handle = pthread_self(); + thread->identifier = thread->handle; + } + + void _ILThreadDestroyHandleSelf(ILThread *thread) + { + #if GC_LINUX_THREADS + GC_unregister_current_thread(); + #endif + } + void _ILThreadInitSystem(ILThread *mainThread) { struct sigaction action; Index: support/thr_defs.h =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/support/thr_defs.h,v retrieving revision 1.16 diff -c -r1.16 thr_defs.h *** support/thr_defs.h 17 Jun 2004 20:12:10 -0000 1.16 --- support/thr_defs.h 3 Oct 2005 15:19:59 -0000 *************** *** 124,129 **** --- 124,131 ---- ILThreadCleanupEntry *lastCleanupEntry; int destroyOnExit; ILWaitHandle *monitor; + /* 1 if the gc knows the thread and is allowed to execute managed code */ + int gcAware; #if defined(IL_INTERRUPT_SUPPORTS) ILInterruptHandler interruptHandler; #endif *************** *** 335,345 **** --- 337,368 ---- void _ILInterruptDeinit(); /* + * Create a new ILThread for the current thread. This one is used + * only for native callbacks executed by non pnet threads. Threads + * initialized this way MUST NOT execute any managed code or create managed + * objects because they might not be controlled by the GC. + */ + ILThread *_ILThreadCreateSelf(); + + /* + * Destroy an ILThread created by _ILThreadCreateSelf. + */ + void _ILThreadDestroySelf(ILThread *thread); + + /* * Function that is called to run a thread after system-specific * initialization has been performed. If this function returns, * the thread must immediately exit. */ void _ILThreadRun(ILThread *thread); + + /* + * This function is only used for initializing an ILThread + * structure for threads not created by pnet. + * This Thread MUST NOT BE USED to run managed code or create + * managed objects because this thread is not controled by the GC. + */ + void _ILThreadInitHandleSelf(ILThread *thread); /* * Create a new system-specific thread. Returns zero if Index: support/thread.c =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/support/thread.c,v retrieving revision 1.30 diff -c -r1.30 thread.c *** support/thread.c 22 Aug 2004 05:01:15 -0000 1.30 --- support/thread.c 3 Oct 2005 15:20:08 -0000 *************** *** 95,100 **** --- 95,101 ---- mainThread.startArg = 0; mainThread.destroyOnExit = 0; mainThread.monitor = ILWaitMonitorCreate(); + mainThread.gcAware = 1; #ifdef IL_INTERRUPT_SUPPORTS mainThread.interruptHandler = 0; #endif *************** *** 246,251 **** --- 247,267 ---- _ILPrivateThreadDestroy(thread, 0); } + void _ILThreadDestroySelf(ILThread *thread) + { + ILWaitHandleClose(thread->monitor); + _ILMutexDestroy(&(thread->lock)); + _ILSemaphoreDestroy(&(thread->suspendAck)); + _ILSemaphoreDestroy(&(thread->resumeAck)); + _ILWakeupQueueDestroy(&(thread->joinQueue)); + + _ILThreadSetSelf(0); + /* Release the handle */ + _ILThreadDestroyHandleSelf(thread); + + ILFree(thread); + } + void _ILThreadRun(ILThread *thread) { /* When a thread starts, it blocks until the ILThreadStart function *************** *** 324,329 **** --- 340,346 ---- _ILWakeupQueueCreate(&(thread->joinQueue)); thread->handle = 0; thread->destroyOnExit = 0; + thread->gcAware = 1; #ifdef IL_INTERRUPT_SUPPORTS thread->interruptHandler = 0; #endif *************** *** 333,338 **** --- 350,397 ---- /* Unlock the thread system and return */ _ILMutexUnlock(&threadLockAll); + return thread; + } + + ILThread *_ILThreadCreateSelf() + { + ILThread *thread; + + /* Create a new thread object and populate it */ + thread = (ILThread *)ILCalloc(1, sizeof(ILThread)); + if(!thread) + { + return 0; + } + + _ILMutexCreate(&(thread->lock)); + thread->state = IL_TS_UNSTARTED; + thread->resumeRequested = 0; + thread->suspendRequested = 0; + thread->numLocksHeld = 0; + thread->firstCleanupEntry = 0; + thread->lastCleanupEntry = 0; + thread->monitor = ILWaitMonitorCreate(); + _ILSemaphoreCreate(&(thread->resumeAck)); + _ILSemaphoreCreate(&(thread->suspendAck)); + thread->startFunc = 0; + thread->userObject = 0; + thread->startArg = 0; + _ILWakeupCreate(&(thread->wakeup)); + _ILWakeupQueueCreate(&(thread->joinQueue)); + thread->handle = 0; + thread->destroyOnExit = 0; + thread->gcAware = 0; + #ifdef IL_INTERRUPT_SUPPORTS + thread->interruptHandler = 0; + #endif + + /* Initialize the handle and the identifier */ + _ILThreadInitHandleSelf(thread); + + /* Set the thread object for the thread */ + _ILThreadSetSelf(thread); + return thread; } Index: support/w32_defs.c =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/support/w32_defs.c,v retrieving revision 1.6 diff -c -r1.6 w32_defs.c *** support/w32_defs.c 15 Jun 2004 22:29:21 -0000 1.6 --- support/w32_defs.c 3 Oct 2005 15:20:17 -0000 *************** *** 88,93 **** --- 88,121 ---- } } + /* + * This function is only used for initializing an ILThread + * structure for threads not created by pnet. + * This Thread MUST NOT BE USED to run managed code or create + * managed objects because this thread is not controled by the GC. + */ + void _ILThreadInitHandleSelf(ILThread *thread) + { + #if GC_WIN32_THREADS + GC_register_current_thread(); + #endif + /* Initialize the thread's handle and identifier. We have + to duplicate the thread handle because "GetCurrentThread()" returns + a pseudo-handle and not a real one. We need the real one */ + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), (HANDLE *)(&(thread->handle)), + 0, 0, DUPLICATE_SAME_ACCESS); + thread->identifier = GetCurrentThreadId(); + } + + void _ILThreadDestroyHandleSelf(ILThread *thread) + { + #if GC_WIN32_THREADS + GC_unregister_current_thread(); + #endif + CloseHandle((thread)->handle); + } + void _ILThreadInitSystem(ILThread *mainThread) { /* Allocate a TLS key for storing thread objects */ Index: support/w32_defs.h =================================================================== RCS file: /cvsroot/dotgnu-pnet/pnet/support/w32_defs.h,v retrieving revision 1.8 diff -c -r1.8 w32_defs.h *** support/w32_defs.h 16 Jun 2004 09:05:06 -0000 1.8 --- support/w32_defs.h 3 Oct 2005 15:20:27 -0000 *************** *** 48,53 **** --- 48,64 ---- ((thread)->identifier == GetCurrentThreadId()) /* + * Initialize a thread's handle that is registering itself. + */ + void _ILThreadInitHandleSelf(ILThread *thread); + + /* + * Unregister a thread's handle which was self registering. + */ + void _ILThreadDestroyHandleSelf(ILThread *thread); + + + /* * Suspend and resume threads. Note: these are the primitive * versions, which are not "suspend-safe". */ #### End of Patch data ####