nuclear@51: #include nuclear@51: #include "sched.h" nuclear@51: #include "proc.h" nuclear@51: #include "intr.h" nuclear@51: #include "asmops.h" nuclear@51: #include "config.h" nuclear@51: nuclear@51: #define EMPTY(q) ((q).head == 0) nuclear@51: nuclear@51: struct proc_list { nuclear@51: struct process *head, *tail; nuclear@51: }; nuclear@51: nuclear@51: static void ins_back(struct proc_list *q, struct process *proc); nuclear@51: static void ins_front(struct proc_list *q, struct process *proc); nuclear@51: static void remove(struct proc_list *q, struct process *proc); nuclear@51: nuclear@51: static struct proc_list runq; nuclear@51: static struct proc_list waitq; nuclear@51: static struct proc_list zombieq; nuclear@51: nuclear@51: void schedule(void) nuclear@51: { nuclear@51: if(EMPTY(runq)) { nuclear@51: /* idle "process". nuclear@51: * make sure interrupts are enabled before halting nuclear@51: */ nuclear@51: enable_intr(); nuclear@51: halt_cpu(); nuclear@51: /* this won't return, it'll just wake up in an interrupt later */ nuclear@51: } nuclear@51: nuclear@51: disable_intr(); nuclear@51: nuclear@51: /* if the current process exhausted its timeslice, nuclear@51: * move it to the back of the queue. nuclear@51: */ nuclear@51: if(runq.head->ticks_left <= 0) { nuclear@51: if(runq.head->next) { nuclear@51: struct process *proc = runq.head; nuclear@51: remove(&runq, proc); nuclear@51: ins_back(&runq, proc); nuclear@51: } nuclear@51: nuclear@51: /* start a new timeslice */ nuclear@51: runq.head->ticks_left = TIMESLICE_TICKS; nuclear@51: } nuclear@51: nuclear@51: /* no need to re-enable interrupts, they will be enabled with the iret */ nuclear@51: context_switch(runq.head->id); nuclear@51: } nuclear@51: nuclear@51: int add_proc(int pid, enum proc_state state) nuclear@51: { nuclear@51: int istate; nuclear@51: struct proc_list *q; nuclear@51: struct process *proc = get_process(pid); nuclear@51: nuclear@51: istate = get_intr_state(); nuclear@51: disable_intr(); nuclear@51: nuclear@51: q = state == STATE_RUNNING ? &runq : &waitq; nuclear@51: nuclear@51: ins_back(q, proc); nuclear@51: proc->state = state; nuclear@51: nuclear@51: set_intr_state(istate); nuclear@51: return 0; nuclear@51: } nuclear@51: nuclear@51: int block_proc(int pid) nuclear@51: { nuclear@51: int istate; nuclear@51: struct process *proc = get_process(pid); nuclear@51: nuclear@51: if(proc->state != STATE_RUNNING) { nuclear@51: printf("block_proc: process %d not running\n", pid); nuclear@51: return -1; nuclear@51: } nuclear@51: nuclear@51: istate = get_intr_state(); nuclear@51: disable_intr(); nuclear@51: nuclear@51: remove(&runq, proc); nuclear@51: ins_back(&waitq, proc); nuclear@51: proc->state = STATE_BLOCKED; nuclear@51: nuclear@51: set_intr_state(istate); nuclear@51: return 0; nuclear@51: } nuclear@51: nuclear@51: int unblock_proc(int pid) nuclear@51: { nuclear@51: int istate; nuclear@51: struct process *proc = get_process(pid); nuclear@51: nuclear@51: if(proc->state != STATE_BLOCKED) { nuclear@51: printf("unblock_proc: process %d not blocked\n", pid); nuclear@51: return -1; nuclear@51: } nuclear@51: nuclear@51: istate = get_intr_state(); nuclear@51: disable_intr(); nuclear@51: nuclear@51: remove(&waitq, proc); nuclear@51: ins_back(&runq, proc); nuclear@51: proc->state = STATE_RUNNING; nuclear@51: nuclear@51: set_intr_state(istate); nuclear@51: return 0; nuclear@51: } nuclear@51: nuclear@51: nuclear@51: static void ins_back(struct proc_list *q, struct process *proc) nuclear@51: { nuclear@51: if(EMPTY(*q)) { nuclear@51: q->head = proc; nuclear@51: } else { nuclear@51: q->tail->next = proc; nuclear@51: } nuclear@51: nuclear@51: proc->next = 0; nuclear@51: proc->prev = q->tail; nuclear@51: q->tail = proc; nuclear@51: } nuclear@51: nuclear@51: static void ins_front(struct proc_list *q, struct process *proc) nuclear@51: { nuclear@51: if(EMPTY(*q)) { nuclear@51: q->tail = proc; nuclear@51: } else { nuclear@51: q->head->prev = proc; nuclear@51: } nuclear@51: nuclear@51: proc->next = q->head; nuclear@51: proc->prev = 0; nuclear@51: q->head = proc; nuclear@51: } nuclear@51: nuclear@51: static void remove(struct proc_list *q, struct process *proc) nuclear@51: { nuclear@51: if(proc->prev) { nuclear@51: proc->prev->next = proc->next; nuclear@51: } nuclear@51: if(proc->next) { nuclear@51: proc->next->prev = proc->prev; nuclear@51: } nuclear@51: if(q->head == proc) { nuclear@51: q->head = proc->next; nuclear@51: } nuclear@51: if(q->tail == proc) { nuclear@51: q->tail = proc->prev; nuclear@51: } nuclear@51: }