1 /* 2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2010, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <kscheduler.h> 9 #include <listeners.h> 10 #include <smp.h> 11 12 #include "scheduler_affine.h" 13 #include "scheduler_simple.h" 14 #include "scheduler_simple_smp.h" 15 #include "scheduler_tracing.h" 16 17 18 struct scheduler_ops* gScheduler; 19 SchedulerListenerList gSchedulerListeners; 20 21 static void (*sRescheduleFunction)(void); 22 23 24 static void 25 scheduler_reschedule_no_op(void) 26 { 27 struct thread* thread = thread_get_current_thread(); 28 if (thread != NULL && thread->next_state != B_THREAD_READY) 29 panic("scheduler_reschedule_no_op() called in non-ready thread"); 30 } 31 32 33 // #pragma mark - 34 35 36 SchedulerListener::~SchedulerListener() 37 { 38 } 39 40 41 /*! Add the given scheduler listener. Thread lock must be held. 42 */ 43 void 44 scheduler_add_listener(struct SchedulerListener* listener) 45 { 46 gSchedulerListeners.Add(listener); 47 } 48 49 50 /*! Remove the given scheduler listener. Thread lock must be held. 51 */ 52 void 53 scheduler_remove_listener(struct SchedulerListener* listener) 54 { 55 gSchedulerListeners.Remove(listener); 56 } 57 58 59 void 60 scheduler_init(void) 61 { 62 int32 cpuCount = smp_get_num_cpus(); 63 dprintf("scheduler_init: found %ld logical cpu%s\n", cpuCount, 64 cpuCount != 1 ? "s" : ""); 65 66 if (cpuCount > 1) { 67 #if 0 68 dprintf("scheduler_init: using affine scheduler\n"); 69 scheduler_affine_init(); 70 #else 71 dprintf("scheduler_init: using simple SMP scheduler\n"); 72 scheduler_simple_smp_init(); 73 #endif 74 } else { 75 dprintf("scheduler_init: using simple scheduler\n"); 76 scheduler_simple_init(); 77 } 78 79 // Disable rescheduling until the basic kernel initialization is done and 80 // CPUs are ready to enable interrupts. 81 sRescheduleFunction = gScheduler->reschedule; 82 gScheduler->reschedule = scheduler_reschedule_no_op; 83 84 #if SCHEDULER_TRACING 85 add_debugger_command_etc("scheduler", &cmd_scheduler, 86 "Analyze scheduler tracing information", 87 "<thread>\n" 88 "Analyzes scheduler tracing information for a given thread.\n" 89 " <thread> - ID of the thread.\n", 0); 90 #endif 91 } 92 93 94 void 95 scheduler_enable_scheduling(void) 96 { 97 gScheduler->reschedule = sRescheduleFunction; 98 } 99 100 101 // #pragma mark - Syscalls 102 103 104 bigtime_t 105 _user_estimate_max_scheduling_latency(thread_id id) 106 { 107 syscall_64_bit_return_value(); 108 109 InterruptsSpinLocker locker(gThreadSpinlock); 110 111 struct thread* thread = id < 0 112 ? thread_get_current_thread() : thread_get_thread_struct_locked(id); 113 if (thread == NULL) 114 return 0; 115 116 return gScheduler->estimate_max_scheduling_latency(thread); 117 } 118