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; }
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; }