void CLR_RT_HeapBlock_Timer::SpawnTimer( CLR_RT_Thread* th ) { NATIVE_PROFILE_CLR_CORE(); //Only one managed timer max _ASSERTE(m_references.NumOfNodes() == 1); CLR_RT_ObjectToEvent_Source* ref = (CLR_RT_ObjectToEvent_Source*)m_references.FirstValidNode(); CLR_RT_HeapBlock* managedTimer = ref->m_objectPtr; CLR_RT_HeapBlock* callback = &managedTimer[ Library_corlib_native_System_Threading_Timer::FIELD__m_callback ]; CLR_RT_HeapBlock* state = &managedTimer[ Library_corlib_native_System_Threading_Timer::FIELD__m_state ]; CLR_RT_HeapBlock_Delegate* delegate = callback->DereferenceDelegate(); CLR_RT_ProtectFromGC gc( *managedTimer ); _ASSERTE(delegate != NULL); if(delegate == NULL) return; _ASSERTE(delegate->DataType() == DATATYPE_DELEGATE_HEAD); m_ticksLastExpiration = g_CLR_RT_ExecutionEngine.m_currentMachineTime; m_timeLastExpiration = m_timeExpire; m_timeExpire = TIMEOUT_INFINITE; if(SUCCEEDED(th->PushThreadProcDelegate( delegate ))) { CLR_RT_StackFrame* stack = th->FirstFrame(); if(stack->Next() != NULL) { int numArgs = stack->m_call.m_target->numArgs; if(numArgs > 0) { stack->m_arguments[ numArgs-1 ].Assign( *state ); } } // // Associate the timer with the thread. // m_flags |= CLR_RT_HeapBlock_Timer::c_Executing; m_flags &= ~CLR_RT_HeapBlock_Timer::c_Triggered; th->m_terminationCallback = CLR_RT_HeapBlock_Timer::ThreadTerminationCallback; th->m_terminationParameter = this; } }