Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
/*
 * 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);
}
Ejemplo n.º 3
0
 *   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)