/* snapshot current PMCs and update counters in the current thread */ static void kpc_update_thread_counters( thread_t thread ) { uint32_t i; uint64_t *tmp = NULL; cpu_data_t *cpu = NULL; cpu = current_cpu_datap(); /* 1. stash current PMCs into latest CPU block */ kpc_get_cpu_counters( FALSE, kpc_thread_classes, NULL, cpu->cpu_kpc_buf[1] ); /* 2. apply delta to old thread */ if( thread->kpc_buf ) for( i = 0; i < kpc_thread_classes_count; i++ ) thread->kpc_buf[i] += cpu->cpu_kpc_buf[1][i] - cpu->cpu_kpc_buf[0][i]; /* schedule any necessary allocations */ if( !current_thread()->kpc_buf ) { current_thread()->kperf_flags |= T_KPC_ALLOC; act_set_kperf(current_thread()); } /* 3. switch the PMC block pointers */ tmp = cpu->cpu_kpc_buf[1]; cpu->cpu_kpc_buf[1] = cpu->cpu_kpc_buf[0]; cpu->cpu_kpc_buf[0] = tmp; }
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); }
int kpc_set_thread_counting(uint32_t classes) { uint32_t count; lck_mtx_lock(&kpc_thread_lock); count = kpc_get_counter_count(classes); if( (classes == 0) || (count == 0) ) { /* shut down */ kpc_threads_counting = FALSE; } else { /* stash the config */ kpc_thread_classes = classes; /* work out the size */ kpc_thread_classes_count = count; assert(kpc_thread_classes_count <= KPC_MAX_COUNTERS); /* enable switch */ kpc_threads_counting = TRUE; /* and schedule an AST for this thread... */ if( !current_thread()->kpc_buf ) { current_thread()->kperf_flags |= T_KPC_ALLOC; act_set_kperf(current_thread()); } } kpc_off_cpu_update(); lck_mtx_unlock(&kpc_thread_lock); return 0; }