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); |