/* * This file contains the clone() function/system call. It creates a new task, * and copies most of the attributes from the parent task into it. */ #include #include #include #include #include extern ObjectList *readyQueue[]; /* Clone a task */ pid_t clone(int flags) { enter_critical_section(); Task *parent = current, *child = new(&taskType), *tmp; pid_t tid = 0; if (flags & CLONE_THREAD) { flags |= CLONE_PARENT; flags |= CLONE_VM; } /* Clone parent's file system namespace */ if (flags & CLONE_FS) child->fs = get(parent->fs); else child->fs = copy(parent->fs); /* Clone parent's files namespace */ if (flags & CLONE_FILES) child->files = get(parent->files); else child->files = copy(parent->files); /* Clone parent's virtual memory namespace */ if (flags & CLONE_VM) child->vm = get(parent->vm); else child->vm = copy(parent->vm); /* Copy stack */ if (parent->stack) child->stack = copy(parent->stack); /* Clone parent's signals namespace */ if (flags & CLONE_SIGHAND) child->signals = get(parent->signals); else child->signals = copy(parent->signals); /* Get executable file */ if (parent->executable) child->executable = get(parent->executable); child->inSyscall = parent->inSyscall; /* After this, anything on the stack is desynchronised */ child->pageDir = clone_dir(); /* Split tasks here */ child->eip = (uintptr_t) &&end; asm volatile("mov %%esp, %0" : "=r" (child->esp)); asm volatile("mov %%ebp, %0" : "=r" (child->ebp)); add(readyQueue[child->priority], child); tid = child->tid; put(child); exit_critical_section(); end: if (tid && !current->inSyscall) { outb(0x20, 0x20); if (apic) LAPIC(0xB0) = 0; } return tid; }