Changeset 17652
- Timestamp:
- 05/30/06 10:17:09 (2 years ago)
- Files:
-
- 1 modified
-
haiku/trunk/src/system/kernel/thread.c (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
haiku/trunk/src/system/kernel/thread.c
r17338 r17652 7 7 */ 8 8 9 /* Threading routines */9 /** Threading routines */ 10 10 11 11 #include <OS.h> … … 43 43 #define THREAD_MAX_MESSAGE_SIZE 65536 44 44 45 static status_t receive_data_etc(thread_id *_sender, void *buffer, size_t bufferSize, int32 flags); 45 // used to pass messages between thread_exit and thread_exit2 46 47 struct thread_exit_args { 48 struct thread *thread; 49 area_id old_kernel_stack; 50 uint32 death_stack; 51 sem_id death_sem; 52 team_id original_team_id; 53 }; 46 54 47 55 struct thread_key { 48 56 thread_id id; 49 57 }; 58 59 static status_t receive_data_etc(thread_id *_sender, void *buffer, 60 size_t bufferSize, int32 flags); 50 61 51 62 // global … … 747 758 748 759 /** Finds a free death stack for us and allocates it. 749 * Leaves interrupts disabled and returns the former interrupt state.760 * Must be called with interrupts enabled. 750 761 */ 751 762 752 static cpu_status753 get_death_stack( uint32 *_stack)763 static uint32 764 get_death_stack(void) 754 765 { 755 766 cpu_status state; … … 768 779 RELEASE_THREAD_LOCK(); 769 780 781 restore_interrupts(state); 782 770 783 // sanity checks 771 784 if (!bit) … … 782 795 TRACE(("get_death_stack: returning 0x%lx\n", sDeathStacks[i].address)); 783 796 784 *_stack = (uint32)i; 785 return state; 786 } 787 797 return (uint32)i; 798 } 799 800 801 /** Returns the thread's death stack to the pool. 802 */ 788 803 789 804 static void 790 put_death_stack_and_reschedule(uint32 index) 791 { 805 put_death_stack(uint32 index) 806 { 807 cpu_status state; 808 792 809 TRACE(("put_death_stack...: passed %lu\n", index)); 793 810 … … 798 815 panic("put_death_stack: passed invalid stack index %d\n", index); 799 816 800 disable_interrupts(); 817 state = disable_interrupts(); 818 801 819 GRAB_THREAD_LOCK(); 802 820 sDeathStackBitmap &= ~(1 << index); 803 821 RELEASE_THREAD_LOCK(); 804 822 823 restore_interrupts(state); 824 805 825 release_sem_etc(sDeathStackSem, 1, B_DO_NOT_RESCHEDULE); 806 826 // we must not have acquired the thread lock when releasing a semaphore 807 808 GRAB_THREAD_LOCK(); 809 scheduler_reschedule(); 810 // requires thread lock to be held 811 } 812 813 814 // used to pass messages between thread_exit and thread_exit2 815 816 struct thread_exit_args { 817 struct thread *thread; 818 area_id old_kernel_stack; 819 cpu_status int_state; 820 uint32 death_stack; 821 sem_id death_sem; 822 team_id original_team_id; 823 }; 827 } 824 828 825 829 … … 857 861 RELEASE_THREAD_LOCK(); 858 862 859 // restore former thread interrupts (doesn't matter much at this point anyway)860 restore_interrupts(args.int_state);863 enable_interrupts(); 864 // needed for the debugger notification below 861 865 862 866 TRACE(("thread_exit2: done removing thread from lists\n")); … … 864 868 if (args.death_sem >= 0) 865 869 release_sem_etc(args.death_sem, 1, B_DO_NOT_RESCHEDULE); 866 867 // set the next state to be gone. Will return the thread structure to a ready pool upon reschedule868 args.thread->next_state = THREAD_STATE_FREE_ON_RESCHED;869 870 870 871 // notify the debugger … … 874 875 } 875 876 877 disable_interrupts(); 878 879 // Set the next state to be gone: this will cause the thread structure 880 // to be returned to a ready pool upon reschedule. 881 // Note, we need to have disabled interrupts at this point, or else 882 // we could get rescheduled too early. 883 args.thread->next_state = THREAD_STATE_FREE_ON_RESCHED; 884 876 885 // return the death stack and reschedule one last time 877 put_death_stack_and_reschedule(args.death_stack); 886 887 put_death_stack(args.death_stack); 888 889 GRAB_THREAD_LOCK(); 890 scheduler_reschedule(); 891 // requires thread lock to be held 878 892 879 893 // never get to here … … 892 906 thread_id mainParentThread = -1; 893 907 bool deleteTeam = false; 894 uint32 death_stack;895 908 sem_id cachedDeathSem = -1, parentDeadSem = -1, groupDeadSem = -1; 896 909 status_t status; … … 1053 1066 struct thread_exit_args args; 1054 1067 1055 args.int_state = get_death_stack(&death_stack);1056 // this disables interrups for us1057 1058 1068 args.thread = thread; 1059 1069 args.old_kernel_stack = thread->kernel_stack_area; 1060 args.death_stack = death_stack;1070 args.death_stack = get_death_stack(); 1061 1071 args.death_sem = cachedDeathSem; 1062 1072 args.original_team_id = teamID; 1063 1073 1064 // set the new kernel stack officially to the death stack, wont be really switched until 1065 // the next function is called. This bookkeeping must be done now before a context switch 1066 // happens, or the processor will interrupt to the old stack 1067 thread->kernel_stack_area = sDeathStacks[death_stack].area; 1068 thread->kernel_stack_base = sDeathStacks[death_stack].address; 1074 disable_interrupts(); 1075 1076 // set the new kernel stack officially to the death stack, it won't be 1077 // switched until the next function is called. This must be done now 1078 // before a context switch, or we'll stay on the old stack 1079 thread->kernel_stack_area = sDeathStacks[args.death_stack].area; 1080 thread->kernel_stack_base = sDeathStacks[args.death_stack].address; 1069 1081 1070 1082 // we will continue in thread_exit2(), on the new stack
