3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 #include <net/socket.h>
35 static void *thread_arg
;
36 static void *(*thread_entry
) (void *);
38 static pid_t newpid
= 0;
43 extern task_t task_list
;
44 extern task_t
*_curr_task
;
45 extern unsigned long timer_ticks
;
49 proc_t
*p
= proc_find (_curr_task
);
55 return proc_create (p
->tty
, p
->name
, p
->task
->state
[0].JMPBUF_IP
)->pid
;
61 printf ("PID\tCMD\tMEM\n");
64 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
)
65 printf ("%d\t%s\t%dkB\n", proc
->pid
, proc
->name
, umem_used_proc (proc
) / 1024);
72 unsigned long ltime
= 0;
82 printf ("TID\tTASK\t\tCPU Usage\n");
85 for (task
= task_list
.next
; task
!= &task_list
; task
= task
->next
) {
86 unsigned usage
= 100 - ((task
->lasttick
- ltime
) / 10);
88 memset (name
, ' ', 16);
89 memcpy (name
, task
->name
, strlen (task
->name
) > 16 ? 16 : strlen (task
->name
));
92 printf ("%d\t%s%d%%\n", task
->id
, name
, usage
> 100 ? 100 : usage
);
98 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
) {
99 printf ("\nPID\tCMD\t\tMEM\tCPU Usage\n");
103 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
) {
105 unsigned usage
= 100 - ((proc
->task
->lasttick
- ltime
) / 10);
107 memset (name
, ' ', 16);
108 memcpy (name
, proc
->task
->name
, strlen (proc
->task
->name
) > 16 ? 16 : strlen (proc
->task
->name
));
110 printf ("%d\t%s%dkB\t%d%%\n", proc
->pid
, name
, umem_used_proc (proc
) / 1024, usage
> 100 ? 100 : usage
);
113 unsigned long stime
= timer_ticks
;
118 while ((stime
+1000) >= timer_ticks
) {
119 if (getkey () == 'q')
127 proc_t
*proc_find (task_t
*task
)
130 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
) {
134 if (proc
->task
->id
== task
->id
)
141 proc_t
*proc_findbypid (pid_t pid
)
144 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
) {
145 if (proc
->pid
== pid
)
152 unsigned proc_fd_close (proc_t
*proc
)
160 for (f
= fd_list
.next
; f
!= &fd_list
; f
= f
->next
) {
161 if (f
->proc
== proc
) {
162 if (f
->flags
& FD_SOCK
) // socket close
179 proc_t
*proc_create (tty_t
*tty
, char *name
, unsigned entry
)
182 task_t
*task
= (task_t
*) task_create (name
, entry
, PROC_USER_PRIORITY
);
185 DPRINT (DBG_PROC
, "proc_create () - !task");
189 /* alloc and init context */
190 proc
= (proc_t
*) kmalloc (sizeof (proc_t
));
193 DPRINT (DBG_PROC
, "proc_create () - !proc");
197 /* remember task, because we need it for scheduler work */
200 /* remember new pid of process */
201 proc
->pid
= ++ newpid
;
203 /* remember tty, where we start this process */
206 /* setup process name */
207 strcpy (proc
->name
, name
);
209 /* clear process info */
222 /* add structure into process list */
223 proc
->next
= &proc_list
;
224 proc
->prev
= proc_list
.prev
;
225 proc
->prev
->next
= proc
;
226 proc
->next
->prev
= proc
;
228 /* create virtual file in /proc with name of new process */
229 vfs_list_add (name
, VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
, "/proc/");
231 DPRINT (DBG_PROC
, "proc -> %s, pid %d, entry 0x%x", name
, newpid
, entry
);
236 extern bool task_done (task_t
*task
);
237 bool proc_done (proc_t
*proc
)
240 /* verify task structure */
244 /* unmap memory pages */
245 proc_vmem_unmap (proc
);
247 /* delete all tasks from process context */
248 unsigned short id
= proc
->task
->id
;
251 task_t
*task
= task_find (id
);
256 if (!task_done (task
))
260 DPRINT (DBG_PROC
, "proc -> pid %d done", proc
->pid
);
262 /* close all un-closed file descriptors */
263 proc_fd_close (proc
);
265 /* delete process from context */
266 proc
->next
->prev
= proc
->prev
;
267 proc
->prev
->next
= proc
->next
;
271 /* free memory from process parameters */
272 proc_arg_free (proc
);
274 /* free all memory blocks allocated by process */
277 /* free process structure */
286 bool proc_signal (proc_t
*proc
, unsigned signal
)
292 /* check for daemon */
293 if (proc
->flags
& PROC_FLAG_DAEMON
)
296 task_t
*task
= proc
->tty
->task
;
298 /* this unlock tty, enable itrs, etc (see command_exec ())*/
301 /* disable interrupts */
305 /* jump back from app code to kernel code (task) */
306 longjmp (task
->state
, 1);
308 DPRINT (DBG_PROC
, "proc_signal: Not implemented for this platform !");
313 sighandler_t
signal (int signum
, sighandler_t handler
)
315 /* try to search current process */
316 proc_t
*proc
= proc_find (_curr_task
);
321 if (proc
->task
!= _curr_task
)
324 if (proc
->tty
!= currtty
)
327 /* send signal to current process */
328 proc_signal (proc
, signum
);
333 bool proc_arg_set (proc_t
*proc
, char *arg
, unsigned argl
)
345 /* First calculate length of array */
347 while (i
< (argl
+1)) {
348 if (arg
[i
] == ' ' || arg
[i
] == '\0')
354 proc
->argv
= (char **) kmalloc (sizeof (unsigned) * (x
+2));
359 proc
->argc
= x
+1; /* +1 because argv[0] is name of process so it is one entry */
361 /* setup program name entry */
362 i
= strlen (proc
->name
);
364 proc
->argv
[0] = (char *) kmalloc (sizeof (char) * (i
+1));
365 memcpy (proc
->argv
[0], proc
->name
, i
);
366 proc
->argv
[0][i
] = '\0';
371 /* assign values to array */
372 while (i
< (argl
+1)) {
373 if (arg
[i
] == ' ' || arg
[i
] == '\0' || i
== argl
) {
375 proc
->argv
[x
] = (char *) kmalloc (sizeof (char) * (i
+1));
380 memcpy (proc
->argv
[x
], arg
, i
);
381 proc
->argv
[x
][i
] = '\0';
383 proc
->argv
[x
] = (char *) kmalloc (sizeof (char) * (i
+1-y
));
388 memcpy (proc
->argv
[x
], arg
+y
+1, i
-y
-1);
389 proc
->argv
[x
][i
-y
-1] = '\0';
402 bool proc_arg_free (proc_t
*proc
)
407 if (!proc
->argv
|| !proc
->argc
)
412 while (i
< proc
->argc
) {
413 kfree (proc
->argv
[i
]);
424 bool proc_arg_get (proc_t
*proc
, unsigned *argc
, char **argv
)
429 if (!proc
->argv
|| !proc
->argc
|| !argc
)
438 bool proc_flag_set (proc_t
*proc
, unsigned short flag
)
443 if (proc
->flags
& flag
)
451 unsigned proc_page_fault ()
453 proc_t
*proc
= proc_find (_curr_task
);
459 printf ("%s: signal SIGSEGV\n", proc
->name
);
461 /* send SIGSEGV signal to running process */
462 proc_signal (proc
, SIGSEGV
);
467 unsigned proc_vmem_map (proc_t
*proc
)
470 /* create new page_cover "shield" for process */
471 proc
->task
->page_cover
= (page_ent_t
*) page_cover_create ();
473 /* map kernel space */
474 page_mmap (proc
->task
->page_cover
, (void *) 0x0, (void *) 0x400000, 1, 0);
476 /* map VESA double buffer memory - enough for 16bit 800x600 - 1MB for framebuffer */
477 page_mmap (proc
->task
->page_cover
, (void *) 0x400000, (void *) proc
->start
, 1, 0);
479 /* calculate size of process image (binary file) */
480 unsigned p
= (unsigned) palign ((void *) (proc
->end
- proc
->start
));
482 /* map process image - app should think, that it is placed at 8MB in ram */
483 page_mmap (proc
->task
->page_cover
, (void *) 0x800000, (void *) 0x800000+p
, 0, 1);
485 /* map end of kernel space */
486 page_mmap (proc
->task
->page_cover
, (void *) proc
->start
+p
, (void *) 0x800000, 1, 0);
488 proc
->heap
= 0x800000;
493 unsigned proc_vmem_unmap (proc_t
*proc
)
501 if (!proc
->task
->page_cover
)
504 page_ent_t
*page_cover
= proc
->task
->page_cover
;
506 /* switch to kernel page directory */
507 page_dir_switch (task_list
.next
->page_cover
->page_dir
);
509 /* unmap kernel area */
510 page_unmmap (page_cover
, (void *) 0x0, (void *) 0x400000);
512 /* unmap framebuffer area */
513 //page_unmmap (page_cover, (void *) 0x400000, (void *) 0x500000);
515 /* unmap process image */
516 page_unmmap (page_cover
, (void *) 0x400000, (void *) proc
->start
);
518 unsigned p
= (unsigned) palign ((void *) (proc
->end
- proc
->start
));
520 /* unmap end of user-space */
521 page_unmmap (page_cover
, (void *) 0x800000, (void *) 0x800000+p
);
524 page_unmmap (page_cover
, (void *) proc
->start
+p
, (void *) 0x800000);
526 /* unmap the allocated memory */
527 page_unmmap (page_cover
, (void *) 0x800000+p
, (void *) proc
->heap
+p
);
529 if (!page_cover_delete (page_cover
)) {
530 DPRINT (DBG_PROC
, "ERROR -> proc_vmem_unmap () - proc: %s", proc
->name
);
534 proc
->task
->page_cover
= 0;
539 void proc_thread_context ()
541 thread_entry (thread_arg
);
547 unsigned proc_thread_create (void *entry
, void *arg
)
549 proc_t
*proc
= proc_find (_curr_task
);
554 char *name
= proc
->name
;
556 unsigned p
= (unsigned) entry
;
558 thread_entry
= (void *) p
;
561 /* create new process thread */
562 task_t
*task
= (task_t
*) task_create (name
, (unsigned) &proc_thread_context
, PROC_USER_PRIORITY
);
567 /* HACK: set task id same as current task (our process) */
569 task
->id
= proc
->task
->id
;
571 /* use same page_cover too for correctly paging */
572 if (proc
->task
->page_cover
)
573 task
->page_cover
= proc
->task
->page_cover
;
577 DPRINT (DBG_PROC
, "process: new thread '%s' : 0x%x", name
, p
);
579 /* NOTE: this is pretty needed, because thread argument and entry point is then same as previous */
585 unsigned proc_thread_destroy (proc_t
*proc
, task_t
*task
)
587 /* we won't close main process thread */
588 if (proc
->task
== task
)
591 if (!task_done (task
))
594 DPRINT (DBG_PROC
, "process: close thread '%s'", task
->name
);
599 unsigned int init_proc (void)
601 proc_list
.next
= &proc_list
;
602 proc_list
.prev
= &proc_list
;
604 proc_kernel
.task
= task_find (0);
606 proc_kernel
.heap
= PAGE_MEM_HIGH
;
608 proc_kernel
.start
= 0;