Rev 3035 | Rev 3425 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3035 | Rev 3424 | ||
---|---|---|---|
Line 43... | Line 43... | ||
43 | #include <mm/slab.h> |
43 | #include <mm/slab.h> |
44 | #include <atomic.h> |
44 | #include <atomic.h> |
45 | #include <synch/spinlock.h> |
45 | #include <synch/spinlock.h> |
46 | #include <synch/waitq.h> |
46 | #include <synch/waitq.h> |
47 | #include <arch.h> |
47 | #include <arch.h> |
- | 48 | #include <arch/barrier.h> |
|
48 | #include <panic.h> |
49 | #include <panic.h> |
49 | #include <adt/avl.h> |
50 | #include <adt/avl.h> |
50 | #include <adt/btree.h> |
51 | #include <adt/btree.h> |
51 | #include <adt/list.h> |
52 | #include <adt/list.h> |
52 | #include <ipc/ipc.h> |
53 | #include <ipc/ipc.h> |
Line 126... | Line 127... | ||
126 | 127 | ||
127 | spinlock_unlock(&tasks_lock); |
128 | spinlock_unlock(&tasks_lock); |
128 | interrupts_restore(ipl); |
129 | interrupts_restore(ipl); |
129 | 130 | ||
130 | #ifdef CONFIG_DEBUG |
131 | #ifdef CONFIG_DEBUG |
131 | printf("Killing task %llu\n", id); |
132 | printf("Killing task %" PRIu64 "\n", id); |
132 | #endif |
133 | #endif |
133 | task_kill(id); |
134 | task_kill(id); |
134 | thread_usleep(10000); |
135 | thread_usleep(10000); |
135 | } else { |
136 | } else { |
136 | spinlock_unlock(&tasks_lock); |
137 | spinlock_unlock(&tasks_lock); |
Line 240... | Line 241... | ||
240 | 241 | ||
241 | free(t); |
242 | free(t); |
242 | TASK = NULL; |
243 | TASK = NULL; |
243 | } |
244 | } |
244 | 245 | ||
245 | /** Create new task with 1 thread and run it |
246 | /** Syscall for reading task ID from userspace. |
246 | * |
247 | * |
247 | * @param program_addr Address of program executable image. |
248 | * @param uspace_task_id Userspace address of 8-byte buffer where to store |
248 | * @param name Program name. |
249 | * current task ID. |
249 | * |
250 | * |
250 | * @return Task of the running program or NULL on error. |
251 | * @return 0 on success or an error code from @ref errno.h. |
251 | */ |
252 | */ |
252 | task_t *task_run_program(void *program_addr, char *name) |
253 | unative_t sys_task_get_id(task_id_t *uspace_task_id) |
253 | { |
254 | { |
254 | as_t *as; |
255 | /* |
255 | as_area_t *a; |
256 | * No need to acquire lock on TASK because taskid |
256 | unsigned int rc; |
257 | * remains constant for the lifespan of the task. |
257 | thread_t *t; |
258 | */ |
258 | task_t *task; |
259 | return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid, |
259 | uspace_arg_t *kernel_uarg; |
260 | sizeof(TASK->taskid)); |
- | 261 | } |
|
260 | 262 | ||
- | 263 | unative_t sys_task_spawn(void *image, size_t size) |
|
- | 264 | { |
|
261 | as = as_create(0); |
265 | void *kimage = malloc(size, 0); |
- | 266 | if (kimage == NULL) |
|
- | 267 | return ENOMEM; |
|
- | 268 | ||
- | 269 | int rc = copy_from_uspace(kimage, image, size); |
|
- | 270 | if (rc != EOK) |
|
262 | ASSERT(as); |
271 | return rc; |
263 | 272 | ||
- | 273 | /* |
|
264 | rc = elf_load((elf_header_t *) program_addr, as); |
274 | * Not very efficient and it would be better to call it on code only, |
265 | if (rc != EE_OK) { |
275 | * but this whole function is a temporary hack anyway and one day it |
266 | as_destroy(as); |
276 | * will go in favor of the userspace dynamic loader. |
267 | return NULL; |
- | |
268 | } |
277 | */ |
- | 278 | smc_coherence_block(kimage, size); |
|
269 | 279 | ||
- | 280 | uspace_arg_t *kernel_uarg; |
|
270 | kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
281 | kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
- | 282 | if (kernel_uarg == NULL) { |
|
- | 283 | free(kimage); |
|
- | 284 | return ENOMEM; |
|
- | 285 | } |
|
- | 286 | ||
271 | kernel_uarg->uspace_entry = |
287 | kernel_uarg->uspace_entry = |
272 | (void *) ((elf_header_t *) program_addr)->e_entry; |
288 | (void *) ((elf_header_t *) kimage)->e_entry; |
273 | kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
289 | kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
274 | kernel_uarg->uspace_thread_function = NULL; |
290 | kernel_uarg->uspace_thread_function = NULL; |
275 | kernel_uarg->uspace_thread_arg = NULL; |
291 | kernel_uarg->uspace_thread_arg = NULL; |
276 | kernel_uarg->uspace_uarg = NULL; |
292 | kernel_uarg->uspace_uarg = NULL; |
277 | 293 | ||
278 | task = task_create(as, name); |
294 | as_t *as = as_create(0); |
- | 295 | if (as == NULL) { |
|
- | 296 | free(kernel_uarg); |
|
279 | ASSERT(task); |
297 | free(kimage); |
- | 298 | return ENOMEM; |
|
280 | 299 | } |
|
281 | /* |
300 | |
- | 301 | unsigned int erc = elf_load((elf_header_t *) kimage, as); |
|
- | 302 | if (erc != EE_OK) { |
|
- | 303 | as_destroy(as); |
|
282 | * Create the data as_area. |
304 | free(kernel_uarg); |
- | 305 | free(kimage); |
|
- | 306 | return ENOENT; |
|
283 | */ |
307 | } |
- | 308 | ||
- | 309 | as_area_t *area = as_area_create(as, |
|
284 | a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, |
310 | AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, |
285 | LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS, |
311 | LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS, |
286 | AS_AREA_ATTR_NONE, &anon_backend, NULL); |
312 | AS_AREA_ATTR_NONE, &anon_backend, NULL); |
287 | - | ||
288 | /* |
- | |
289 | * Create the main thread. |
313 | if (area == NULL) { |
290 | */ |
314 | as_destroy(as); |
291 | t = thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE, |
315 | free(kernel_uarg); |
292 | "uinit", false); |
316 | free(kimage); |
293 | ASSERT(t); |
317 | return ENOMEM; |
- | 318 | } |
|
294 | 319 | ||
- | 320 | task_t *task = task_create(as, "app"); |
|
- | 321 | if (task == NULL) { |
|
295 | thread_ready(t); |
322 | as_destroy(as); |
- | 323 | free(kernel_uarg); |
|
296 | 324 | free(kimage); |
|
297 | return task; |
325 | return ENOENT; |
298 | } |
326 | } |
299 | 327 | ||
300 | /** Syscall for reading task ID from userspace. |
328 | // FIXME: control the capabilities |
- | 329 | cap_set(task, cap_get(TASK)); |
|
301 | * |
330 | |
302 | * @param uspace_task_id Userspace address of 8-byte buffer where to store |
331 | thread_t *thread = thread_create(uinit, kernel_uarg, task, |
- | 332 | THREAD_FLAG_USPACE, "user", false); |
|
- | 333 | if (thread == NULL) { |
|
303 | * current task ID. |
334 | task_destroy(task); |
304 | * |
335 | as_destroy(as); |
305 | * @return 0 on success or an error code from @ref errno.h. |
336 | free(kernel_uarg); |
306 | */ |
337 | free(kimage); |
307 | unative_t sys_task_get_id(task_id_t *uspace_task_id) |
338 | return ENOENT; |
308 | { |
339 | } |
309 | /* |
340 | |
310 | * No need to acquire lock on TASK because taskid |
- | |
311 | * remains constant for the lifespan of the task. |
341 | thread_ready(thread); |
312 | */ |
342 | |
313 | return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid, |
- | |
314 | sizeof(TASK->taskid)); |
343 | return EOK; |
315 | } |
344 | } |
316 | 345 | ||
317 | /** Find task structure corresponding to task ID. |
346 | /** Find task structure corresponding to task ID. |
318 | * |
347 | * |
319 | * The tasks_lock must be already held by the caller of this function |
348 | * The tasks_lock must be already held by the caller of this function |
Line 427... | Line 456... | ||
427 | spinlock_lock(&t->lock); |
456 | spinlock_lock(&t->lock); |
428 | 457 | ||
429 | uint64_t cycles; |
458 | uint64_t cycles; |
430 | char suffix; |
459 | char suffix; |
431 | order(task_get_accounting(t), &cycles, &suffix); |
460 | order(task_get_accounting(t), &cycles, &suffix); |
432 | 461 | ||
433 | if (sizeof(void *) == 4) |
462 | #ifdef __32_BITS__ |
434 | printf("%-6llu %-10s %-3ld %#10zx %#10zx %9llu%c %7zd %6zd", |
463 | printf("%-6" PRIu64 " %-10s %-3" PRIu32 " %10p %10p %9" PRIu64 |
435 | t->taskid, t->name, t->context, t, t->as, cycles, suffix, |
464 | "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, |
436 | t->refcount, atomic_get(&t->active_calls)); |
465 | suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); |
437 | else |
466 | #endif |
- | 467 | ||
- | 468 | #ifdef __64_BITS__ |
|
438 | printf("%-6llu %-10s %-3ld %#18zx %#18zx %9llu%c %7zd %6zd", |
469 | printf("%-6" PRIu64 " %-10s %-3" PRIu32 " %18p %18p %9" PRIu64 |
439 | t->taskid, t->name, t->context, t, t->as, cycles, suffix, |
470 | "%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, |
440 | t->refcount, atomic_get(&t->active_calls)); |
471 | suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); |
- | 472 | #endif |
|
- | 473 | ||
441 | for (j = 0; j < IPC_MAX_PHONES; j++) { |
474 | for (j = 0; j < IPC_MAX_PHONES; j++) { |
442 | if (t->phones[j].callee) |
475 | if (t->phones[j].callee) |
443 | printf(" %zd:%#zx", j, t->phones[j].callee); |
476 | printf(" %d:%p", j, t->phones[j].callee); |
444 | } |
477 | } |
445 | printf("\n"); |
478 | printf("\n"); |
446 | 479 | ||
447 | spinlock_unlock(&t->lock); |
480 | spinlock_unlock(&t->lock); |
448 | return true; |
481 | return true; |
Line 454... | Line 487... | ||
454 | ipl_t ipl; |
487 | ipl_t ipl; |
455 | 488 | ||
456 | /* Messing with task structures, avoid deadlock */ |
489 | /* Messing with task structures, avoid deadlock */ |
457 | ipl = interrupts_disable(); |
490 | ipl = interrupts_disable(); |
458 | spinlock_lock(&tasks_lock); |
491 | spinlock_lock(&tasks_lock); |
459 | 492 | ||
460 | if (sizeof(void *) == 4) { |
493 | #ifdef __32_BITS__ |
461 | printf("taskid name ctx address as " |
494 | printf("taskid name ctx address as " |
462 | "cycles threads calls callee\n"); |
495 | "cycles threads calls callee\n"); |
463 | printf("------ ---------- --- ---------- ---------- " |
496 | printf("------ ---------- --- ---------- ---------- " |
464 | "---------- ------- ------ ------>\n"); |
497 | "---------- ------- ------ ------>\n"); |
465 | } else { |
498 | #endif |
- | 499 | ||
- | 500 | #ifdef __64_BITS__ |
|
466 | printf("taskid name ctx address as " |
501 | printf("taskid name ctx address as " |
467 | "cycles threads calls callee\n"); |
502 | "cycles threads calls callee\n"); |
468 | printf("------ ---------- --- ------------------ ------------------ " |
503 | printf("------ ---------- --- ------------------ ------------------ " |
469 | "---------- ------- ------ ------>\n"); |
504 | "---------- ------- ------ ------>\n"); |
470 | } |
505 | #endif |
471 | 506 | ||
472 | avltree_walk(&tasks_tree, task_print_walker, NULL); |
507 | avltree_walk(&tasks_tree, task_print_walker, NULL); |
473 | 508 | ||
474 | spinlock_unlock(&tasks_lock); |
509 | spinlock_unlock(&tasks_lock); |
475 | interrupts_restore(ipl); |
510 | interrupts_restore(ipl); |