Esempio n. 1
0
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;
}
Esempio n. 2
0
/*
 * 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;
	}
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
/*
 * 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;
}
Esempio n. 5
0
	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;
			}
		}
	}
Esempio n. 6
0
/*
 * 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;
}
Esempio n. 7
0
//エンキュー
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;
}
Esempio n. 8
0
 void primaryContextSwitch(ContextFunctor f) {
   if (!QOpenGLContext::globalShareContext()) return;
   contextSwitch(QOpenGLContext::globalShareContext(), f);
 }
Esempio n. 9
0
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;
  }
  
}