/* * sched_call_thread: * * Call out invoked by the scheduler. Used only for high-priority * thread call group. */ static void sched_call_thread( int type, __unused thread_t thread) { thread_call_group_t group; group = &thread_call_groups[THREAD_CALL_PRIORITY_HIGH]; /* XXX */ thread_call_lock_spin(); switch (type) { case SCHED_CALL_BLOCK: --group->active_count; if (group->pending_count > 0) thread_call_wake(group); break; case SCHED_CALL_UNBLOCK: group->active_count++; break; } thread_call_unlock(); }
boolean_t thread_call_enter1( thread_call_t call, thread_call_param_t param1) { boolean_t result = TRUE; thread_call_group_t group = &thread_call_group0; spl_t s; s = splsched(); thread_call_lock_spin(); if (call->queue != &group->pending_queue) { result = _pending_call_enqueue(call, group); if (group->active_count == 0) thread_call_wake(group); } call->param1 = param1; thread_call_unlock(); splx(s); return (result); }
/* * _pending_call_enqueue: * * Place an entry at the end of the * pending queue, to be executed soon. * * Returns TRUE if the entry was already * on a queue. * * Called with thread_call_lock held. */ static __inline__ boolean_t _pending_call_enqueue( thread_call_t call, thread_call_group_t group) { queue_head_t *old_queue; old_queue = call_entry_enqueue_tail(CE(call), &group->pending_queue); if (old_queue == NULL) { call->tc_submit_count++; } group->pending_count++; thread_call_wake(group); return (old_queue != NULL); }
/* * thread_call_func: * * Enqueue a function callout. * * Guarantees { function, argument } * uniqueness if unique_call is TRUE. */ void thread_call_func( thread_call_func_t func, thread_call_param_t param, boolean_t unique_call) { thread_call_t call; thread_call_group_t group = &thread_call_group0; spl_t s; s = splsched(); thread_call_lock_spin(); call = TC(queue_first(&group->pending_queue)); while (unique_call && !queue_end(&group->pending_queue, qe(call))) { if ( call->func == func && call->param0 == param ) { break; } call = TC(queue_next(qe(call))); } if (!unique_call || queue_end(&group->pending_queue, qe(call))) { call = _internal_call_allocate(); call->func = func; call->param0 = param; call->param1 = NULL; _pending_call_enqueue(call, group); if (group->active_count == 0) thread_call_wake(group); } thread_call_unlock(); splx(s); }
/* * sched_call_thread: * * Call out invoked by the scheduler. */ static void sched_call_thread( int type, __unused thread_t thread) { thread_call_group_t group = &thread_call_group0; thread_call_lock_spin(); switch (type) { case SCHED_CALL_BLOCK: if (--group->active_count == 0 && group->pending_count > 0) thread_call_wake(group); break; case SCHED_CALL_UNBLOCK: group->active_count++; break; } thread_call_unlock(); }
void thread_call_delayed_timer( timer_call_param_t p0, __unused timer_call_param_t p1 ) { thread_call_t call; thread_call_group_t group = p0; boolean_t new_pending = FALSE; uint64_t timestamp; thread_call_lock_spin(); timestamp = mach_absolute_time(); call = TC(queue_first(&group->delayed_queue)); while (!queue_end(&group->delayed_queue, qe(call))) { if (call->deadline <= timestamp) { _pending_call_enqueue(call, group); new_pending = TRUE; } else break; call = TC(queue_first(&group->delayed_queue)); } if (!queue_end(&group->delayed_queue, qe(call))) _set_delayed_call_timer(call, group); if (new_pending && group->active_count == 0) thread_call_wake(group); thread_call_unlock(); }