void CondBroadcast (struct Cond *cond) { struct Process *proc; if (current_process == NULL) return; do { DisableInterrupts(); proc = LIST_HEAD (&cond->blocked_list); if (proc != NULL) { LIST_REM_HEAD (&cond->blocked_list, blocked_entry); proc->state = PROC_STATE_READY; SchedReady (proc); Reschedule(); } proc = LIST_HEAD (&cond->blocked_list); EnableInterrupts(); } while (proc != NULL); }
void CondWait (struct Cond *cond, struct Mutex *mutex) { struct Process *proc; if (current_process == NULL) return; DisableInterrupts(); /* Release Mutex */ if (mutex->locked == TRUE) { proc = LIST_HEAD (&mutex->blocked_list); if (proc != NULL) { LIST_REM_HEAD (&mutex->blocked_list, blocked_entry); proc->state = PROC_STATE_READY; SchedReady (proc); } else { mutex->locked = FALSE; } } else { KPANIC ("CondWait() on a free mutex"); } /* Block current process on Condvar */ LIST_ADD_TAIL (&cond->blocked_list, current_process, blocked_entry); current_process->state = PROC_STATE_COND_BLOCKED; SchedUnready (current_process); Reschedule(); /* Now acquire mutex */ if (mutex->locked == TRUE) { LIST_ADD_TAIL (&mutex->blocked_list, current_process, blocked_entry); current_process->state = PROC_STATE_MUTEX_BLOCKED; SchedUnready (current_process); Reschedule(); } else { mutex->locked = TRUE; } EnableInterrupts(); }
void Wakeup (struct Rendez *rendez) { struct Process *proc; DisablePreemption(); if ((proc = LIST_HEAD(&rendez->process_list)) == NULL) return; LIST_REM_HEAD (&rendez->process_list, rendez_link); proc->sleeping_on = NULL; proc->state = PROC_STATE_READY; SchedReady(proc); }
void WakeupProcess (struct Process *proc) { struct Rendez *rendez; DisablePreemption(); KASSERT (proc->state == PROC_STATE_SLEEP); rendez = proc->sleeping_on; LIST_REM_ENTRY (&rendez->process_list, proc, rendez_link); proc->sleeping_on = NULL; proc->state = PROC_STATE_READY; SchedReady(proc); }
int Fork (void) { struct Process *newproc; KPRINTF ("Fork()"); if ((newproc = AllocProcess(PROC_TYPE_USER)) != NULL) { StrLCpy (newproc->exe_name, current_process->exe_name, PROC_NAME_SZ); if (*newproc->exe_name == '\0') { KPRINTF ("Fork() exe_name == 0"); while(1) KWait(0); } if (DuplicateAddressSpace (¤t_process->as, &newproc->as) == 0) { newproc->user_as = &newproc->as; if (0 == FSCreateProcess (current_process, newproc, current_process->current_dir, DUP_FD)) { USigFork (current_process, newproc); if (ArchInitFork (newproc) == 0) { DisableInterrupts(); newproc->state = PROC_STATE_READY; newproc->priority = 0; SchedReady (newproc); Reschedule(); EnableInterrupts(); return newproc->pid; } FSExitProcess (newproc); } FreeAddressSpace (&newproc->as); } FreeProcess (newproc); } return -1; }
void CondTimedWaitCallout (struct Timer *timer, void *arg) { struct Process *proc; struct Cond *cond; cond = *(struct Cond **)arg; proc = timer->process; if (proc->state == PROC_STATE_COND_BLOCKED) { *(struct Cond **)arg = NULL; LIST_REM_HEAD (&cond->blocked_list, blocked_entry); proc->state = PROC_STATE_READY; SchedReady (proc); Reschedule(); } }
int CondTimedWait (volatile struct Cond *cond, struct Mutex *mutex, struct TimeVal *tv) { struct Process *proc; struct Timer timer; if (current_process == NULL) return 0; DisableInterrupts(); if (mutex->locked == TRUE) { /* Release Mutex */ proc = LIST_HEAD (&mutex->blocked_list); if (proc != NULL) { LIST_REM_HEAD (&mutex->blocked_list, blocked_entry); proc->state = PROC_STATE_READY; SchedReady (proc); } else { mutex->locked = FALSE; } } else { KPANIC ("CondTimedWait() on a free mutex"); } /* Block current process on Condvar */ LIST_ADD_TAIL (&cond->blocked_list, current_process, blocked_entry); SetTimer (&timer, TIMER_TYPE_RELATIVE, tv, &CondTimedWaitCallout, &cond); current_process->state = PROC_STATE_COND_BLOCKED; SchedUnready (current_process); Reschedule(); CancelTimer (&timer); /* Now acquire mutex */ if (mutex->locked == TRUE) { LIST_ADD_TAIL (&mutex->blocked_list, current_process, blocked_entry); current_process->state = PROC_STATE_MUTEX_BLOCKED; SchedUnready (current_process); Reschedule(); } else { mutex->locked = TRUE; } EnableInterrupts(); if (cond == NULL) return -1; else return 0; }
SYSCALL int Spawn (struct SpawnArgs *user_sa, void **user_segments, int segment_cnt) { struct Process *proc, *current; void *segments[NSPAWNSEGMENTS]; struct Segment *vs_ptrs[NSPAWNSEGMENTS]; int h; int t; struct SpawnArgs sa; current = GetCurrentProcess(); if (!(current->flags & PROCF_FILESYS)) return privilegeErr; if (segment_cnt < 1 || segment_cnt > NSPAWNSEGMENTS) return paramErr; CopyIn (&sa, user_sa, sizeof sa); CopyIn (segments, user_segments, sizeof (void *) * segment_cnt); if (free_handle_cnt < (1 + 3 + 1) || free_process_cnt < 1) return resourceErr; if (sa.namespace_handle == -1) return paramErr; if (FindHandle (current, sa.namespace_handle) == NULL) return paramErr; if (SegmentFindMultiple (vs_ptrs, segments, segment_cnt) < 0) return paramErr; DisablePreemption(); h = AllocHandle(); proc = AllocProcess(); proc->handle = h; proc->flags = sa.flags & ~PROCF_SYSTEMMASK; proc->namespace_handle = sa.namespace_handle; handle_table[sa.namespace_handle].owner = proc; handle_table[sa.namespace_handle].flags |= HANDLEF_GRANTED_ONCE; proc->sighangup_handle = AllocHandle(); SetObject (proc, proc->sighangup_handle, HANDLE_TYPE_SYSTEMEVENT, NULL); handle_table[proc->sighangup_handle].flags |= HANDLEF_GRANTED_ONCE; proc->sigterm_handle = AllocHandle(); SetObject (proc, proc->sigterm_handle, HANDLE_TYPE_PROCESS, NULL); handle_table[proc->sigterm_handle].flags |= HANDLEF_GRANTED_ONCE; current->argv = sa.argv; current->argc = sa.argc; current->envv = sa.envv; current->envc = sa.envc; ArchAllocProcess(proc, sa.entry, sa.stack_top); SetObject (current, h, HANDLE_TYPE_PROCESS, proc); for (t=0; t < segment_cnt; t++) { PmapRemoveRegion (vs_ptrs[t]); vs_ptrs[t]->owner = proc; } proc->state = PROC_STATE_READY; SchedReady(proc); return h; }
struct Process *CreateProcess (void (*entry)(void), void *stack, int policy, int priority, bits32_t flags, struct CPU *cpu) { int handle; struct Process *proc; proc = AllocProcess(); handle = AllocHandle(); KASSERT (handle >= 0); SetObject (proc, handle, HANDLE_TYPE_PROCESS, proc); proc->handle = handle; proc->exit_status = 0; proc->flags = flags; // FIXME: Move into AllocProcess ???????????????? LIST_INIT (&proc->pending_handle_list); LIST_INIT (&proc->close_handle_list); PmapInit (proc); proc->task_state.cpu = cpu; proc->task_state.flags = 0; proc->task_state.pc = (uint32)entry; proc->task_state.r0 = 0; if (proc->flags & PROCF_DAEMON) { proc->task_state.cpsr = cpsr_dnm_state | SYS_MODE | CPSR_DEFAULT_BITS; } else { proc->task_state.cpsr = cpsr_dnm_state | USR_MODE | CPSR_DEFAULT_BITS; } proc->task_state.r1 = 0; proc->task_state.r2 = 0; proc->task_state.r3 = 0; proc->task_state.r4 = 0; proc->task_state.r5 = 0; proc->task_state.r6 = 0; proc->task_state.r7 = 0; proc->task_state.r8 = 0; proc->task_state.r9 = 0; proc->task_state.r10 = 0; proc->task_state.r11 = 0; proc->task_state.r12 = 0; proc->task_state.sp = (uint32)stack; proc->task_state.lr = 0; if (policy == SCHED_RR || policy == SCHED_FIFO) { proc->quanta_used = 0; proc->sched_policy = policy; proc->tickets = priority; SchedReady (proc); } else if (policy == SCHED_OTHER) { proc->quanta_used = 0; proc->sched_policy = policy; proc->tickets = priority; proc->stride = STRIDE1 / proc->tickets; proc->remaining = proc->stride; proc->pass = global_pass; SchedReady (proc); } else if (policy == SCHED_IDLE) { cpu->idle_process = proc; } return proc; }