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>
21 #include <memkernel.h>
32 #include <interrupt.h>
35 * Initializes process management
36 * @return -1=Success; 0=Failure
39 proc_all
= llist_create();
40 proc_running
= llist_create();
41 proc_sleeping
= llist_create();
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;
75 * Creates a new process
76 * @param name Process name
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
++;
89 new->name
= strdup(name
);
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();
105 new->ticks_rem
= NICE2TICKS(new->nice
);
108 new->is_sleeping
= !running
;
112 llist_push(proc_all
,new);
113 llist_push(running
?proc_running
:proc_sleeping
,new);
119 * @param proc Process
122 int proc_destroy(proc_t
*proc
) {
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
));
139 * Finds a process by PID
143 proc_t
*proc_find(pid_t pid
) {
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
;
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
) {
163 for (i
=0;(child
= llist_get(parent
->children
,i
));i
++) {
164 if (proc
==child
) return 1;
170 * Sends a process sleeping
171 * @param proc Process
172 * @param sleep Reference to sleep variable
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();
187 * @param proc Process
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;
200 * Save registers of process
201 * @param proc Process
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
);
226 * Load registers of process
227 * @param proc Process
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
);
252 * Loads next process for execution
254 void proc_shedule() {
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();
264 /// @todo maybe put these 2 lines in proc_idle
265 proc_regs_save(proc_current
);
271 // Process finished its time slice
272 if (proc_current
!=NULL
) {
273 proc_current
->ticks_rem
--;
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
);
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
);
315 if (proc
->parent
!=NULL
) return proc
->parent
->pid
;
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
);
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
;
340 * @param idmask Which ID to return
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
;
352 * @param idmask Which ID to set
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
;
364 * @param idmask Which ID to return
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
;
376 * @param idmask Which ID to set
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)
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
);
397 strncpy(buf
,proc
->name
,maxlen
);
400 else return strlen(proc
->name
)+1;
406 * Sets new process name (Syscall)
407 * @param proc_pid PID
408 * @param name New process name
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
) {
416 proc
->name
= strdup(name
);
423 * Gets PID by process name
424 * @param name Process name
425 * @return PID of process
427 pid_t
proc_getpidbyname(const char *name
) {
430 for (i
=0;(proc
= llist_get(proc_all
,i
));i
++) {
431 if (strcmp(proc
->name
,name
)==0) return proc
->pid
;
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
;
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
) {
465 proc_t
*proc
= proc_find(pid
);
468 *stat_loc
= proc
->ret
;
469 /// @todo remove child
475 proc_current
->wait_pid
= pid
;
476 proc_current
->wait_stat
= stat_loc
;
477 proc_current
->wait
= 1;
478 proc_sleep(proc_current
);
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;
513 * Aborts process (Syscall)
520 * Stops process (Syscall)
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
,...) {
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);
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
;
557 * Push an element on user stack
558 * @param proc Process
561 void proc_push(proc_t
*proc
,int val
) {
562 uint32_t *esp
= proc_current
==proc
?interrupt_curregs
.esp
:&proc
->registers
.esp
;
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
574 int proc_pop(proc_t
*proc
) {
575 int val
= *((int*)proc
->registers
.esp
);
576 proc
->registers
.esp
+= sizeof(int);
581 * Idles until next schedule
584 asm("mov %0,%%esp"::"r"(cpu_this
->tss
->esp0
)); // reload ESP0 in TSS "by hand"
590 * Creates a process (Syscall)
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
);
601 proc_t
*proc
= proc_create(name
,uid
,gid
,parent
,0,0);
602 return proc
!=NULL
?proc
->pid
:-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
);
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
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
);
636 pte_t pte
= paging_getpte_pd(virt
,proc
->addrspace
->pagedir
);
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
);
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
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;
667 * Unmaps a page from a process' address space
668 * @param proc_pid Process' PID
669 * @param virt Virtual address to unmap
672 int proc_memunmap(pid_t proc_pid
,void *virt
) {
673 if (proc_current
->system
) {
674 proc_t
*proc
= proc_find(proc_pid
);
676 memuser_load_addrspace(proc
->addrspace
);
678 memuser_load_addrspace(proc_current
->addrspace
);
679 llist_remove(proc
->addrspace
->pages_imaginary
,llist_find(proc
->addrspace
->pages_imaginary
,virt
));
687 * Frees a page from a process' address space
688 * @param proc_pid Process' PID
689 * @param virt Virtual address to unmap
692 int proc_memfree(pid_t proc_pid
,void *virt
) {
693 if (proc_current
->system
) {
694 proc_t
*proc
= proc_find(proc_pid
);
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
));
707 * Gets information about page of process
708 * @param proc_pid Process' PID
709 * @param virt Virtual address to get information about
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
);
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
;
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
);
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
);
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
;
754 * Gives/Withdraws a process system privilegs
755 * @param proc_pid Process' PID
756 * @param system Whether process should have system privilegs or not
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
;
771 * Jumps a process to a specified destination
772 * @param proc_pid Process' PID
773 * @param dest Destination to jump to
776 int proc_jump(pid_t proc_pid
,void *dest
) {
777 if (proc_current
->system
) {
778 proc_t
*proc
= proc_find(proc_pid
);
780 proc
->registers
.eip
= (uint32_t)dest
;
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
;