/* * Exit the current thread. * Calling this function initiates a context switch. */ void Exit(int exitCode) { struct Kernel_Thread* current = g_currentThread; if (Interrupts_Enabled()) Disable_Interrupts(); /* Thread is dead */ current->exitCode = exitCode; current->alive = false; /* Clean up any thread-local memory */ Tlocal_Exit(g_currentThread); /* Notify the thread's owner, if any */ Wake_Up(¤t->joinQueue); /* Remove the thread's implicit reference to itself. */ Detach_Thread(g_currentThread); /* * Schedule a new thread. * Since the old thread wasn't placed on any * thread queue, it won't get scheduled again. */ Schedule(); /* Shouldn't get here */ KASSERT(false); }
/* * Wake up all threads waiting on the given condition. * The mutex guarding the condition should be held! */ void Cond_Broadcast(struct Condition* cond) { KASSERT(Interrupts_Enabled()); Disable_Interrupts(); /* prevent scheduling */ Wake_Up(&cond->waitQueue); Enable_Interrupts(); /* resume scheduling */ }
int Destroy_Semaphore(int sid) { if (!validateSID(sid)) { return EINVALID; } bool atomic = Begin_Int_Atomic(); KASSERT(0 < g_Semaphores[sid].references); g_Semaphores[sid].references--; Clear_Bit(g_currentThread->semaphores, sid); if (g_Semaphores[sid].references == 0) { g_Semaphores[sid].available = true; /* mark it available */ Wake_Up(&g_Semaphores[sid].waitingThreads); /* wake all threads */ } End_Int_Atomic(atomic); return 0; }
/* * Handler for keyboard interrupts. */ static 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(); /* * Print("code=%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: %x\n", scanCode); goto done; } /* Process the key */ shift = ((s_shiftState & SHIFT_MASK) != 0); keycode = shift ? s_scanTableWithShift[scanCode] : s_scanTableNoShift[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 = true; } done: End_IRQ(state); }
/* * Hand given thread to the reaper for destruction. * Must be called with interrupts disabled! */ static void Reap_Thread(struct Kernel_Thread* kthread) { KASSERT(!Interrupts_Enabled()); Enqueue_Thread(&s_graveyardQueue, kthread); Wake_Up(&s_reaperWaitQueue); }
/* * Wake up any threads in the floppy wait queue. */ static void Floppy_Interrupt_Handler(struct Interrupt_State* state) { Begin_IRQ(state); Wake_Up(&s_floppyInterruptWaitQueue); End_IRQ(state); }