libmeinos: +llist2
[meinos.git] / kernel2 / procm.c
blobfbd542efaa375fe6efc2fbab11606fa01c811120
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 //kprintf("running=%d; sleeping=%d\r",llist_size(proc_running),llist_size(proc_sleeping));
279 // Search for process that still has time
280 for (i=0;(proc = llist_get(proc_running,i));i++) {
281 if (proc->ticks_rem>0) proc_current = proc;
284 // If no processes with time, fill time slices
285 if (proc_current==NULL) {
286 //kprintf("Refilling time slices\n");
287 for (i=0;(proc = llist_get(proc_running,i));i++) proc->ticks_rem = NICE2TICKS(proc->nice);
288 proc_current = llist_get(proc_running,0);
291 // Set context and load address space
292 if (proc_old!=proc_current) {
293 if (proc_old!=NULL) proc_regs_save(proc_old);
294 proc_regs_load(proc_current);
295 memuser_load_addrspace(proc_current->addrspace);
300 * Gets PID (Syscall)
301 * @return PID
303 pid_t proc_getpid() {
304 return proc_current->pid;
308 * Gets Parent PID (Syscall)
309 * @param pid Process to get parent's PID of
310 * @return Parent's PID
312 pid_t proc_getparent(pid_t pid) {
313 proc_t *proc = proc_find(pid);
314 if (proc!=NULL) {
315 if (proc->parent!=NULL) return proc->parent->pid;
317 return 0;
321 * Gets PID of a child (Syscall)
322 * @param pid Process to get child's PID of
323 * @param i Number of child
324 * @return Child's PID
326 pid_t proc_getchild(pid_t pid,size_t i) {
327 proc_t *proc = proc_find(pid);
328 if (proc!=NULL) {
329 if (proc->parent!=NULL) {
330 proc_t *child = llist_get(proc->parent->children,i);
331 if (child==NULL) return -1;
332 else return child->pid;
335 return 0;
339 * Gets UID (Syscall)
340 * @param idmask Which ID to return
341 * @return UID
343 uid_t proc_getuid(int idmask) {
344 if ((idmask&1)) return proc_current->uid;
345 else if ((idmask&2)) return proc_current->euid;
346 else if ((idmask&4)) return proc_current->suid;
347 else return 0;
351 * Sets UID (Syscall)
352 * @param idmask Which ID to set
353 * @param uid New UID
354 * @todo Check permissions
356 void proc_setuid(int idmask,uid_t uid) {
357 if ((idmask&1)) proc_current->uid = uid;
358 else if ((idmask&2)) proc_current->euid = uid;
359 else if ((idmask&4)) proc_current->suid = uid;
363 * Gets GID (Syscall)
364 * @param idmask Which ID to return
365 * @return GID
367 gid_t proc_getgid(int idmask) {
368 if ((idmask&1)) return proc_current->gid;
369 else if ((idmask&2)) return proc_current->egid;
370 else if ((idmask&4)) return proc_current->sgid;
371 else return 0;
375 * Sets GID (Syscall)
376 * @param idmask Which ID to set
377 * @param uid New GID
378 * @todo Check permissions
380 void proc_setgid(int idmask,gid_t gid) {
381 if ((idmask&1)) proc_current->gid = gid;
382 else if ((idmask&2)) proc_current->egid = gid;
383 else if ((idmask&4)) proc_current->sgid = gid;
387 * Gets process name (Syscall)
388 * @param pid PID
389 * @param buf Buffer for name
390 * @param maxlen Maximal length of name
391 * @return Success? (if buf==NULL length of name is returned)
393 ssize_t proc_getname(pid_t pid,char *buf,size_t maxlen) {
394 proc_t *proc = proc_find(pid);
395 if (proc!=NULL) {
396 if (buf!=NULL) {
397 strncpy(buf,proc->name,maxlen);
398 return 0;
400 else return strlen(proc->name)+1;
402 else return -1;
406 * Sets new process name (Syscall)
407 * @param proc_pid PID
408 * @param name New process name
409 * @return Success?
411 int proc_setname(pid_t proc_pid,const char *name) {
412 if (proc_current->system) {
413 proc_t *proc = proc_find(proc_pid);
414 if (proc!=NULL && proc!=proc_current) {
415 free(proc->name);
416 proc->name = strdup(name);
419 return -1;
423 * Gets PID by process name
424 * @param name Process name
425 * @return PID of process
427 pid_t proc_getpidbyname(const char *name) {
428 size_t i;
429 proc_t *proc;
430 for (i=0;(proc = llist_get(proc_all,i));i++) {
431 if (strcmp(proc->name,name)==0) return proc->pid;
433 return -1;
437 * Gets private variable
438 * @param pid Process' PID
439 * @return private variable
441 int proc_getvar(pid_t pid) {
442 proc_t *proc = proc_find(pid);
443 if (proc!=NULL && (proc_current->system || proc_current==proc)) return proc->var;
444 else return -1;
448 * Sets private variable
449 * @param pid Process' PID
450 * @param var New private variable
452 void proc_setvar(pid_t pid,int var) {
453 proc_t *proc = proc_find(pid);
454 if (proc!=NULL) proc->var = var;
458 * Waits for child(ren)
459 * @param pid PID of child to wait for (-1 for all childs)
460 * @param stat_loc Reference for status
461 * @param options Options
463 pid_t proc_waitpid(pid_t pid,int *stat_loc,int options) {
464 if (pid>0) {
465 proc_t *proc = proc_find(pid);
466 if (proc!=NULL) {
467 if (proc->defunc) {
468 *stat_loc = proc->ret;
469 /// @todo remove child
470 return pid;
473 else return -1;
475 proc_current->wait_pid = pid;
476 proc_current->wait_stat = stat_loc;
477 proc_current->wait = 1;
478 proc_sleep(proc_current);
479 return -1;
483 * Exits process (Syscall)
484 * @param ret Return value
486 void proc_exit(int ret) {
487 if (proc_current->parent!=NULL) {
488 if (proc_current->parent->wait) {
489 pid_t pid = proc_current->parent->wait_pid;
490 if (pid==-1 || pid==proc_current->pid || (pid==0 && proc_current->gid==proc_current->parent->gid) || (pid<-1 && -pid==proc_current->gid)) {
491 proc_current->parent->registers.eax = proc_current->pid;
492 if (proc_current->parent->wait_stat!=NULL) {
493 memuser_load_addrspace(proc_current->parent->addrspace);
494 *(proc_current->parent->wait_stat) = ret;
495 memuser_load_addrspace(proc_current->addrspace);
497 proc_current->parent->wait = 0;
498 proc_wake(proc_current->parent);
503 proc_current->ret = ret;
504 proc_current->defunc = 1;
505 llist_remove(proc_running,llist_find(proc_running,proc_current));
506 //memuser_destroy_addrspace(proc_current->addrspace);
507 //proc_current->addrspace = NULL;
508 proc_current = NULL;
509 proc_idle();
513 * Aborts process (Syscall)
515 void proc_abort() {
516 proc_exit(1);
520 * Stops process (Syscall)
522 void proc_stop() {
523 proc_sleep(proc_current);
527 * Calls a function in process
528 * @param proc Process
529 * @param func Function
530 * @param numparams Number of parameters
531 * @param ... Parameters
533 void proc_call(proc_t *proc,void *func,size_t numparams,...) {
534 if (!proc->defunc) {
535 va_list args;
536 size_t i;
537 int *params = malloc(numparams*sizeof(int));
538 uint32_t *eip = proc_current==proc?interrupt_curregs.eip:&proc->registers.eip;
540 va_start(args,numparams);
541 for (i=0;i<numparams;i++) params[numparams-(i+1)] = va_arg(args,int);
542 va_end(args);
544 memuser_load_addrspace(proc->addrspace);
545 for (i=0;i<numparams;i++) proc_push(proc,params[i]);
546 proc_push(proc,*eip);
547 if (proc_current!=NULL) {
548 memuser_load_addrspace(proc_current->addrspace);
550 *eip = (uint32_t)func;
552 //proc_wake(proc);
557 * Push an element on user stack
558 * @param proc Process
559 * @param val Value
561 void proc_push(proc_t *proc,int val) {
562 uint32_t *esp = proc_current==proc?interrupt_curregs.esp:&proc->registers.esp;
563 *esp -= sizeof(int);
564 //memuser_load_addrspace(proc->addrspace);
565 *((int*)(*esp)) = val;
566 //memuser_load_addrspace(proc_current->addrspace);
570 * Pops an element from user stack
571 * @param proc Process
572 * @return Value
574 int proc_pop(proc_t *proc) {
575 int val = *((int*)proc->registers.esp);
576 proc->registers.esp += sizeof(int);
577 return val;
581 * Idles until next schedule
583 void proc_idle() {
584 asm("mov %0,%%esp"::"r"(cpu_this->tss->esp0)); // reload ESP0 in TSS "by hand"
585 interrupt_enable(1);
586 cpu_halt();
590 * Creates a process (Syscall)
591 * @param name Name
592 * @param uid UID
593 * @param gid GID
594 * @param parent_pid Parent's PID
595 * @return PID of created process
597 pid_t proc_create_syscall(char *name,uid_t uid,gid_t gid,pid_t parent_pid) {
598 if (proc_current->system) {
599 proc_t *parent = proc_find(parent_pid);
600 if (parent!=NULL) {
601 proc_t *proc = proc_create(name,uid,gid,parent,0,0);
602 return proc!=NULL?proc->pid:-1;
605 return -1;
609 * Destroys a process (Syscall)
610 * @param proc_pid PID of process to destroy
612 int proc_destroy_syscall(pid_t proc_pid) {
613 if (proc_current->system) {
614 proc_t *proc = proc_find(proc_pid);
615 if (proc!=NULL && proc!=proc_current) {
616 return proc_destroy(proc);
619 return -1;
623 * Maps a page to a process' address space
624 * @param proc_pid Process' PID
625 * @param virt Virtual address where to map
626 * @param phys Address of physical page
627 * @param writable Whether to map it writable
628 * @param cow Map page as COW
629 * @return Success?
630 * @todo remove memuser_load_addrspace()
632 int proc_memmap(pid_t proc_pid,void *virt,void *phys,int writable,int swappable,int cow) {
633 if (proc_current->system) {
634 proc_t *proc = proc_find(proc_pid);
635 if (proc!=NULL) {
636 pte_t pte = paging_getpte_pd(virt,proc->addrspace->pagedir);
637 if (!pte.exists) {
638 memuser_load_addrspace(proc->addrspace);
639 paging_map_pd(virt,phys,1,writable && !cow,swappable,cow && writable,proc->addrspace->pagedir);
640 memuser_load_addrspace(proc_current->addrspace);
641 llist_push(proc->addrspace->pages_loaded,virt);
642 return 0;
646 return -1;
650 * Allocates a page for a process
651 * @param proc_pid Process' PID
652 * @param virt Virtual address
653 * @param writable Whether to alloc wirtable memory
654 * @param swappable Whether memory should be swappable
655 * @return Success?
657 int proc_memalloc(pid_t proc_pid,void *virt,int writable,int swappable) {
658 void *page = memphys_alloc();
659 if (proc_memmap(proc_pid,virt,page,writable,swappable,0)==0) return 0;
660 else {
661 memphys_free(page);
662 return -1;
667 * Unmaps a page from a process' address space
668 * @param proc_pid Process' PID
669 * @param virt Virtual address to unmap
670 * @return Success?
672 int proc_memunmap(pid_t proc_pid,void *virt) {
673 if (proc_current->system) {
674 proc_t *proc = proc_find(proc_pid);
675 if (proc!=NULL) {
676 memuser_load_addrspace(proc->addrspace);
677 paging_unmap(virt);
678 memuser_load_addrspace(proc_current->addrspace);
679 llist_remove(proc->addrspace->pages_imaginary,llist_find(proc->addrspace->pages_imaginary,virt));
680 return 0;
683 return -1;
687 * Frees a page from a process' address space
688 * @param proc_pid Process' PID
689 * @param virt Virtual address to unmap
690 * @return Success?
692 int proc_memfree(pid_t proc_pid,void *virt) {
693 if (proc_current->system) {
694 proc_t *proc = proc_find(proc_pid);
695 if (proc!=NULL) {
696 memuser_load_addrspace(proc->addrspace);
697 memphys_free(paging_unmap(virt));
698 memuser_load_addrspace(proc_current->addrspace);
699 llist_remove(proc->addrspace->pages_imaginary,llist_find(proc->addrspace->pages_imaginary,virt));
700 return 0;
703 return -1;
707 * Gets information about page of process
708 * @param proc_pid Process' PID
709 * @param virt Virtual address to get information about
710 * @return Success?
712 void *proc_memget(pid_t proc_pid,void *virt,int *exists,int *writable,int *swappable,int *cow) {
713 if (proc_current->system) {
714 proc_t *proc = proc_find(proc_pid);
715 if (proc!=NULL) {
716 pte_t pte = paging_getpte_pd(virt,proc->addrspace->pagedir);
717 if (exists!=NULL) *exists = pte.exists;
718 if (writable!=NULL) *writable = pte.writable;
719 if (swappable!=NULL) *swappable = pte.swappable;
720 if (cow!=NULL) *cow = pte.cow;
721 return pte.in_memory?PAGE2ADDR(pte.page):NULL;
724 *exists = 0;
725 return NULL;
729 * Gets page list (Syscall)
730 * @param proc_pid Process' PID
731 * @param virt Virtual address to get information about
732 * @return Number of pages in list
734 size_t proc_mempagelist(pid_t proc_pid,void **list,size_t n) {
735 if (proc_current->system) {
736 proc_t *proc = proc_find(proc_pid);
737 if (proc!=NULL) {
738 if (list==NULL || n==0) return llist_size(proc->addrspace->pages_loaded)+llist_size(proc->addrspace->pages_imaginary)+llist_size(proc->addrspace->pages_swapped);
739 else {
740 size_t i;
741 size_t j = 0;
742 void *addr;
743 for (i=0;(addr = llist_get(proc->addrspace->pages_loaded,i)) && j<n;i++) list[j++] = addr;
744 for (i=0;(addr = llist_get(proc->addrspace->pages_imaginary,i)) && j<n;i++) list[j++] = addr;
745 for (i=0;(addr = llist_get(proc->addrspace->pages_swapped,i)) && j<n;i++) list[j++] = addr;
746 return j;
750 return -1;
754 * Gives/Withdraws a process system privilegs
755 * @param proc_pid Process' PID
756 * @param system Whether process should have system privilegs or not
757 * @return Success?
759 int proc_system(pid_t proc_pid,int system) {
760 if (proc_current->system) {
761 proc_t *proc = proc_find(proc_pid);
762 if (proc!=NULL && (system==1 || proc_current==proc->parent || proc_current==proc)) {
763 proc->system = system;
764 return 0;
767 return -1;
771 * Jumps a process to a specified destination
772 * @param proc_pid Process' PID
773 * @param dest Destination to jump to
774 * @return Success
776 int proc_jump(pid_t proc_pid,void *dest) {
777 if (proc_current->system) {
778 proc_t *proc = proc_find(proc_pid);
779 if (proc!=NULL) {
780 proc->registers.eip = (uint32_t)dest;
781 return 0;
784 return -1;
788 * Creates a stack for a process
789 * @param proc_pid Process' PID
790 * @return Stack address
792 int *proc_createstack(pid_t proc_pid) {
793 if (proc_current->system) {
794 proc_t *proc = proc_find(proc_pid);
795 if (proc!=NULL && proc->addrspace->stack==NULL) {
796 int *stack = memuser_create_stack(proc->addrspace);
797 proc->registers.esp = (uint32_t)stack;
798 return stack;
801 return NULL;