Rev 3034 | Rev 3425 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3034 | Rev 3424 | ||
|---|---|---|---|
| Line 65... | Line 65... | ||
| 65 | #include <mm/slab.h> |
65 | #include <mm/slab.h> |
| 66 | #include <debug.h> |
66 | #include <debug.h> |
| 67 | #include <main/uinit.h> |
67 | #include <main/uinit.h> |
| 68 | #include <syscall/copy.h> |
68 | #include <syscall/copy.h> |
| 69 | #include <errno.h> |
69 | #include <errno.h> |
| - | 70 | ||
| - | 71 | ||
| 70 | #include <console/klog.h> |
72 | #ifndef LOADED_PROG_STACK_PAGES_NO |
| - | 73 | #define LOADED_PROG_STACK_PAGES_NO 1 |
|
| - | 74 | #endif |
|
| 71 | 75 | ||
| 72 | 76 | ||
| 73 | /** Thread states */ |
77 | /** Thread states */ |
| 74 | char *thread_states[] = { |
78 | char *thread_states[] = { |
| 75 | "Invalid", |
79 | "Invalid", |
| Line 289... | Line 293... | ||
| 289 | t = (thread_t *) slab_alloc(thread_slab, 0); |
293 | t = (thread_t *) slab_alloc(thread_slab, 0); |
| 290 | if (!t) |
294 | if (!t) |
| 291 | return NULL; |
295 | return NULL; |
| 292 | 296 | ||
| 293 | /* Not needed, but good for debugging */ |
297 | /* Not needed, but good for debugging */ |
| 294 | memsetb((uintptr_t) t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, |
298 | memsetb(t->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0); |
| 295 | 0); |
- | |
| 296 | 299 | ||
| 297 | ipl = interrupts_disable(); |
300 | ipl = interrupts_disable(); |
| 298 | spinlock_lock(&tidlock); |
301 | spinlock_lock(&tidlock); |
| 299 | t->tid = ++last_tid; |
302 | t->tid = ++last_tid; |
| 300 | spinlock_unlock(&tidlock); |
303 | spinlock_unlock(&tidlock); |
| Line 452... | Line 455... | ||
| 452 | * moment the task was created, new userspace threads |
455 | * moment the task was created, new userspace threads |
| 453 | * can only be created by threads of the same task. |
456 | * can only be created by threads of the same task. |
| 454 | * We are safe to perform cleanup. |
457 | * We are safe to perform cleanup. |
| 455 | */ |
458 | */ |
| 456 | ipc_cleanup(); |
459 | ipc_cleanup(); |
| 457 | futex_cleanup(); |
460 | futex_cleanup(); |
| 458 | klog_printf("Cleanup of task %llu completed.", |
461 | LOG("Cleanup of task %" PRIu64" completed.", TASK->taskid); |
| 459 | TASK->taskid); |
- | |
| 460 | } |
462 | } |
| 461 | } |
463 | } |
| 462 | 464 | ||
| 463 | restart: |
465 | restart: |
| 464 | ipl = interrupts_disable(); |
466 | ipl = interrupts_disable(); |
| Line 590... | Line 592... | ||
| 590 | interrupts_restore(ipl); |
592 | interrupts_restore(ipl); |
| 591 | } |
593 | } |
| 592 | 594 | ||
| 593 | static bool thread_walker(avltree_node_t *node, void *arg) |
595 | static bool thread_walker(avltree_node_t *node, void *arg) |
| 594 | { |
596 | { |
| 595 | thread_t *t; |
- | |
| 596 | - | ||
| 597 | t = avltree_get_instance(node, thread_t, threads_tree_node); |
597 | thread_t *t = avltree_get_instance(node, thread_t, threads_tree_node); |
| 598 | 598 | ||
| 599 | uint64_t cycles; |
599 | uint64_t cycles; |
| 600 | char suffix; |
600 | char suffix; |
| 601 | order(t->cycles, &cycles, &suffix); |
601 | order(t->cycles, &cycles, &suffix); |
| 602 | 602 | ||
| 603 | if (sizeof(void *) == 4) |
603 | #ifdef __32_BITS__ |
| 604 | printf("%-6llu %-10s %#10zx %-8s %#10zx %-3ld %#10zx %#10zx %9llu%c ", |
604 | printf("%-6" PRIu64" %-10s %10p %-8s %10p %-3" PRIu32 " %10p %10p %9" PRIu64 "%c ", |
| 605 | t->tid, t->name, t, thread_states[t->state], t->task, |
605 | t->tid, t->name, t, thread_states[t->state], t->task, |
| 606 | t->task->context, t->thread_code, t->kstack, cycles, suffix); |
606 | t->task->context, t->thread_code, t->kstack, cycles, suffix); |
| 607 | else |
607 | #endif |
| - | 608 | ||
| - | 609 | #ifdef __64_BITS__ |
|
| 608 | printf("%-6llu %-10s %#18zx %-8s %#18zx %-3ld %#18zx %#18zx %9llu%c ", |
610 | printf("%-6" PRIu64" %-10s %18p %-8s %18p %-3" PRIu32 " %18p %18p %9" PRIu64 "%c ", |
| 609 | t->tid, t->name, t, thread_states[t->state], t->task, |
611 | t->tid, t->name, t, thread_states[t->state], t->task, |
| 610 | t->task->context, t->thread_code, t->kstack, cycles, suffix); |
612 | t->task->context, t->thread_code, t->kstack, cycles, suffix); |
| - | 613 | #endif |
|
| 611 | 614 | ||
| 612 | if (t->cpu) |
615 | if (t->cpu) |
| 613 | printf("%-4zd", t->cpu->id); |
616 | printf("%-4u", t->cpu->id); |
| 614 | else |
617 | else |
| 615 | printf("none"); |
618 | printf("none"); |
| 616 | 619 | ||
| 617 | if (t->state == Sleeping) { |
620 | if (t->state == Sleeping) { |
| 618 | if (sizeof(uintptr_t) == 4) |
621 | #ifdef __32_BITS__ |
| 619 | printf(" %#10zx", t->sleep_queue); |
622 | printf(" %10p", t->sleep_queue); |
| 620 | else |
623 | #endif |
| - | 624 | ||
| - | 625 | #ifdef __64_BITS__ |
|
| 621 | printf(" %#18zx", t->sleep_queue); |
626 | printf(" %18p", t->sleep_queue); |
| - | 627 | #endif |
|
| 622 | } |
628 | } |
| 623 | 629 | ||
| 624 | printf("\n"); |
630 | printf("\n"); |
| 625 | 631 | ||
| 626 | return true; |
632 | return true; |
| Line 632... | Line 638... | ||
| 632 | ipl_t ipl; |
638 | ipl_t ipl; |
| 633 | 639 | ||
| 634 | /* Messing with thread structures, avoid deadlock */ |
640 | /* Messing with thread structures, avoid deadlock */ |
| 635 | ipl = interrupts_disable(); |
641 | ipl = interrupts_disable(); |
| 636 | spinlock_lock(&threads_lock); |
642 | spinlock_lock(&threads_lock); |
| 637 | 643 | ||
| 638 | if (sizeof(uintptr_t) == 4) { |
644 | #ifdef __32_BITS__ |
| 639 | printf("tid name address state task " |
645 | printf("tid name address state task " |
| 640 | "ctx code stack cycles cpu " |
646 | "ctx code stack cycles cpu " |
| 641 | "waitqueue\n"); |
647 | "waitqueue\n"); |
| 642 | printf("------ ---------- ---------- -------- ---------- " |
648 | printf("------ ---------- ---------- -------- ---------- " |
| 643 | "--- ---------- ---------- ---------- ---- " |
649 | "--- ---------- ---------- ---------- ---- " |
| 644 | "----------\n"); |
650 | "----------\n"); |
| 645 | } else { |
651 | #endif |
| - | 652 | ||
| - | 653 | #ifdef __64_BITS__ |
|
| 646 | printf("tid name address state task " |
654 | printf("tid name address state task " |
| 647 | "ctx code stack cycles cpu " |
655 | "ctx code stack cycles cpu " |
| 648 | "waitqueue\n"); |
656 | "waitqueue\n"); |
| 649 | printf("------ ---------- ------------------ -------- ------------------ " |
657 | printf("------ ---------- ------------------ -------- ------------------ " |
| 650 | "--- ------------------ ------------------ ---------- ---- " |
658 | "--- ------------------ ------------------ ---------- ---- " |
| 651 | "------------------\n"); |
659 | "------------------\n"); |
| 652 | } |
660 | #endif |
| 653 | 661 | ||
| 654 | avltree_walk(&threads_tree, thread_walker, NULL); |
662 | avltree_walk(&threads_tree, thread_walker, NULL); |
| 655 | 663 | ||
| 656 | spinlock_unlock(&threads_lock); |
664 | spinlock_unlock(&threads_lock); |
| 657 | interrupts_restore(ipl); |
665 | interrupts_restore(ipl); |
| Line 674... | Line 682... | ||
| 674 | 682 | ||
| 675 | return node != NULL; |
683 | return node != NULL; |
| 676 | } |
684 | } |
| 677 | 685 | ||
| 678 | 686 | ||
| - | 687 | /** Create new user task with 1 thread from image |
|
| - | 688 | * |
|
| - | 689 | * @param program_addr Address of program executable image. |
|
| - | 690 | * @param name Program name. |
|
| - | 691 | * |
|
| - | 692 | * @return Initialized main thread of the task or NULL on error. |
|
| - | 693 | */ |
|
| - | 694 | thread_t *thread_create_program(void *program_addr, char *name) |
|
| - | 695 | { |
|
| - | 696 | as_t *as; |
|
| - | 697 | as_area_t *area; |
|
| - | 698 | unsigned int rc; |
|
| - | 699 | task_t *task; |
|
| - | 700 | uspace_arg_t *kernel_uarg; |
|
| - | 701 | ||
| - | 702 | kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
|
| - | 703 | if (kernel_uarg == NULL) |
|
| - | 704 | return NULL; |
|
| - | 705 | ||
| - | 706 | kernel_uarg->uspace_entry = |
|
| - | 707 | (void *) ((elf_header_t *) program_addr)->e_entry; |
|
| - | 708 | kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
|
| - | 709 | kernel_uarg->uspace_thread_function = NULL; |
|
| - | 710 | kernel_uarg->uspace_thread_arg = NULL; |
|
| - | 711 | kernel_uarg->uspace_uarg = NULL; |
|
| - | 712 | ||
| - | 713 | as = as_create(0); |
|
| - | 714 | if (as == NULL) { |
|
| - | 715 | free(kernel_uarg); |
|
| - | 716 | return NULL; |
|
| - | 717 | } |
|
| - | 718 | ||
| - | 719 | rc = elf_load((elf_header_t *) program_addr, as); |
|
| - | 720 | if (rc != EE_OK) { |
|
| - | 721 | free(kernel_uarg); |
|
| - | 722 | as_destroy(as); |
|
| - | 723 | return NULL; |
|
| - | 724 | } |
|
| - | 725 | ||
| - | 726 | /* |
|
| - | 727 | * Create the data as_area. |
|
| - | 728 | */ |
|
| - | 729 | area = as_area_create(as, |
|
| - | 730 | AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, |
|
| - | 731 | LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS, |
|
| - | 732 | AS_AREA_ATTR_NONE, &anon_backend, NULL); |
|
| - | 733 | if (area == NULL) { |
|
| - | 734 | free(kernel_uarg); |
|
| - | 735 | as_destroy(as); |
|
| - | 736 | return NULL; |
|
| - | 737 | } |
|
| - | 738 | ||
| - | 739 | task = task_create(as, name); |
|
| - | 740 | if (task == NULL) { |
|
| - | 741 | free(kernel_uarg); |
|
| - | 742 | as_destroy(as); |
|
| - | 743 | return NULL; |
|
| - | 744 | } |
|
| - | 745 | ||
| - | 746 | /* |
|
| - | 747 | * Create the main thread. |
|
| - | 748 | */ |
|
| - | 749 | return thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE, |
|
| - | 750 | "uinit", false); |
|
| - | 751 | } |
|
| - | 752 | ||
| - | 753 | ||
| 679 | /** Update accounting of current thread. |
754 | /** Update accounting of current thread. |
| 680 | * |
755 | * |
| 681 | * Note that thread_lock on THREAD must be already held and |
756 | * Note that thread_lock on THREAD must be already held and |
| 682 | * interrupts must be already disabled. |
757 | * interrupts must be already disabled. |
| 683 | * |
758 | * |