// program_load(p, program_id) // Load the code corresponding to program `programnumber` into the process // `p` and set `p->p_registers.reg_eip` to its entry point. Calls // `physical_page_alloc` to allocate virtual memory for `p` as required. // Returns 0 on success and -1 on failure (e.g. out-of-memory). int program_load(proc* p, int program_id) { // is this a valid program? int nprograms = sizeof(ramimages) / sizeof(ramimages[0]); assert(program_id >= 0 && program_id < nprograms); elf_header* eh = (elf_header*) ramimages[program_id].begin; assert(eh->e_magic == ELF_MAGIC); // load each loadable program segment into memory elf_program* ph = (elf_program*) ((const uint8_t*) eh + eh->e_phoff); for (int i = 0; i < eh->e_phnum; ++i) if (ph[i].p_type == ELF_PTYPE_LOAD) if (copyseg(p, &ph[i], (const uint8_t*) eh + ph[i].p_offset) < 0) return -1; // set the entry point from the ELF header p->p_registers.reg_eip = eh->e_entry; return 0; }
/* * Create a new process-- the internal version of * sys fork. * It returns 1 in the new process. * How this happens is rather hard to understand. * The essential fact is that the new process is created * in such a way that appears to have started executing * in the same call to newproc as the parent; * but in fact the code that runs is that of swtch. * The subtle implication of the returned value of swtch * (see above) is that this is the value that newproc's * caller in the new process sees. */ newproc() { int a1, a2; struct proc *p, *up; register struct proc *rpp; register *rip, n; p = NULL; /* * First, just locate a slot for a process * and copy the useful info from this process into it. * The panic "cannot happen" because fork has already * checked for the existence of a slot. */ retry: mpid++; if(mpid < 0) { mpid = 0; goto retry; } for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) { if(rpp->p_stat == NULL && p==NULL) p = rpp; if (rpp->p_pid==mpid) goto retry; } if ((rpp = p)==NULL) panic("no procs"); /* * make proc entry for new proc */ rip = u.u_procp; up = rip; rpp->p_stat = SRUN; rpp->p_flag = SLOAD; rpp->p_uid = rip->p_uid; rpp->p_ttyp = rip->p_ttyp; rpp->p_nice = rip->p_nice; rpp->p_textp = rip->p_textp; rpp->p_pid = mpid; rpp->p_ppid = rip->p_pid; rpp->p_time = 0; /* * make duplicate entries * where needed */ for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOFILE];) if((rpp = *rip++) != NULL) rpp->f_count++; if((rpp=up->p_textp) != NULL) { rpp->x_count++; rpp->x_ccount++; } u.u_cdir->i_count++; /* * Partially simulate the environment * of the new process so that when it is actually * created (by copying) it will look right. */ savu(u.u_rsav); rpp = p; u.u_procp = rpp; rip = up; n = rip->p_size; a1 = rip->p_addr; rpp->p_size = n; a2 = malloc(coremap, n); /* * If there is not enough core for the * new process, swap out the current process to generate the * copy. */ if(a2 == NULL) { rip->p_stat = SIDL; rpp->p_addr = a1; savu(u.u_ssav); xswap(rpp, 0, 0); rpp->p_flag =| SSWAP; rip->p_stat = SRUN; } else { /* * There is core, so just copy. */ rpp->p_addr = a2; while(n--) copyseg(a1++, a2++); } u.u_procp = rip; return(0); }