⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kern_cpureserve.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
字号:
/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Data structures for reserve management.  The current kernel * implementation uses a fixed-priority strategy for implementing * cpu reserves. */#include <kerninc/kernel.hxx>#include <kerninc/Thread.hxx>#include <kerninc/CpuReserve.hxx>#include <kerninc/Machine.hxx>#include <kerninc/PhysMem.hxx>#include <arch-kerninc/KernTune.hxx>#include <eros/Reserve.h>const int DEFAULT_SCHED_QUANTA = 10; /* in ms */CpuReserve *CpuReserve::Current = 0;/* Reserves associated with ordinary schedule keys -- the 'priority' * is actually an index into the reserve table: */CpuReserve *CpuReserve::CpuReserveTable;/* Processes that lack a schedule capability need a reserve that they * can be parked on so as to ensure that they are never scheduled. The * priority of this reserve needs to be BELOW the idle priority. */CpuReserve CpuReserve::InactiveReserve(Prio::Inactive);/* Idle thread requires it's own scheduling reserve, as the user-level * idle reserve is actually higher priority than this one. */CpuReserve CpuReserve::KernIdleCpuReserve(Prio::KernIdle);/* Other kernel threads require their own copy of the normal priority * reserve because the reserve table isn't allocated yet when we * allocate some of the early kernel threads. */CpuReserve CpuReserve::KernThreadCpuReserve(Prio::Normal);/* OnQuantaExpiration()  is called whenever the residual quanta of a * reserve goes to zero (i.e. when whenever the quanta expires).  When * a process hits the end of it's quanta, we recompute the reserve's * effective priority and re-queue the process at that priority. *  * The basic idea is that the * low level clock code will down-count the residual quanta.  When it * hits zero, it will call Thread::ShouldYield() on the current * thread.  The Yield() code will recompute priority for current * thread if appropriate and drop it to the back of the run queue at * that priority. */voidCpuReserve::OnQuantaExpiration(){  /* dprintf(false, "Quanta expired on cpu reserve 0x%08x\n", this); */    Thread::Current()->Preempt();#if 0  if (!Thread::Current()->CAN_PREEMPT()) {    printf("CpuReserve::OnQuantaExpiration(): 0x%08x Quanta expires in NOPREEMPT, state %d.\n",		   Thread::Current(), Thread::Current()->state);   }#endif    if (residDuration) {	/* reserve still active. */    residQuanta = min(residDuration, quanta);    residDuration -= quanta;  }  else {			/* not running under reserve. */    if (active)      Deplenish();        residQuanta = quanta;  }  expired = false;}voidCpuReserve::AdjustCurPrio(int prio){  curPrio = prio;    Link *nextLink = threadChain.prev;    while (nextLink) {    Thread *t = Thread::ThreadFromCpuReserveLinkage(nextLink);    nextLink = nextLink->next;    /* Reposition the thread in the run queue: */    t->Unlink();    t->Wakeup();  }}/* Note that both Deplenish() and Replenish() preserve ordering of * threads in the run queue! */voidCpuReserve::Deplenish(){  /*  dprintf(false, "Deplenishing CpuReserve 0x%08x\n", this); */  active = false;  AdjustCurPrio(normPrio);}voidCpuReserve::Replenish(){  /* dprintf(false, "Replenishing CpuReserve 0x%08x\n", this); */  /* If a thread under this reserve happens to be currently running,   * it gets an extra boost via quanta extension.   */  if (period && duration) {    active = true;    residQuanta = quanta;    residDuration = duration - quanta;      AdjustCurPrio(rsrvPrio);    uint64_t nextPeriod = SysTimer::Now() + period;    reserveTimer.WakeupAtTick(nextPeriod, &CpuReserve::Replenish);  }  else {    active = false;    AdjustCurPrio(normPrio);  }  expired = false;}voidCpuReserve::Replenish(Timer* timer){  CpuReserve &r = *((CpuReserve *) timer->client_ptr);  r.Replenish();}CpuReserve::CpuReserve(){  start = 0ll;  quanta = Machine::MillisecondsToTicks(DEFAULT_SCHED_QUANTA);  duration = 0ll;  period = 0ll;  expired = false;  residQuanta = quanta;  residDuration = 0ll;  rsrvPrio = Prio::Inactive;  normPrio = Prio::Inactive;  active = false;  curPrio = normPrio;    reserveTimer.client_ptr = this;}CpuReserve::CpuReserve(int prio){  start = 0ll;  quanta = Machine::MillisecondsToTicks(DEFAULT_SCHED_QUANTA);  duration = 0ll;  period = 0ll;  expired = false;  residQuanta = quanta;  residDuration = 0ll;  rsrvPrio = Prio::Inactive;  normPrio = prio;  active = false;  curPrio = normPrio;    reserveTimer.client_ptr = this;}voidCpuReserve::AddKernelThread(Thread *t){  AddUserThread(t);  assert (t->context);  t->context->cpuReserve = this;}/* Reserve linkage not circular! */voidCpuReserve::AddUserThread(Thread *t){  Link& reserveLinkage = t->reserveLinkage;#if 0  if (t->IsUser())    dprintf(true, "Add user thrd 0x%08x to rsrv 0x%08x\n", t,		    this);  else {    assert (reserveLinkage.next == 0);    assert (reserveLinkage.prev == 0);  }#endif    reserveLinkage.Unlink();  t->cpuReserve = this;      reserveLinkage.next = threadChain.next;  if (threadChain.next)    threadChain.next->prev = &reserveLinkage;  threadChain.next = &reserveLinkage;  reserveLinkage.prev = &threadChain;}voidCpuReserve::AllocUserCpuReserves(){  CpuReserveTable = new (0) CpuReserve[MAX_CPU_RESERVE];  for (int i = 0; i < STD_CPU_RESERVE; i++) {    CpuReserveTable[i].normPrio = i;    CpuReserveTable[i].AdjustCurPrio(i);  }  printf("Allocated CPU Reserves: 0x%x at 0x%08x\n",		 sizeof(CpuReserve[MAX_CPU_RESERVE]), CpuReserveTable);}voidCpuReserve::Reset(){  if (quanta == 0)    quanta = Machine::MillisecondsToTicks(DEFAULT_SCHED_QUANTA);  if (duration && period) {    if (start)      reserveTimer.WakeupAtTick(start, Replenish);    else			/* wake it up right now. */      Replenish();  }  else {    Deplenish();  }}CpuReserve&CpuReserve::GetReserve(const Key& k){  if (k.IsType(KT_Sched))    return CpuReserveTable[k.keyData];  return InactiveReserve;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -