// Free List Reconstruction Task routine. // void dispatch_FreeListReconstruction(void *pUnused, int iUnused) { UNUSED_PARAMETER(pUnused); UNUSED_PARAMETER(iUnused); if (mudconf.control_flags & CF_DBCHECK) { const char *cmdsave = mudstate.debug_cmd; mudstate.debug_cmd = (char *)"< dbck >"; do_dbck(NOTHING, NOTHING, NOTHING, 0); Guest.CleanUp(); pcache_trim(); pool_reset(); mudstate.debug_cmd = cmdsave; } // Schedule ourselves again. // CLinearTimeAbsolute ltaNow; ltaNow.GetUTC(); CLinearTimeDelta ltd; ltd.SetSeconds(mudconf.check_interval); mudstate.check_counter = ltaNow + ltd; scheduler.DeferTask(mudstate.check_counter, PRIORITY_SYSTEM, dispatch_FreeListReconstruction, 0, 0); }
static CLinearTimeDelta GetProcessorUsage(void) { CLinearTimeDelta ltd; #ifdef WIN32 if (fpGetProcessTimes) { FILETIME ftCreate; FILETIME ftExit; FILETIME ftKernel; FILETIME ftUser; fpGetProcessTimes(hGameProcess, &ftCreate, &ftExit, &ftKernel, &ftUser); ltd.Set100ns(*(INT64 *)(&ftUser)); return ltd; } #endif #if !defined(WIN32) && defined(HAVE_GETRUSAGE) struct rusage usage; getrusage(RUSAGE_SELF, &usage); ltd.SetTimeValueStruct(&usage.ru_utime); return ltd; #else // Either this Unix doesn't have getrusage or this is a // fall-through case for Win32. // CLinearTimeAbsolute ltaNow; ltaNow.GetLocal(); ltd = ltaNow - mudstate.start_time; return ltd; #endif }
// --------------------------------------------------------------------------- // do_queue: Queue management // void do_queue(dbref executor, dbref caller, dbref enactor, int eval, int key, char *arg) { UNUSED_PARAMETER(caller); UNUSED_PARAMETER(enactor); UNUSED_PARAMETER(eval); if (key == QUEUE_KICK) { int i = mux_atol(arg); int save_minPriority = scheduler.GetMinPriority(); if (save_minPriority <= PRIORITY_CF_DEQUEUE_DISABLED) { notify(executor, "Warning: automatic dequeueing is disabled."); scheduler.SetMinPriority(PRIORITY_CF_DEQUEUE_ENABLED); } CLinearTimeAbsolute lsaNow; lsaNow.GetUTC(); scheduler.ReadyTasks(lsaNow); int ncmds = scheduler.RunTasks(i); scheduler.SetMinPriority(save_minPriority); if (!Quiet(executor)) { notify(executor, tprintf("%d commands processed.", ncmds)); } } else if (key == QUEUE_WARP) { int iWarp = mux_atol(arg); ltdWarp.SetSeconds(iWarp); if (scheduler.GetMinPriority() <= PRIORITY_CF_DEQUEUE_DISABLED) { notify(executor, "Warning: automatic dequeueing is disabled."); } scheduler.TraverseUnordered(CallBack_Warp); if (Quiet(executor)) { return; } if (iWarp > 0) { notify(executor, tprintf("WaitQ timer advanced %d seconds.", iWarp)); } else if (iWarp < 0) { notify(executor, tprintf("WaitQ timer set back %d seconds.", iWarp)); } else { notify(executor, "Object queue appended to player queue."); } } }
void init_timer(void) { CLinearTimeAbsolute ltaNow; ltaNow.GetUTC(); // Setup re-occuring Free List Reconstruction task. // CLinearTimeDelta ltd; ltd.SetSeconds((mudconf.check_offset == 0) ? mudconf.check_interval : mudconf.check_offset); mudstate.check_counter = ltaNow + ltd; scheduler.DeferTask(mudstate.check_counter, PRIORITY_SYSTEM, dispatch_FreeListReconstruction, 0, 0); // Setup re-occuring Database Dump task. // ltd.SetSeconds((mudconf.dump_offset == 0) ? mudconf.dump_interval : mudconf.dump_offset); mudstate.dump_counter = ltaNow + ltd; scheduler.DeferTask(mudstate.dump_counter, PRIORITY_SYSTEM, dispatch_DatabaseDump, 0, 0); // Setup re-occuring Idle Check task. // ltd.SetSeconds(mudconf.idle_interval); mudstate.idle_counter = ltaNow + ltd; scheduler.DeferTask(mudstate.idle_counter, PRIORITY_SYSTEM, dispatch_IdleCheck, 0, 0); // Setup re-occuring Check Events task. // mudstate.events_counter = ltaNow + time_15s; scheduler.DeferTask(mudstate.events_counter, PRIORITY_SYSTEM, dispatch_CheckEvents, 0, 0); #ifndef MEMORY_BASED // Setup re-occuring cache_tick task. // ltd.SetSeconds(0); if (mudconf.cache_tick_period <= ltd) { mudconf.cache_tick_period.SetSeconds(1); } scheduler.DeferTask(ltaNow+mudconf.cache_tick_period, PRIORITY_SYSTEM, dispatch_CacheTick, 0, 0); #endif // !MEMORY_BASED #if 0 // Setup comsys channel scrubbing. // scheduler.DeferTask(ltaNow+time_45s, PRIORITY_SYSTEM, dispatch_CleanChannels, 0, 0); #endif // 0 // Setup one-shot task to enable restarting 10 seconds after startmux. // scheduler.DeferTask(ltaNow+time_15s, PRIORITY_OBJECT, dispatch_CanRestart, 0, 0); }
void dispatch_CleanChannels(void *pUnused, int iUnused) { const char *cmdsave = mudstate.debug_cmd; mudstate.debug_cmd = (char *)"< cleanchannels >"; do_cleanupchannels(); // Schedule ourselves again. // CLinearTimeAbsolute ltaNextTime; ltaNextTime.GetUTC(); CLinearTimeDelta ltd = time_15m; ltaNextTime += ltd; scheduler.DeferTask(ltaNextTime, PRIORITY_SYSTEM, dispatch_CleanChannels, 0, 0); mudstate.debug_cmd = cmdsave; }
// Check Events Task routine. // void dispatch_CheckEvents(void *pUnused, int iUnused) { UNUSED_PARAMETER(pUnused); UNUSED_PARAMETER(iUnused); if (mudconf.control_flags & CF_EVENTCHECK) { const char *cmdsave = mudstate.debug_cmd; mudstate.debug_cmd = (char *)"< eventcheck >"; check_events(); mudstate.debug_cmd = cmdsave; } // Schedule ourselves again. // CLinearTimeAbsolute ltaNow; ltaNow.GetUTC(); CLinearTimeDelta ltd = time_15m; mudstate.events_counter = ltaNow + ltd; scheduler.DeferTask(mudstate.events_counter, PRIORITY_SYSTEM, dispatch_CheckEvents, 0, 0); }
// Idle Check Task routine. // void dispatch_IdleCheck(void *pUnused, int iUnused) { UNUSED_PARAMETER(pUnused); UNUSED_PARAMETER(iUnused); if (mudconf.control_flags & CF_IDLECHECK) { const char *cmdsave = mudstate.debug_cmd; mudstate.debug_cmd = (char *)"< idlecheck >"; check_idle(); mudstate.debug_cmd = cmdsave; } // Schedule ourselves again. // CLinearTimeAbsolute ltaNow; ltaNow.GetUTC(); CLinearTimeDelta ltd; ltd.SetSeconds(mudconf.idle_interval); mudstate.idle_counter = ltaNow + ltd; scheduler.DeferTask(mudstate.idle_counter, PRIORITY_SYSTEM, dispatch_IdleCheck, 0, 0); }
// Database Dump Task routine. // void dispatch_DatabaseDump(void *pUnused, int iUnused) { UNUSED_PARAMETER(pUnused); UNUSED_PARAMETER(iUnused); int nNextTimeInSeconds = mudconf.dump_interval; if (mudconf.control_flags & CF_CHECKPOINT) { const char *cmdsave = mudstate.debug_cmd; mudstate.debug_cmd = (char *)"< dump >"; #ifndef WIN32 if (mudstate.dumping) { // There is a dump in progress. These usually happen very quickly. // We will reschedule ourselves to try again in 20 seconds. // Ordinarily, you would think "...a dump is a dump...", but some // dumps might not be the type of dump we're going to do. // nNextTimeInSeconds = 20; } else #endif // !WIN32 { fork_and_dump(0); } mudstate.debug_cmd = cmdsave; } // Schedule ourselves again. // CLinearTimeAbsolute ltaNow; ltaNow.GetUTC(); CLinearTimeDelta ltd; ltd.SetSeconds(nNextTimeInSeconds); mudstate.dump_counter = ltaNow + ltd; scheduler.DeferTask(mudstate.dump_counter, PRIORITY_SYSTEM, dispatch_DatabaseDump, 0, 0); }
void dispatch_CacheTick(void *pUnused, int iUnused) { UNUSED_PARAMETER(pUnused); UNUSED_PARAMETER(iUnused); const char *cmdsave = mudstate.debug_cmd; mudstate.debug_cmd = (char *)"< cachetick >"; CLinearTimeDelta ltd = 0; if (mudconf.cache_tick_period <= ltd) { mudconf.cache_tick_period.SetSeconds(1); } cache_tick(); // Schedule ourselves again. // CLinearTimeAbsolute ltaNextTime; ltaNextTime.GetUTC(); ltaNextTime += mudconf.cache_tick_period; scheduler.DeferTask(ltaNextTime, PRIORITY_SYSTEM, dispatch_CacheTick, 0, 0); mudstate.debug_cmd = cmdsave; }
WPARAM CFidgetApp::Run(void) { HACCEL hAccelTable = LoadAccelerators(m_hInstance, (LPCTSTR)IDC_FIDGET); // Main message loop: // WPARAM iReturn = 0; bool bFinished = false; while (!bFinished) { CLinearTimeAbsolute ltaCurrent; ltaCurrent.GetUTC(); // Execute background tasks at specifically scheduled times. // scheduler.RunTasks(ltaCurrent); CLinearTimeAbsolute ltaWakeUp; if (!scheduler.WhenNext(<aWakeUp)) { ltaWakeUp = ltaCurrent + time_30m; } else if (ltaWakeUp < ltaCurrent) { // This is necessary to deal with computer time jumping backwards // which can happen when someone sets or resets the computer clock. // ltaWakeUp = ltaCurrent; } CLinearTimeDelta ltdTimeOut = ltaWakeUp - ltaCurrent; DWORD dwTimeout = ltdTimeOut.ReturnMilliseconds(); DWORD nHandles = 0; DWORD dwObject = MsgWaitForMultipleObjectsEx(nHandles, NULL, dwTimeout, QS_ALLINPUT, 0); if (WAIT_OBJECT_0 + nHandles == dwObject) { for (; !bFinished;) { // There is at least one new message waiting to be processed. // MSG msg; BOOL bGM = GetMessage(&msg, NULL, 0, 0); if (0 == bGM) { // WM_QUIT message was received. It is time to terminate // ourselves. // iReturn = msg.wParam; bFinished = true; } else if (-1 == bGM) { // An unexpected problem occured. // bFinished = true; } else { // Translate and dispatch message to Windows Procedure. // if ( ( NULL == m_hwndNewSession || !IsDialogMessage(m_hwndNewSession, &msg)) && ( NULL == m_hwndAbout || !IsDialogMessage(m_hwndAbout, &msg)) && !TranslateMDISysAccel(g_theApp.m_pMainFrame->m_pMDIControl->m_hwnd, &msg) && !TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } // We must process all messages in the queue before making // another MsgWaitForMultipleObjectsEx() call. // if (!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE|PM_NOYIELD)) { break; } } } else if (WAIT_TIMEOUT != dwObject) { // An unexpected event occured. // bFinished = true; } // It's time to perform some background task. // } DestroyAcceleratorTable(hAccelTable); return iReturn; }
// --------------------------------------------------------------------------- // do_wait: Command interface to wait_que // void do_wait ( dbref executor, dbref caller, dbref enactor, int eval, int key, char *event, char *cmd, char *cargs[], int ncargs ) { CLinearTimeAbsolute ltaWhen; CLinearTimeDelta ltd; // If arg1 is all numeric, do simple (non-sem) timed wait. // if (is_rational(event)) { if (key & WAIT_UNTIL) { ltaWhen.SetSecondsString(event); } else { ltaWhen.GetUTC(); ltd.SetSecondsString(event); ltaWhen += ltd; } wait_que(executor, caller, enactor, eval, true, ltaWhen, NOTHING, 0, cmd, ncargs, cargs, mudstate.global_regs); return; } // Semaphore wait with optional timeout. // char *what = parse_to(&event, '/', 0); init_match(executor, what, NOTYPE); match_everything(0); dbref thing = noisy_match_result(); if (!Good_obj(thing)) { return; } else if (!Controls(executor, thing) && !Link_ok(thing)) { notify(executor, NOPERM_MESSAGE); } else { // Get timeout, default 0. // int atr = A_SEMAPHORE; bool bTimed = false; if (event && *event) { if (is_rational(event)) { if (key & WAIT_UNTIL) { ltaWhen.SetSecondsString(event); } else { ltaWhen.GetUTC(); ltd.SetSecondsString(event); ltaWhen += ltd; } bTimed = true; } else { ATTR *ap = atr_str(event); if (!ap) { atr = mkattr(executor, event); if (atr <= 0) { notify_quiet(executor, "Invalid attribute."); return; } ap = atr_num(atr); } else { atr = ap->number; } if (!bCanSetAttr(executor, thing, ap)) { notify_quiet(executor, NOPERM_MESSAGE); return; } } } int num = add_to(thing, 1, atr); if (num <= 0) { // Thing over-notified, run the command immediately. // thing = NOTHING; bTimed = false; } wait_que(executor, caller, enactor, eval, bTimed, ltaWhen, thing, atr, cmd, ncargs, cargs, mudstate.global_regs); } }
// This Task assumes that pEntry is already unlinked from any lists it may // have been related to. // static void Task_RunQueueEntry(void *pEntry, int iUnused) { UNUSED_PARAMETER(iUnused); BQUE *point = (BQUE *)pEntry; dbref executor = point->executor; if ( Good_obj(executor) && !Going(executor)) { giveto(executor, mudconf.waitcost); mudstate.curr_enactor = point->enactor; mudstate.curr_executor = executor; a_Queue(Owner(executor), -1); point->executor = NOTHING; if (!Halted(executor)) { // Load scratch args. // for (int i = 0; i < MAX_GLOBAL_REGS; i++) { if (mudstate.global_regs[i]) { RegRelease(mudstate.global_regs[i]); mudstate.global_regs[i] = NULL; } mudstate.global_regs[i] = point->scr[i]; point->scr[i] = NULL; } char *command = point->comm; mux_assert(!mudstate.inpipe); mux_assert(mudstate.pipe_nest_lev == 0); mux_assert(mudstate.poutobj == NOTHING); mux_assert(!mudstate.pout); break_called = false; while ( command && !break_called) { mux_assert(!mudstate.poutnew); mux_assert(!mudstate.poutbufc); char *cp = parse_to(&command, ';', 0); if ( cp && *cp) { // Will command be piped? // if ( command && *command == '|' && mudstate.pipe_nest_lev < mudconf.ntfy_nest_lim) { command++; mudstate.pipe_nest_lev++; mudstate.inpipe = true; mudstate.poutnew = alloc_lbuf("process_command.pipe"); mudstate.poutbufc = mudstate.poutnew; mudstate.poutobj = executor; } else { mudstate.inpipe = false; mudstate.poutobj = NOTHING; } CLinearTimeAbsolute ltaBegin; ltaBegin.GetUTC(); MuxAlarm.Set(mudconf.max_cmdsecs); CLinearTimeDelta ltdUsageBegin = GetProcessorUsage(); char *log_cmdbuf = process_command(executor, point->caller, point->enactor, point->eval, false, cp, point->env, point->nargs); CLinearTimeAbsolute ltaEnd; ltaEnd.GetUTC(); if (MuxAlarm.bAlarmed) { notify(executor, "GAME: Expensive activity abbreviated."); s_Flags(point->enactor, FLAG_WORD1, Flags(point->enactor) | HALT); s_Flags(point->executor, FLAG_WORD1, Flags(point->executor) | HALT); halt_que(point->enactor, NOTHING); halt_que(executor, NOTHING); } MuxAlarm.Clear(); CLinearTimeDelta ltdUsageEnd = GetProcessorUsage(); CLinearTimeDelta ltd = ltdUsageEnd - ltdUsageBegin; db[executor].cpu_time_used += ltd; ltd = ltaEnd - ltaBegin; if (ltd > mudconf.rpt_cmdsecs) { STARTLOG(LOG_PROBLEMS, "CMD", "CPU"); log_name_and_loc(executor); char *logbuf = alloc_lbuf("do_top.LOG.cpu"); mux_sprintf(logbuf, LBUF_SIZE, " queued command taking %s secs (enactor #%d): ", ltd.ReturnSecondsString(4), point->enactor); log_text(logbuf); free_lbuf(logbuf); log_text(log_cmdbuf); ENDLOG; } } // Transition %| value. // if (mudstate.pout) { free_lbuf(mudstate.pout); mudstate.pout = NULL; } if (mudstate.poutnew) { *mudstate.poutbufc = '\0'; mudstate.pout = mudstate.poutnew; mudstate.poutnew = NULL; mudstate.poutbufc = NULL; } } // Clean up %| value. // if (mudstate.pout) { free_lbuf(mudstate.pout); mudstate.pout = NULL; } mudstate.pipe_nest_lev = 0; mudstate.inpipe = false; mudstate.poutobj = NOTHING; } } for (int i = 0; i < MAX_GLOBAL_REGS; i++) { if (point->scr[i]) { RegRelease(point->scr[i]); point->scr[i] = NULL; } if (mudstate.global_regs[i]) { RegRelease(mudstate.global_regs[i]); mudstate.global_regs[i] = NULL; } } MEMFREE(point->text); point->text = NULL; free_qentry(point); }
// --------------------------------------------------------------------------- // do_ps: tell executor what commands they have pending in the queue // void do_ps(dbref executor, dbref caller, dbref enactor, int eval, int key, char *target) { UNUSED_PARAMETER(caller); UNUSED_PARAMETER(enactor); UNUSED_PARAMETER(eval); char *bufp; dbref executor_targ, obj_targ; // Figure out what to list the queue for. // if ((key & PS_ALL) && !See_Queue(executor)) { notify(executor, NOPERM_MESSAGE); return; } if (!target || !*target) { obj_targ = NOTHING; if (key & PS_ALL) { executor_targ = NOTHING; } else { executor_targ = Owner(executor); if (!isPlayer(executor)) { obj_targ = executor; } } } else { executor_targ = Owner(executor); obj_targ = match_controlled(executor, target); if (obj_targ == NOTHING) { return; } if (key & PS_ALL) { notify(executor, "Can't specify a target and /all"); return; } if (isPlayer(obj_targ)) { executor_targ = obj_targ; obj_targ = NOTHING; } } key = key & ~PS_ALL; switch (key) { case PS_BRIEF: case PS_SUMM: case PS_LONG: break; default: notify(executor, "Illegal combination of switches."); return; } Show_lsaNow.GetUTC(); Total_SystemTasks = 0; Total_RunQueueEntry = 0; Shown_RunQueueEntry = 0; Total_SemaphoreTimeout = 0; Shown_SemaphoreTimeout = 0; Show_Player_Target = executor_targ; Show_Object_Target = obj_targ; Show_Key = key; Show_Player = executor; Show_bFirstLine = true; scheduler.TraverseOrdered(CallBack_ShowWait); Show_bFirstLine = true; scheduler.TraverseOrdered(CallBack_ShowSemaphore); #ifdef QUERY_SLAVE Show_bFirstLine = true; scheduler.TraverseOrdered(CallBack_ShowSQLQueries); #endif // QUERY_SLAVE if (Wizard(executor)) { notify(executor, "----- System Queue -----"); scheduler.TraverseOrdered(CallBack_ShowDispatches); } // Display stats. // bufp = alloc_mbuf("do_ps"); #ifdef QUERY_SLAVE mux_sprintf(bufp, MBUF_SIZE, "Totals: Wait Queue...%d/%d Semaphores...%d/%d SQL %d/%d", Shown_RunQueueEntry, Total_RunQueueEntry, Shown_SemaphoreTimeout, Total_SemaphoreTimeout, Shown_SQLTimeout, Total_SQLTimeout); #else mux_sprintf(bufp, MBUF_SIZE, "Totals: Wait Queue...%d/%d Semaphores...%d/%d", Shown_RunQueueEntry, Total_RunQueueEntry, Shown_SemaphoreTimeout, Total_SemaphoreTimeout); #endif // QUERY_SLAVE notify(executor, bufp); if (Wizard(executor)) { mux_sprintf(bufp, MBUF_SIZE, " System Tasks.....%d", Total_SystemTasks); notify(executor, bufp); } free_mbuf(bufp); }
void init_timer(void) { CLinearTimeAbsolute ltaNow; ltaNow.GetUTC(); }