int Scheduler::dispatch() { /*** * On the first dispatch, _currentPCB will be NULL. In this special case, the logic is slightly different. ***/ if(_currentPCB == NULL) { _currentPCB = dequeueNextProcess(); _currentPCB->_status = RUNNING; _currentPCB->_runCount++; jmp_buf tmpBuffer; if(setjmp(tmpBuffer) == 0) { longjmp(_currentPCB->_context,1); } return SUCCESS; } // Ensure that _currentPCB has been properly queued if(_currentPCB->_status == RUNNING) { return g_RTX->terminate(); // a serious error has occured, which may result in unexpected behaviour. Fail-fast } /*** * Switch processes to the next process. When dispatch is called, the current process' status and storage will * have already been handled by the appropriate system call (makeReady, etc). The dispatcher only needs to find * a new process to run, update the _currentPCB variable and status, and perform the context switch. ***/ PCB* oldPCB = _currentPCB; _currentPCB = dequeueNextProcess(); //removes it from the ready queue _currentPCB->_status = RUNNING; _currentPCB->_runCount++; contextSwitch(oldPCB, _currentPCB); return SUCCESS; }
/* * Description: This function terminates the thread with ID tid and deletes * it from all relevant control structures. All the resources allocated by * the library for this thread should be released. If no thread with ID tid * exists it is considered as an error. Terminating the main thread * (tid == 0) will result in the termination of the entire process using * exit(0) [after releasing the assigned library memory]. * Return value: The function returns 0 if the thread was successfully * terminated and -1 otherwise. If a thread terminates itself or the main * thread is terminated, the function does not return. */ int uthread_terminate(int tid) { // Block SIGTVALRM signal sigset_t oldSet; blockSignal(SIGVTALRM, &oldSet); // If main thread is terminated, delete all threads and quit. // The deleteThread function checks and manages data for future // process run, which is un-needed in this point. if (tid == MAIN_THREAD_ID) { for (auto th : livingThreads) { delete th.second; } exit(EXIT_SUCC); } // If no such thread exists, return failure. if (livingThreads.find(tid) == livingThreads.end()) { std::cerr << LIB_ERROR_MSG <<"terminate(" << tid << ") failed - no such thread id" << std::endl; resetSigMask(&oldSet); return EXIT_FAIL; } // Otherwise, delete thread tid, if it's not sleeping. if (livingThreads[tid]->get_state() == uthread::state::SLEEPING) { std::cerr << LIB_ERROR_MSG << "can't terminate a sleeping thread" << std::endl; resetSigMask(&oldSet); return EXIT_FAIL; } // If deleted yourself, goto contextSwitch. if ((uthread::id)tid == currentThread) { // Set this tid as the one that needs to be deleted // in the next contextSwitch toDelete = tid; resetSigMask(&oldSet); contextSwitch(SIGVTALRM); return EXIT_SUCC; // This should not be reached } // Otherwise, delete and return else { // Unblock SIGVTALRM and return resetSigMask(&oldSet); deleteThread(tid); return EXIT_SUCC; } }
void X86Process::execute() { /* Refresh I/O bitmap. */ memory->mapVirtual(ioMapAddr, (Address) &kernelioBitMap); /* Perform a context switch. */ contextSwitch( scheduler->old() ? &scheduler->old()->stackAddr : ZERO, pageDirAddr, stackAddr, &kernelTss, kernelStackAddr); }
/* * Description: This function blocks the thread with ID tid. The thread may * be resumed later using uthread_resume. If no thread with ID tid exists it * is considered as an error. In addition, it is an error to try blocking the * main thread (tid == 0). If a thread blocks itself, a scheduling decision * should be made. Blocking a thread in BLOCKED or SLEEPING states has no * effect and is not considered as an error. * Return value: On success, return 0. On failure, return -1. */ int uthread_block(int tid) { // Block SIGTVALRM signal sigset_t oldSet; blockSignal(SIGVTALRM, &oldSet); // Blocking the main thread is an error if (tid == MAIN_THREAD_ID) { std::cerr << LIB_ERROR_MSG << "can't block main thread." << std::endl; resetSigMask(&oldSet); return EXIT_FAIL; } // If no such thread exists, it is an error if (livingThreads.find(tid) == livingThreads.end()) { std::cerr << LIB_ERROR_MSG << "block(" << tid << ") failed - no such thread id" << std::endl; resetSigMask(&oldSet); return EXIT_FAIL; } // Check if the thread CAN be blocked // if not, do nothing. uthread *curr = livingThreads[tid]; if (curr->get_state() == uthread::state::BLOCKED || curr->get_state() == uthread::state::SLEEPING) { resetSigMask(&oldSet); return EXIT_SUCC; } // If a thread blocks itself switch context and exit // (the return will be executed after the thread is resumed) else if ((uthread::id)tid == currentThread) { curr->set_state(uthread::state::BLOCKED); resetSigMask(&oldSet); contextSwitch(SIGVTALRM); return EXIT_SUCC; } // Otherwise, change the thread's state to BLOCKED and remove it // from the READY list. curr->set_state(uthread::state::BLOCKED); auto th = std::find(readyThreads.begin(), readyThreads.end(), tid); readyThreads.erase(th); resetSigMask(&oldSet); return EXIT_SUCC; }
void FCFS::updateRunningProcess() { // if there is one process in Running state if (runningProcess) { runningProcess->elapsedBurstTime++; runningProcess->elapsedTotalTime++; if (!runningProcess->isBurstFinished(random)) return; else { runningProcess->endBurst(currentCPUCycle, IODelay); if (!runningProcess->isProcessDone()) wait.push(runningProcess); contextSwitch(); runningProcess = NULL; } } }
/* * Description: This function puts the RUNNING thread to sleep for a period * of num_quantums (not including the current quantum) after which it is moved * to the READY state. num_quantums must be a positive number. It is an error * to try to put the main thread (tid==0) to sleep. Immediately after a thread * transitions to the SLEEPING state a scheduling decision should be made. * Return value: On success, return 0. On failure, return -1. */ int uthread_sleep(int num_quantums) { // Block SIGTVALRM signal sigset_t oldSet; blockSignal(SIGVTALRM, &oldSet); if (currentThread == MAIN_THREAD_ID) { std::cerr << LIB_ERROR_MSG << "can't put main thread to sleep" << std::endl; resetSigMask(&oldSet); return EXIT_FAIL; } uthread *curr = livingThreads[currentThread]; curr->set_wakeup(totalQuanta + num_quantums); curr->set_state(uthread::state::SLEEPING); contextSwitch(SIGVTALRM); // Unblock SIGVTALRM and return resetSigMask(&oldSet); return EXIT_SUCC; }
//エンキュー bool logQueue::enqueue(const logPrintInfo& print_info) { const char* message = print_info.message(); if (!message)//messege が nullptr ならエンキュー成功扱い return true; //メッセージのバッファ割り当て char* queue_message = nullptr; const std::size_t queue_message_size = print_info.messageSize() > 0 ? print_info.messageSize() : strlen_fast(message) + 1; { static const int spin_count = GASHA_ DEFAULT_SPIN_COUNT; int spin_count_now = spin_count; while (!m_abort.load()) { //一時停止中は何もせずループする if (m_pause.load()) { GASHA_ contextSwitch(GASHA_ forceContextSwitch); continue; } //メッセージバッファの割り当て queue_message = reinterpret_cast<char*>(m_messageBuff.alloc(queue_message_size)); if (queue_message || IS_NO_WAIT_MODE) break; //メッセージバッファの割り当てができなければリトライ if (spin_count == 1 || (spin_count > 1 && --spin_count_now == 0)) { defaultContextSwitch(); spin_count_now = spin_count; } } if (!queue_message) return false; std::memcpy(queue_message, message, queue_message_size); } //メッセージのエンキュー logPrintInfo* info = nullptr; { const id_type id = print_info.id() > 0 ? print_info.id() : reserve(1); static const int spin_count = GASHA_ DEFAULT_SPIN_COUNT; int spin_count_now = spin_count; while (!m_abort.load()) { //一時停止中は何もせずループする if (m_pause.load()) { GASHA_ defaultContextSwitch(); continue; } //エンキュー logPrintInfo _print_info(print_info); _print_info.setId(id); _print_info.setMessage(queue_message); _print_info.setMessageSize(queue_message_size); info = m_queue.push(_print_info); if (info || IS_NO_WAIT_MODE) break; //キューイングできなければリトライ if (spin_count == 1 || (spin_count > 1 && --spin_count_now == 0)) { defaultContextSwitch(); spin_count_now = spin_count; } } //キューイングに失敗したらメッセージを解放して終了 if (!info) { m_messageBuff.free(queue_message); return false; } } return true; }
void primaryContextSwitch(ContextFunctor f) { if (!QOpenGLContext::globalShareContext()) return; contextSwitch(QOpenGLContext::globalShareContext(), f); }
void runSim(MMUSim* sim, Dllist* traces){ SimStats* simStats; simStats = &(sim->simStats); Dllist nil; nil = dll_nil(*traces); Dllist t; t = dll_first(*traces); MMUProcess* currProc; while(t != nil){ Trace* trace; trace = t->val.v; MMUProcess* proc; proc = getProcess(sim, trace->pid); if(currProc != proc){ contextSwitch(sim); } currProc = proc; ProcessStats* pStat; pStat = &proc->stats; pStat->memoryRef = pStat->memoryRef + 1; simStats->memoryRef = simStats->memoryRef + 1; unsigned int pageNum; unsigned int pageOffset; getPageNumOffset(sim, trace->address, &pageNum, &pageOffset); int op = trace->op; if(sim->log){ char* operation; if(op == 1) {operation = "Load from";} else if(op == 2) {operation = "Store to";} else if(op == 3) {operation = "Instruction fetch from";} fprintf(stderr, "Process[%u]: %s 0x%x (page: %u, offset: %u)\n", trace->pid, operation, trace->address, pageNum, pageOffset); } // Is the PTE in the TLB? PageTableEntry* tlbHit; retry: tlbHit = checkTLB(sim, pageNum); simStats->overallLat = simStats->overallLat + sim->tlbLat; if((int)tlbHit != -1){ // TLB hit if(sim->log) {fprintf(stderr, "\tTLB hit? yes\n");} simStats->overallLat = simStats->overallLat + sim->memLat; // if write, mark dirty if(op == 2){ // Is a write operation? tlbHit->dirty = 1; } if(sim->log) {fprintf(stderr, "\tpage %d in frame %d\n", pageNum, tlbHit->physicalFrame->num);} touchFrame(sim, tlbHit->physicalFrame); }else{ // TLB miss if(sim->log) {fprintf(stderr, "\tTLB hit? no\n");} pStat->tlbMisses = pStat->tlbMisses + 1; simStats->tlbMisses = simStats->tlbMisses + 1; // Is the Physical Frame of the PTE present? PageTableEntry* pte; pte = checkPageTable(sim, proc->pgtbl, pageNum); if(pte->present){ // Present bit is set if(sim->log) {fprintf(stderr, "\tPage fault? no\n");} addPageToTlb(sim, trace->address, pte); simStats->overallLat = simStats->overallLat + sim->tlbLat; // retry goto retry; } else { // Physical frame is not loaded (present) if(sim->log) {fprintf(stderr, "\tPage fault? yes\n");} pStat->pageFaults = pStat->pageFaults + 1; simStats->pageFaults = simStats->pageFaults + 1; // Is there room? PhysicalFrame* pfn; pfn = findFreePhysicalPage(sim); if(pfn != -1){ // We found a free physical frame if(sim->log) {fprintf(stderr, "\tMain memory eviction? no\n");} } else { // no physical frame was found, need to evict if(sim->log) {fprintf(stderr, "\tMain memory eviction? yes\n");} // Update evicted PTE PhysicalFrame* evPte; // evicted PTE PfEvict(sim); // evict a frame based on the chosen policy evPte = findFreePhysicalPage(sim); // go and find that frame MMUProcess* evProc; evProc = getProcess(sim, evPte->pid); // get the process for the evicted frame PageTableEntry* evPageTable; evPageTable = evProc->pgtbl->table; unsigned int evIndex = evPte->pageNum; PageTableEntry* evPageTableEntry; // evicted PageTableEntry evPageTableEntry = &evPageTable[evIndex]; evPageTableEntry->present = 0; pfn = evPte; // clean eviction? if(evPageTableEntry->dirty){ // the frame in memory is dirty and needs disk write if(sim->log) {fprintf(stderr, "\tProcess %d page %u (dirty) evicted from memory\n", evProc->pid, evPte->pageNum);} pStat->dirtyEvict = pStat->dirtyEvict + 1; simStats->dirtyEvict = simStats->dirtyEvict + 1; // wite to disk + disk access simStats->overallLat = simStats->overallLat + sim->diskLat; } else { // frame is clean if(sim->log) {fprintf(stderr, "\tProcess %d page %u (clean) evicted from memory\n", evProc->pid, evPte->pageNum);} pStat->cleanEvict = pStat->cleanEvict + 1; simStats->cleanEvict = simStats->cleanEvict + 1; } // update PTE } pte->page = pageNum; pte->physicalFrame = pfn; simStats->overallLat = simStats->overallLat + sim->diskLat; pte->pid = proc->pid; pte->present = 1; pfn->pid = proc->pid; pfn->pageNum = pageNum; simStats->overallLat = simStats->overallLat + sim->memLat; // update tlb addPageToTlb(sim, trace->address, pte); simStats->overallLat = simStats->overallLat + sim->tlbLat; goto retry; } } if(sim->log) {fprintf(stderr, "\n");} t = t->flink; } }