static void umem_lockup(void) { umem_cache_t *cp; (void) mutex_lock(&umem_init_lock); /* * If another thread is busy initializing the library, we must * wait for it to complete (by calling umem_init()) before allowing * the fork() to proceed. */ if (umem_ready == UMEM_READY_INITING && umem_init_thr != thr_self()) { (void) mutex_unlock(&umem_init_lock); (void) umem_init(); (void) mutex_lock(&umem_init_lock); } (void) mutex_lock(&umem_cache_lock); (void) mutex_lock(&umem_update_lock); (void) mutex_lock(&umem_flags_lock); umem_lockup_cache(&umem_null_cache); for (cp = umem_null_cache.cache_prev; cp != &umem_null_cache; cp = cp->cache_prev) umem_lockup_cache(cp); umem_lockup_log_header(umem_transaction_log); umem_lockup_log_header(umem_content_log); umem_lockup_log_header(umem_failure_log); umem_lockup_log_header(umem_slab_log); (void) cond_broadcast(&umem_update_cv); vmem_sbrk_lockup(); vmem_lockup(); }
const mdb_modinfo_t * _mdb_init(void) { if (umem_init() != 0) return (NULL); return (&modinfo); }
vmem_t * vmem_heap_arena(vmem_alloc_t **allocp, vmem_free_t **freep) { static mutex_t arena_mutex = DEFAULTMUTEX; /* * Allow the init thread through, block others until the init completes */ if (umem_ready != UMEM_READY && umem_init_thr != thr_self() && umem_init() == 0) return (NULL); (void) mutex_lock(&arena_mutex); if (vmem_heap == NULL) vmem_heap_init(); (void) mutex_unlock(&arena_mutex); if (allocp != NULL) *allocp = vmem_heap_alloc; if (freep != NULL) *freep = vmem_heap_free; return (vmem_heap); }
int32_t fork() { /* Time to... fork! * I had spent a long time preparing for this! * now I am done, it's time to start working on fork(). */ int32_t i; proc_t *newproc; /* create a new process structure: */ newproc = kmalloc(sizeof(proc_t)); if (newproc == NULL) return -1; /* set parent */ newproc->parent = curproc; /* initialize descriptors: */ newproc->plist.proc = newproc; newproc->sched.proc = newproc; newproc->irqd.proc = newproc; newproc->semad.proc = newproc; /* create memory: */ if (umem_init(&(newproc->umem))) { kfree(newproc); return -1; /* error. */ } /* inherit parent's memory: */ if (umem_copy(&(curproc->umem), &(newproc->umem))) { umem_free(&(newproc->umem)); kfree(newproc); return -1; /* error. */ } /* create a new kernel stack. */ newproc->kstack = (unsigned char *) kmalloc(KERNEL_STACK_SIZE); if (newproc->kstack == NULL) { umem_free(&(newproc->umem)); kfree(newproc); return -1; /* error. */ } initproc->phy_stack_bot = arch_vmpage_getAddr(NULL, newproc->kstack); /* initialize kernel stack... * this invokes page faults to allocate memory for * the stack early. */ for (i = 0; i < KERNEL_STACK_SIZE; i++) newproc->kstack[i] = 0; /* copy context from parent's stack to child's stack: */ copy_context(newproc); /* copy the set of file descriptors: */ for (i = 0; i < FD_MAX; i++) { if (curproc->file[i] == NULL) { newproc->file[i] = NULL; } else { curproc->file[i]->fcount++; newproc->file[i] = curproc->file[i]; } } /* inherit the current working directory: */ curproc->cwd->fcount++; newproc->cwd = curproc->cwd; /* set pid: */ newproc->pid = ++last_pid; /* inform the scheduler that this is a just-forked process: */ newproc->after_fork = 1; /* initialize inbox */ newproc->inbox_lock = 0; newproc->blocked_for_msg = 0; linkedlist_init(&(newproc->inbox)); /* children */ newproc->blocked_for_child = 0; /* not blocked */ newproc->blocked = 0; newproc->lock_to_unlock = NULL; /* exit status: */ newproc->terminated = 0; newproc->status = 0; /* add the new process to the list of processes: */ linkedlist_addlast((linkedlist*)&proclist, (linknode*)&(newproc->plist)); /* add to scheduler's queue: */ linkedlist_addlast((linkedlist*)&q_ready, (linknode*)&(newproc->sched)); /* call the scheduler */ scheduler(); /* return */ if (curproc == newproc) { return 0; } else { return newproc->pid; } }
void proc_init() { /* Process Manager Initialization */ int32_t i, err = 0; char *initpath = "/bin/init"; /* (I) Initialize linked lists: */ /* ----------------------------- */ linkedlist_init((linkedlist *) &proclist); linkedlist_init((linkedlist *) &q_ready); linkedlist_init((linkedlist *) &q_blocked); /* (II) Create "init" process: */ /* ---------------------------- */ /* Allocate memory for process structures: */ initproc = (proc_t *) kmalloc(sizeof(proc_t)); /* set parent */ initproc->parent = NULL; /* initialize descriptors: */ initproc->plist.proc = initproc; initproc->sched.proc = initproc; initproc->irqd.proc = initproc; /* Set "init" pid <1>: */ initproc->pid = 1; /* Add it to process list: */ linkedlist_addlast((linkedlist *) &proclist, (linknode *) &(initproc->plist)); /* Kernel-mode stack: */ initproc->kstack = kernel_stack; /* User memory: */ umem_init(&(initproc->umem)); /* initialize file descriptors: */ for(i = 0; i < FD_MAX; i++) initproc->file[i] = NULL; /* current working directory: */ file_open("/", 0, &(initproc->cwd)); /* not forked: */ initproc->after_fork = 0; /* initialize inbox */ initproc->inbox_lock = 0; initproc->blocked_for_msg = 0; linkedlist_init(&(initproc->inbox)); /* children */ initproc->blocked_for_child = 0; /* not blocked */ initproc->blocked = 0; /* exit status: */ initproc->terminated = 0; initproc->status = 0; /* (III) Run the "init" process: */ /* ------------------------------ */ curproc = initproc; /* init process is running! */ arch_vmswitch(&(initproc->umem)); /* (IV) Enable multitasking: */ /* -------------------------- */ scheduler_enabled = 1; /* start multitasking! */ /* (V) Open console streams: */ /* -------------------------- */ /* create device file for console: */ mknod("/dev/console", FT_SPECIAL, system_console->devid); /* open console file: */ open("/dev/console", 0); /* this will open the file at fd "0". */ dup(0); /* duplicate at fd "1". */ dup(0); /* duplicate at fd "2". */ /* (VI) Execute "init" program to initialize the operating system: */ /* ---------------------------------------------------------------- */ printk("Executing \"%s\" ...\n\n", initpath); printk("%a", 0x0E); execve(initpath, 0, 0); printk("FATAL: Error happened during execution.\n"); idle(); }