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 // 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
);
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
);
313 if (proc
->parent
!=NULL
) return proc
->parent
->pid
;
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
);
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
;
338 * @param idmask Which ID to return
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
;
350 * @param idmask Which ID to set
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
;
362 * @param idmask Which ID to return
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
;
374 * @param idmask Which ID to set
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)
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
);
395 strncpy(buf
,proc
->name
,maxlen
);
398 else return strlen(proc
->name
)+1;
404 * Sets new process name (Syscall)
405 * @param proc_pid PID
406 * @param name New process name
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
) {
414 proc
->name
= strdup(name
);
421 * Gets PID by process name
422 * @param name Process name
423 * @return PID of process
425 pid_t
proc_getpidbyname(const char *name
) {
428 for (i
=0;(proc
= llist_get(proc_all
,i
));i
++) {
429 if (strcmp(proc
->name
,name
)==0) return proc
->pid
;
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
;
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
) {
463 proc_t
*proc
= proc_find(pid
);
466 *stat_loc
= proc
->ret
;
467 /// @todo remove child
473 proc_current
->wait_pid
= pid
;
474 proc_current
->wait_stat
= stat_loc
;
475 proc_current
->wait
= 1;
476 proc_sleep(proc_current
);
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;
511 * Aborts process (Syscall)
518 * Stops process (Syscall)
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
,...) {
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);
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
;
555 * Push an element on user stack
556 * @param proc Process
559 void proc_push(proc_t
*proc
,int val
) {
560 uint32_t *esp
= proc_current
==proc
?interrupt_curregs
.esp
:&proc
->registers
.esp
;
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
572 int proc_pop(proc_t
*proc
) {
573 int val
= *((int*)proc
->registers
.esp
);
574 proc
->registers
.esp
+= sizeof(int);
579 * Idles until next schedule
582 asm("mov %0,%%esp"::"r"(cpu_this
->tss
->esp0
)); // reload ESP0 in TSS "by hand"
588 * Creates a process (Syscall)
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
);
599 proc_t
*proc
= proc_create(name
,uid
,gid
,parent
,0,0);
600 return proc
!=NULL
?proc
->pid
:-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
);
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
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
);
634 pte_t pte
= paging_getpte_pd(virt
,proc
->addrspace
->pagedir
);
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
);
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
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;
665 * Unmaps a page from a process' address space
666 * @param proc_pid Process' PID
667 * @param virt Virtual address to unmap
670 int proc_memunmap(pid_t proc_pid
,void *virt
) {
671 if (proc_current
->system
) {
672 proc_t
*proc
= proc_find(proc_pid
);
674 memuser_load_addrspace(proc
->addrspace
);
676 memuser_load_addrspace(proc_current
->addrspace
);
677 llist_remove(proc
->addrspace
->pages_imaginary
,llist_find(proc
->addrspace
->pages_imaginary
,virt
));
685 * Frees a page from a process' address space
686 * @param proc_pid Process' PID
687 * @param virt Virtual address to unmap
690 int proc_memfree(pid_t proc_pid
,void *virt
) {
691 if (proc_current
->system
) {
692 proc_t
*proc
= proc_find(proc_pid
);
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
));
705 * Gets information about page of process
706 * @param proc_pid Process' PID
707 * @param virt Virtual address to get information about
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
);
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
;
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
);
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
);
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
;
752 * Gives/Withdraws a process system privilegs
753 * @param proc_pid Process' PID
754 * @param system Whether process should have system privilegs or not
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
;
769 * Jumps a process to a specified destination
770 * @param proc_pid Process' PID
771 * @param dest Destination to jump to
774 int proc_jump(pid_t proc_pid
,void *dest
) {
775 if (proc_current
->system
) {
776 proc_t
*proc
= proc_find(proc_pid
);
778 proc
->registers
.eip
= (uint32_t)dest
;
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
;