static void sys_unmap_wrap(struct x86_exregs *regs) { L4_Word_t control = regs->eax; /* TODO: pass utcb to sys_unmap()? */ void *utcb = thread_get_utcb(get_current_thread()); if((control & 0x3f) > 0) L4_VREG(utcb, L4_TCR_MR(0)) = regs->esi; sys_unmap(control); regs->esi = L4_VREG(utcb, L4_TCR_MR(0)); }
/* the IAPC PIT 1000hz interrupt. */ void isr_irq0_bottom(struct x86_exregs *regs) { uint64_t now = ++global_timer_count; (*systemclock_p) += 1000; (*global_pic.send_eoi)(0); if(now < preempt_timer_count) return; TRACE("%s: preempt hit at now=%u\n", __func__, (unsigned)now); preempt_timer_count = ~0ull; assert(preempt_thread == NULL || thread_is_valid(preempt_thread)); if(irq_in_kernel(regs) && !kernel_irq_ok) { /* defer a magical call to on_preempt() as though it were any old * interrupt. */ irq_defer(0x20); TRACE("%s: preempt deferred\n", __func__); return; } struct thread *current = get_current_thread(); bool ctx_saved = false; if(CHECK_FLAG(preempt_status, PS_DELAYED) || (current != NULL && preempt_thread != NULL && preempt_thread->pri <= current->sens_pri && current->max_delay == 0 && CHECK_FLAG_ALL(L4_VREG(thread_get_utcb(current), L4_TCR_COP_PREEMPT), 0x60))) { assert(!CHECK_FLAG(current->flags, TF_SYSCALL)); save_user_ex(regs); ctx_saved = true; } struct thread *next = on_preempt(0x20); if(current == NULL) { /* scheduled activation from idle. */ if(next != NULL) { TRACE("%s: scheduled activation of next=%lu:%lu\n", __func__, TID_THREADNUM(next->id), TID_VERSION(next->id)); } else { TRACE("%s: idle -> idle\n", __func__); } kernel_irq_ok = false; } else if(next != current) { /* async preëmption of @current. */ assert(!CHECK_FLAG(current->flags, TF_SYSCALL)); TRACE("%s: async preëmpt of %lu:%lu\n", __func__, TID_THREADNUM(current->id), TID_VERSION(current->id)); if(!ctx_saved) save_user_ex(regs); if(!IS_IPC(current->status)) { current->status = TS_READY; current->wakeup_time = 0; sq_update_thread(current); } } return_from_irq(next); TRACE("%s: returning to userspace (preempt_timer_count'=%u)\n", __func__, (unsigned)preempt_timer_count); BUG_ON(next != current, "shouldn't get here!"); }