]> git.corax.cc Git - corax/commitdiff
Make use of pg_dir_foreach_region() function in process_create() function to clone...
authorMatthias Kruk <m@m10k.eu>
Mon, 18 Nov 2019 08:56:38 +0000 (17:56 +0900)
committerMatthias Kruk <m@m10k.eu>
Mon, 18 Nov 2019 08:56:38 +0000 (17:56 +0900)
kernel/core/process.c

index d1c860f98bce5ced6d8656249c9c1743d0d8e615..118b9771fddbb441473c419f010034330cd9511d 100644 (file)
@@ -159,6 +159,70 @@ static inline int DQ(process_t *p)
        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;
@@ -206,6 +270,10 @@ int process_create(process_t **dst, pid_t pid, u32_t ppl, void *entry)
                        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);
@@ -269,6 +337,16 @@ int process_create(process_t **dst, pid_t pid, u32_t ppl, void *entry)
                        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