xref: /haiku/src/system/kernel/scheduler/scheduler.cpp (revision 97901ec593ec4dd50ac115c1c35a6d72f6e489a5)
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