/* * The reaper thread. Its job is to de-allocate memory * used by threads which have finished. */ static void Reaper(ulong_t arg) { struct Kernel_Thread *kthread; Disable_Interrupts(); while (true) { /* See if there are any threads needing disposal. */ if ((kthread = s_graveyardQueue.head) == 0) { /* Graveyard is empty, so wait for a thread to die. */ Wait(&s_reaperWaitQueue); } else { /* Make the graveyard queue empty. */ Clear_Thread_Queue(&s_graveyardQueue); /* * Now we can re-enable interrupts, since we * have removed all the threads needing disposal. */ Enable_Interrupts(); Yield(); /* allow other threads to run? */ /* Dispose of the dead threads. */ while (kthread != 0) { struct Kernel_Thread* next = Get_Next_In_Thread_Queue(kthread); #if 0 Print("Reaper: disposing of thread @ %x, stack @ %x\n", kthread, kthread->stackPage); #endif Destroy_Thread(kthread); kthread = next; } /* * Disable interrupts again, since we're going to * do another iteration. */ Disable_Interrupts(); } } }
DC_ID CScriptModule::Resume_Thread(DC_ID ThreadID) { THREAD_MAP_ITER iFind = m_Threads.find(ThreadID); if( iFind == m_Threads.end() ) { Log(LOG_SCRIPT, "Invalid Thread ID: %d\n", ThreadID); return DC_INVALID_ID; } CThread* pThread = iFind->second; // Do the resume int status = lua_resume( pThread->m_pState, NULL, 0); if(status == LUA_YIELD) { return pThread->GetID(); } else if( status == 0 ) { // Thread exited normally Destroy_Thread(pThread->GetID()); return DC_INVALID_ID; } return DC_INVALID_ID; }
DC_ID CScriptModule::Call_Threaded_Script_Method(const char* func, const char* sig, ...) { va_list vl; int narg, nres; // New Thread CThread* pNewThread = Create_Thread(); lua_State* pThread = pNewThread->m_pState; // Push the method lua_getglobal( pThread, func ); va_start(vl, sig); narg = 0; while (*sig) { switch (*sig++) { case 'd': { lua_pushnumber(pThread, va_arg(vl, double)); break; } case 'i': { lua_pushnumber(pThread, va_arg(vl, int)); break; } case 's': { lua_pushstring(pThread, va_arg(vl, char *)); break; } case '>': { goto endwhile; } default: { break; } } narg++; luaL_checkstack(pThread, 1, "Too many arguments\n"); } endwhile: nres = strlen(sig); int status = lua_resume( pThread, NULL, narg ); // Thread exited normally if( status == 0 ) { DLog(LOG_SCRIPT, "Thread exited normally\n"); } else if( status == LUA_YIELD ) { DLog(LOG_SCRIPT, "Thread yielded\n"); } else { // TODO: check the stack here string errmsg = lua_tostring( pThread, -1 ); Log( LOG_SCRIPT, "Error running thread: %s\n", errmsg.c_str() ); lua_pop( pThread, 1 ); return DC_INVALID_ID; } nres = -nres; while (*sig) { switch (*sig++) { case 'd': { if (!lua_isnumber(pThread, nres)) { DLog(LOG_SCRIPT, "Wrong result type\n"); } *va_arg(vl, double *) = lua_tonumber(pThread, nres); break; } case 'i': { if (!lua_isnumber(pThread, nres)) { DLog(LOG_SCRIPT, "Wrong result type\n"); } *va_arg(vl, int *) = (int)lua_tonumber(pThread, nres); break; } case 's': { if (!lua_isstring(pThread, nres)) { DLog(LOG_SCRIPT, "Wrong result type\n"); } *va_arg(vl, const char **) = lua_tostring(pThread, nres); break; } default: { DLog(LOG_SCRIPT, "Invalid option\n"); } } nres++; } va_end(vl); if( status ==0 ) { Destroy_Thread(pNewThread->GetID()); return DC_INVALID_ID; } else { return pNewThread->GetID(); } }