kernel2: Be quiet when abort()ing
[meinos.git] / kernel2 / procm.c
blob62ef98febc46309582100849b656fe303386cfe4
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <stdint.h>
21 #include <memkernel.h>
22 #include <procm.h>
23 #include <llist.h>
24 #include <string.h>
25 #include <memuser.h>
26 #include <memphys.h>
27 #include <malloc.h>
28 #include <kprint.h>
29 #include <gdt.h>
30 #include <cpu.h>
31 #include <syscall.h>
32 #include <interrupt.h>
34 /**
35 * Initializes process management
36 * @return -1=Success; 0=Failure
38 int proc_init() {
39 proc_all = llist_create();
40 proc_running = llist_create();
41 proc_sleeping = llist_create();
42 proc_nextpid = 1;
43 proc_current = NULL;
44 if (syscall_create(SYSCALL_PROC_GETPID,proc_getpid,0)==-1) return -1;
45 if (syscall_create(SYSCALL_PROC_GETUID,proc_getuid,1)==-1) return -1;
46 if (syscall_create(SYSCALL_PROC_GETGID,proc_getgid,1)==-1) return -1;
47 if (syscall_create(SYSCALL_PROC_SETUID,proc_setuid,2)==-1) return -1;
48 if (syscall_create(SYSCALL_PROC_SETGID,proc_setgid,2)==-1) return -1;
49 if (syscall_create(SYSCALL_PROC_GETPARENT,proc_getparent,1)==-1) return -1;
50 if (syscall_create(SYSCALL_PROC_GETCHILD,proc_getchild,2)==-1) return -1;
51 if (syscall_create(SYSCALL_PROC_GETNAME,proc_getname,3)==-1) return -1;
52 if (syscall_create(SYSCALL_PROC_SETNAME,proc_setname,2)==-1) return -1;
53 if (syscall_create(SYSCALL_PROC_GETPIDBYNAME,proc_getpidbyname,1)==-1) return -1;
54 if (syscall_create(SYSCALL_PROC_GETVAR,proc_getvar,1)==-1) return -1;
55 if (syscall_create(SYSCALL_PROC_SETVAR,proc_setvar,2)==-1) return -1;
56 if (syscall_create(SYSCALL_PROC_EXIT,proc_exit,1)==-1) return -1;
57 if (syscall_create(SYSCALL_PROC_ABORT,proc_abort,0)==-1) return -1;
58 if (syscall_create(SYSCALL_PROC_STOP,proc_stop,0)==-1) return -1;
59 if (syscall_create(SYSCALL_PROC_CREATE,proc_create_syscall,4)==-1) return -1;
60 if (syscall_create(SYSCALL_PROC_DESTROY,proc_destroy_syscall,1)==-1) return -1;
61 if (syscall_create(SYSCALL_PROC_MEMMAP,proc_memmap,6)==-1) return -1;
62 if (syscall_create(SYSCALL_PROC_MEMALLOC,proc_memalloc,4)==-1) return -1;
63 if (syscall_create(SYSCALL_PROC_MEMUNMAP,proc_memunmap,2)==-1) return -1;
64 if (syscall_create(SYSCALL_PROC_MEMFREE,proc_memfree,2)==-1) return -1;
65 if (syscall_create(SYSCALL_PROC_MEMGET,proc_memget,6)==-1) return -1;
66 if (syscall_create(SYSCALL_PROC_MEMPAGELIST,proc_mempagelist,6)==-1) return -1;
67 if (syscall_create(SYSCALL_PROC_SYSTEM,proc_system,2)==-1) return -1;
68 if (syscall_create(SYSCALL_PROC_JUMP,proc_jump,2)==-1) return -1;
69 if (syscall_create(SYSCALL_PROC_CREATESTACK,proc_createstack,1)==-1) return -1;
70 if (syscall_create(SYSCALL_PROC_WAITPID,proc_waitpid,3)==-1) return -1;
71 return 0;
74 /**
75 * Creates a new process
76 * @param name Process name
77 * @return Process
79 proc_t *proc_create(char *name,uid_t uid,gid_t gid,proc_t *parent,int running,int system) {
80 proc_t *new = malloc(sizeof(proc_t));
82 new->pid = proc_nextpid++;
83 new->uid = uid;
84 new->euid = uid;
85 new->suid = uid;
86 new->gid = gid;
87 new->egid = gid;
88 new->sgid = gid;
89 new->name = strdup(name);
90 new->system = system;
91 new->parent = parent;
92 if (parent!=NULL) llist_push(parent->children,new);
93 new->children = llist_create();
94 memset(&(new->registers),0,sizeof(new->registers));
95 new->registers.efl = 0x202;
96 new->registers.cs = IDX2SEL(3,PRIV_USER);
97 new->registers.ds = IDX2SEL(4,PRIV_USER);
98 new->registers.es = IDX2SEL(4,PRIV_USER);
99 new->registers.fs = IDX2SEL(4,PRIV_USER);
100 new->registers.gs = IDX2SEL(4,PRIV_USER);
101 new->registers.ss = IDX2SEL(4,PRIV_USER);
102 new->addrspace = memuser_create_addrspace(new);
103 new->time_handler = llist_create();
104 new->nice = 0;
105 new->ticks_rem = NICE2TICKS(new->nice);
106 new->var = -1;
107 new->defunc = 0;
108 new->is_sleeping = !running;
109 new->signal = NULL;
110 new->is_vm86 = 0;
112 llist_push(proc_all,new);
113 llist_push(running?proc_running:proc_sleeping,new);
114 return new;
118 * Destroys a process
119 * @param proc Process
120 * @return Success?
122 int proc_destroy(proc_t *proc) {
123 proc_t *child;
125 free(proc->name);
126 while ((child = llist_pop(proc->children))) child->parent = proc->parent;
127 llist_destroy(proc->children);
128 if (proc->parent!=NULL) llist_remove(proc->parent->children,llist_find(proc->parent->children,proc));
129 if (proc->addrspace!=NULL) memuser_destroy_addrspace(proc->addrspace);
130 llist_destroy(proc->time_handler);
132 llist_remove(proc_all,llist_find(proc_all,proc));
133 if (llist_remove(proc_running,llist_find(proc_running,proc))!=proc) llist_remove(proc_sleeping,llist_find(proc_sleeping,proc));
134 free(proc);
135 return 0;
139 * Finds a process by PID
140 * @param PID
141 * @return Process
143 proc_t *proc_find(pid_t pid) {
144 size_t i;
145 proc_t *proc;
146 if (proc_current->pid==pid) return proc_current;
147 for (i=0;(proc = llist_get(proc_all,i));i++) {
148 if (proc->pid==pid) return proc;
150 return NULL;
154 * Checks if proc is a child of parent
155 * @param parent Parent process
156 * @param proc Process to check if it's a child of proc
157 * @return If proc is a child of parent
159 int proc_ischild(proc_t *parent,proc_t *proc) {
160 proc_t *child;
161 size_t i;
163 for (i=0;(child = llist_get(parent->children,i));i++) {
164 if (proc==child) return 1;
166 return 0;
170 * Sends a process sleeping
171 * @param proc Process
172 * @param sleep Reference to sleep variable
173 * @return Success?
175 int proc_sleep(proc_t *proc) {
176 if (!proc->is_sleeping) {
177 llist_remove(proc_running,llist_find(proc_running,proc));
178 llist_push(proc_sleeping,proc);
179 proc->is_sleeping = 1;
180 if (proc==proc_current) proc_shedule();
182 return 0;
186 * Wakes a process
187 * @param proc Process
188 * @return Success?
190 int proc_wake(proc_t *proc) {
191 if (proc->is_sleeping) {
192 llist_remove(proc_sleeping,llist_find(proc_sleeping,proc));
193 llist_push(proc_running,proc);
194 proc->is_sleeping = 0;
196 return 0;
200 * Save registers of process
201 * @param proc Process
202 * @return Success?
204 int proc_regs_save(proc_t *proc) {
205 proc->registers.eax = *interrupt_curregs.eax;
206 proc->registers.ebx = *interrupt_curregs.ebx;
207 proc->registers.ecx = *interrupt_curregs.ecx;
208 proc->registers.edx = *interrupt_curregs.edx;
209 proc->registers.esi = *interrupt_curregs.esi;
210 proc->registers.edi = *interrupt_curregs.edi;
211 proc->registers.ebp = *interrupt_curregs.ebp;
212 proc->registers.esp = *interrupt_curregs.esp;
213 proc->registers.eip = *interrupt_curregs.eip;
214 proc->registers.efl = *interrupt_curregs.efl;
215 proc->registers.cs = *interrupt_curregs.cs;
216 proc->registers.ds = *interrupt_curregs.ds;
217 proc->registers.es = *interrupt_curregs.es;
218 proc->registers.fs = *interrupt_curregs.fs;
219 proc->registers.gs = *interrupt_curregs.gs;
220 proc->registers.ss = *interrupt_curregs.ss;
221 if (proc->is_vm86) vm86_save_segregs(proc);
222 return 0;
226 * Load registers of process
227 * @param proc Process
228 * @return Success?
230 int proc_regs_load(proc_t *proc) {
231 *interrupt_curregs.eax = proc->registers.eax;
232 *interrupt_curregs.ebx = proc->registers.ebx;
233 *interrupt_curregs.ecx = proc->registers.ecx;
234 *interrupt_curregs.edx = proc->registers.edx;
235 *interrupt_curregs.esi = proc->registers.esi;
236 *interrupt_curregs.edi = proc->registers.edi;
237 *interrupt_curregs.ebp = proc->registers.ebp;
238 *interrupt_curregs.esp = proc->registers.esp;
239 *interrupt_curregs.eip = proc->registers.eip;
240 *interrupt_curregs.efl = proc->registers.efl;
241 *interrupt_curregs.cs = proc->registers.cs;
242 *interrupt_curregs.ds = proc->registers.ds;
243 *interrupt_curregs.es = proc->registers.es;
244 *interrupt_curregs.fs = proc->registers.fs;
245 *interrupt_curregs.gs = proc->registers.gs;
246 *interrupt_curregs.ss = proc->registers.ss;
247 if (proc->is_vm86) vm86_load_segregs(proc);
248 return 0;
252 * Loads next process for execution
254 void proc_shedule() {
255 size_t i;
256 proc_t *proc;
257 proc_t *proc_old = proc_current;
259 // if no processes running hold machine (until next interrupt)
260 if (llist_empty(proc_running)) {
261 // if no processes at all, shutdown
262 if (llist_empty(proc_sleeping)) cpu_shutdown();
263 else {
264 /// @todo maybe put these 2 lines in proc_idle
265 proc_regs_save(proc_current);
266 proc_current = NULL;
267 proc_idle();
271 // Process finished its time slice
272 if (proc_current!=NULL) {
273 proc_current->ticks_rem--;
274 proc_current = NULL;
277 // Search for process that still has time
278 for (i=0;(proc = llist_get(proc_running,i));i++) {
279 if (proc->ticks_rem>0) proc_current = proc;
282 // If no processes with time, fill time slices
283 if (proc_current==NULL) {
284 //kprintf("Refilling time slices\n");
285 for (i=0;(proc = llist_get(proc_running,i));i++) proc->ticks_rem = NICE2TICKS(proc->nice);
286 proc_current = llist_get(proc_running,0);
289 // Set context and load address space
290 if (proc_old!=proc_current) {
291 if (proc_old!=NULL) proc_regs_save(proc_old);
292 proc_regs_load(proc_current);
293 memuser_load_addrspace(proc_current->addrspace);
298 * Gets PID (Syscall)
299 * @return PID
301 pid_t proc_getpid() {
302 return proc_current->pid;
306 * Gets Parent PID (Syscall)
307 * @param pid Process to get parent's PID of
308 * @return Parent's PID
310 pid_t proc_getparent(pid_t pid) {
311 proc_t *proc = proc_find(pid);
312 if (proc!=NULL) {
313 if (proc->parent!=NULL) return proc->parent->pid;
315 return 0;
319 * Gets PID of a child (Syscall)
320 * @param pid Process to get child's PID of
321 * @param i Number of child
322 * @return Child's PID
324 pid_t proc_getchild(pid_t pid,size_t i) {
325 proc_t *proc = proc_find(pid);
326 if (proc!=NULL) {
327 if (proc->parent!=NULL) {
328 proc_t *child = llist_get(proc->parent->children,i);
329 if (child==NULL) return -1;
330 else return child->pid;
333 return 0;
337 * Gets UID (Syscall)
338 * @param idmask Which ID to return
339 * @return UID
341 uid_t proc_getuid(int idmask) {
342 if ((idmask&1)) return proc_current->uid;
343 else if ((idmask&2)) return proc_current->euid;
344 else if ((idmask&4)) return proc_current->suid;
345 else return 0;
349 * Sets UID (Syscall)
350 * @param idmask Which ID to set
351 * @param uid New UID
352 * @todo Check permissions
354 void proc_setuid(int idmask,uid_t uid) {
355 if ((idmask&1)) proc_current->uid = uid;
356 else if ((idmask&2)) proc_current->euid = uid;
357 else if ((idmask&4)) proc_current->suid = uid;
361 * Gets GID (Syscall)
362 * @param idmask Which ID to return
363 * @return GID
365 gid_t proc_getgid(int idmask) {
366 if ((idmask&1)) return proc_current->gid;
367 else if ((idmask&2)) return proc_current->egid;
368 else if ((idmask&4)) return proc_current->sgid;
369 else return 0;
373 * Sets GID (Syscall)
374 * @param idmask Which ID to set
375 * @param uid New GID
376 * @todo Check permissions
378 void proc_setgid(int idmask,gid_t gid) {
379 if ((idmask&1)) proc_current->gid = gid;
380 else if ((idmask&2)) proc_current->egid = gid;
381 else if ((idmask&4)) proc_current->sgid = gid;
385 * Gets process name (Syscall)
386 * @param pid PID
387 * @param buf Buffer for name
388 * @param maxlen Maximal length of name
389 * @return Success? (if buf==NULL length of name is returned)
391 ssize_t proc_getname(pid_t pid,char *buf,size_t maxlen) {
392 proc_t *proc = proc_find(pid);
393 if (proc!=NULL) {
394 if (buf!=NULL) {
395 strncpy(buf,proc->name,maxlen);
396 return 0;
398 else return strlen(proc->name)+1;
400 else return -1;
404 * Sets new process name (Syscall)
405 * @param proc_pid PID
406 * @param name New process name
407 * @return Success?
409 int proc_setname(pid_t proc_pid,const char *name) {
410 if (proc_current->system) {
411 proc_t *proc = proc_find(proc_pid);
412 if (proc!=NULL && proc!=proc_current) {
413 free(proc->name);
414 proc->name = strdup(name);
417 return -1;
421 * Gets PID by process name
422 * @param name Process name
423 * @return PID of process
425 pid_t proc_getpidbyname(const char *name) {
426 size_t i;
427 proc_t *proc;
428 for (i=0;(proc = llist_get(proc_all,i));i++) {
429 if (strcmp(proc->name,name)==0) return proc->pid;
431 return -1;
435 * Gets private variable
436 * @param pid Process' PID
437 * @return private variable
439 int proc_getvar(pid_t pid) {
440 proc_t *proc = proc_find(pid);
441 if (proc!=NULL && (proc_current->system || proc_current==proc)) return proc->var;
442 else return -1;
446 * Sets private variable
447 * @param pid Process' PID
448 * @param var New private variable
450 void proc_setvar(pid_t pid,int var) {
451 proc_t *proc = proc_find(pid);
452 if (proc!=NULL) proc->var = var;
456 * Waits for child(ren)
457 * @param pid PID of child to wait for (-1 for all childs)
458 * @param stat_loc Reference for status
459 * @param options Options
461 pid_t proc_waitpid(pid_t pid,int *stat_loc,int options) {
462 if (pid>0) {
463 proc_t *proc = proc_find(pid);
464 if (proc!=NULL) {
465 if (proc->defunc) {
466 *stat_loc = proc->ret;
467 /// @todo remove child
468 return pid;
471 else return -1;
473 proc_current->wait_pid = pid;
474 proc_current->wait_stat = stat_loc;
475 proc_current->wait = 1;
476 proc_sleep(proc_current);
477 return -1;
481 * Exits process (Syscall)
482 * @param ret Return value
484 void proc_exit(int ret) {
485 if (proc_current->parent!=NULL) {
486 if (proc_current->parent->wait) {
487 pid_t pid = proc_current->parent->wait_pid;
488 if (pid==-1 || pid==proc_current->pid || (pid==0 && proc_current->gid==proc_current->parent->gid) || (pid<-1 && -pid==proc_current->gid)) {
489 proc_current->parent->registers.eax = proc_current->pid;
490 if (proc_current->parent->wait_stat!=NULL) {
491 memuser_load_addrspace(proc_current->parent->addrspace);
492 *(proc_current->parent->wait_stat) = ret;
493 memuser_load_addrspace(proc_current->addrspace);
495 proc_current->parent->wait = 0;
496 proc_wake(proc_current->parent);
501 proc_current->ret = ret;
502 proc_current->defunc = 1;
503 llist_remove(proc_running,llist_find(proc_running,proc_current));
504 //memuser_destroy_addrspace(proc_current->addrspace);
505 //proc_current->addrspace = NULL;
506 proc_current = NULL;
507 proc_idle();
511 * Aborts process (Syscall)
513 void proc_abort() {
514 proc_exit(1);
518 * Stops process (Syscall)
520 void proc_stop() {
521 proc_sleep(proc_current);
525 * Calls a function in process
526 * @param proc Process
527 * @param func Function
528 * @param numparams Number of parameters
529 * @param ... Parameters
531 void proc_call(proc_t *proc,void *func,size_t numparams,...) {
532 if (!proc->defunc) {
533 va_list args;
534 size_t i;
535 int *params = malloc(numparams*sizeof(int));
536 uint32_t *eip = proc_current==proc?interrupt_curregs.eip:&proc->registers.eip;
538 va_start(args,numparams);
539 for (i=0;i<numparams;i++) params[numparams-(i+1)] = va_arg(args,int);
540 va_end(args);
542 memuser_load_addrspace(proc->addrspace);
543 for (i=0;i<numparams;i++) proc_push(proc,params[i]);
544 proc_push(proc,*eip);
545 if (proc_current!=NULL) {
546 memuser_load_addrspace(proc_current->addrspace);
548 *eip = (uint32_t)func;
550 //proc_wake(proc);
555 * Push an element on user stack
556 * @param proc Process
557 * @param val Value
559 void proc_push(proc_t *proc,int val) {
560 uint32_t *esp = proc_current==proc?interrupt_curregs.esp:&proc->registers.esp;
561 *esp -= sizeof(int);
562 //memuser_load_addrspace(proc->addrspace);
563 *((int*)(*esp)) = val;
564 //memuser_load_addrspace(proc_current->addrspace);
568 * Pops an element from user stack
569 * @param proc Process
570 * @return Value
572 int proc_pop(proc_t *proc) {
573 int val = *((int*)proc->registers.esp);
574 proc->registers.esp += sizeof(int);
575 return val;
579 * Idles until next schedule
581 void proc_idle() {
582 asm("mov %0,%%esp"::"r"(cpu_this->tss->esp0)); // reload ESP0 in TSS "by hand"
583 interrupt_enable(1);
584 cpu_halt();
588 * Creates a process (Syscall)
589 * @param name Name
590 * @param uid UID
591 * @param gid GID
592 * @param parent_pid Parent's PID
593 * @return PID of created process
595 pid_t proc_create_syscall(char *name,uid_t uid,gid_t gid,pid_t parent_pid) {
596 if (proc_current->system) {
597 proc_t *parent = proc_find(parent_pid);
598 if (parent!=NULL) {
599 proc_t *proc = proc_create(name,uid,gid,parent,0,0);
600 return proc!=NULL?proc->pid:-1;
603 return -1;
607 * Destroys a process (Syscall)
608 * @param proc_pid PID of process to destroy
610 int proc_destroy_syscall(pid_t proc_pid) {
611 if (proc_current->system) {
612 proc_t *proc = proc_find(proc_pid);
613 if (proc!=NULL && proc!=proc_current) {
614 return proc_destroy(proc);
617 return -1;
621 * Maps a page to a process' address space
622 * @param proc_pid Process' PID
623 * @param virt Virtual address where to map
624 * @param phys Address of physical page
625 * @param writable Whether to map it writable
626 * @param cow Map page as COW
627 * @return Success?
628 * @todo remove memuser_load_addrspace()
630 int proc_memmap(pid_t proc_pid,void *virt,void *phys,int writable,int swappable,int cow) {
631 if (proc_current->system) {
632 proc_t *proc = proc_find(proc_pid);
633 if (proc!=NULL) {
634 pte_t pte = paging_getpte_pd(virt,proc->addrspace->pagedir);
635 if (!pte.exists) {
636 memuser_load_addrspace(proc->addrspace);
637 paging_map_pd(virt,phys,1,writable && !cow,swappable,cow && writable,proc->addrspace->pagedir);
638 memuser_load_addrspace(proc_current->addrspace);
639 llist_push(proc->addrspace->pages_loaded,virt);
640 return 0;
644 return -1;
648 * Allocates a page for a process
649 * @param proc_pid Process' PID
650 * @param virt Virtual address
651 * @param writable Whether to alloc wirtable memory
652 * @param swappable Whether memory should be swappable
653 * @return Success?
655 int proc_memalloc(pid_t proc_pid,void *virt,int writable,int swappable) {
656 void *page = memphys_alloc();
657 if (proc_memmap(proc_pid,virt,page,writable,swappable,0)==0) return 0;
658 else {
659 memphys_free(page);
660 return -1;
665 * Unmaps a page from a process' address space
666 * @param proc_pid Process' PID
667 * @param virt Virtual address to unmap
668 * @return Success?
670 int proc_memunmap(pid_t proc_pid,void *virt) {
671 if (proc_current->system) {
672 proc_t *proc = proc_find(proc_pid);
673 if (proc!=NULL) {
674 memuser_load_addrspace(proc->addrspace);
675 paging_unmap(virt);
676 memuser_load_addrspace(proc_current->addrspace);
677 llist_remove(proc->addrspace->pages_imaginary,llist_find(proc->addrspace->pages_imaginary,virt));
678 return 0;
681 return -1;
685 * Frees a page from a process' address space
686 * @param proc_pid Process' PID
687 * @param virt Virtual address to unmap
688 * @return Success?
690 int proc_memfree(pid_t proc_pid,void *virt) {
691 if (proc_current->system) {
692 proc_t *proc = proc_find(proc_pid);
693 if (proc!=NULL) {
694 memuser_load_addrspace(proc->addrspace);
695 memphys_free(paging_unmap(virt));
696 memuser_load_addrspace(proc_current->addrspace);
697 llist_remove(proc->addrspace->pages_imaginary,llist_find(proc->addrspace->pages_imaginary,virt));
698 return 0;
701 return -1;
705 * Gets information about page of process
706 * @param proc_pid Process' PID
707 * @param virt Virtual address to get information about
708 * @return Success?
710 void *proc_memget(pid_t proc_pid,void *virt,int *exists,int *writable,int *swappable,int *cow) {
711 if (proc_current->system) {
712 proc_t *proc = proc_find(proc_pid);
713 if (proc!=NULL) {
714 pte_t pte = paging_getpte_pd(virt,proc->addrspace->pagedir);
715 if (exists!=NULL) *exists = pte.exists;
716 if (writable!=NULL) *writable = pte.writable;
717 if (swappable!=NULL) *swappable = pte.swappable;
718 if (cow!=NULL) *cow = pte.cow;
719 return pte.in_memory?PAGE2ADDR(pte.page):NULL;
722 *exists = 0;
723 return NULL;
727 * Gets page list (Syscall)
728 * @param proc_pid Process' PID
729 * @param virt Virtual address to get information about
730 * @return Number of pages in list
732 size_t proc_mempagelist(pid_t proc_pid,void **list,size_t n) {
733 if (proc_current->system) {
734 proc_t *proc = proc_find(proc_pid);
735 if (proc!=NULL) {
736 if (list==NULL || n==0) return llist_size(proc->addrspace->pages_loaded)+llist_size(proc->addrspace->pages_imaginary)+llist_size(proc->addrspace->pages_swapped);
737 else {
738 size_t i;
739 size_t j = 0;
740 void *addr;
741 for (i=0;(addr = llist_get(proc->addrspace->pages_loaded,i)) && j<n;i++) list[j++] = addr;
742 for (i=0;(addr = llist_get(proc->addrspace->pages_imaginary,i)) && j<n;i++) list[j++] = addr;
743 for (i=0;(addr = llist_get(proc->addrspace->pages_swapped,i)) && j<n;i++) list[j++] = addr;
744 return j;
748 return -1;
752 * Gives/Withdraws a process system privilegs
753 * @param proc_pid Process' PID
754 * @param system Whether process should have system privilegs or not
755 * @return Success?
757 int proc_system(pid_t proc_pid,int system) {
758 if (proc_current->system) {
759 proc_t *proc = proc_find(proc_pid);
760 if (proc!=NULL && (system==1 || proc_current==proc->parent || proc_current==proc)) {
761 proc->system = system;
762 return 0;
765 return -1;
769 * Jumps a process to a specified destination
770 * @param proc_pid Process' PID
771 * @param dest Destination to jump to
772 * @return Success
774 int proc_jump(pid_t proc_pid,void *dest) {
775 if (proc_current->system) {
776 proc_t *proc = proc_find(proc_pid);
777 if (proc!=NULL) {
778 proc->registers.eip = (uint32_t)dest;
779 return 0;
782 return -1;
786 * Creates a stack for a process
787 * @param proc_pid Process' PID
788 * @return Stack address
790 int *proc_createstack(pid_t proc_pid) {
791 if (proc_current->system) {
792 proc_t *proc = proc_find(proc_pid);
793 if (proc!=NULL && proc->addrspace->stack==NULL) {
794 int *stack = memuser_create_stack(proc->addrspace);
795 proc->registers.esp = (uint32_t)stack;
796 return stack;
799 return NULL;