void thread_delay(unsigned msecs) { thread_t *prev, *next; uint64_t st; uint64_t delay; if (!msecs) return; st = clock_get_ticks(); delay = clock_convert_msecs_to_ticks(msecs); prev = scheduler_running_thread(); if (!scheduler_delay_thread(st + delay)) { kernel_panic("cannot delay a thread.\n"); return; } schedule_thread(); next = scheduler_running_thread(); switch_context(prev->context, next->context); }
void switch_tasks() { uint32_t eflags = disable_interrupts(); task_t *old_task = current_task(); task_t *current_candidate = old_task->next; task_t *first_candidate = current_candidate; task_t *selected = NULL; // Buscamos una tarea que este lista para ejecutarse. Si no hay ninguna, // hacemos halt hasta que ocurra una interrupcion. do { do { if (!(current_candidate->waiting)) { selected = current_candidate; break; } current_candidate = current_candidate->next; } while(current_candidate != first_candidate); if (selected == NULL) { outb(PIC1_DATA, (PIC_ALL_ENABLED & (~PIC_TIMER)) | PIC_TIMER); wait_for_interrupt(); outb(PIC1_DATA, PIC_ALL_ENABLED); } } while (selected == NULL); task_list = selected; switch_context(old_task, current_task()); restore_eflags(eflags); }
/* Handles the timer. In this case, it's very simple: We * increment the 'timer_ticks' variable every time the * timer fires. By default, the timer fires 18.222 times * per second. Why 18.222Hz? Some engineer at IBM must've * been smoking something funky */ void timer_handler() { static int once = 0; static char *video_buf = NULL; //printf("Timer interrupt"); if(once == 0 || (uint64_t)video_buf != (((uint64_t)global_video_vaddr) + 4000)) { once = 1; video_buf = (char*)(((uint64_t)global_video_vaddr) + 4000); /* end of video memory */ *(video_buf-2) = *(video_buf-4) = '0'; *(video_buf-8) = *(video_buf-10) = '0'; *(video_buf-14) = *(video_buf-16) = '0'; *(video_buf-6) = *(video_buf-12) = ':'; } /* Increment our 'tick count' */ timer_ticks++; sys_wakeup_timer(); /* Switch every 10ms */ if(timer_ticks % 100 == 0){ /* And yes, that's a 60 pointer CS506 project! :) Preemption! */ switch_context(); } /* Every 18 clocks (approximately 1 second), we will * display a message on the screen */ if (timer_ticks % PIT_CLOCK_HZ == 0) { timer_ticks = 0; if(++time_sec == 60) { time_sec = 0; if(++time_min == 60) { time_min = 0; ++time_hour; *(video_buf-16) = '0' + (time_hour/10); *(video_buf-14) = '0' + (time_hour%10); } *(video_buf-10) = '0' + (time_min/10); *(video_buf-8) = '0' + (time_min%10); } *(video_buf-4) = '0' + (time_sec/10); *(video_buf-2) = '0' + (time_sec%10); //printf("%d:%d:%d\n",time_hour,time_min,time_sec); } }
void reschedule(void) { size_t** stack; uint8_t flags; flags = irq_nested_disable(); if ((stack = scheduler())) switch_context(stack); irq_nested_enable(flags); }
void sched_sleep(int param_time, int pid) { sleeping_pid=pid; sleep_time=param_time; //video_write_byte(param_time+'0'); sleep_flag=1; set_state(pid,SLEEPING); //__print_debug("Entra aca"); //__video_debug(pid+'0'); switch_context(); }
void schedule() { struct task_t* old_task = current_task; current_task = current_task->next; if(!current_task) current_task = ready_queue_start; if(current_task != old_task) switch_context(&old_task->context, current_task->context); }
void Thread_Switch(Thread * newTh) { Thread *oldTh = g_CurrTh; g_CurrTh = newTh; stat_ContextSwitch++; newTh->nrUsed++; switch_context(&newTh->regSP, &oldTh->regSP); /* **************************************************************** * Everything below switch_registers will be done in the new * context (or not at all if the new context was not left here). **************************************************************** */ }
void thread_schedule() { thread_t* target = thread_pick(); assert(target); if(thread_current == target) return; s64 new_cr3 = 0; if(target->process) { new_cr3 = VIR2PHY(target->process->page_dir); } *(void**)PHY2VIR(tss64_rsp0) = target->kstack_end; // set rsp0 switch_context(target, new_cr3); }
void Dispatcher(){ while(readyHead == NULL && timerHead!= NULL) { CALL(Z502Idle()); } if(readyHead!=NULL) { schedular_printer(READY); lockReady(); CALL(makeReadyToRun(readyHead)); current_PCB_PTR=makeReady; current_PCB_PTR->p_status = RUNNING; unlockReady(); CALL(switch_context(current_PCB_PTR)); } return; }
void thread_lock_mutex(mutex_t *mtx) { thread_t *prev, *next; BOOL is_locked; if (!mtx) { return; } prev = scheduler_running_thread(); is_locked = mutex_is_locked(mtx); if (lock_mutex(prev->tid, mtx) && is_locked) { scheduler_wait_thread(THREAD_FLAG_WAIT_MUTEX); schedule_thread(); next = scheduler_running_thread(); switch_context(prev->context, next->context); } }
void thread_suspend() { thread_t *prev, *next; prev = scheduler_running_thread(); if (!scheduler_suspend_thread()) { kernel_panic("cannot suspend a thread.\n"); return; } schedule_thread(); next = scheduler_running_thread(); /* No one to wait for */ if (prev == next) { return; } switch_context(prev->context, next->context); }
void timer_handler(void *arg) { tickcnt++; mtpr(0xc1, PR_ICCS); /* start multitask? */ if ((sched_on == 1) && (sched_running == 0)) { sched_running = 1; } /* stop multitask? */ if (current_process == 0) { if ((sched_on == 0) && (sched_running == 1)) { sched_running = 0; } } /* schedule? */ if (sched_running) { switch_context(); /* schedule and pre-dispatch in clock IPL */ mtpr(3, PR_SIRR); /* request soft int in IPL 3 to real hardware switch */ } }
int do_ptrace(int request, int child_id, DWORD addr, DWORD data, DWORD * ret) { NEWPROCESS *child; #ifdef CONFIG_KDEB if (child_id == 1) return KDEB_ptrace(request, addr, data, ret); #endif if (!(child = find_process(child_id))) return EMX_ESRCH; if (child->pptr != npz || !(child->p_flags & PF_DEBUG)) return EMX_ESRCH; if (child->p_status != PS_STOP) return EMX_ESRCH; *ret = 0; switch (request) { case PTRACE_TRACEME: case PTRACE_SESSION: return 0; case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: if (verify_illegal(child, addr, 4)) return EMX_EIO; *ret = read32(child->data32sel, addr); return 0; case PTRACE_POKETEXT: case PTRACE_POKEDATA: if (verify_illegal(child, addr, 4)) return EMX_EIO; if (dpmi10) { WORD page, pageorg; read32(child->data32sel, addr); /* page in */ if (GetPageAttributes(child->memhandle, addr & ~0xFFFL, 1, &pageorg)) return EMX_EIO; pageorg &= ~16; /* don't modify access/dirty */ page = pageorg | 8; /* read/write access */ if (ModifyPageAttributes(child->memhandle, addr & ~0xFFFL, 1, &page)) return EMX_EIO; store32(child->data32sel, addr, data); ModifyPageAttributes(child->memhandle, addr & ~0xFFFL, 1, &pageorg); } else store32(child->data32sel, addr, data); *ret = data; return 0; case PTRACE_EXIT: /* to do : switch to child -> do_signal(); */ child->p_flags |= PF_WAIT_WAIT; return 0; case PTRACE_PEEKUSER: if (addr == 0x30) { /* u_ar0 */ *ret = 0xE0000000 + ((DWORD) (UINT) & (child->regs)); return 0; } else { /* peek regs */ DWORD *peekat; peekat = (DWORD *) (UINT) (addr); if (peekat < &(child->regs.gs) || peekat > &(child->regs.ss)) return EMX_EIO; *ret = *peekat; return 0; } case PTRACE_POKEUSER: { /* poke regs */ DWORD *pokeat; pokeat = (DWORD *) (UINT) addr; if (pokeat < &(child->regs.gs) || pokeat > &(child->regs.ss)) return EMX_EIO; /* change data for critical regs */ if (pokeat == &(child->regs.eflags)) { data &= FLAG_MASK; data |= *pokeat & ~FLAG_MASK; } else if (pokeat <= &(child->regs.ds) || pokeat == &(child->regs.cs)) data = *pokeat; else if (pokeat == &(child->regs.esp)) { if (verify_illegal(child, data, 4)) return EMX_EIO; child->regs.esp = data; child->regs.esporg = data + 12L; } else if (pokeat == &(child->regs.esporg)) { if (verify_illegal(child, data, 4)) return EMX_EIO; child->regs.esporg = data; child->regs.esp = data - 12L; } else if (pokeat == &(child->regs.eip)) if (verify_illegal(child, data, 4)) return EMX_EIO; *pokeat = data; *ret = data; return 0; } case PTRACE_STEP: if ((int)data > 0 && (int)data <= MAX_SIGNALS) send_signal(child, (WORD) data); child->regs.eflags |= SINGLE_STEP; if (child->regs.esp == child->regs.esporg) child->regs.esp -= 12; npz->p_status = PS_STOP; switch_context(child); npz->p_status = PS_RUN; return 0; case PTRACE_RESUME: if ((int)data > 0 && (int)data <= MAX_SIGNALS) send_signal(child, (int) data); if (child->regs.esp == child->regs.esporg) child->regs.esp -= 12; npz->p_status = PS_STOP; switch_context(child); npz->p_status = PS_RUN; return 0; default: return EMX_EIO; } }
int daemon_main(int argc, char *argv[]) { int opt; bool fork_flag = false; bool replace_flag = false; bool patch_sepolicy = true; enum { OPT_ALLOW_ROOT_CLIENT = 1000, OPT_NO_PATCH_SEPOLICY = 1001, OPT_SIGSTOP_WHEN_READY = 1002, OPT_LOG_TO_KMSG = 1003, OPT_LOG_TO_STDIO = 1004, OPT_NO_UNSHARE = 1005, }; static struct option long_options[] = { {"daemonize", no_argument, 0, 'd'}, {"replace", no_argument, 0, 'r'}, {"help", no_argument, 0, 'h'}, {"allow-root-client", no_argument, 0, OPT_ALLOW_ROOT_CLIENT}, {"no-patch-sepolicy", no_argument, 0, OPT_NO_PATCH_SEPOLICY}, {"sigstop-when-ready", no_argument, 0, OPT_SIGSTOP_WHEN_READY}, {"log-to-kmsg", no_argument, 0, OPT_LOG_TO_KMSG}, {"log-to-stdio", no_argument, 0, OPT_LOG_TO_STDIO}, {"no-unshare", no_argument, 0, OPT_NO_UNSHARE}, {0, 0, 0, 0} }; int long_index = 0; while ((opt = getopt_long(argc, argv, "drh", long_options, &long_index)) != -1) { switch (opt) { case 'd': fork_flag = true; break; case 'r': replace_flag = true; break; case 'h': daemon_usage(0); return EXIT_SUCCESS; case OPT_ALLOW_ROOT_CLIENT: allow_root_client = true; break; case OPT_NO_PATCH_SEPOLICY: patch_sepolicy = false; break; case OPT_SIGSTOP_WHEN_READY: sigstop_when_ready = true; break; case OPT_LOG_TO_KMSG: log_to_kmsg = true; break; case OPT_LOG_TO_STDIO: log_to_stdio = true; break; case OPT_NO_UNSHARE: no_unshare = true; break; default: daemon_usage(1); return EXIT_FAILURE; } } // There should be no other arguments if (argc - optind != 0) { daemon_usage(1); return EXIT_FAILURE; } if (!no_unshare && unshare(CLONE_NEWNS) < 0) { fprintf(stderr, "unshare() failed: %s\n", strerror(errno)); return EXIT_FAILURE; } if (patch_sepolicy) { patch_loaded_sepolicy(SELinuxPatch::MAIN); } if (!switch_context(MB_EXEC_CONTEXT)) { fprintf(stderr, "Failed to switch context; %s may not run properly", argv[0]); } if (replace_flag) { PROCTAB *proc = openproc(PROC_FILLCOM | PROC_FILLSTAT); if (proc) { pid_t curpid = getpid(); while (proc_t *info = readproc(proc, nullptr)) { // NOTE: Can't check 'strcmp(info->cmd, "mbtool") == 0' (which // is the basename of /proc/<pid>/cmd) because the binary is not // always called "mbtool". For example, when run via SignedExec, // it's just called "binary". // If we can read the cmdline and argc >= 2 if (info->cmdline && info->cmdline[0] && info->cmdline[1]) { const char *name = strrchr(info->cmdline[0], '/'); if (name) { ++name; } else { name = info->cmdline[0]; } if (strcmp(name, "mbtool") == 0 // This is mbtool && strstr(info->cmdline[1], "daemon") // And it's a daemon process && info->tid != curpid) { // And we're not killing ourself // Kill the daemon process LOGV("Killing PID %d", info->tid); kill(info->tid, SIGTERM); } } freeproc(info); } closeproc(proc); } // Give processes a chance to exit usleep(500000); } if (fork_flag) { run_daemon_fork(); } else { return (daemon_init() && run_daemon()) ? EXIT_SUCCESS : EXIT_FAILURE; } }
int __xnsched_run(struct xnsched *sched) { struct xnthread *prev, *next, *curr; int switched, shadow; spl_t s; if (xnarch_escalate()) return 0; trace_cobalt_schedule(sched); xnlock_get_irqsave(&nklock, s); curr = sched->curr; /* * CAUTION: xnthread_host_task(curr) may be unsynced and even * stale if curr = &rootcb, since the task logged by * leave_root() may not still be the current one. Use * "current" for disambiguating. */ xntrace_pid(current->pid, xnthread_current_priority(curr)); reschedule: switched = 0; if (!test_resched(sched)) goto out; next = xnsched_pick_next(sched); if (next == curr) { if (unlikely(xnthread_test_state(next, XNROOT))) { if (sched->lflags & XNHTICK) xnintr_host_tick(sched); if (sched->lflags & XNHDEFER) xnclock_program_shot(&nkclock, sched); } goto out; } prev = curr; trace_cobalt_switch_context(prev, next); if (xnthread_test_state(next, XNROOT)) xnsched_reset_watchdog(sched); sched->curr = next; shadow = 1; if (xnthread_test_state(prev, XNROOT)) { leave_root(prev); shadow = 0; } else if (xnthread_test_state(next, XNROOT)) { if (sched->lflags & XNHTICK) xnintr_host_tick(sched); if (sched->lflags & XNHDEFER) xnclock_program_shot(&nkclock, sched); enter_root(next); } xnstat_exectime_switch(sched, &next->stat.account); xnstat_counter_inc(&next->stat.csw); switch_context(sched, prev, next); /* * Test whether we transitioned from primary mode to secondary * over a shadow thread, caused by a call to xnthread_relax(). * In such a case, we are running over the regular schedule() * tail code, so we have to skip our tail code. */ if (shadow && ipipe_root_p) goto shadow_epilogue; switched = 1; sched = xnsched_finish_unlocked_switch(sched); /* * Re-read the currently running thread, this is needed * because of relaxed/hardened transitions. */ curr = sched->curr; xnthread_switch_fpu(sched); xntrace_pid(current->pid, xnthread_current_priority(curr)); out: if (switched && xnsched_maybe_resched_after_unlocked_switch(sched)) goto reschedule; if (curr->lock_count) sched->lflags |= XNINLOCK; xnlock_put_irqrestore(&nklock, s); return switched; shadow_epilogue: __ipipe_complete_domain_migration(); XENO_BUG_ON(COBALT, xnthread_current() == NULL); /* * Interrupts must be disabled here (has to be done on entry * of the Linux [__]switch_to function), but it is what * callers expect, specifically the reschedule of an IRQ * handler that hit before we call xnsched_run in * xnthread_suspend() when relaxing a thread. */ XENO_BUG_ON(COBALT, !hard_irqs_disabled()); return 1; }