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 | * |