return(ret_val);
}
+int _fork_region(pg_dir_t *parent_dir, region_t *reg, void *data)
+{
+ pg_dir_t *child_dir;
+ int ret_val;
+
+ ret_val = 0;
+ child_dir = (pg_dir_t*)data;
+
+ if(!(reg->reg_flags & REGION_PRIV)) {
+ /* skip regions that are private to the parent */
+
+ switch(reg->reg_type) {
+ case REGION_TEXT:
+ case REGION_BSS:
+ case REGION_DATA:
+ case REGION_RODATA:
+ /* copy the region and its contents */
+ ret_val = pg_dir_clone_region(child_dir, parent_dir, reg);
+ break;
+
+ case REGION_KSTACK:
+ case REGION_STACK:
+ case REGION_HEAP:
+ /* don't clone KSTACK/STACK/HEAP regions */
+ default:
+ break;
+ }
+ }
+
+ return(ret_val);
+}
+
+int _vfork_region(pg_dir_t *parent_dir, region_t *reg, void *data)
+{
+ pg_dir_t *child_dir;
+ int ret_val;
+
+ ret_val = 0;
+ child_dir = (pg_dir_t*)data;
+
+ if(!(reg->reg_flags & REGION_PRIV)) {
+ /* skip private regions */
+
+ switch(reg->reg_type) {
+ case REGION_TEXT:
+ case REGION_BSS:
+ case REGION_DATA:
+ case REGION_RODATA:
+ /* directly map the region into the new page directory */
+ ret_val = pg_dir_map_region(child_dir, parent_dir, reg);
+ break;
+
+ case REGION_KSTACK:
+ case REGION_STACK:
+ case REGION_HEAP:
+ /* don't map these */
+ default:
+ break;
+ }
+ }
+
+ return(ret_val);
+}
+
int process_create(process_t **dst, pid_t pid, u32_t ppl, void *entry)
{
int ret_val;
goto cleanup;
}
+ /*
+ * The new page directory contains only the kernel regions.
+ */
+
pdbr = pg_dir_get_pdbr(proc->p_pgdir);
kstack = pg_dir_get_kstack(proc->p_pgdir);
ustack = pg_dir_get_ustack(proc->p_pgdir);
cproc = (process_t*)ctask->t_proc;
custack = pg_dir_get_ustack(cproc->p_pgdir);
+ /*
+ * The address space of the new process doesn't contain any memory segments
+ * but those relevant for the kernel. If the process is a fork, clone all non-kernel
+ * memory segments that are present in the parent's page directory. If it is a vfork,
+ * directly map the segments into this address space.
+ */
+ pg_dir_foreach_region(cproc->p_pgdir,
+ entry == PROC_ENTRY_FORK ? _fork_region : _vfork_region,
+ proc->p_pgdir);
+
/*
* In the case of fork() and vfork() we have to get the address that the
* interrupt is supposed to return to. The stack that the address was pushed