3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 #include <net/socket.h>
39 extern task_t task_list
;
40 extern task_t
*_curr_task
;
41 extern unsigned long timer_ticks
;
45 proc_t
*p
= proc_find (_curr_task
);
51 return proc_create (p
->tty
, p
->name
, p
->task
->state
[0].JMPBUF_IP
)->pid
;
57 printf ("PID\tCMD\tMEM\n");
60 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
)
61 printf ("%d\t%s\t%dkB\n", proc
->pid
, proc
->name
, umem_used_proc (proc
) / 1024);
68 unsigned long ltime
= 0;
78 printf ("TID\tTASK\t\tCPU Usage\n");
81 for (task
= task_list
.next
; task
!= &task_list
; task
= task
->next
) {
82 unsigned usage
= 100 - ((task
->lasttick
- ltime
) / 10);
84 memset (name
, ' ', 16);
85 memcpy (name
, task
->name
, strlen (task
->name
) > 16 ? 16 : strlen (task
->name
));
88 printf ("%d\t%s%d%%\n", task
->id
, name
, usage
> 100 ? 100 : usage
);
94 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
) {
95 printf ("\nPID\tCMD\t\tMEM\tCPU Usage\n");
99 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
) {
101 unsigned usage
= 100 - ((proc
->task
->lasttick
- ltime
) / 10);
103 memset (name
, ' ', 16);
104 memcpy (name
, proc
->task
->name
, strlen (proc
->task
->name
) > 16 ? 16 : strlen (proc
->task
->name
));
106 printf ("%d\t%s%dkB\t%d%%\n", proc
->pid
, name
, umem_used_proc (proc
) / 1024, usage
> 100 ? 100 : usage
);
109 unsigned long stime
= timer_ticks
;
114 while ((stime
+1000) >= timer_ticks
) {
115 if (getkey () == 'q')
123 proc_t
*proc_find (task_t
*task
)
126 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
) {
130 if (proc
->task
->id
== task
->id
)
137 proc_t
*proc_findbypid (pid_t pid
)
140 for (proc
= proc_list
.next
; proc
!= &proc_list
; proc
= proc
->next
) {
141 if (proc
->pid
== pid
)
148 unsigned proc_fd_close (proc_t
*proc
)
156 for (f
= fd_list
.next
; f
!= &fd_list
; f
= f
->next
) {
157 if (f
->proc
== proc
) {
158 if (f
->flags
& FD_SOCK
) // socket close
175 proc_t
*proc_create (tty_t
*tty
, char *name
, unsigned entry
)
178 task_t
*task
= (task_t
*) task_create (name
, entry
, PROC_USER_PRIORITY
);
181 DPRINT ("proc_create () - !task");
185 /* alloc and init context */
186 proc
= (proc_t
*) kmalloc (sizeof (proc_t
));
189 DPRINT ("proc_create () - !proc");
193 /* remember task, because we need it for scheduler work */
196 /* remember new pid of process */
197 proc
->pid
= ++ newpid
;
199 /* remember tty, where we start this process */
202 /* setup process name */
203 strcpy (proc
->name
, name
);
205 /* clear process info */
218 /* add structure into process list */
219 proc
->next
= &proc_list
;
220 proc
->prev
= proc_list
.prev
;
221 proc
->prev
->next
= proc
;
222 proc
->next
->prev
= proc
;
224 /* create virtual file in /proc with name of new process */
225 vfs_list_add (name
, VFS_FILEATTR_FILE
| VFS_FILEATTR_SYSTEM
, "/proc/");
227 DPRINT ("proc -> %s, pid %d, entry 0x%x", name
, newpid
, entry
);
232 extern bool task_done (task_t
*task
);
233 bool proc_done (proc_t
*proc
)
236 /* verify task structure */
240 /* unmap memory pages */
241 proc_vmem_unmap (proc
);
243 /* delete all tasks from process context */
244 unsigned short id
= proc
->task
->id
;
247 task_t
*task
= task_find (id
);
252 if (!task_done (task
))
256 DPRINT ("proc -> pid %d done", proc
->pid
);
258 /* close all un-closed file descriptors */
259 proc_fd_close (proc
);
261 /* delete process from context */
262 proc
->next
->prev
= proc
->prev
;
263 proc
->prev
->next
= proc
->next
;
267 /* free memory from process parameters */
268 proc_arg_free (proc
);
270 /* free all memory blocks allocated by process */
273 /* free process structure */
282 bool proc_signal (proc_t
*proc
, unsigned signal
)
288 /* check for daemon */
289 if (proc
->flags
& PROC_FLAG_DAEMON
)
292 task_t
*task
= proc
->tty
->task
;
294 /* this unlock tty, enable itrs, etc (see command_exec ())*/
297 /* disable interrupts */
301 /* jump back from app code to kernel code (task) */
302 longjmp (task
->state
, 1);
304 DPRINT ("proc_signal: Not implemented for this platform !");
309 sighandler_t
signal (int signum
, sighandler_t handler
)
311 /* try to search current process */
312 proc_t
*proc
= proc_find (_curr_task
);
317 if (proc
->task
!= _curr_task
)
320 if (proc
->tty
!= currtty
)
323 /* send signal to current process */
324 proc_signal (proc
, signum
);
329 bool proc_arg_set (proc_t
*proc
, char *arg
, unsigned argl
)
341 /* First calculate length of array */
343 while (i
< (argl
+1)) {
344 if (arg
[i
] == ' ' || arg
[i
] == '\0')
350 proc
->argv
= (char **) kmalloc (sizeof (unsigned) * (x
+2));
355 proc
->argc
= x
+1; /* +1 because argv[0] is name of process so it is one entry */
357 /* setup program name entry */
358 i
= strlen (proc
->name
);
360 proc
->argv
[0] = (char *) kmalloc (sizeof (char) * (i
+1));
361 memcpy (proc
->argv
[0], proc
->name
, i
);
362 proc
->argv
[0][i
] = '\0';
367 /* assign values to array */
368 while (i
< (argl
+1)) {
369 if (arg
[i
] == ' ' || arg
[i
] == '\0' || i
== argl
) {
371 proc
->argv
[x
] = (char *) kmalloc (sizeof (char) * (i
+1));
376 memcpy (proc
->argv
[x
], arg
, i
);
377 proc
->argv
[x
][i
] = '\0';
379 proc
->argv
[x
] = (char *) kmalloc (sizeof (char) * (i
+1-y
));
384 memcpy (proc
->argv
[x
], arg
+y
+1, i
-y
-1);
385 proc
->argv
[x
][i
-y
-1] = '\0';
398 bool proc_arg_free (proc_t
*proc
)
403 if (!proc
->argv
|| !proc
->argc
)
408 while (i
< proc
->argc
) {
409 kfree (proc
->argv
[i
]);
420 bool proc_arg_get (proc_t
*proc
, unsigned *argc
, char **argv
)
425 if (!proc
->argv
|| !proc
->argc
|| !argc
)
434 bool proc_flag_set (proc_t
*proc
, unsigned short flag
)
439 if (proc
->flags
& flag
)
447 unsigned proc_page_fault ()
449 proc_t
*proc
= proc_find (_curr_task
);
455 printf ("%s: signal SIGSEGV\n", proc
->name
);
457 /* send SIGSEGV signal to running process */
458 proc_signal (proc
, SIGSEGV
);
463 unsigned proc_vmem_map (proc_t
*proc
)
466 /* create new page_cover "shield" for process */
467 proc
->task
->page_cover
= (page_ent_t
*) page_cover_create ();
469 /* map kernel space */
470 page_mmap (proc
->task
->page_cover
, (void *) 0x0, (void *) 0x400000, 1, 0);
472 /* map VESA double buffer memory - enough for 16bit 800x600 - 1MB for framebuffer */
473 page_mmap (proc
->task
->page_cover
, (void *) 0x400000, (void *) proc
->start
, 1, 0);
475 /* calculate size of process image (binary file) */
476 unsigned p
= (unsigned) palign ((void *) (proc
->end
- proc
->start
));
478 /* map process image - app should think, that it is placed at 8MB in ram */
479 page_mmap (proc
->task
->page_cover
, (void *) 0x800000, (void *) 0x800000+p
, 0, 1);
481 /* map end of kernel space */
482 page_mmap (proc
->task
->page_cover
, (void *) proc
->start
+p
, (void *) 0x800000, 1, 0);
484 proc
->heap
= 0x800000;
489 unsigned proc_vmem_unmap (proc_t
*proc
)
497 if (!proc
->task
->page_cover
)
500 page_ent_t
*page_cover
= proc
->task
->page_cover
;
502 /* switch to kernel page directory */
503 page_dir_switch (task_list
.next
->page_cover
->page_dir
);
505 /* unmap kernel area */
506 page_unmmap (page_cover
, (void *) 0x0, (void *) 0x400000);
508 /* unmap framebuffer area */
509 //page_unmmap (page_cover, (void *) 0x400000, (void *) 0x500000);
511 /* unmap process image */
512 page_unmmap (page_cover
, (void *) 0x400000, (void *) proc
->start
);
514 unsigned p
= (unsigned) palign ((void *) (proc
->end
- proc
->start
));
516 /* unmap end of user-space */
517 page_unmmap (page_cover
, (void *) 0x800000, (void *) 0x800000+p
);
520 page_unmmap (page_cover
, (void *) proc
->start
+p
, (void *) 0x800000);
522 /* unmap the allocated memory */
523 page_unmmap (page_cover
, (void *) 0x800000+p
, (void *) proc
->heap
+p
);
525 if (!page_cover_delete (page_cover
)) {
526 DPRINT ("ERROR -> proc_vmem_unmap () - proc: %s", proc
->name
);
530 proc
->task
->page_cover
= 0;
535 void *(*thread_entry
) (void *);
538 void proc_thread_context ()
540 thread_entry (thread_arg
);
546 unsigned proc_thread_create (void *entry
, void *arg
)
548 proc_t
*proc
= proc_find (_curr_task
);
553 char *name
= "proc_thread";
555 unsigned p
= (unsigned) entry
;
557 thread_entry
= (void *) p
;
560 /* create new process thread */
561 task_t
*task
= (task_t
*) task_create (name
, (unsigned) &proc_thread_context
, PROC_USER_PRIORITY
);
566 /* HACK: set task id same as current task (our process) */
568 task
->id
= proc
->task
->id
;
570 /* use same page_cover too for correctly paging */
571 if (proc
->task
->page_cover
)
572 task
->page_cover
= proc
->task
->page_cover
;
576 /* NOTE: this is pretty needed, because thread argument and entry point is then same as previous */
579 DPRINT ("process: new thread '%s' : 0x%x", name
, p
);
584 unsigned proc_thread_destroy (proc_t
*proc
, task_t
*task
)
586 /* we won't close main process thread */
587 if (proc
->task
== task
)
590 if (!task_done (task
))
593 DPRINT ("process: close thread '%s'", task
->name
);
598 unsigned int init_proc (void)
600 proc_list
.next
= &proc_list
;
601 proc_list
.prev
= &proc_list
;
603 proc_kernel
.task
= task_find (0);
604 proc_kernel
.heap
= 0x800000;
605 proc_kernel
.start
= 0;