]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/chud/chud_thread.c
xnu-2422.115.4.tar.gz
[apple/xnu.git] / osfmk / chud / chud_thread.c
index 0f955bb6e0c5eb4c8f18b5a26eab519f1eca1a33..1a827aadd46f237008e197fe230251b3b7ac92b6 100644 (file)
 
 #include <libkern/OSAtomic.h>
 
+#if KPC
+#include <kern/kpc.h>
+#endif
+
+#if KPERF
+#include <kperf/kperf.h>
+#endif
+
 // include the correct file to find real_ncpus
 #if defined(__i386__) || defined(__x86_64__)
 #      include <i386/mp.h>     
-#elif defined(__ppc__) || defined(__ppc64__)
-#      include <ppc/cpu_internal.h>
 #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;
+}