- /* FIXME: probably want a faster allocator here... :P */
- struct kperf_sample *sbuf = kalloc( sizeof(*sbuf) );
- if( sbuf == NULL )
- {
- /* FIXME: error code */
- BUF_INFO1( PERF_AST_ERROR, 0 );
- goto error;
+ ctx.cur_thread = current_thread();
+ ctx.cur_pid = task_pid(get_threadtask(ctx.cur_thread));
+ ctx.trigger_type = TRIGGER_TYPE_KDEBUG;
+ ctx.trigger_id = 0;
+
+ s = ml_set_interrupts_enabled(0);
+
+ sample = kperf_intr_sample_buffer();
+
+ if (!ml_at_interrupt_context()) {
+ sample_flags |= SAMPLE_FLAG_NON_INTERRUPT;
+ ctx.starting_fp = starting_fp;
+ }
+
+ kr = kperf_sample(sample, &ctx, kperf_kdebug_get_action(), sample_flags);
+
+ ml_set_interrupts_enabled(s);
+ BUF_VERB(PERF_KDBG_HNDLR | DBG_FUNC_END, kr);
+}
+
+/*
+ * This function allocates >2.3KB of the stack. Prevent the compiler from
+ * inlining this function into ast_taken and ensure the stack memory is only
+ * allocated for the kperf AST.
+ */
+__attribute__((noinline))
+void
+kperf_thread_ast_handler(thread_t thread)
+{
+ BUF_INFO(PERF_AST_HNDLR | DBG_FUNC_START, thread, kperf_get_thread_flags(thread));
+
+ /* ~2KB of the stack for the sample since this is called from AST */
+ struct kperf_sample sbuf;
+ memset(&sbuf, 0, sizeof(struct kperf_sample));
+
+ task_t task = get_threadtask(thread);
+
+ if (task_did_exec(task) || task_is_exec_copy(task)) {
+ BUF_INFO(PERF_AST_HNDLR | DBG_FUNC_END, SAMPLE_CONTINUE);
+ return;