AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
procfs.c
Go to the documentation of this file.
1
13
14#include <core/system.h>
15#include <core/arch.h>
16#include <core/module.h>
17#include <core/string.h>
18#include <core/time.h>
19#include <aquila/errno.h>
20#include <boot/boot.h>
21
22#include <fs/vfs.h>
23#include <fs/iobuf.h>
24#include <fs/devfs.h>
25#include <fs/posix.h>
26#include <fs/vcache.h>
27
28#include <sys/proc.h>
29#include <sys/sched.h>
30
31#include <mm/vm.h>
32#include <mm/buddy.h>
33#include <ds/buddy.h>
34
35struct fs procfs;
36
39 char *name;
40 ssize_t (*read)(off_t off, size_t size, char *buf);
41};
42
43/* procfs's root directory, usually mounted on /proc */
45struct vcache procfs_vcache = {0};
46
48static ssize_t procfs_meminfo(off_t off, size_t size, char *buf)
49{
50 char meminfo_buf[512];
52
53 int sz = snprintf(meminfo_buf, 512,
54 "MemTotal: %d kB\n"
55 "MemFree: %d kB\n"
56 "KVMemUsed: %d KB\n"
57 "KVMemObjCnt: %d\n"
58 "Slab: %d kB\n",
59 (int) (k_total_mem/1024),
60 (int) ((k_total_mem-k_used_mem)/1024),
61 (int) (kvmem_used/1024),
62 (int) kvmem_obj_cnt,
63 (int) (slab_used/1024)
64 );
65
66 if (off < sz) {
67 ssize_t ret = MIN(size, (size_t)(sz - off));
68 memcpy(buf, meminfo_buf + off, ret);
69 return ret;
70 }
71
72 return 0;
73}
74
76static ssize_t procfs_kvmem(off_t off, size_t size, char *buf)
77{
78 extern struct queue *malloc_types;
79
80 char kvmem_buf[1024];
81 int sz = 0;
82
83 queue_for (node, malloc_types) {
84 struct malloc_type *type = (struct malloc_type *) node->value;
85 sz += snprintf(kvmem_buf + sz, sizeof(kvmem_buf) - sz,
86 "%s %d %d\n", type->name, type->nr, type->total);
87
88 if ((size_t) sz >= sizeof(kvmem_buf))
89 break;
90 }
91
92 if (off < sz) {
93 ssize_t ret = MIN(size, (size_t)(sz - off));
94 memcpy(buf, kvmem_buf + off, ret);
95 return ret;
96 }
97
98 return 0;
99}
100
102static ssize_t procfs_version(off_t off, size_t size, char *buf)
103{
104 char version_buf[512];
105
106 int sz = snprintf(version_buf, 512,
107 "%s version %s (%s version %s) %s\n",
112 );
113
114 if (off < sz) {
115 ssize_t ret = MIN(size, (size_t)(sz - off));
116 memcpy(buf, version_buf + off, ret);
117 return ret;
118 }
119
120 return 0;
121}
122
124static ssize_t procfs_uptime(off_t off, size_t size, char *buf)
125{
126 char uptime_buf[64];
127
128 int sz = snprintf(uptime_buf, 64, "%ld\n", arch_rtime_ms() / 1000);
129
130 if (off < sz) {
131 ssize_t ret = MIN(size, (size_t)(sz - off));
132 memcpy(buf, uptime_buf + off, ret);
133 return ret;
134 }
135
136 return 0;
137}
138
139/* the architecture's description of its interrupts, if it has one */
140int arch_interrupts_info(char *buf, size_t size) __attribute__((weak));
141
144static ssize_t procfs_interrupts(off_t off, size_t size, char *buf)
145{
146 char info[2048];
147 int sz = arch_interrupts_info ? arch_interrupts_info(info, sizeof(info)) : 0;
148
149 sz = MIN(sz, (int) sizeof(info) - 1);
150
151 if (off < sz) {
152 ssize_t ret = MIN(size, (size_t)(sz - off));
153 memcpy(buf, info + off, ret);
154 return ret;
155 }
156
157 return 0;
158}
159
161static ssize_t procfs_filesystems(off_t off, size_t size, char *buf)
162{
163 char fs_buf[512];
164
165 extern struct fs_list *registered_fs;
166
167 int sz = 0;
168
169 for (struct fs_list *fs = registered_fs; fs; fs = fs->next) {
170 sz += snprintf(fs_buf + sz, sizeof(fs_buf) - sz, "%s\t%s\n", fs->fs->nodev? "nodev" : "", fs->name);
171 if ((size_t) sz >= sizeof(fs_buf))
172 break;
173 }
174
175 if (off < sz) {
176 ssize_t ret = MIN(size, (size_t)(sz - off));
177 memcpy(buf, fs_buf + off, ret);
178 return ret;
179 }
180
181 return 0;
182}
183
185static ssize_t procfs_cmdline(off_t off, size_t size, char *buf)
186{
187 char cmdline_buf[512];
188
189 extern struct boot *__kboot;
190
191 int sz = snprintf(cmdline_buf, 512, "%s\n", __kboot->cmdline);
192
193 if (off < sz) {
194 ssize_t ret = MIN(size, (size_t)(sz - off));
195 memcpy(buf, cmdline_buf + off, ret);
196 return ret;
197 }
198
199 return 0;
200}
201
203static ssize_t procfs_rdcmdline(off_t off, size_t size, char *buf)
204{
205 char rdcmdline_buf[512];
206
207 extern struct boot *__kboot;
208
209 /* none, from a disk (root=): an empty line */
211
212 int sz = snprintf(rdcmdline_buf, 512, "%s\n", cmdline);
213
214 if (off < sz) {
215 ssize_t ret = MIN(size, (size_t)(sz - off));
216 memcpy(buf, rdcmdline_buf + off, ret);
217 return ret;
218 }
219
220 return 0;
221}
222
224static ssize_t procfs_mounts(off_t off, size_t size, char *buf)
225{
226 char mounts_buf[4096];
227
228 extern struct queue *mounts;
229 int sz = 0;
230
231 queue_for (node, mounts) {
232 struct mountpoint *mp = node->value;
233 sz += snprintf(mounts_buf + sz, sizeof(mounts_buf) - sz,
234 "%s %s %s %s\n", mp->dev, mp->path, mp->type, mp->options);
235 if ((size_t) sz >= sizeof(mounts_buf))
236 break;
237 }
238
239
240 if (off < sz) {
241 ssize_t ret = MIN(size, (size_t)(sz - off));
242 memcpy(buf, mounts_buf + off, ret);
243 return ret;
244 }
245
246 return 0;
247}
248
250static ssize_t procfs_buddyinfo(off_t off, size_t size, char *buf)
251{
252 char buddyinfo_buf[4096];
253
254 extern struct buddy buddies[BUDDY_ZONE_NR][BUDDY_MAX_ORDER+1];
255
256 int sz = 0;
257
258 sz += snprintf(buddyinfo_buf + sz, sizeof(buddyinfo_buf) - sz, "Zone DMA\n");
259 for (int i = 0; i < BUDDY_MAX_ORDER + 1; ++i) {
260 sz += snprintf(buddyinfo_buf + sz, sizeof(buddyinfo_buf) - sz, "2^%d: %d\n",
261 12 + i, buddies[0][i].usable);
262 }
263
264 sz += snprintf(buddyinfo_buf + sz, sizeof(buddyinfo_buf) - sz, "\nZone Normal\n");
265 for (int i = 0; i < BUDDY_MAX_ORDER + 1; ++i) {
266 sz += snprintf(buddyinfo_buf + sz, sizeof(buddyinfo_buf) - sz, "2^%d: %d\n",
267 12 + i, buddies[1][i].usable);
268 }
269
270 sz += snprintf(buddyinfo_buf + sz, sizeof(buddyinfo_buf) - sz, "\n");
271
272
273 if (off < sz) {
274 ssize_t ret = MIN(size, (size_t)(sz - off));
275 memcpy(buf, buddyinfo_buf + off, ret);
276 return ret;
277 }
278
279 return 0;
280}
281
283static ssize_t procfs_devices(off_t off, size_t size, char *buf)
284{
285 char dev_buf[512];
286
287 int sz = 0;
288
289 extern struct dev *chrdev[256];
290 extern struct dev *blkdev[256];
291
292 sz += snprintf(dev_buf + sz, sizeof(dev_buf) - sz, "chrdev:\n");
293 for (int i = 0; i < 256; ++i) {
294 if (chrdev[i]) {
295 sz += snprintf(dev_buf + sz, sizeof(dev_buf) - sz, "%d\t%s\n", i, chrdev[i]->name);
296 if ((size_t) sz >= sizeof(dev_buf))
297 break;
298 }
299 }
300
301 sz += snprintf(dev_buf + sz, sizeof(dev_buf) - sz, "\nblkdev:\n");
302 for (int i = 0; i < 256; ++i) {
303 if (blkdev[i]) {
304 sz += snprintf(dev_buf + sz, sizeof(dev_buf) - sz, "%d\t%s\n", i, blkdev[i]->name);
305 if ((size_t) sz >= sizeof(dev_buf))
306 break;
307 }
308 }
309
310 if (off < sz) {
311 ssize_t ret = MIN(size, (size_t)(sz - off));
312 memcpy(buf, dev_buf + off, ret);
313 return ret;
314 }
315
316 return 0;
317}
318
319/* the top directory's files */
320static struct procfs_entry entries[] = {
321 {"meminfo", procfs_meminfo},
322 {"cmdline", procfs_cmdline},
323 {"rdcmdline", procfs_rdcmdline},
324 {"version", procfs_version},
325 {"uptime", procfs_uptime},
326 {"interrupts", procfs_interrupts},
327 {"filesystems", procfs_filesystems},
328 {"buddyinfo", procfs_buddyinfo},
329 {"kvmem", procfs_kvmem},
330 {"mounts", procfs_mounts},
331 {"devices", procfs_devices},
332};
333
334#define PROCFS_ENTRIES (sizeof(entries)/sizeof(entries[0]))
335
337static ssize_t procfs_proc_status(int pid, off_t off, size_t size, void *buf)
338{
339 struct proc *proc = proc_pid_find(pid);
340
341 if (!proc)
342 return -ESRCH;
343
344 char status_buf[1024], cwd[256];
345
346 if (!proc->cwd || vfs_vnode_path(proc->cwd, NULL, cwd, sizeof(cwd)))
347 strcpy(cwd, proc->cwd ? "?" : "/");
348
349 int sz = snprintf(status_buf, sizeof(status_buf),
350 "name: %s\n"
351 "pid: %d\n"
352 "ppid: %d\n"
353 "cwd: %s\n"
354 "umask: %x\n"
355 "uid: %d\n"
356 "gid: %d\n"
357 "heap: 0x%x\n"
358 "threads_nr: %d\n"
359 "sigmask: 0x%x\n"
360 "sigpending: 0x%x\n",
361 proc->name,
362 proc->pid,
363 proc->parent ? proc->parent->pid : 0,
364 cwd,
365 proc->mask,
366 proc->uid,
367 proc->gid,
368 proc->heap,
370 (unsigned) proc->sigmask,
371 (unsigned) proc->sig_pending
372 );
373
374 /* what each thread is doing: running (or ready to), sleeping (ISLEEP,
375 * signals wake it) or waiting (USLEEP), and with a deadline */
376 static const char *states[] = {"running", "sleeping", "waiting", "zombie"};
377
378 queue_for (node, &proc->threads) {
379 struct thread *thread = node->value;
380 const char *state = thread->state < sizeof(states) / sizeof(states[0]) ?
381 states[thread->state] : "?";
382
383 sz += snprintf(status_buf + sz, sizeof(status_buf) - sz,
384 "thread %d%s%s: %s%s%s%s\n", thread->tid,
385 thread->name ? " " : "", thread->name ? thread->name : "", state,
386 thread->waitq ? " on a queue" : "",
387 list_linked(&thread->timer_link) ? " with a deadline" : "",
388 list_linked(&thread->run_link) && !thread->waitq ? " (ready)" :
389 thread == curthread ? " (current)" : "");
390 }
391
392 if (off < sz) {
393 ssize_t ret = MIN(size, (size_t)(sz - off));
394 memcpy(buf, status_buf + off, ret);
395 return ret;
396 }
397
398 return 0;
399}
400
403static ssize_t procfs_proc_maps(int pid, off_t off, size_t size, void *buf)
404{
405 struct proc *proc = proc_pid_find(pid);
406
407 if (!proc)
408 return -ESRCH;
409
410 char maps_buf[4096];
411
412 int sz = 0;
413
414 struct queue *vm_entries = &proc->vm_space.vm_entries;
415 queue_for (node, vm_entries) {
416 struct vm_entry *vm_entry = node->value;
417
418 char perm[5] = {0};
419 perm[0] = vm_entry->flags & VM_UR? 'r' : '-';
420 perm[1] = vm_entry->flags & VM_UW? 'w' : '-';
421 perm[2] = vm_entry->flags & VM_UX? 'x' : '-';
422 perm[3] = vm_entry->flags & VM_SHARED? 's' : 'p';
423
424 char *desc = "";
425
426 if (vm_entry == proc->stack_vm)
427 desc = "[stack]";
428
429 if (vm_entry == proc->heap_vm)
430 desc = "[heap]";
431
432 struct vnode *vnode = NULL;
433
435 vnode = (struct vnode *) vm_entry->vm_object->p;
436
437 sz += snprintf(maps_buf + sz, sizeof(maps_buf) - sz,
438 "%x-%x %s %x %x %x %s\n",
439 vm_entry->base, /* its start */
440 vm_entry->base + vm_entry->size, /* its end */
441 perm, /* its permissions */
442 vm_entry->off, /* its offset in the file */
443 vnode? vnode->dev : 0, /* the file's device */
444 vnode? vnode->ino : 0, /* the file's inode */
445 desc);
446 }
447
448 if (off < sz) {
449 ssize_t ret = MIN(size, (size_t)(sz - off));
450 memcpy(buf, maps_buf + off, ret);
451 return ret;
452 }
453
454 return 0;
455}
456
458static ssize_t procfs_proc_vmstats(int pid, off_t off, size_t size, void *buf)
459{
460 struct proc *proc = proc_pid_find(pid);
461
462 if (!proc)
463 return -ESRCH;
464
465 char vmstats_buf[4096];
466
467 int sz = 0;
468
469 struct queue *vm_entries = &proc->vm_space.vm_entries;
470
471 queue_for (node, vm_entries) {
472 struct vm_entry *vm_entry = node->value;
473
474 char perm[5] = {0};
475 perm[0] = vm_entry->flags & VM_UR? 'r' : '-';
476 perm[1] = vm_entry->flags & VM_UW? 'w' : '-';
477 perm[2] = vm_entry->flags & VM_UX? 'x' : '-';
478 perm[3] = vm_entry->flags & VM_SHARED? 's' : 'p';
479
480 const char *type = "";
481 if (vm_entry->vm_object) {
482 switch (vm_entry->vm_object->type) {
483 case VMOBJ_FILE: type = "file"; break;
484 case VMOBJ_ZERO: type = "anon"; break;
485 }
486 }
487
488 sz += snprintf(vmstats_buf + sz, sizeof(vmstats_buf) - sz,
489 "%p-%p %s %p %p %s\n",
490 vm_entry->base,
492 perm,
493 vm_entry->off,
495 type);
496 }
497
498 if (off < sz) {
499 ssize_t ret = MIN(size, (size_t)(sz - off));
500 memcpy(buf, vmstats_buf + off, ret);
501 return ret;
502 }
503
504 return 0;
505}
506
509 char *name;
510 ssize_t (*read)(int pid, off_t off, size_t size, void *buf);
511};
512
514 {"status", procfs_proc_status},
515 {"maps", procfs_proc_maps},
516 {"vmstats", procfs_proc_vmstats},
517};
518
519#define PROCFS_PROC_ENTRIES (sizeof(proc_entries)/sizeof(proc_entries[0]))
520
521/* the inode number of a process's directory; its files' follow it. They
522 * start from process 0's, which isn't inode 0 */
523#define PROC_INO(pid) (((pid) + 1) * (PROCFS_PROC_ENTRIES + 1))
524#define INO_PID(ino) ((ino) / (PROCFS_PROC_ENTRIES + 1) - 1)
525
528static ssize_t procfs_entry_read(struct vnode *node, off_t offset, size_t size, char *buf)
529{
530 size_t id = (size_t) node->p;
531
532 if ((ssize_t) node->ino < 0) {
533 if (id < PROCFS_ENTRIES)
534 return entries[id].read(offset, size, buf);
535 } else {
536 size_t pid = INO_PID(node->ino);
537 id -= 1;
538 if (id < PROCFS_PROC_ENTRIES)
539 return proc_entries[id].read(pid, offset, size, buf);
540 }
541
542 return -ENOSYS;
543}
544
547static ssize_t procfs_read(struct vnode *node, off_t offset, struct iobuf *io)
548{
549 char *buf = kmalloc(PAGE_SIZE, &M_BUFFER, 0);
550
551 if (!buf)
552 return -ENOMEM;
553
554 size_t size = io->resid, done = 0;
555 ssize_t r = 0;
556
557 while (done < size) {
558 size_t len = MIN(size - done, PAGE_SIZE);
559
560 if ((r = procfs_entry_read(node, offset + done, len, buf)) <= 0)
561 break;
562
563 size_t made = r;
564
565 if ((r = iobuf_out(io, buf, made)) < 0)
566 break;
567
568 done += r;
569
570 /* the end of the text, or a fault */
571 if ((size_t) r < len)
572 break;
573 }
574
575 kfree(buf);
576 return done ? (ssize_t) done : r;
577}
578
582static ssize_t procfs_readdir(struct vnode *vnode, off_t offset, struct dirent *dirent)
583{
584 if (vnode == procfs_root) {
585 if (offset == 0) {
586 dirent->d_ino = 0;
587 strcpy(dirent->d_name, ".");
588 return 1;
589 } else if (offset == 1) {
590 dirent->d_ino = 1;
591 strcpy(dirent->d_name, "..");
592 return 1;
593 }
594
595 offset -= 2;
596
597 if ((size_t) offset < PROCFS_ENTRIES) {
598 strcpy(dirent->d_name, entries[offset].name);
599 return 1;
600 }
601
602 /* then self, and the processes */
603 offset -= PROCFS_ENTRIES;
604
605 if (!offset) {
606 snprintf(dirent->d_name, 10, "self");
607 return 1;
608 }
609
610 --offset;
611
612 queue_for (node, procs) {
613 if (!offset) {
614 struct proc *proc = node->value;
615 snprintf(dirent->d_name, 10, "%d", proc->pid);
616 return 1;
617 }
618
619 --offset;
620 }
621 } else if (vnode->ino > 0) {
622 size_t pid = INO_PID(vnode->ino);
623
624 if (offset == 0) {
625 dirent->d_ino = 0;
626 strcpy(dirent->d_name, ".");
627 return 1;
628 } else if (offset == 1) {
629 dirent->d_ino = 1;
630 strcpy(dirent->d_name, "..");
631 return 1;
632 }
633
634 offset -= 2;
635
636 if ((size_t) offset < PROCFS_PROC_ENTRIES) {
637 strcpy(dirent->d_name, proc_entries[offset].name);
638 return 1;
639 }
640 }
641
642 return 0;
643}
644
646static int procfs_finddir(struct vnode *parent, const char *name, struct dirent *dirent)
647{
648 if (parent->ino == (ino_t) procfs_root) {
649 for (size_t i = 0; i < PROCFS_ENTRIES; ++i) {
650 if (!strcmp(name, entries[i].name)) {
651 dirent->d_ino = -(i + 1);
652 return 0;
653 }
654 }
655
656 if (!strcmp(name, "self")) {
657 dirent->d_ino = PROC_INO(curproc->pid);
658 return 0;
659 }
660
661 queue_for (node, procs) {
662 struct proc *proc = node->value;
663 char buf[10];
664 snprintf(buf, 10, "%d", proc->pid);
665
666 if (!strcmp(buf, name)) {
667 dirent->d_ino = PROC_INO(proc->pid);
668 return 0;
669 }
670 }
671 } else if (parent->ino > 0) {
672 size_t pid = INO_PID(parent->ino);
673
674 /* a process's directory's parent is /proc */
675 if (!strcmp(name, "..")) {
676 dirent->d_ino = (vino_t) procfs_root;
677 return 0;
678 }
679
680 for (size_t i = 0; i < PROCFS_PROC_ENTRIES; ++i) {
681 if (!strcmp(proc_entries[i].name, name)) {
682 dirent->d_ino = PROC_INO(pid) + i + 1;
683 return 0;
684 }
685 }
686 }
687
688 return -ENOENT;
689}
690
692static int procfs_vget(struct vnode *super, ino_t ino, struct vnode **vnode)
693{
694 int err = 0;
695
696 if (ino == (vino_t) procfs_root) {
697 if (vnode) *vnode = procfs_root;
698 return 0;
699 } else if ((ssize_t) ino < 0) {
700 intptr_t id = -ino - 1;
701
702 if ((size_t) id < PROCFS_ENTRIES) {
703 struct vnode *node = NULL;
704 if (!(node = vcache_find(&procfs_vcache, ino))) { /* not in use yet */
705 node = kmalloc(sizeof(struct vnode), &M_VNODE, M_ZERO);
706 if (!node) goto e_nomem;
707
708 node->ino = ino;
709 node->mode = S_IFREG | 0555;
710 node->fs = &procfs;
711 node->p = (void *) id;
712
713 struct timespec ts;
714 gettime(&ts);
715
716 node->ctime = ts;
717 node->atime = ts;
718 node->mtime = ts;
719
721 }
722
723 if (vnode) *vnode = node;
724 return 0;
725 } else {
726 return -ENOENT;
727 }
728 } else {
729 size_t pid = INO_PID(ino);
730 size_t id = ino % (PROCFS_PROC_ENTRIES + 1);
731 struct vnode *node = NULL;
732
733 if (!(node = vcache_find(&procfs_vcache, ino))) { /* not in use yet */
734 node = kmalloc(sizeof(struct vnode), &M_VNODE, M_ZERO);
735 if (!node) goto e_nomem;
736
737 node->ino = ino;
738
739 if (id) {
740 node->mode = S_IFREG | 0555;
741 } else {
742 node->mode = S_IFDIR | 0555;
743 }
744
745 node->fs = &procfs;
746 node->p = (void *) id;
747
748 struct timespec ts;
749 gettime(&ts);
750
751 node->ctime = ts;
752 node->atime = ts;
753 node->mtime = ts;
754
756 }
757
758 if (vnode) *vnode = node;
759
760 return 0;
761 }
762
763e_nomem:
764 err = -ENOMEM;
765error:
766 return err;
767}
768
770static int procfs_close(struct vnode *vnode)
771{
772 /* the root vnode is never freed */
773 if (vnode == procfs_root) {
774 return 0;
775 }
776
777 if (vnode->ref == 0) {
780
782 kfree(vnode);
783 }
784
785 return 0;
786}
787
789static int procfs_init()
790{
791 procfs_root = kmalloc(sizeof(struct vnode), &M_VNODE, M_ZERO);
792 if (!procfs_root) return -ENOMEM;
793
794 procfs_root->mode = S_IFDIR | 0555;
797 procfs_root->ref = 1;
798
799 struct timespec ts;
800 gettime(&ts);
801
802 procfs_root->ctime = ts;
803 procfs_root->atime = ts;
804 procfs_root->mtime = ts;
805
807
809 return 0;
810}
811
815static int procfs_mount(struct vnode *dir, int flags, void *data)
816{
817 return vfs_bind(dir, procfs_root);
818}
819
820struct fs procfs = {
821 .name = "procfs",
822 .nodev = 1,
823 .init = procfs_init,
824 .mount = procfs_mount,
825
826 .vops = {
827 .read = procfs_read,
828 .readdir = procfs_readdir,
829 .finddir = procfs_finddir,
830 .vget = procfs_vget,
831 .close = procfs_close,
832 },
833
834 .fops = {
835 .open = posix_file_open,
836 .read = posix_file_read,
837 .readdir = posix_file_readdir,
838 .close = posix_file_close,
839
840 .eof = __vfs_eof_always, /* a read is a snapshot: its end is the end */
841 },
842};
843
struct boot * __kboot
Definition init.c:19
int arch_interrupts_info(char *buf, size_t size)
Definition irq.c:105
#define PAGE_SIZE
Definition system.h:7
size_t k_total_mem
Definition buddy.c:20
size_t k_used_mem
Definition buddy.c:20
struct buddy buddies[BUDDY_ZONE_NR][BUDDY_MAX_ORDER+1]
Definition buddy.c:48
void vnode_pages_free(struct vnode *vnode)
Frees a vnode's vm object and its cached pages, when the vnode itself is freed.
Definition vm_object.c:172
#define __CONFIG_COMPILER__
Definition config.h:33
#define __CONFIG_TIMESTAMP__
Definition config.h:43
#define UTSNAME_SYSNAME
Definition config.h:37
#define UTSNAME_RELEASE
Definition config.h:38
#define __CONFIG_COMPILER_VERSION__
Definition config.h:34
#define MIN(a, b)
Definition system.h:11
ssize_t iobuf_out(struct iobuf *io, const void *src, size_t n)
Copies bytes from the kernel into the iobuf's buffer, and moves past them.
Definition iobuf.c:115
struct dev * blkdev[256]
Definition kdev.c:22
struct dev * chrdev[256]
Definition kdev.c:21
struct queue * malloc_types
Definition kvmem.c:30
size_t kvmem_used
Definition kvmem.c:44
size_t kvmem_obj_cnt
Definition kvmem.c:45
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 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
int vfs_vnode_path(struct vnode *vnode, struct vnode *root, char *buf, size_t size)
Computes a vnode's path, for getcwd() and /proc/mounts: it goes up through .., and finds each directo...
Definition lookup.c:532
#define BUDDY_ZONE_NR
Definition buddy.h:15
#define BUDDY_MAX_ORDER
Definition buddy.h:10
#define MODULE_INIT(name, i, f)
Definition module.h:10
struct queue * mounts
Definition mount.c:14
int posix_file_open(struct file *file)
Finishes opening a file: with O_TRUNC, a regular file is truncated to 0 bytes.
Definition open.c:17
int posix_file_close(struct file *file)
Closes an open file by dropping its reference to its vnode.
Definition close.c:15
ssize_t posix_file_read(struct file *file, struct iobuf *io)
Reads from an open file at its offset, and moves the offset past what was read.
Definition read.c:29
ssize_t posix_file_readdir(struct file *file, struct dirent *dirent)
Reads the directory entry at an open directory's offset, and moves the offset past it.
Definition readdir.c:22
struct proc * proc_pid_find(pid_t pid)
Finds a process by its ID.
Definition proc.c:179
struct queue * procs
Definition proc.c:37
struct vcache procfs_vcache
Definition procfs.c:45
static ssize_t procfs_entry_read(struct vnode *node, off_t offset, size_t size, char *buf)
Makes the text of a file of procfs, from an offset, into a kernel buffer.
Definition procfs.c:528
static ssize_t procfs_interrupts(off_t off, size_t size, char *buf)
Makes /proc/interrupts: the interrupt controller and the IRQs, as the architecture describes them.
Definition procfs.c:144
static ssize_t procfs_buddyinfo(off_t off, size_t size, char *buf)
Makes /proc/buddyinfo: the buddy allocator's free blocks, by size.
Definition procfs.c:250
static ssize_t procfs_rdcmdline(off_t off, size_t size, char *buf)
Makes /proc/rdcmdline: the RAM disk module's command line.
Definition procfs.c:203
static int procfs_vget(struct vnode *super, ino_t ino, struct vnode **vnode)
Gets the vnode of an inode number, making it if it isn't in use.
Definition procfs.c:692
struct fs procfs
Definition procfs.c:35
static ssize_t procfs_proc_status(int pid, off_t off, size_t size, void *buf)
Makes a process's status: its IDs, its state and its threads'.
Definition procfs.c:337
static ssize_t procfs_kvmem(off_t off, size_t size, char *buf)
Makes /proc/kvmem: the kernel's allocations, by malloc type.
Definition procfs.c:76
static int procfs_finddir(struct vnode *parent, const char *name, struct dirent *dirent)
Finds the entry of a directory that has a name, and its inode number.
Definition procfs.c:646
#define PROCFS_ENTRIES
Definition procfs.c:334
static ssize_t procfs_proc_maps(int pid, off_t off, size_t size, void *buf)
Makes a process's maps: its mappings, as Linux's /proc/<pid>/maps shows them.
Definition procfs.c:403
static ssize_t procfs_devices(off_t off, size_t size, char *buf)
Makes /proc/devices: the registered device drivers.
Definition procfs.c:283
static ssize_t procfs_read(struct vnode *node, off_t offset, struct iobuf *io)
Reads a file of procfs: its text is made a page at a time, and copied out through the iobuf.
Definition procfs.c:547
static ssize_t procfs_cmdline(off_t off, size_t size, char *buf)
Makes /proc/cmdline: the kernel's command line.
Definition procfs.c:185
struct vnode * procfs_root
Definition procfs.c:44
static int procfs_mount(struct vnode *dir, int flags, void *data)
Mounts procfs on a directory: its one root directory is bound there.
Definition procfs.c:815
#define INO_PID(ino)
Definition procfs.c:524
static ssize_t procfs_meminfo(off_t off, size_t size, char *buf)
Makes /proc/meminfo: the memory there is, and how it's used.
Definition procfs.c:48
static ssize_t procfs_filesystems(off_t off, size_t size, char *buf)
Makes /proc/filesystems: the installed filesystems.
Definition procfs.c:161
static int procfs_close(struct vnode *vnode)
Frees a vnode that has no references left; the root stays.
Definition procfs.c:770
static ssize_t procfs_proc_vmstats(int pid, off_t off, size_t size, void *buf)
Makes a process's vmstats: its mappings and their vm objects.
Definition procfs.c:458
#define PROCFS_PROC_ENTRIES
Definition procfs.c:519
#define PROC_INO(pid)
Definition procfs.c:523
static struct procfs_proc_entry proc_entries[]
Definition procfs.c:513
static ssize_t procfs_readdir(struct vnode *vnode, off_t offset, struct dirent *dirent)
Reads a directory's entry at an offset.
Definition procfs.c:582
static ssize_t procfs_uptime(off_t off, size_t size, char *buf)
Makes /proc/uptime: the time since boot.
Definition procfs.c:124
static struct procfs_entry entries[]
Definition procfs.c:320
static ssize_t procfs_mounts(off_t off, size_t size, char *buf)
Makes /proc/mounts: the mounted filesystems.
Definition procfs.c:224
static int procfs_init()
Sets procfs up at boot: its root directory, and its vnode cache.
Definition procfs.c:789
static ssize_t procfs_version(off_t off, size_t size, char *buf)
Makes /proc/version: the kernel's name and version.
Definition procfs.c:102
#define queue_for(n, q)
Definition queue.h:37
#define curproc
Definition sched.h:13
#define curthread
Definition sched.h:12
size_t slab_used
Definition slab.c:45
int snprintf(char *s, size_t n, const char *fmt,...)
Formats a string into a buffer.
Definition snprintf.c:226
#define NULL
Definition stddef.h:27
__SIZE_TYPE__ size_t
Definition stddef.h:7
__PTRDIFF_TYPE__ intptr_t
Definition stddef.h:11
Definition boot.h:35
char * cmdline
Definition boot.h:36
module_t * modules
Definition boot.h:41
int modules_count
Definition boot.h:39
One order of a buddy allocator's zone (mm/buddy.c): a bitmap of its blocks, a set bit for a block tha...
Definition buddy.h:9
size_t usable
Definition buddy.h:11
A device driver: its operations, any of which may be NULL.
Definition dev.h:28
char * name
Definition dev.h:29
The list of registered filesystem types.
Definition vfs.h:187
A filesystem type.
Definition vfs.h:98
int nodev
Definition vfs.h:108
char * name
Definition vfs.h:99
An iobuf.
Definition iobuf.h:35
size_t resid
Definition iobuf.h:38
A malloc type: what an allocation is for, which /proc/kvmem counts by.
Definition kvmem.h:14
const char * name
Definition kvmem.h:15
size_t total
Definition kvmem.h:18
size_t nr
Definition kvmem.h:17
char * cmdline
Definition boot.h:18
A mount's description, as /proc/mounts shows it.
Definition vfs.h:307
const char * type
Definition vfs.h:310
const char * options
Definition vfs.h:311
const char * path
Definition vfs.h:309
const char * dev
Definition vfs.h:308
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 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
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
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
sigset_t sig_pending
its pending signals, a bit (1 << sig) each: a signal sent again while it's pending is delivered once ...
Definition proc.h:148
sigset_t sigmask
its blocked signals, a bit (1 << sig) each
Definition proc.h:151
A file of the top directory: its name, and what makes its text.
Definition procfs.c:38
char * name
Definition procfs.c:39
ssize_t(*) read(off_t off, size_t size, char *buf)
Definition procfs.c:40
A file of a process's directory: its name, and what makes its text.
Definition procfs.c:508
ssize_t(*) read(int pid, off_t off, size_t size, void *buf)
Definition procfs.c:510
char * name
Definition procfs.c:509
A queue.
Definition queue.h:29
size_t count
Definition queue.h:30
A thread.
Definition thread.h:23
struct list_node run_link
it's on the ready list (sched.c) while it's ready to run, or on the wait queue it sleeps on (waitq); ...
Definition thread.h:45
struct list_node timer_link
it's on the timer's list while it waits with a deadline
Definition thread.h:75
state_t state
its state
Definition thread.h:28
tid_t tid
the thread's ID, in its process
Definition thread.h:25
struct waitq * waitq
Definition thread.h:46
const char * name
A kernel thread's (process 0's): its name, and what it runs.
Definition thread.h:34
A filesystem's vnode cache (fs/vcache.c): its vnodes in memory, by their inode number,...
Definition vcache.h:10
A mapping (map entry): a range of an address space, its permissions, and where its pages come from.
Definition vm.h:66
uint32_t flags
its permissions and flags (VM_*)
Definition vm.h:78
size_t off
where the mapping starts in its object
Definition vm.h:87
vaddr_t base
where the mapping starts in its address space
Definition vm.h:72
struct vm_object * vm_object
its object: what its other pages come from (a file)
Definition vm.h:84
size_t size
its size
Definition vm.h:75
void * p
the pager's own data (a file's vnode)
Definition vm.h:146
int type
its kind (VMOBJ_*)
Definition vm.h:137
struct queue vm_entries
its mappings (map entries), in address order
Definition vm.h:30
A file in memory (a vnode): what its inode says, and the kernel's own state.
Definition vfs.h:113
ino_t ino
Definition vfs.h:114
_time_t atime
Definition vfs.h:123
_time_t ctime
Definition vfs.h:125
dev_t dev
Definition vfs.h:116
size_t ref
how many references there are to it
Definition vfs.h:133
struct fs * fs
Definition vfs.h:127
_time_t mtime
Definition vfs.h:124
size_t size
Definition vfs.h:115
void * p
the filesystem's own data
Definition vfs.h:130
mode_t mode
Definition vfs.h:118
int gettime(struct timespec *ts)
Reads the wall clock (CLOCK_REALTIME).
Definition time.c:29
uint64_t arch_rtime_ms(void)
Reads the monotonic clock, in milliseconds.
Definition timer.c:73
uintptr_t ino_t
Definition types.h:23
uintptr_t vino_t
Definition types.h:14
long int ssize_t
Definition types.h:12
long int off_t
Definition types.h:10
void vcache_init(struct vcache *vcache)
Sets up an empty vnode cache.
Definition vcache.c:25
struct vnode * vcache_find(struct vcache *vcache, ino_t ino)
Finds the cached vnode of an inode.
Definition vcache.c:80
int vcache_insert(struct vcache *vcache, struct vnode *vnode)
Adds a vnode to a cache.
Definition vcache.c:37
int vcache_remove(struct vcache *vcache, struct vnode *vnode)
Takes a vnode out of a cache.
Definition vcache.c:56
int vfs_bind(struct vnode *dir, struct vnode *root)
Mounts a filesystem on a directory: a lookup that reaches dir goes on in root instead.
Definition vfs.c:53
struct fs_list * registered_fs
The installed filesystems.
Definition vfs.c:25
int vfs_install(struct fs *fs)
Installs a filesystem, so that it can be mounted by name.
Definition vfs.c:85
#define VMOBJ_ZERO
pages of zeros
Definition vm.h:59
#define VMOBJ_FILE
a file's pages
Definition vm.h:60
#define VM_UR
user read
Definition vm.h:41
#define VM_SHARED
shared: a fork doesn't copy it
Definition vm.h:46
#define VM_UX
user execute
Definition vm.h:43
#define VM_UW
user write
Definition vm.h:42