AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
fork.c
Go to the documentation of this file.
1
10
11#include <core/system.h>
12#include <core/string.h>
13#include <core/arch.h>
14#include <mm/mm.h>
15#include <mm/vm.h>
16#include <mm/pmap.h>
17#include <sys/proc.h>
18#include <ds/queue.h>
19#include <aquila/errno.h>
20#include <net/socket.h>
21
22MALLOC_DECLARE(M_FDS);
23
27static int copy_fds(struct proc *parent, struct proc *fork)
28{
29 fork->fds = kmalloc(FDS_COUNT * sizeof(struct fd), &M_FDS, M_ZERO);
30
31 if (!fork->fds)
32 return -ENOMEM;
33
34 for (int i = 0; i < FDS_COUNT; ++i) {
35 /* a descriptor that another thread is still setting up isn't
36 * copied */
37 struct file *file = proc_fd_file(parent, i);
38
39 if (file)
40 fork->fds[i] = (struct fd) {.file = file_ref(file), .flags = parent->fds[i].flags};
41 }
42
43 return 0;
44}
45
50static int fork_proc_copy(struct proc *parent, struct proc *fork)
51{
52 fork->pgrp = parent->pgrp;
53
54 if (!(fork->pgrp_node = enqueue(fork->pgrp->procs, fork)))
55 return -ENOMEM;
56
57 fork->mask = parent->mask;
58 fork->uid = parent->uid;
59 fork->sigmask = parent->sigmask;
60 fork->gid = parent->gid;
61
62 fork->heap_start = parent->heap_start;
63 fork->heap = parent->heap;
64 fork->entry = parent->entry;
65
66 memcpy(fork->sigaction, parent->sigaction, sizeof(parent->sigaction));
67
68 return 0;
69}
70
81int proc_fork(struct thread *thread, struct proc **ref)
82{
83 int err = 0;
84 struct proc *fork = NULL;
85 struct thread *fork_thread = NULL;
86
87 /* the new process */
88 if ((err = proc_new(&fork)))
89 goto error;
90
91 /* its main thread */
92 fork_thread = (struct thread *) fork->threads.head->value;
93
94 /* the parent */
95 struct proc *proc = thread->owner;
96
97 /* what the child inherits from the parent's structure */
98 if ((err = fork_proc_copy(proc, fork)))
99 goto error;
100
101 /* the parent's name */
102 if (!(fork->name = strdup(proc->name))) {
103 err = -ENOMEM;
104 goto error;
105 }
106
107 /* a new process ID */
108 if ((fork->pid = proc_pid_alloc()) == -1) {
109 fork->pid = 0;
110 err = -EAGAIN;
111 goto error;
112 }
113
114 /* the parent, for wait() */
115 fork->parent = proc;
116
117 /* the child's thread starts as if it had been switched away from:
118 * from where fork() returns */
119 fork_thread->spawned = 1;
120
121 /* the same current directory */
122 if ((fork->cwd = proc->cwd))
123 fork->cwd->ref++;
124
125 /* the descriptors */
126 if ((err = copy_fds(proc, fork)))
127 goto error;
128
129 /* the address space, copy on write */
130 if ((err = vm_space_fork(&proc->vm_space, &fork->vm_space)))
131 goto error;
132
133 /* point the child's heap_vm and stack_vm at its copies of the
134 * parent's: the copies are in the same order as the originals */
135 struct qnode *pvm_node = proc->vm_space.vm_entries.head;
136 struct qnode *fvm_node = fork->vm_space.vm_entries.head;
137
138 while (pvm_node) {
139 struct vm_entry *pvm_entry = pvm_node->value;
140 struct vm_entry *fvm_entry = fvm_node->value;
141
142 if (pvm_entry == proc->heap_vm)
143 fork->heap_vm = fvm_entry;
144
145 if (pvm_entry == proc->stack_vm)
146 fork->stack_vm = fvm_entry;
147
148 pvm_node = pvm_node->next;
149 fvm_node = fvm_node->next;
150 }
151
152 /* the thread's CPU state, a copy of the caller's */
153 err = arch_proc_fork(thread, fork);
154
155 if (err)
156 goto error;
157
158 /* fork() returns 0 in the child, set in its registers since it is
159 * another thread (the parent gets the child's PID: sys_fork()'s
160 * result) */
161 arch_syscall_return(fork_thread, 0);
162
163 if (ref)
164 *ref = fork;
165
166 return 0;
167
168error:
169 /* undo what was done; the caller returns err to the parent */
170 if (fork) {
171 /* close the copied descriptors (drops the references they took) */
172 if (fork->fds) {
173 for (int i = 0; i < FDS_COUNT; ++i)
174 proc_fd_close(fork, i);
175
176 kfree(fork->fds);
177 }
178
181
182 if (fork->name)
183 kfree(fork->name);
184 if (fork->cwd)
185 vfs_close(fork->cwd);
186
187 /* free the main thread (it never ran) */
188 struct thread *_thread = NULL;
189 while ((_thread = dequeue(&fork->threads)))
190 kfree(_thread);
191
192 if (fork->pgrp_node)
193 queue_node_remove(fork->pgrp->procs, fork->pgrp_node);
194
195 if (fork->pid > 0)
196 proc_pid_free(fork->pid);
197
198 queue_remove(procs, fork);
199 kfree(fork);
200 }
201
202 return err;
203}
int arch_proc_fork(struct thread *thread, struct proc *fork)
Sets up the CPU state of a fork() child's thread: a copy of the parent's kernel stack,...
Definition fork.c:21
void arch_syscall_return(struct thread *thread, uintptr_t val)
Sets the result of a thread's system call, in the register that returns it to user mode.
Definition syscall.c:43
int vfs_close(struct vnode *vnode)
Drops a reference to a vnode.
Definition close.c:18
struct file * file_ref(struct file *file)
Adds a reference to an open file.
Definition file.c:48
#define FDS_COUNT
Definition config.h:46
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
Definition kvmem.c:123
#define MALLOC_DECLARE(type)
Definition kvmem.h:29
#define M_ZERO
Definition kvmem.h:26
void kfree(void *)
Frees an object that kmalloc() gave.
Definition kvmem.c:146
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
Definition libc.c:11
void pmap_decref(struct pmap *pmap)
Drops a reference to an address space's page tables, freeing them with the last one.
Definition pmap.c:271
int proc_fd_close(struct proc *proc, int fd)
Closes a descriptor: it is free again, and its reference to the open file is dropped.
Definition proc.c:578
void proc_pid_free(int pid)
Frees a process ID.
Definition proc.c:102
int proc_fork(struct thread *thread, struct proc **ref)
Makes a child process, a copy of the process of thread.
Definition fork.c:81
struct file * proc_fd_file(struct proc *proc, int fd)
Finds the open file a descriptor refers to.
Definition proc.c:560
pid_t proc_pid_alloc(void)
Allocates a process ID, from 1 (init's) on.
Definition proc.c:80
int proc_new(struct proc **ref)
Makes a new process structure, with one thread and an empty address space, on the list of every proce...
Definition proc.c:114
struct queue * procs
Definition proc.c:37
#define NULL
Definition stddef.h:27
A file descriptor: the open file it refers to (fs/file.c, shared with the descriptors that dup() and ...
Definition proc.h:47
int flags
Definition proc.h:49
struct file * file
Definition proc.h:48
An open file (POSIX's "open file description", fs/file.c).
Definition vfs.h:157
int flags
Definition vfs.h:164
struct queue * procs
its processes
Definition proc.h:67
A process.
Definition proc.h:75
pid_t pid
the process's ID
Definition proc.h:77
struct proc * parent
its parent
Definition proc.h:90
struct aquila_sigaction sigaction[SIG_MAX+1]
its signal actions
Definition proc.h:157
struct qnode * pgrp_node
Definition proc.h:81
struct vm_space vm_space
its address space
Definition proc.h:129
struct vm_entry * stack_vm
Definition proc.h:133
struct vnode * cwd
its current directory (a reference), or NULL for the root
Definition proc.h:93
uintptr_t heap_start
where its heap starts, and where it ends now (sbrk())
Definition proc.h:122
struct vm_entry * heap_vm
its heap's and its stack's mappings
Definition proc.h:132
gid_t gid
Definition proc.h:119
uintptr_t heap
Definition proc.h:123
struct fd * fds
its file descriptors (FDS_COUNT of them)
Definition proc.h:87
mode_t mask
its file mode creation mask (umask)
Definition proc.h:96
char * name
its name: the program it runs
Definition proc.h:84
uid_t uid
its user and group IDs
Definition proc.h:118
struct queue threads
its threads
Definition proc.h:136
struct pgroup * pgrp
its process group, and its node on the group's list
Definition proc.h:80
uintptr_t entry
its program's entry point
Definition proc.h:126
sigset_t sigmask
its blocked signals, a bit (1 << sig) each
Definition proc.h:151
A queue's node, holding one entry.
Definition queue.h:19
void * value
Definition queue.h:20
struct qnode * next
Definition queue.h:22
struct qnode * head
Definition queue.h:31
A thread.
Definition thread.h:23
int spawned
whether it has run yet
Definition thread.h:87
struct proc * owner
its process
Definition thread.h:31
A mapping (map entry): a range of an address space, its permissions, and where its pages come from.
Definition vm.h:66
struct pmap * pmap
its page tables (the architecture's)
Definition vm.h:27
struct queue vm_entries
its mappings (map entries), in address order
Definition vm.h:30
size_t ref
how many references there are to it
Definition vfs.h:133
static int copy_fds(struct proc *parent, struct proc *fork)
Copies the parent's descriptors to the child.
Definition fork.c:27
static int fork_proc_copy(struct proc *parent, struct proc *fork)
Copies what the child inherits from the parent's process structure: its process group,...
Definition fork.c:50
int vm_space_fork(struct vm_space *parent, struct vm_space *child)
Copies an address space's mappings into another, for fork().
Definition vm_space.c:152
void vm_space_destroy(struct vm_space *vm_space)
Removes all the mappings of an address space: its entries are released and freed, and its page tables...
Definition vm_space.c:124