1/* 2 * Copyright 2008-2011, 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 18struct scheduler_ops* gScheduler; 19spinlock gSchedulerLock = B_SPINLOCK_INITIALIZER; 20SchedulerListenerList gSchedulerListeners; 21 22static void (*sRescheduleFunction)(void); 23 24 25static void 26scheduler_reschedule_no_op(void) 27{ 28 Thread* thread = thread_get_current_thread(); 29 if (thread != NULL && thread->next_state != B_THREAD_READY) 30 panic("scheduler_reschedule_no_op() called in non-ready thread"); 31} 32 33 34// #pragma mark - SchedulerListener 35 36 37SchedulerListener::~SchedulerListener() 38{ 39} 40 41 42// #pragma mark - kernel private 43 44 45/*! Add the given scheduler listener. Thread lock must be held. 46*/ 47void 48scheduler_add_listener(struct SchedulerListener* listener) 49{ 50 gSchedulerListeners.Add(listener); 51} 52 53 54/*! Remove the given scheduler listener. Thread lock must be held. 55*/ 56void 57scheduler_remove_listener(struct SchedulerListener* listener) 58{ 59 gSchedulerListeners.Remove(listener); 60} 61 62 63void 64scheduler_init(void) 65{ 66 int32 cpuCount = smp_get_num_cpus(); 67 dprintf("scheduler_init: found %" B_PRId32 " logical cpu%s\n", cpuCount, 68 cpuCount != 1 ? "s" : ""); 69 70 if (cpuCount > 1) { 71#if 0 72 dprintf("scheduler_init: using affine scheduler\n"); 73 scheduler_affine_init(); 74#else 75 dprintf("scheduler_init: using simple SMP scheduler\n"); 76 scheduler_simple_smp_init(); 77#endif 78 } else { 79 dprintf("scheduler_init: using simple scheduler\n"); 80 scheduler_simple_init(); 81 } 82 83 // Disable rescheduling until the basic kernel initialization is done and 84 // CPUs are ready to enable interrupts. 85 sRescheduleFunction = gScheduler->reschedule; 86 gScheduler->reschedule = scheduler_reschedule_no_op; 87 88#if SCHEDULER_TRACING 89 add_debugger_command_etc("scheduler", &cmd_scheduler, 90 "Analyze scheduler tracing information", 91 "<thread>\n" 92 "Analyzes scheduler tracing information for a given thread.\n" 93 " <thread> - ID of the thread.\n", 0); 94#endif 95} 96 97 98void 99scheduler_enable_scheduling(void) 100{ 101 gScheduler->reschedule = sRescheduleFunction; 102} 103 104 105// #pragma mark - Syscalls 106 107 108bigtime_t 109_user_estimate_max_scheduling_latency(thread_id id) 110{ 111 syscall_64_bit_return_value(); 112 113 // get the thread 114 Thread* thread; 115 if (id < 0) { 116 thread = thread_get_current_thread(); 117 thread->AcquireReference(); 118 } else { 119 thread = Thread::Get(id); 120 if (thread == NULL) 121 return 0; 122 } 123 BReference<Thread> threadReference(thread, true); 124 125 // ask the scheduler for the thread's latency 126 InterruptsSpinLocker locker(gSchedulerLock); 127 return gScheduler->estimate_max_scheduling_latency(thread); 128} 129