X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/b0d623f7f2ae71ed96e60569f61f9a9a27016e80..8a3053a07cee346dca737a5670e546fd26a7c9d6:/osfmk/chud/chud_thread.c?ds=inline diff --git a/osfmk/chud/chud_thread.c b/osfmk/chud/chud_thread.c index 0f955bb6e..1a827aadd 100644 --- a/osfmk/chud/chud_thread.c +++ b/osfmk/chud/chud_thread.c @@ -43,11 +43,17 @@ #include +#if KPC +#include +#endif + +#if KPERF +#include +#endif + // include the correct file to find real_ncpus #if defined(__i386__) || defined(__x86_64__) # include -#elif defined(__ppc__) || defined(__ppc64__) -# include #else // fall back on declaring it extern. The linker will sort us out. extern unsigned int real_ncpus; @@ -124,6 +130,51 @@ chudxnu_thread_get_idle(thread_t thread) { return ((thread->state & TH_IDLE) == TH_IDLE); } +__private_extern__ int +chudxnu_thread_get_scheduler_state(thread_t thread) { + /* + * Instantaneous snapshot of the scheduler state of + * a given thread. + * + * MUST ONLY be called on an interrupted or + * locked thread, to avoid a race. + */ + + int state = 0; + int schedulerState = (volatile int)(thread->state); + processor_t lastProcessor = (volatile processor_t)(thread->last_processor); + + if ((PROCESSOR_NULL != lastProcessor) && (thread == lastProcessor->active_thread)) { + state |= CHUDXNU_TS_RUNNING; + } + + if (schedulerState & TH_RUN) { + state |= CHUDXNU_TS_RUNNABLE; + } + + if (schedulerState & TH_WAIT) { + state |= CHUDXNU_TS_WAIT; + } + + if (schedulerState & TH_UNINT) { + state |= CHUDXNU_TS_UNINT; + } + + if (schedulerState & TH_SUSP) { + state |= CHUDXNU_TS_SUSP; + } + + if (schedulerState & TH_TERMINATE) { + state |= CHUDXNU_TS_TERMINATE; + } + + if (schedulerState & TH_IDLE) { + state |= CHUDXNU_TS_IDLE; + } + + return state; +} + #if 0 #pragma mark **** task and thread info **** #endif @@ -507,3 +558,83 @@ chudxnu_thread_set_marked(thread_t thread, boolean_t new_value) return FALSE; } +/* XXX: good thing this code is experimental... */ + +/* external handler */ +extern void (*chudxnu_thread_ast_handler)(thread_t); +void (*chudxnu_thread_ast_handler)(thread_t) = NULL; + +/* AST callback to dispatch to AppleProfile */ +extern void chudxnu_thread_ast(thread_t); +void +chudxnu_thread_ast(thread_t thread) +{ +#if KPC + /* check for PMC work */ + kpc_thread_ast_handler(thread); +#endif + +#if KPERF + /* check for kperf work */ + kperf_thread_ast_handler(thread); +#endif + + /* atomicness for kdebug events */ + void (*handler)(thread_t) = chudxnu_thread_ast_handler; + if( handler ) + handler( thread ); + + thread->t_chud = 0; +} + + + +/* Get and set bits on the thread and trigger an AST handler */ +void chudxnu_set_thread_ast( thread_t thread ); +void +chudxnu_set_thread_ast( thread_t thread ) +{ + /* FIXME: only call this on current thread from an interrupt handler for now... */ + if( thread != current_thread() ) + panic( "unsafe AST set" ); + + act_set_kperf(thread); +} + +/* get and set the thread bits */ +extern uint32_t chudxnu_get_thread_bits( thread_t thread ); +extern void chudxnu_set_thread_bits( thread_t thread, uint32_t bits ); + +uint32_t +chudxnu_get_thread_bits( thread_t thread ) +{ + return thread->t_chud; +} + +void +chudxnu_set_thread_bits( thread_t thread, uint32_t bits ) +{ + thread->t_chud = bits; +} + +/* get and set thread dirty bits. so CHUD can track whether the thread + * has been dispatched since it last looked. caller must hold the + * thread lock + */ +boolean_t +chudxnu_thread_get_dirty(thread_t thread) +{ + if( thread->c_switch != thread->chud_c_switch ) + return TRUE; + else + return FALSE; +} + +void +chudxnu_thread_set_dirty(thread_t thread, boolean_t makedirty) +{ + if( makedirty ) + thread->chud_c_switch = thread->c_switch - 1; + else + thread->chud_c_switch = thread->c_switch; +}