- /*
- * thread_block needs to know if the thread's quantum
- * expired so the thread can be put on the tail of
- * run queue. One of the previous actions might well
- * have woken a high-priority thread, so we also use
- * csw_needed check.
- */
- reasons &= (AST_BLOCK | AST_QUANTUM);
- if (reasons == 0) {
- mp_disable_preemption();
- mypr = current_processor();
- if (csw_needed(self, mypr)) {
- reasons = (mypr->first_quantum ? AST_BLOCK : AST_QUANTUM);
+ assert((reasons & AST_TELEMETRY_ALL) != AST_TELEMETRY_ALL); /* only one is valid at a time */
+ interrupted_userspace = (reasons & AST_TELEMETRY_USER) ? TRUE : FALSE;
+ is_windowed = ((reasons & AST_TELEMETRY_WINDOWED) ? TRUE : FALSE);
+ thread_ast_clear(thread, AST_TELEMETRY_ALL);
+ telemetry_ast(thread, interrupted_userspace, is_windowed);
+ }
+#endif
+
+ ml_set_interrupts_enabled(FALSE);
+
+#if CONFIG_SCHED_SFI
+ if (reasons & AST_SFI) {
+ sfi_ast(thread);
+ }
+#endif
+
+ /*
+ * Check for preemption. Conditions may have changed from when the AST_PREEMPT was originally set.
+ */
+ thread_lock(thread);
+ if (reasons & AST_PREEMPT)
+ reasons = csw_check(current_processor(), reasons & AST_QUANTUM);
+ thread_unlock(thread);
+
+ assert(waitq_wait_possible(thread));
+
+ if (reasons & AST_PREEMPT) {
+ counter(c_ast_taken_block++);
+ thread_block_reason((thread_continue_t)thread_exception_return, NULL, reasons & AST_PREEMPTION);
+ }