#ifndef _KERN_SCHED_PRIM_H_
#define _KERN_SCHED_PRIM_H_
#include <mach/boolean.h>
#include <mach/machine/vm_types.h>
#include <mach/kern_return.h>
#include <kern/clock.h>
#include <kern/kern_types.h>
#include <kern/thread.h>
#include <sys/cdefs.h>
#ifdef MACH_KERNEL_PRIVATE
#include <mach/branch_predicates.h>
extern void sched_init(void);
extern void sched_startup(void);
extern void sched_timebase_init(void);
extern boolean_t thread_stop(
thread_t thread,
boolean_t until_not_runnable);
extern void thread_unstop(
thread_t thread);
extern void thread_wait(
thread_t thread,
boolean_t until_not_runnable);
extern boolean_t thread_unblock(
thread_t thread,
wait_result_t wresult);
extern kern_return_t thread_go(
thread_t thread,
wait_result_t wresult);
extern void thread_dispatch(
thread_t old_thread,
thread_t new_thread);
extern int thread_run(
thread_t self,
thread_continue_t continuation,
void *parameter,
thread_t new_thread);
extern void thread_continue(
thread_t old_thread);
extern void call_continuation(
thread_continue_t continuation,
void *parameter,
wait_result_t wresult);
extern void set_sched_pri(
thread_t thread,
int priority);
extern void sched_set_thread_base_priority(
thread_t thread,
int priority);
extern void sched_set_thread_throttled(thread_t thread,
boolean_t wants_throttle);
extern void sched_set_thread_mode(thread_t thread,
sched_mode_t mode);
extern void sched_thread_mode_demote(thread_t thread,
uint32_t reason);
extern void sched_thread_mode_undemote(thread_t thread,
uint32_t reason);
void thread_recompute_priority(thread_t thread);
void thread_recompute_qos(thread_t thread);
extern void thread_recompute_sched_pri(
thread_t thread,
boolean_t override_depress);
extern void sched_init_thread(void (*)(void));
extern boolean_t can_update_priority(
thread_t thread);
extern void update_priority(
thread_t thread);
extern void lightweight_update_priority(
thread_t thread);
extern void sched_default_quantum_expire(thread_t thread);
extern void idle_thread(void);
extern kern_return_t idle_thread_create(
processor_t processor);
extern void thread_syscall_return(
kern_return_t ret);
extern wait_result_t thread_block_reason(
thread_continue_t continuation,
void *parameter,
ast_t reason);
extern void thread_setrun(
thread_t thread,
integer_t options);
#define SCHED_TAILQ 1
#define SCHED_HEADQ 2
#define SCHED_PREEMPT 4
extern uintptr_t sched_thread_on_rt_queue;
#define THREAD_ON_RT_RUNQ ((processor_t)(uintptr_t)&sched_thread_on_rt_queue)
extern processor_set_t task_choose_pset(
task_t task);
extern processor_t thread_bind(
processor_t processor);
extern processor_t choose_processor(
processor_set_t pset,
processor_t processor,
thread_t thread);
extern void thread_quantum_init(
thread_t thread);
extern void run_queue_init(
run_queue_t runq);
extern thread_t run_queue_dequeue(
run_queue_t runq,
integer_t options);
extern boolean_t run_queue_enqueue(
run_queue_t runq,
thread_t thread,
integer_t options);
extern void run_queue_remove(
run_queue_t runq,
thread_t thread);
struct sched_update_scan_context
{
uint64_t earliest_bg_make_runnable_time;
uint64_t earliest_normal_make_runnable_time;
uint64_t earliest_rt_make_runnable_time;
};
typedef struct sched_update_scan_context *sched_update_scan_context_t;
#if defined(CONFIG_SCHED_TIMESHARE_CORE)
extern boolean_t thread_update_add_thread(thread_t thread);
extern void thread_update_process_threads(void);
extern boolean_t runq_scan(run_queue_t runq, sched_update_scan_context_t scan_context);
extern void sched_timeshare_init(void);
extern void sched_timeshare_timebase_init(void);
extern void sched_timeshare_maintenance_continue(void);
extern boolean_t priority_is_urgent(int priority);
extern uint32_t sched_timeshare_initial_quantum_size(thread_t thread);
extern int sched_compute_timeshare_priority(thread_t thread);
#endif
extern void rt_runq_scan(sched_update_scan_context_t scan_context);
extern boolean_t thread_run_queue_remove(thread_t thread);
thread_t thread_run_queue_remove_for_handoff(thread_t thread);
extern void thread_run_queue_reinsert(thread_t thread, integer_t options);
extern void thread_timer_expire(
void *thread,
void *p1);
extern boolean_t thread_eager_preemption(
thread_t thread);
extern boolean_t sched_generic_direct_dispatch_to_idle_processors;
__private_extern__ wait_interrupt_t thread_interrupt_level(
wait_interrupt_t interruptible);
__private_extern__ wait_result_t thread_mark_wait_locked(
thread_t thread,
wait_interrupt_t interruptible);
__private_extern__ kern_return_t clear_wait_internal(
thread_t thread,
wait_result_t result);
extern void sched_stats_handle_csw(
processor_t processor,
int reasons,
int selfpri,
int otherpri);
extern void sched_stats_handle_runq_change(
struct runq_stats *stats,
int old_count);
#define SCHED_STATS_CSW(processor, reasons, selfpri, otherpri) \
do { \
if (__builtin_expect(sched_stats_active, 0)) { \
sched_stats_handle_csw((processor), \
(reasons), (selfpri), (otherpri)); \
} \
} while (0)
#define SCHED_STATS_RUNQ_CHANGE(stats, old_count) \
do { \
if (__builtin_expect(sched_stats_active, 0)) { \
sched_stats_handle_runq_change((stats), \
(old_count)); \
} \
} while (0)
extern uint32_t sched_debug_flags;
#define SCHED_DEBUG_FLAG_PLATFORM_TRACEPOINTS 0x00000001
#define SCHED_DEBUG_FLAG_CHOOSE_PROCESSOR_TRACEPOINTS 0x00000002
#define SCHED_DEBUG_PLATFORM_KERNEL_DEBUG_CONSTANT(...) do { \
if (__improbable(sched_debug_flags & SCHED_DEBUG_FLAG_PLATFORM_TRACEPOINTS)) { \
KERNEL_DEBUG_CONSTANT(__VA_ARGS__); \
} \
} while(0)
#define SCHED_DEBUG_CHOOSE_PROCESSOR_KERNEL_DEBUG_CONSTANT(...) do { \
if (__improbable(sched_debug_flags & SCHED_DEBUG_FLAG_CHOOSE_PROCESSOR_TRACEPOINTS)) { \
KERNEL_DEBUG_CONSTANT(__VA_ARGS__); \
} \
} while(0)
#define THREAD_URGENCY_NONE 0
#define THREAD_URGENCY_BACKGROUND 1
#define THREAD_URGENCY_NORMAL 2
#define THREAD_URGENCY_REAL_TIME 3
#define THREAD_URGENCY_MAX 4
extern int thread_get_urgency(
thread_t thread,
uint64_t *rt_period,
uint64_t *rt_deadline);
extern void thread_tell_urgency(
int urgency,
uint64_t rt_period,
uint64_t rt_deadline,
uint64_t sched_latency,
thread_t nthread);
extern void active_rt_threads(
boolean_t active);
#endif
__BEGIN_DECLS
#ifdef XNU_KERNEL_PRIVATE
extern boolean_t assert_wait_possible(void);
#define CPU_THROTTLE_DISABLE 0
#define CPU_THROTTLE_ENABLE 1
extern void sys_override_cpu_throttle(int flag);
extern void thread_vm_bind_group_add(void);
extern kern_return_t clear_wait(
thread_t thread,
wait_result_t result);
extern void thread_bootstrap_return(void);
extern void thread_exception_return(void) __dead2;
#define SCHED_STRING_MAX_LENGTH (48)
extern char sched_string[SCHED_STRING_MAX_LENGTH];
extern kern_return_t sched_work_interval_notify(thread_t thread, uint64_t work_interval_id, uint64_t start, uint64_t finish, uint64_t deadline, uint64_t next_start, uint32_t flags);
#endif
extern wait_result_t thread_block(
thread_continue_t continuation);
extern wait_result_t thread_block_parameter(
thread_continue_t continuation,
void *parameter);
extern wait_result_t assert_wait(
event_t event,
wait_interrupt_t interruptible);
extern wait_result_t assert_wait_timeout(
event_t event,
wait_interrupt_t interruptible,
uint32_t interval,
uint32_t scale_factor);
extern wait_result_t assert_wait_timeout_with_leeway(
event_t event,
wait_interrupt_t interruptible,
wait_timeout_urgency_t urgency,
uint32_t interval,
uint32_t leeway,
uint32_t scale_factor);
extern wait_result_t assert_wait_deadline(
event_t event,
wait_interrupt_t interruptible,
uint64_t deadline);
extern wait_result_t assert_wait_deadline_with_leeway(
event_t event,
wait_interrupt_t interruptible,
wait_timeout_urgency_t urgency,
uint64_t deadline,
uint64_t leeway);
extern kern_return_t thread_wakeup_prim(
event_t event,
boolean_t one_thread,
wait_result_t result);
extern kern_return_t thread_wakeup_prim_internal(
event_t event,
boolean_t one_thread,
wait_result_t result,
int priority);
#define thread_wakeup(x) \
thread_wakeup_prim((x), FALSE, THREAD_AWAKENED)
#define thread_wakeup_with_result(x, z) \
thread_wakeup_prim((x), FALSE, (z))
#define thread_wakeup_one(x) \
thread_wakeup_prim((x), TRUE, THREAD_AWAKENED)
#ifdef MACH_KERNEL_PRIVATE
#define thread_wakeup_one_with_pri(x, pri) \
thread_wakeup_prim_internal((x), TRUE, THREAD_AWAKENED, pri)
#endif
extern boolean_t preemption_enabled(void);
#ifdef MACH_KERNEL_PRIVATE
#if !defined(CONFIG_SCHED_TRADITIONAL) && !defined(CONFIG_SCHED_PROTO) && !defined(CONFIG_SCHED_GRRR) && !defined(CONFIG_SCHED_MULTIQ)
#error Enable at least one scheduler algorithm in osfmk/conf/MASTER.XXX
#endif
#define SCHED(f) (sched_current_dispatch->f)
struct sched_dispatch_table {
const char *sched_name;
void (*init)(void);
void (*timebase_init)(void);
void (*processor_init)(processor_t processor);
void (*pset_init)(processor_set_t pset);
void (*maintenance_continuation)(void);
thread_t (*choose_thread)(
processor_t processor,
int priority,
ast_t reason);
boolean_t steal_thread_enabled;
thread_t (*steal_thread)(
processor_set_t pset);
int (*compute_timeshare_priority)(thread_t thread);
processor_t (*choose_processor)(
processor_set_t pset,
processor_t processor,
thread_t thread);
boolean_t (*processor_enqueue)(
processor_t processor,
thread_t thread,
integer_t options);
void (*processor_queue_shutdown)(
processor_t processor);
boolean_t (*processor_queue_remove)(
processor_t processor,
thread_t thread);
boolean_t (*processor_queue_empty)(processor_t processor);
boolean_t (*priority_is_urgent)(int priority);
ast_t (*processor_csw_check)(processor_t processor);
boolean_t (*processor_queue_has_priority)(processor_t processor,
int priority,
boolean_t gte);
uint32_t (*initial_quantum_size)(thread_t thread);
sched_mode_t (*initial_thread_sched_mode)(task_t parent_task);
boolean_t (*can_update_priority)(thread_t thread);
void (*update_priority)(thread_t thread);
void (*lightweight_update_priority)(thread_t thread);
void (*quantum_expire)(thread_t thread);
int (*processor_runq_count)(processor_t processor);
uint64_t (*processor_runq_stats_count_sum)(processor_t processor);
boolean_t (*processor_bound_count)(processor_t processor);
void (*thread_update_scan)(sched_update_scan_context_t scan_context);
boolean_t direct_dispatch_to_idle_processors;
boolean_t multiple_psets_enabled;
boolean_t sched_groups_enabled;
};
#if defined(CONFIG_SCHED_TRADITIONAL)
extern const struct sched_dispatch_table sched_traditional_dispatch;
extern const struct sched_dispatch_table sched_traditional_with_pset_runqueue_dispatch;
#endif
#if defined(CONFIG_SCHED_MULTIQ)
extern const struct sched_dispatch_table sched_multiq_dispatch;
extern const struct sched_dispatch_table sched_dualq_dispatch;
#endif
#if defined(CONFIG_SCHED_PROTO)
extern const struct sched_dispatch_table sched_proto_dispatch;
#endif
#if defined(CONFIG_SCHED_GRRR)
extern const struct sched_dispatch_table sched_grrr_dispatch;
#endif
extern const struct sched_dispatch_table *sched_current_dispatch;
#endif
__END_DECLS
#endif