1 /* 2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef KERNEL_SCHEDULER_COMMON_H 6 #define KERNEL_SCHEDULER_COMMON_H 7 8 9 #include <kscheduler.h> 10 #include <smp.h> 11 #include <user_debugger.h> 12 13 14 /*! Switches the currently running thread. 15 This is a service function for scheduler implementations. 16 17 \param fromThread The currently running thread. 18 \param toThread The thread to switch to. Must be different from 19 \a fromThread. 20 */ 21 static inline void 22 scheduler_switch_thread(Thread* fromThread, Thread* toThread) 23 { 24 // notify the user debugger code 25 if ((fromThread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) 26 user_debug_thread_unscheduled(fromThread); 27 28 // stop CPU time based user timers 29 if (fromThread->HasActiveCPUTimeUserTimers() 30 || fromThread->team->HasActiveCPUTimeUserTimers()) { 31 user_timer_stop_cpu_timers(fromThread, toThread); 32 } 33 34 // update CPU and Thread structures and perform the context switch 35 cpu_ent* cpu = fromThread->cpu; 36 toThread->previous_cpu = toThread->cpu = cpu; 37 fromThread->cpu = NULL; 38 cpu->running_thread = toThread; 39 cpu->previous_thread = fromThread; 40 41 arch_thread_set_current_thread(toThread); 42 arch_thread_context_switch(fromThread, toThread); 43 44 // The use of fromThread below looks weird, but is correct. fromThread had 45 // been unscheduled earlier, but is back now. For a thread scheduled the 46 // first time the same is done in thread.cpp:common_thread_entry(). 47 48 // continue CPU time based user timers 49 if (fromThread->HasActiveCPUTimeUserTimers() 50 || fromThread->team->HasActiveCPUTimeUserTimers()) { 51 user_timer_continue_cpu_timers(fromThread, cpu->previous_thread); 52 } 53 54 // notify the user debugger code 55 if ((fromThread->flags & THREAD_FLAGS_DEBUGGER_INSTALLED) != 0) 56 user_debug_thread_scheduled(fromThread); 57 } 58 59 60 static inline void 61 scheduler_update_thread_times(Thread* oldThread, Thread* nextThread) 62 { 63 bigtime_t now = system_time(); 64 if (oldThread == nextThread) { 65 acquire_spinlock(&oldThread->time_lock); 66 oldThread->kernel_time += now - oldThread->last_time; 67 oldThread->last_time = now; 68 release_spinlock(&oldThread->time_lock); 69 } else { 70 acquire_spinlock(&oldThread->time_lock); 71 oldThread->kernel_time += now - oldThread->last_time; 72 release_spinlock(&oldThread->time_lock); 73 74 acquire_spinlock(&nextThread->time_lock); 75 nextThread->last_time = now; 76 release_spinlock(&nextThread->time_lock); 77 } 78 79 // If the old thread's team has user time timers, check them now. 80 Team* team = oldThread->team; 81 if (team->HasActiveUserTimeUserTimers()) 82 user_timer_check_team_user_timers(team); 83 } 84 85 86 #endif // KERNEL_SCHEDULER_COMMON_H 87