X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..e8c3f78193f1895ea514044358b93b1add9322f3:/osfmk/kperf/kperf.h diff --git a/osfmk/kperf/kperf.h b/osfmk/kperf/kperf.h index 12b168acd..673a02cd3 100644 --- a/osfmk/kperf/kperf.h +++ b/osfmk/kperf/kperf.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2018 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,68 +22,147 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ -#ifndef __KPERF_H__ -#define __KPERF_H__ +#ifndef KPERF_H +#define KPERF_H -/* The various trigger types supported by kperf */ -#define TRIGGER_TYPE_TIMER (0) -#define TRIGGER_TYPE_PMI (1) -#define TRIGGER_TYPE_TRACE (2) +#include +#include -/* Helpers to get and set AST bits on a thread */ -extern uint32_t kperf_get_thread_bits( thread_t thread ); -extern void kperf_set_thread_bits( thread_t thread, uint32_t bits ); -extern void kperf_set_thread_ast( thread_t thread ); +extern lck_grp_t kperf_lck_grp; -/* Possible states of kperf sampling */ -#define KPERF_SAMPLING_OFF 0 -#define KPERF_SAMPLING_ON 1 -#define KPERF_SAMPLING_SHUTDOWN 2 +/* the trigger types supported by kperf */ +#define TRIGGER_TYPE_TIMER (0) +#define TRIGGER_TYPE_PMI (1) +#define TRIGGER_TYPE_KDEBUG (2) +#define TRIGGER_TYPE_LAZY_WAIT (3) +#define TRIGGER_TYPE_LAZY_CPU (3) -/* Init kperf module. Must be called before use, can be called as many - * times as you like. +/* helpers to get and set AST flags on a thread */ +uint32_t kperf_get_thread_flags(thread_t thread); +void kperf_set_thread_flags(thread_t thread, uint32_t flags); + +/* + * Get and set dirtiness of thread, so kperf can track whether the thread + * has been dispatched since it last looked. + */ +boolean_t kperf_thread_get_dirty(thread_t thread); +void kperf_thread_set_dirty(thread_t thread, boolean_t dirty); + +/* possible states of kperf sampling */ +#define KPERF_SAMPLING_OFF (0) +#define KPERF_SAMPLING_ON (1) +#define KPERF_SAMPLING_SHUTDOWN (2) + +/* + * Initialize kperf. Must be called before use and can be called multiple times. */ extern int kperf_init(void); -/* Get and set sampling status */ +/* get and set sampling status */ extern unsigned kperf_sampling_status(void); extern int kperf_sampling_enable(void); extern int kperf_sampling_disable(void); -/* kperf AST handler +/* get a per-CPU sample buffer */ +struct kperf_sample *kperf_intr_sample_buffer(void); + +/* + * Callbacks into kperf from other systems. */ -extern void kperf_thread_ast_handler( thread_t thread ); -/* kperf kdebug callback +/* + * kperf AST handler + * + * Prevent inlining, since the sampling function allocates on the stack and + * branches calling ast_taken (but never on a kperf AST) may blow their stacks. */ -extern void kperf_kdebug_callback(uint32_t debugid); +extern __attribute__((noinline)) void kperf_thread_ast_handler(thread_t thread); -/* get and set whether we're recording stacks on interesting kdebug events */ -extern int kperf_kdbg_get_stacks(void); -extern int kperf_kdbg_set_stacks(int); +/* update whether the callback is set */ +void kperf_on_cpu_update(void); -/* given a task port, find out its pid */ -int kperf_port_to_pid(mach_port_name_t portname); +/* for scheduler switching threads on */ +static inline void +kperf_on_cpu(thread_t thread, thread_continue_t continuation, + uintptr_t *starting_fp) +{ + extern boolean_t kperf_on_cpu_active; + void kperf_on_cpu_internal(thread_t thread, thread_continue_t continuation, + uintptr_t *starting_fp); + + if (__improbable(kperf_on_cpu_active)) { + kperf_on_cpu_internal(thread, continuation, starting_fp); + } +} + +/* for scheduler switching threads off */ +static inline void +kperf_off_cpu(thread_t thread) +{ + extern unsigned int kperf_lazy_cpu_action; + void kperf_lazy_off_cpu(thread_t thread); + + if (__improbable(kperf_lazy_cpu_action != 0)) { + kperf_lazy_off_cpu(thread); + } +} + +/* for scheduler making threads runnable */ +static inline void +kperf_make_runnable(thread_t thread, int interrupt) +{ + extern unsigned int kperf_lazy_cpu_action; + void kperf_lazy_make_runnable(thread_t thread, bool interrupt); + + if (__improbable(kperf_lazy_cpu_action != 0)) { + kperf_lazy_make_runnable(thread, interrupt); + } +} + +/* for interrupt handler epilogue */ +static inline void +kperf_interrupt(void) +{ + extern unsigned int kperf_lazy_cpu_action; + extern void kperf_lazy_cpu_sample(thread_t thread, unsigned int flags, + bool interrupt); + + if (__improbable(kperf_lazy_cpu_action != 0)) { + kperf_lazy_cpu_sample(current_thread(), 0, true); + } +} -/* Check whether the current process has been blessed to allow access - * to kperf facilities. +/* for kdebug on every traced event */ +static inline void +kperf_kdebug_callback(uint32_t debugid, uintptr_t *starting_fp) +{ + extern boolean_t kperf_kdebug_active; + void kperf_kdebug_handler(uint32_t debugid, uintptr_t *starting_fp); + + if (__improbable(kperf_kdebug_active)) { + kperf_kdebug_handler(debugid, starting_fp); + } +} + +/* + * Used by ktrace to reset kperf. ktrace_lock must be held. */ -extern int kperf_access_check(void); +extern void kperf_reset(void); -/* track recursion on kdebug tracepoint tracking */ -extern int kperf_kdbg_recurse(int step); -#define KPERF_RECURSE_IN (1) -#define KPERF_RECURSE_out (-1) +/* + * Configure kperf from the kernel (e.g. during boot). + */ +void kperf_kernel_configure(const char *config); -/* context switch tracking */ -extern int kperf_cswitch_hook; -extern void kperf_switch_context( thread_t old, thread_t new ); +/* given a task port, find out its pid */ +int kperf_port_to_pid(mach_port_name_t portname); -/* bootstrap */ -extern void kperf_bootstrap(void); +#if DEVELOPMENT || DEBUG +extern _Atomic long long kperf_pending_ipis; +#endif /* DEVELOPMENT || DEBUG */ -#endif /* __KPERF_H__ */ +#endif /* !defined(KPERF_H) */