void Timer_Interrupt_Handler(struct Interrupt_State *state) { int i; int id; struct Kernel_Thread *current = CURRENT_THREAD; Begin_IRQ(state); id = Get_CPU_ID(); if(!id) { /* Update global number of ticks - only on core 0 so won't count a rate equal to number of cores */ ++g_numTicks; } /* Update per-thread number of ticks and per core ticks */ ++current->numTicks; ++current->totalTime; CPUs[id].ticks++; /* * If thread has been running for an entire quantum, * inform the interrupt return code that we want * to choose a new thread. */ if(!id) { // XXXX - only core #0 is currently handling new timer events /* update timer events */ for(i = 0; i < timeEventCount; i++) { if(pendingTimerEvents[i].ticks == 0) { if(timerDebug) Print("timer: event %d expired (%d ticks)\n", pendingTimerEvents[i].id, pendingTimerEvents[i].origTicks); (pendingTimerEvents[i].callBack) (pendingTimerEvents[i]. id); } else { if(timerDebug) Print("timer: event %d at %d ticks\n", pendingTimerEvents[i].id, pendingTimerEvents[i].ticks); pendingTimerEvents[i].ticks--; } } } if(current->numTicks >= g_Quantum) { g_needReschedule[id] = true; // TODO: /* * The current process is moved to a lower priority queue, * since it consumed a full quantum. */ } End_IRQ(state); }
/* * Handler for keyboard interrupts. */ void Keyboard_Interrupt_Handler(struct Interrupt_State *state) { uchar_t status, scanCode; unsigned flag = 0; bool release = false, shift; Keycode keycode; Begin_IRQ(state); status = In_Byte(KB_CMD); IO_Delay(); if ((status & KB_OUTPUT_FULL) != 0) { /* There is a byte available */ scanCode = In_Byte(KB_DATA); IO_Delay(); DEBUG_KEYBOARD("code=%x%s\n", scanCode, (scanCode & 0x80) ? " [release]" : ""); shift = ((s_shiftState & SHIFT_MASK) != 0); static const Keycode *scantable_using_current_modifiers; scantable_using_current_modifiers = shift ? s_scanTableWithShift : s_scanTableNoShift; if (scanCode == 0xe0) { /* e0 is a prefix for keypad arrows and right alt/ctrl. */ scanCode = In_Byte(KB_DATA); IO_Delay(); scantable_using_current_modifiers = s_scanTableE0; DEBUG_KEYBOARD("suffixcode=%x%s\n", scanCode, (scanCode & 0x80) ? " [release]" : ""); } if (scanCode & KB_KEY_RELEASE) { release = true; scanCode &= ~(KB_KEY_RELEASE); } if (scanCode >= SCAN_TABLE_SIZE) { Print("Unknown scan code: 0x%x\n", scanCode); goto done; } keycode = scantable_using_current_modifiers[scanCode]; /* Update shift, control and alt state */ switch (keycode) { case KEY_LSHIFT: flag = LEFT_SHIFT; break; case KEY_RSHIFT: flag = RIGHT_SHIFT; break; case KEY_LCTRL: flag = LEFT_CTRL; break; case KEY_RCTRL: flag = RIGHT_CTRL; break; case KEY_LALT: flag = LEFT_ALT; break; case KEY_RALT: flag = RIGHT_ALT; break; default: goto noflagchange; } if (release) s_shiftState &= ~(flag); else s_shiftState |= flag; /* * Shift, control and alt keys don't have to be * queued, flags will be set! */ goto done; noflagchange: /* Format the new keycode */ if (shift) keycode |= KEY_SHIFT_FLAG; if ((s_shiftState & CTRL_MASK) != 0) keycode |= KEY_CTRL_FLAG; if ((s_shiftState & ALT_MASK) != 0) keycode |= KEY_ALT_FLAG; if (release) keycode |= KEY_RELEASE_FLAG; /* Put the keycode in the buffer */ Enqueue_Keycode(keycode); /* Wake up event consumers */ Wake_Up(&s_waitQueue); /* * Pick a new thread upon return from interrupt * (hopefully the one waiting for the keyboard event) */ g_needReschedule[Get_CPU_ID()] = true; } done: End_IRQ(state); }
* state - saved processor registers describing the state when * the thread was interrupted */ void Switch_To_User_Context(struct Kernel_Thread *kthread, struct Interrupt_State *state __attribute__ ((unused))) { int cpuID; extern int userDebug; struct User_Context *userContext = kthread->userContext; /* * FIXME: could avoid resetting ss0/esp0 if not returning * to user space. */ cpuID = Get_CPU_ID(); KASSERT(!Interrupts_Enabled()); if (CPUs[cpuID].s_currentUserContext && userContext == 0) { /* Kernel mode thread: muse switch kernel address space. another core could delete a user context while this thread is using it otherwise. */ Set_PDBR((void *)Kernel_Page_Dir()); CPUs[cpuID].s_currentUserContext = NULL; return; } /* Switch only if the user context is indeed different */ if (userContext != CPUs[cpuID].s_currentUserContext) { if (userDebug)