1/*
2 * Copyright 2013, Pawe�� Dziepak, pdziepak@quarnos.org.
3 * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Copyright 2005-2010, Axel D��rfler, axeld@pinc-software.de.
5 * Distributed under the terms of the MIT License.
6 */
7#ifndef KERNEL_SCHEDULER_H
8#define KERNEL_SCHEDULER_H
9
10
11#include <cpu.h>
12#include <int.h>
13#include <smp.h>
14#include <thread_types.h>
15
16
17struct scheduling_analysis;
18struct SchedulerListener;
19
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
25/*!	Enqueues the thread in the ready-to-run queue.
26	The caller must hold the enqueued thread \c scheduler_lock.
27*/
28void scheduler_enqueue_in_run_queue(Thread* thread);
29
30void scheduler_reschedule_ici(void);
31
32/*!	Selects a thread from the ready-to-run queue and, if that's not the
33	calling thread, switches the current CPU's context to run the selected
34	thread.
35	If it's the same thread, the thread will just continue to run.
36	In either case, unless the thread is dead or is sleeping/waiting
37	indefinitely, the function will eventually return.
38	The caller must hold the current thread \c scheduler_lock.
39*/
40void scheduler_reschedule(int32 next_state);
41
42/*!	Sets the given thread's priority.
43	The thread may be running or may be in the ready-to-run queue.
44*/
45int32 scheduler_set_thread_priority(Thread* thread, int32 priority);
46
47/*!	Called when the Thread structure is first created.
48	Per-thread housekeeping resources can be allocated.
49	Interrupts must be enabled.
50*/
51status_t scheduler_on_thread_create(Thread* thread, bool idleThread);
52
53/*!	Called when a Thread structure is initialized and made ready for
54	use.
55	The per-thread housekeeping data structures are reset, if needed.
56*/
57void scheduler_on_thread_init(Thread* thread);
58
59/*!	Called when a Thread structure is freed.
60	Frees up any per-thread resources allocated on the scheduler's part. The
61	function may be called even if on_thread_create() failed.
62	Interrupts must be enabled.
63*/
64void scheduler_on_thread_destroy(Thread* thread);
65
66/*!	Called in the early boot process to start thread scheduling on the
67	current CPU.
68	The function is called once for each CPU.
69*/
70void scheduler_start(void);
71
72/*! Sets scheduler operation mode.
73 */
74status_t scheduler_set_operation_mode(scheduler_mode mode);
75
76/*! Dumps scheduler specific thread information.
77*/
78void scheduler_dump_thread_data(Thread* thread);
79
80void scheduler_new_thread_entry(Thread* thread);
81
82void scheduler_set_cpu_enabled(int32 cpu, bool enabled);
83
84void scheduler_add_listener(struct SchedulerListener* listener);
85void scheduler_remove_listener(struct SchedulerListener* listener);
86
87void scheduler_init(void);
88void scheduler_enable_scheduling(void);
89void scheduler_update_policy(void);
90
91bigtime_t _user_estimate_max_scheduling_latency(thread_id thread);
92status_t _user_analyze_scheduling(bigtime_t from, bigtime_t until, void* buffer,
93	size_t size, struct scheduling_analysis* analysis);
94
95status_t _user_set_scheduler_mode(int32 mode);
96int32 _user_get_scheduler_mode(void);
97
98#ifdef __cplusplus
99}
100#endif
101
102
103/*!	Reschedules, if necessary.
104	The caller must hold the scheduler lock (with disabled interrupts).
105*/
106static inline void
107scheduler_reschedule_if_necessary_locked()
108{
109	if (gCPU[smp_get_current_cpu()].invoke_scheduler)
110		scheduler_reschedule(B_THREAD_READY);
111}
112
113
114/*!	Reschedules, if necessary.
115	Is a no-op, if interrupts are disabled.
116*/
117static inline void
118scheduler_reschedule_if_necessary()
119{
120	if (are_interrupts_enabled()) {
121		cpu_status state = disable_interrupts();
122
123		Thread* thread = get_cpu_struct()->running_thread;
124		acquire_spinlock(&thread->scheduler_lock);
125
126		scheduler_reschedule_if_necessary_locked();
127
128		release_spinlock(&thread->scheduler_lock);
129
130		restore_interrupts(state);
131	}
132}
133
134
135#endif /* KERNEL_SCHEDULER_H */
136