void ILGCDeinit() { _FinalizerStopFlag = 1; GC_TRACE("ILGCDeinit: Performing final GC [thread:%d]\n", (int)ILThreadSelf()); /* Do a final GC */ ILGCCollect(); /* Cleanup the finalizer thread */ if (_FinalizerThread && _FinalizerThreadStarted) { GC_TRACE("ILGCDeinit: Peforming last finalizer run [thread:%d]\n", (int)ILThreadSelf()); ILWaitEventSet(_FinalizerSignal); GC_TRACE("ILGCDeinit: Waiting for finalizer thread to end [thread:%d]\n", (int)ILThreadSelf()); /* Wait for the finalizer thread */ if (ILThreadJoin(_FinalizerThread, 15000)) { GC_TRACE("ILGCDeinit: Finalizer thread finished [thread:%d]\n", (int)ILThreadSelf()); } else { GC_TRACE("ILGCDeinit: Finalizer thread not responding [thread:%d]\n", (int)ILThreadSelf()); } /* Destroy the finalizer thread */ ILThreadDestroy(_FinalizerThread); } _ILMutexDestroy(&_FinalizerLock); }
/* * 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. */ ILThreadRunSelf(_DelegateInvokeFromNewThread, (void *)¶ms); } 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)))
/* * Waits for a handle and if an interrupt or abort is encountered during the * wait sequence the function will return the proper wait error code but only * after it has managed to aquire the handle (by continuously retrying). * If the wait times out, the handle will not be aquired and the function will * return with either IL_WAIT_TIMEOUT, IL_WAIT_ABORTED or IL_WAIT_INTERRUPTED. */ int _ILWaitOneBackupInterruptsAndAborts(ILWaitHandle *handle, int timeout) { ILThread *thread = ILThreadSelf(); int result, retval = 0, threadstate = 0; for (;;) { /* Wait to re-acquire the monitor (add ourselves to the "ready queue") */ result = ILWaitOne(handle, timeout); if (result < IL_WAIT_TIMEOUT) { /* We were aborted or interrupted. Save the thread state and keep trying to reaquire the monitor */ _ILMutexLock(&thread->lock); threadstate |= thread->state; if (result == IL_WAIT_INTERRUPTED) { /* Interrupted is cleared by ILWaitOne so save it manually */ threadstate |= IL_TS_INTERRUPTED; } thread->state &= ~(IL_TS_ABORT_REQUESTED | IL_TS_INTERRUPTED); if (result < retval) { retval = result; } _ILMutexUnlock(&thread->lock); continue; } else { if (threadstate != 0) { _ILMutexLock(&thread->lock); /* Set the thread state to the thread state that was stored and clear the interrupted flag */ thread->state |= (threadstate & ~IL_TS_INTERRUPTED); _ILMutexUnlock(&thread->lock); } else { retval = result; } return retval; } } }
int ILWaitOne(ILWaitHandle *handle, ILUInt32 timeout) { ILThread *thread = ILThreadSelf(); _ILWakeup *wakeup = &(thread->wakeup); int result; /* Enter the "wait/sleep/join" state */ result = _ILEnterWait(thread); if(result != 0) { return result; } /* Set the limit for the thread's wakeup object */ if(!_ILWakeupSetLimit(wakeup, 1)) { return _ILLeaveWait(thread, IL_WAIT_INTERRUPTED); } /* Register this thread with the handle */ result = (*(handle->registerFunc))(handle, wakeup); if(result == IL_WAITREG_ACQUIRED) { /* We were able to acquire the wait handle immediately */ _ILWakeupAdjustLimit(wakeup, 0); return _ILLeaveWaitHandle(thread, handle, 0); } else if(result == IL_WAITREG_FAILED) { /* Something serious happened which prevented registration */ _ILWakeupAdjustLimit(wakeup, 0); return _ILLeaveWait(thread, IL_WAIT_FAILED); } /* Wait until we are signalled, timed out, or interrupted */ result = _ILWakeupWait(wakeup, timeout, 0); /* Unregister the thread from the wait handle */ (*(handle->unregisterFunc))(handle, wakeup, (result <= 0)); /* Tell the caller what happened */ if(result > 0) { /* We have to account for "_ILLeaveWait" detecting interrupt or abort after we already acquired the wait handle */ return _ILLeaveWaitHandle(thread, handle, 0); } else if(result == 0) { return _ILLeaveWait(thread, IL_WAIT_TIMEOUT); } else { return _ILLeaveWait(thread, IL_WAIT_INTERRUPTED); } }
/* * 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); } return 0; }
/* * 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()); /* This *must* to be set before checking for !_FinalizersDisabled to prevent a race with ILGCDisableFinalizers */ _FinalizersRunning = 1; ILThreadMemoryBarrier(); if (GC_should_invoke_finalizers() && !_FinalizersDisabled) { 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()); } _FinalizersRunning = 0; ILThreadMemoryBarrier(); 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); /* Wake all waiting threads */ ILWaitEventPulse(_FinalizerResponse); return; } GC_TRACE("GC:_FinalizerThread: Response [thread:%d]\n", (int)ILThreadSelf()); ILWaitEventReset(_FinalizerSignal); /* Wake all waiting threads */ ILWaitEventPulse(_FinalizerResponse); } }
int ILWaitAll(ILWaitHandle **handles, ILUInt32 numHandles, ILUInt32 timeout) { ILThread *thread = ILThreadSelf(); _ILWakeup *wakeup = &(thread->wakeup); int result; ILUInt32 index, index2; ILWaitHandle *handle; ILUInt32 limit; /* Enter the "wait/sleep/join" state */ result = _ILEnterWait(thread); if(result != 0) { return result; } /* Set the limit for the thread's wakeup object. This may be reduced later if we were able to acquire some objects during the registration step */ limit = numHandles; if(!_ILWakeupSetLimit(wakeup, limit)) { return _ILLeaveWait(thread, IL_WAIT_INTERRUPTED); } /* Register this thread with all of the wait handles */ for(index = 0; index < numHandles; ++index) { handle = handles[index]; result = (*(handle->registerFunc))(handle, wakeup); if(result == IL_WAITREG_ACQUIRED) { /* We were able to acquire this wait handle immediately */ --limit; } else if(result == IL_WAITREG_FAILED) { /* Something serious happened which prevented registration */ _ILWakeupAdjustLimit(wakeup, 0); /* Unregister the handles we have registered so far */ for(index2 = 0; index2 < index; ++index2) { handle = handles[index2]; (*(handle->unregisterFunc))(handle, wakeup, 1); } return _ILLeaveWait(thread, IL_WAIT_FAILED); } } /* Adjust the wait limit to reflect handles we already acquired */ _ILWakeupAdjustLimit(wakeup, limit); if (limit == 0) { /* No need to wait since we managed to aquire every handle immediately. */ result = 1; } else { /* Wait until we are signalled, timed out, or interrupted */ result = _ILWakeupWait(wakeup, timeout, 0); } /* Unregister the thread from the wait handles */ for(index = 0; index < numHandles; ++index) { handle = handles[index]; (*(handle->unregisterFunc))(handle, wakeup, (result <= 0)); } /* Tell the caller what happened */ if(result > 0) { /* We have to account for "_ILLeaveWait" detecting interrupt or abort after we already acquired the wait handles */ result = _ILLeaveWait(thread, 0); if(result == 0) { return 0; } else { for(index = 0; index < numHandles; ++index) { handle = handles[index]; (*(handle->unregisterFunc))(handle, wakeup, 1); } return result; } } else if(result == 0) { return _ILLeaveWait(thread, IL_WAIT_TIMEOUT); } else { return _ILLeaveWait(thread, IL_WAIT_INTERRUPTED); } }
int ILWaitAny(ILWaitHandle **handles, ILUInt32 numHandles, ILUInt32 timeout) { ILThread *thread = ILThreadSelf(); _ILWakeup *wakeup = &(thread->wakeup); int result; ILUInt32 index, index2; ILWaitHandle *handle; ILWaitHandle *resultHandle; /* Enter the "wait/sleep/join" state */ result = _ILEnterWait(thread); if(result != 0) { return result; } /* Set the limit for the thread's wakeup object */ if(!_ILWakeupSetLimit(wakeup, 1)) { return _ILLeaveWait(thread, IL_WAIT_INTERRUPTED); } /* Register this thread with all of the wait handles */ for(index = 0; index < numHandles; ++index) { handle = handles[index]; result = (*(handle->registerFunc))(handle, wakeup); if(result == IL_WAITREG_ACQUIRED) { /* We were able to acquire this wait handle immediately */ _ILWakeupAdjustLimit(wakeup, 0); /* Unregister the handles we have registered so far */ for(index2 = 0; index2 < index; ++index2) { handle = handles[index2]; (*(handle->unregisterFunc))(handle, wakeup, 1); } return _ILLeaveWaitHandle(thread, handles[index], index); } else if(result == IL_WAITREG_FAILED) { /* Something serious happened which prevented registration */ _ILWakeupAdjustLimit(wakeup, 0); /* Unregister the handles we have registered so far */ for(index2 = 0; index2 < index; ++index2) { handle = handles[index2]; (*(handle->unregisterFunc))(handle, wakeup, 1); } return _ILLeaveWait(thread, IL_WAIT_FAILED); } } /* Wait until we are signalled, timed out, or interrupted */ resultHandle = 0; result = _ILWakeupWait(wakeup, timeout, (void *)&resultHandle); /* Unregister the thread from the wait handles */ index2 = 0; for(index = 0; index < numHandles; ++index) { handle = handles[index]; if(handle == resultHandle && result > 0) { index2 = index; (*(handle->unregisterFunc))(handle, wakeup, 0); } else { (*(handle->unregisterFunc))(handle, wakeup, 1); } } /* Tell the caller what happened */ if(result > 0) { /* We have to account for "_ILLeaveWait" detecting interrupt or abort after we already acquired the wait handle */ return _ILLeaveWaitHandle(thread, resultHandle, (int)index2); } else if(result == 0) { return _ILLeaveWait(thread, IL_WAIT_TIMEOUT); } else { return _ILLeaveWait(thread, IL_WAIT_INTERRUPTED); } }
/* * Notify the finalization thread that there is work to do. */ static int PrivateGCNotifyFinalize(int timeout, int ignoreDisabled) { int result; if (_FinalizersDisabled && !ignoreDisabled) { return 0; } /* Prevent recursive finalization */ if (_FinalizersRunningSynchronously || ILThreadSelf() == _FinalizerThread) { return 0; } #ifdef GC_TRY_INVOKE_SYNCHRONOUSLY /* Try to invoke synchronously (for performance & single threaded systems) */ if (_InvokeFinalizersSynchronously() == 0) { return 0; } #endif /* There is no finalizer thread! We've already attempted to invoke synchronously (above) so just exit. */ if (_FinalizerThread == 0) { return 0; } /* Finalizers need to be run on a seperate thread. 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("PrivateGCInvokeFinalizers: Couldn't " \ "start finalizer thread [thread: %d]\n", (int)ILThreadSelf()); _ILMutexUnlock(&_FinalizerLock); return 0; } _FinalizerThreadStarted = 1; } _ILMutexUnlock(&_FinalizerLock); } /* Signal the finalizer thread */ GC_TRACE("PrivateGCInvokeFinalizers: Invoking finalizers " \ "and waiting [thread: %d]\n", (int)ILThreadSelf()); result = ILSignalAndWait(_FinalizerSignal, _FinalizerResponse, timeout); GC_TRACE("PrivateGCInvokeFinalizers: Finalizers finished[thread: %d]\n", (int)ILThreadSelf()); return result; }