PatchworkOS
Loading...
Searching...
No Matches
process.c
Go to the documentation of this file.
2
3#include <kernel/cpu/cpu.h>
4#include <kernel/cpu/smp.h>
5#include <kernel/fs/file.h>
6#include <kernel/fs/path.h>
7#include <kernel/fs/sysfs.h>
8#include <kernel/fs/vfs.h>
9#include <kernel/log/log.h>
10#include <kernel/log/panic.h>
11#include <kernel/mem/vmm.h>
12#include <kernel/sched/thread.h>
13#include <kernel/sched/timer.h>
14#include <kernel/sched/wait.h>
15#include <kernel/sync/lock.h>
16#include <kernel/sync/rwlock.h>
17
18#include <assert.h>
19#include <stdatomic.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <sys/io.h>
24#include <sys/list.h>
25#include <sys/math.h>
26#include <sys/proc.h>
27
29static bool kernelProcessInitalized = false;
30
31static _Atomic(pid_t) newPid = ATOMIC_VAR_INIT(0);
32
33static mount_t* procMount = NULL;
34static dentry_t* selfDir = NULL;
35
36static list_t zombies = LIST_CREATE(zombies);
37static clock_t lastReaperTime = 0;
38static lock_t zombiesLock = LOCK_CREATE;
39
40// TODO: Implement a proper reaper.
41static void process_reaper_timer(interrupt_frame_t* frame, cpu_t* cpu)
42{
43 (void)frame; // Unused
44 (void)cpu; // Unused
45
46 LOCK_SCOPE(&zombiesLock);
47
49 if (uptime - lastReaperTime < CONFIG_PROCESS_REAPER_INTERVAL)
50 {
51 return;
52 }
53 lastReaperTime = uptime;
54
55 list_t* current = &zombies;
56 while (!list_is_empty(current))
57 {
58 process_t* process = CONTAINER_OF(list_pop(current), process_t, zombieEntry);
59
60 DEREF(process->dir);
61 DEREF(process->prioFile);
62 DEREF(process->cwdFile);
63 DEREF(process->cmdlineFile);
64 DEREF(process->noteFile);
65 DEREF(process->waitFile);
66 DEREF(process->self);
67
68 DEREF(process);
69 }
70}
71
73{
74 process_t* process = file->inode->private;
75 if (process == NULL)
76 {
77 LOG_DEBUG("process_file_get_process: inode private is NULL\n");
78 errno = EINVAL;
79 return NULL;
80 }
81
82 if (process == &kernelProcess)
83 {
84 errno = EACCES;
85 return NULL;
86 }
87
88 return process;
89}
90
92{
94 if (process == NULL)
95 {
96 return ERR;
97 }
98
99 priority_t priority = atomic_load(&process->priority);
100
101 char prioStr[MAX_NAME];
102 uint32_t length = snprintf(prioStr, MAX_NAME, "%llu", priority);
103 return BUFFER_READ(buffer, count, offset, prioStr, length);
104}
105
107{
108 (void)offset; // Unused
109
111 if (process == NULL)
112 {
113 return ERR;
114 }
115
116 char prioStr[MAX_NAME];
117 if (count >= MAX_NAME)
118 {
119 errno = EINVAL;
120 return ERR;
121 }
122
123 memcpy(prioStr, buffer, count);
124 prioStr[count] = '\0';
125
126 long long int prio = atoll(prioStr);
127 if (prio < 0)
128 {
129 errno = EINVAL;
130 return ERR;
131 }
132 if (prio >= PRIORITY_MAX_USER)
133 {
134 errno = EACCES;
135 return ERR;
136 }
137
138 atomic_store(&process->priority, prio);
139 return count;
140}
141
144 .write = process_prio_write,
145};
146
148{
150 if (process == NULL)
151 {
152 return ERR;
153 }
154
155 path_t cwd = PATH_EMPTY;
156 if (vfs_ctx_get_cwd(&process->vfsCtx, &cwd) == ERR)
157 {
158 return ERR;
159 }
160 PATH_DEFER(&cwd);
161
162 pathname_t cwdName;
163 if (path_to_name(&cwd, &cwdName) == ERR)
164 {
165 return ERR;
166 }
167
168 uint64_t length = strlen(cwdName.string);
169 return BUFFER_READ(buffer, count, offset, cwdName.string, length);
170}
171
174};
175
177{
179 if (process == NULL)
180 {
181 return ERR;
182 }
183
184 uint64_t length;
185 const char* strings = argv_get_strings(&process->argv, &length);
186 return BUFFER_READ(buffer, count, offset, strings, length);
187}
188
192
194{
195 (void)offset; // Unused
196
197 if (count == 0)
198 {
199 return 0;
200 }
201
203 if (process == NULL)
204 {
205 return ERR;
206 }
207
208 LOCK_SCOPE(&process->threads.lock);
209
210 thread_t* thread = CONTAINER_OF_SAFE(list_first(&process->threads.list), thread_t, processEntry);
211 if (thread == NULL)
212 {
213 errno = EINVAL;
214 return ERR;
215 }
216
217 if (thread_send_note(thread, buffer, count) == ERR)
218 {
219 return ERR;
220 }
221
222 return count;
223}
224
228
230{
232 if (process == NULL)
233 {
234 return ERR;
235 }
236
237 WAIT_BLOCK(&process->dyingWaitQueue, atomic_load(&process->isDying));
238
239 char status[MAX_PATH];
240 int length = snprintf(status, sizeof(status), "%llu", atomic_load(&process->status));
241 if (length < 0)
242 {
243 return ERR;
244 }
245
246 return BUFFER_READ(buffer, count, offset, status, (uint64_t)length);
247}
248
250{
252 if (process == NULL)
253 {
254 return NULL;
255 }
256
257 if (atomic_load(&process->isDying))
258 {
259 *revents |= POLLIN;
260 return &process->dyingWaitQueue;
261 }
262
263 return &process->dyingWaitQueue;
264}
265
268 .poll = process_wait_poll,
269};
270
272{
273 process_t* process = inode->private;
274 DEREF(process);
275}
276
280
281static uint64_t process_dir_init(process_t* process, const char* name)
282{
283 process->dir = sysfs_dir_new(procMount->root, name, &inodeOps, REF(process));
284 if (process->dir == NULL)
285 {
286 return ERR;
287 }
288
289 process->prioFile = sysfs_file_new(process->dir, "prio", &inodeOps, &prioOps, REF(process));
290 if (process->prioFile == NULL)
291 {
292 goto error;
293 }
294
295 process->cwdFile = sysfs_file_new(process->dir, "cwd", &inodeOps, &cwdOps, REF(process));
296 if (process->cwdFile == NULL)
297 {
298 goto error;
299 }
300
301 process->cmdlineFile = sysfs_file_new(process->dir, "cmdline", &inodeOps, &cmdlineOps, REF(process));
302 if (process->cmdlineFile == NULL)
303 {
304 goto error;
305 }
306
307 process->noteFile = sysfs_file_new(process->dir, "note", &inodeOps, &noteOps, REF(process));
308 if (process->noteFile == NULL)
309 {
310 goto error;
311 }
312
313 process->waitFile = sysfs_file_new(process->dir, "wait", &inodeOps, &waitOps, REF(process));
314 if (process->waitFile == NULL)
315 {
316 goto error;
317 }
318
319 path_t selfPath = PATH_CREATE(procMount, selfDir);
320 process->self = namespace_bind(&process->namespace, process->dir, &selfPath);
321 path_put(&selfPath);
322 if (process->self == NULL)
323 {
324 goto error;
325 }
326
327 return 0;
328
329error:
330 DEREF(process->waitFile);
331 DEREF(process->noteFile);
332 DEREF(process->cmdlineFile);
333 DEREF(process->cwdFile);
334 DEREF(process->prioFile);
335 DEREF(process->dir);
336 return ERR;
337}
338
339static void process_free(process_t* process)
340{
341 LOG_DEBUG("freeing process pid=%d\n", process->id);
342 assert(list_is_empty(&process->threads.list));
343
344 if (!atomic_load(&process->isDying))
345 {
346 process_kill(process, EXIT_SUCCESS);
347 }
348
349 if (process->parent != NULL)
350 {
351 RWLOCK_WRITE_SCOPE(&process->parent->childrenLock);
352 list_remove(&process->parent->children, &process->siblingEntry);
353 DEREF(process->parent);
354 process->parent = NULL;
355 }
356
358 if (!list_is_empty(&process->children))
359 {
360 panic(NULL, "Freeing process pid=%d with children", process->id);
361 }
363
364 space_deinit(&process->space);
365 argv_deinit(&process->argv);
367 futex_ctx_deinit(&process->futexCtx);
368 free(process);
369}
370
371static uint64_t process_init(process_t* process, process_t* parent, const char** argv, const path_t* cwd,
372 priority_t priority)
373{
374 ref_init(&process->ref, process_free);
375 process->id = atomic_fetch_add(&newPid, 1);
376 atomic_init(&process->priority, priority);
377 atomic_init(&process->status, EXIT_SUCCESS);
378
379 if (argv_init(&process->argv, argv) == ERR)
380 {
381 return ERR;
382 }
383
384 if (namespace_init(&process->namespace, parent != NULL ? &parent->namespace : NULL, process) == ERR)
385 {
386 argv_deinit(&process->argv);
387 return ERR;
388 }
389
392 {
393 namespace_deinit(&process->namespace);
394 argv_deinit(&process->argv);
395 return ERR;
396 }
397
398 if (cwd != NULL)
399 {
400 vfs_ctx_init(&process->vfsCtx, cwd);
401 }
402 else if (parent != NULL)
403 {
404 path_t parentCwd = PATH_EMPTY;
405 if (vfs_ctx_get_cwd(&parent->vfsCtx, &parentCwd) == ERR)
406 {
407 argv_deinit(&process->argv);
408 namespace_deinit(&process->namespace);
409 space_deinit(&process->space);
410 return ERR;
411 }
412
413 vfs_ctx_init(&process->vfsCtx, &parentCwd);
414
415 path_put(&parentCwd);
416 }
417 else
418 {
419 vfs_ctx_init(&process->vfsCtx, NULL);
420 }
421
422 futex_ctx_init(&process->futexCtx);
424 atomic_init(&process->isDying, false);
425 process->threads.newTid = 0;
426 list_init(&process->threads.list);
427 lock_init(&process->threads.lock);
428
429 rwlock_init(&process->childrenLock);
430 list_entry_init(&process->siblingEntry);
431 list_init(&process->children);
432 list_entry_init(&process->zombieEntry);
433 if (parent != NULL)
434 {
436 list_push(&parent->children, &process->siblingEntry);
437 process->parent = REF(parent);
438 }
439 else
440 {
441 process->parent = NULL;
442 }
443
444 process->dir = NULL;
445 process->prioFile = NULL;
446 process->cwdFile = NULL;
447 process->cmdlineFile = NULL;
448 process->noteFile = NULL;
449 process->waitFile = NULL;
450 process->self = NULL;
451
452 assert(process == &kernelProcess || process_is_child(process, kernelProcess.id));
453
454 LOG_DEBUG("new pid=%d parent=%d priority=%d\n", process->id, parent ? parent->id : 0, priority);
455 return 0;
456}
457
458process_t* process_new(process_t* parent, const char** argv, const path_t* cwd, priority_t priority)
459{
460 process_t* process = malloc(sizeof(process_t));
461 if (process == NULL)
462 {
463 return NULL;
464 }
465
466 if (process_init(process, parent, argv, cwd, priority) == ERR)
467 {
468 free(process);
469 return NULL;
470 }
471
472 char name[MAX_NAME];
473 snprintf(name, MAX_NAME, "%d", process->id);
474 if (process_dir_init(process, name) == ERR)
475 {
476 DEREF(process);
477 return NULL;
478 }
479
480 return process;
481}
482
483void process_kill(process_t* process, uint64_t status)
484{
485 LOG_DEBUG("killing process pid=%d with status=%llu refCount=%d\n", process->id, status, process->ref.count);
486 LOCK_SCOPE(&process->threads.lock);
487
488 if (atomic_exchange(&process->isDying, true))
489 {
490 return;
491 }
492
493 atomic_store(&process->status, status);
494
495 uint64_t killCount = 0;
496 thread_t* thread;
497 LIST_FOR_EACH(thread, &process->threads.list, processEntry)
498 {
499 thread_send_note(thread, "kill", 4);
500 killCount++;
501 }
502
503 if (killCount > 0)
504 {
505 LOG_DEBUG("sent kill note to %llu threads in process pid=%d\n", killCount, process->id);
506 }
507
508 // Anything that another process could be waiting on must be cleaned up here.
509 namespace_deinit(&process->namespace);
510 vfs_ctx_deinit(&process->vfsCtx);
511 // The dir entries have refs to the process, but a parent process might want to read files in /proc/[pid] after the
512 // process has exited especially its wait file, so for now we defer dereferencing them until the reaper runs. This
513 // is really not ideal so
514 // TODO: implement a proper reaper.
515 /*DEREF(process->dir);
516 DEREF(process->prioFile);
517 DEREF(process->cwdFile);
518 DEREF(process->cmdlineFile);
519 DEREF(process->noteFile);
520 DEREF(process->waitFile);
521 DEREF(process->self);*/
523
524 LOCK_SCOPE(&zombiesLock);
525 list_push(&zombies, &REF(process)->zombieEntry);
526 lastReaperTime = timer_uptime(); // Delay reaper run
527}
528
529bool process_is_child(process_t* process, pid_t parentId)
530{
531 process_t* current = REF(process);
532 bool found = false;
533 while (current != NULL)
534 {
535 process_t* parent = NULL;
536
537 if (current->parent == NULL)
538 {
539 break;
540 }
541
542 RWLOCK_READ_SCOPE(&current->parent->childrenLock);
543 if (current->parent == NULL)
544 {
545 break;
546 }
547
548 if (current->parent->id == parentId)
549 {
550 found = true;
551 break;
552 }
553
554 parent = REF(current->parent);
555 DEREF(current);
556 current = parent;
557 }
558
559 if (current != NULL)
560 {
561 DEREF(current);
562 }
563
564 return found;
565}
566
568{
569 procMount = sysfs_mount_new(NULL, "proc", NULL, NULL);
570 if (procMount == NULL)
571 {
572 panic(NULL, "Failed to mount /proc filesystem");
573 }
574
575 selfDir = sysfs_dir_new(procMount->root, "self", NULL, NULL);
576 if (selfDir == NULL)
577 {
578 panic(NULL, "Failed to create /proc/self directory");
579 }
580
582
583 // Kernel process was created before sysfs was initialized, so we have to delay this until now.
584 char name[MAX_NAME];
585 snprintf(name, MAX_NAME, "%d", kernelProcess.id);
586 if (process_dir_init(&kernelProcess, name) == ERR)
587 {
588 panic(NULL, "Failed to create /proc/[pid] directory for kernel process");
589 }
590
591 timer_subscribe(&smp_self_unsafe()->timer, process_reaper_timer);
592}
593
595{
597 {
599 {
600 panic(NULL, "Failed to init kernel process");
601 }
602 LOG_INFO("kernel process initialized with pid=%d\n", kernelProcess.id);
604 }
605
606 return &kernelProcess;
607}
608
610{
611 return sched_process()->id;
612}
#define MAX_NAME
Maximum length of names.
Definition MAX_NAME.h:11
#define MAX_PATH
Maximum length of filepaths.
Definition MAX_PATH.h:11
#define assert(expression)
Definition assert.h:29
static cpu_t * smp_self_unsafe(void)
Returns a pointer to the cpu_t structure of the current CPU.
Definition smp.h:90
#define SYS_GETPID
Definition syscalls.h:27
#define SYSCALL_DEFINE(num, returnType,...)
Macro to define a syscall.
Definition syscalls.h:100
void namespace_deinit(namespace_t *ns)
Deinitializes a namespace.
Definition namespace.c:48
mount_t * namespace_bind(namespace_t *ns, dentry_t *source, path_t *mountpoint)
Bind a directory to a mountpoint in a namespace.
Definition namespace.c:195
uint64_t namespace_init(namespace_t *ns, namespace_t *parent, process_t *owner)
Initializes a namespace.
Definition namespace.c:28
void path_put(path_t *path)
Put a path.
Definition path.c:257
#define PATH_CREATE(inMount, inDentry)
Helper to create a path.
Definition path.h:195
#define PATH_DEFER(path)
Defer path put.
Definition path.h:53
uint64_t path_to_name(const path_t *path, pathname_t *pathname)
Convert a path to a pathname.
Definition path.c:583
#define PATH_EMPTY
Helper to create an empty path.
Definition path.h:182
void vfs_ctx_deinit(vfs_ctx_t *ctx)
Deinitialize a VFS context.
Definition vfs_ctx.c:30
void vfs_ctx_init(vfs_ctx_t *ctx, const path_t *cwd)
Initialize a VFS context.
Definition vfs_ctx.c:11
uint64_t vfs_ctx_get_cwd(vfs_ctx_t *ctx, path_t *outCwd)
Definition vfs_ctx.c:67
#define BUFFER_READ(buffer, count, offset, src, size)
Helper macros for implementing file operations dealing with simple buffers.
Definition vfs.h:372
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:362
#define LOG_INFO(format,...)
Definition log.h:87
#define LOG_DEBUG(format,...)
Definition log.h:81
void space_deinit(space_t *space)
Deinitializes a virtual address space.
Definition space.c:124
uint64_t space_init(space_t *space, uintptr_t startAddress, uintptr_t endAddress, space_flags_t flags)
Initializes a virtual address space.
Definition space.c:62
@ SPACE_MAP_KERNEL_HEAP
Map the kernel heap into the address space.
Definition space.h:36
@ SPACE_MAP_IDENTITY
Map the identity mapped physical memory into the address space.
Definition space.h:37
@ SPACE_MAP_KERNEL_BINARY
Map the kernel binary into the address space.
Definition space.h:35
#define VMM_USER_SPACE_MAX
The maximum address for user space.
Definition vmm.h:74
#define VMM_USER_SPACE_MIN
The minimum address for user space.
Definition vmm.h:75
void argv_deinit(argv_t *argv)
Deinitializes an argument vector, freeing any allocated memory.
Definition argv.c:65
uint64_t argv_init(argv_t *argv, const char **src)
Initializes an argument vector from a source array of strings.
Definition argv.c:9
const char * argv_get_strings(const argv_t *argv, uint64_t *length)
Retrieves a pointer to the start of the first string.
Definition argv.c:74
void process_kill(process_t *process, uint64_t status)
Kills a process.
Definition process.c:483
bool process_is_child(process_t *process, pid_t parentId)
Checks if a process is a child of another process.
Definition process.c:529
process_t * process_get_kernel(void)
Gets the kernel process.
Definition process.c:594
process_t * process_new(process_t *parent, const char **argv, const path_t *cwd, priority_t priority)
Allocates and initializes a new process.
Definition process.c:458
void process_procfs_init(void)
Initializes the /proc directory.
Definition process.c:567
uint64_t thread_send_note(thread_t *thread, const void *buffer, uint64_t count)
Send a note to a thread.
Definition thread.c:132
uint64_t wait_unblock(wait_queue_t *waitQueue, uint64_t amount, errno_t err)
Unblock threads waiting on a wait queue.
Definition wait.c:168
void wait_queue_init(wait_queue_t *waitQueue)
Initialize wait queue.
Definition wait.c:71
#define WAIT_ALL
Wait for all.
Definition wait.h:26
#define WAIT_BLOCK(waitQueue, condition)
Basic block.
Definition wait.h:37
void wait_queue_deinit(wait_queue_t *waitQueue)
Deinitialize wait queue.
Definition wait.c:77
process_t * sched_process(void)
Retrieves the process of the currently running thread.
Definition sched.c:164
void futex_ctx_deinit(futex_ctx_t *ctx)
Deinitialize a per-process futex context. *.
Definition futex.c:21
void futex_ctx_init(futex_ctx_t *ctx)
Initialize a per-process futex context.
Definition futex.c:15
static void lock_init(lock_t *lock)
Initializes a lock.
Definition lock.h:80
#define LOCK_CREATE
Create a lock initializer. @macro LOCK_CREATE.
Definition lock.h:66
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:57
void rwlock_write_acquire(rwlock_t *lock)
Acquires a rwlock for writing, blocking until it is available.
Definition rwlock.c:65
#define RWLOCK_READ_SCOPE(lock)
Acquires a rwlock for reading for the reminder of the current scope.
Definition rwlock.h:27
void rwlock_write_release(rwlock_t *lock)
Releases a rwlock from writing.
Definition rwlock.c:116
void rwlock_init(rwlock_t *lock)
Initializes a rwlock.
Definition rwlock.c:8
#define RWLOCK_WRITE_SCOPE(lock)
Acquires a rwlock for writing for the reminder of the current scope.
Definition rwlock.h:36
void timer_subscribe(timer_ctx_t *ctx, timer_callback_t callback)
Subscribe to timer interrupts.
Definition timer.c:111
clock_t timer_uptime(void)
Time since boot.
Definition timer.c:73
static void ref_init(ref_t *ref, void *free)
Initialize a reference counter.
Definition ref.h:92
#define REF(ptr)
Increment reference count.
Definition ref.h:65
#define DEREF(ptr)
Decrement reference count.
Definition ref.h:80
#define CONFIG_PROCESS_REAPER_INTERVAL
Process reaper interval configuration.
Definition config.h:186
#define EINVAL
Invalid argument.
Definition errno.h:142
#define errno
Error number variable.
Definition errno.h:27
#define EACCES
Permission denied.
Definition errno.h:97
#define EOK
No error.
Definition errno.h:32
poll_events_t
Poll events type.
Definition io.h:288
@ POLLIN
File descriptor is ready to read.
Definition io.h:290
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
Definition list.h:65
static list_entry_t * list_first(list_t *list)
Gets the first entry in the list without removing it.
Definition list.h:382
#define LIST_CREATE(name)
Creates a list initializer.
Definition list.h:176
static void list_remove(list_t *list, list_entry_t *entry)
Removes a list entry from its current list.
Definition list.h:317
static void list_push(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:345
static bool list_is_empty(list_t *list)
Checks if a list is empty.
Definition list.h:229
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:184
static void list_init(list_t *list)
Initializes a list.
Definition list.h:198
static list_entry_t * list_pop(list_t *list)
Pops the first entry from the list.
Definition list.h:361
#define PRIORITY_MAX_USER
Definition proc.h:43
clock_t uptime(void)
System call for retreving the time since boot.
Definition uptime.c:6
#define PRIORITY_MAX
Definition proc.h:42
uint8_t priority_t
Priority type.
Definition proc.h:41
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
#define CONTAINER_OF(ptr, type, member)
Container of macro.
__UINT64_TYPE__ pid_t
Process Identifier.
Definition pid_t.h:11
#define CONTAINER_OF_SAFE(ptr, type, member)
Safe container of macro.
__UINT64_TYPE__ clock_t
A nanosecond time.
Definition clock_t.h:13
static dentry_t * file
Definition log_file.c:17
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static inode_ops_t inodeOps
Definition process.c:277
static uint64_t process_cmdline_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition process.c:176
static void process_inode_cleanup(inode_t *inode)
Definition process.c:271
static process_t * process_file_get_process(file_t *file)
Definition process.c:72
static wait_queue_t * process_wait_poll(file_t *file, poll_events_t *revents)
Definition process.c:249
static file_ops_t noteOps
Definition process.c:225
static uint64_t process_wait_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition process.c:229
static process_t kernelProcess
Definition process.c:28
static file_ops_t prioOps
Definition process.c:142
static uint64_t process_note_write(file_t *file, const void *buffer, uint64_t count, uint64_t *offset)
Definition process.c:193
static uint64_t process_prio_write(file_t *file, const void *buffer, uint64_t count, uint64_t *offset)
Definition process.c:106
static void process_free(process_t *process)
Definition process.c:339
static file_ops_t cwdOps
Definition process.c:172
static uint64_t process_prio_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition process.c:91
static uint64_t process_init(process_t *process, process_t *parent, const char **argv, const path_t *cwd, priority_t priority)
Definition process.c:371
static file_ops_t waitOps
Definition process.c:266
static uint64_t process_cwd_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition process.c:147
static uint64_t process_dir_init(process_t *process, const char *name)
Definition process.c:281
static bool kernelProcessInitalized
Definition process.c:29
static file_ops_t cmdlineOps
Definition process.c:189
static atomic_long count
Definition main.c:9
#define atomic_store(object, desired)
Definition stdatomic.h:289
#define atomic_exchange(object, desired)
Definition stdatomic.h:282
#define _Atomic(T)
Definition stdatomic.h:59
#define atomic_load(object)
Definition stdatomic.h:288
#define ATOMIC_VAR_INIT(value)
Definition stdatomic.h:74
#define atomic_fetch_add(object, operand)
Definition stdatomic.h:283
#define atomic_init(obj, value)
Definition stdatomic.h:75
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC int snprintf(char *_RESTRICT s, size_t n, const char *_RESTRICT format,...)
Definition snprintf.c:3
#define EXIT_SUCCESS
Definition stdlib.h:46
_PUBLIC long long int atoll(const char *nptr)
Definition atoll.c:8
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:4
_PUBLIC size_t strlen(const char *s)
Definition strlen.c:3
CPU structure.
Definition cpu.h:42
Directory entry structure.
Definition dentry.h:83
inode_t * inode
Definition dentry.h:87
File operations structure.
Definition file.h:57
uint64_t(* write)(file_t *file, const void *buffer, uint64_t count, uint64_t *offset)
Definition file.h:62
uint64_t(* read)(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition file.h:61
File structure.
Definition file.h:37
void(* cleanup)(inode_t *inode)
Definition inode.h:98
Inode structure.
Definition inode.h:54
void * private
Definition inode.h:66
Trap Frame Structure.
Definition interrupt.h:42
A doubly linked list.
Definition list.h:51
A simple ticket lock implementation.
Definition lock.h:43
Mount structure.
Definition mount.h:36
dentry_t * root
The root dentry of the mounted filesystem.
Definition mount.h:42
Path structure.
Definition path.h:110
Pathname structure.
Definition path.h:122
char string[MAX_PATH]
Definition path.h:123
Process structure.
Definition process.h:53
dentry_t * prioFile
The /proc/[pid]/prio file.
Definition process.h:72
mount_t * self
The /proc/[pid]/self mount point.
Definition process.h:77
list_entry_t siblingEntry
Definition process.h:67
struct process * parent
Definition process.h:70
futex_ctx_t futexCtx
Definition process.h:62
dentry_t * dir
The /proc/[pid] directory for this process.
Definition process.h:71
ref_t ref
Definition process.h:54
argv_t argv
Definition process.h:58
space_t space
Definition process.h:59
dentry_t * noteFile
The /proc/[pid]/note file.
Definition process.h:75
list_entry_t zombieEntry
Definition process.h:69
dentry_t * waitFile
The /proc/[pid]/wait file.
Definition process.h:76
pid_t id
Definition process.h:55
vfs_ctx_t vfsCtx
Definition process.h:61
process_threads_t threads
Definition process.h:65
list_t children
Definition process.h:68
dentry_t * cwdFile
The /proc/[pid]/cwd file.
Definition process.h:73
rwlock_t childrenLock
Definition process.h:66
dentry_t * cmdlineFile
The /proc/[pid]/cmdline file.
Definition process.h:74
atomic_bool isDying
Definition process.h:64
wait_queue_t dyingWaitQueue
Definition process.h:63
atomic_uint32_t count
Atomic reference counter.
Definition ref.h:40
Thread of execution structure.
Definition thread.h:55
Wait queue structure.
Definition wait.h:166
mount_t * sysfs_mount_new(const path_t *parent, const char *name, namespace_t *ns, const superblock_ops_t *superblockOps)
Mount a new instance of SysFS.
Definition sysfs.c:100
dentry_t * sysfs_dir_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, void *private)
Create a new directory inside a mounted SysFS instance.
Definition sysfs.c:174
dentry_t * sysfs_file_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, const file_ops_t *fileOps, void *private)
Create a new file inside a mounted SysFS instance.
Definition sysfs.c:216