Beispiel #1
0
/*
 *	thread_call_func_delayed:
 *
 *	Enqueue a function callout to
 *	occur at the stated time.
 */
void
thread_call_func_delayed(
		thread_call_func_t		func,
		thread_call_param_t		param,
		uint64_t			deadline)
{
	thread_call_t		call;
	thread_call_group_t	group = &thread_call_groups[THREAD_CALL_PRIORITY_HIGH];
	spl_t			s;

	s = splsched();
	thread_call_lock_spin();

	call = _internal_call_allocate();
	call->tc_call.func	= func;
	call->tc_call.param0	= param;
	call->tc_call.param1	= 0;

	_delayed_call_enqueue(call, group, deadline);

	if (queue_first(&group->delayed_queue) == qe(call))
		_set_delayed_call_timer(call, group);

	thread_call_unlock();
	splx(s);
}
Beispiel #2
0
boolean_t
thread_call_enter1_delayed(
		thread_call_t			call,
		thread_call_param_t		param1,
		uint64_t			deadline)
{
	boolean_t		result = TRUE;
	thread_call_group_t	group;
	spl_t			s;

	group = thread_call_get_group(call);

	s = splsched();
	thread_call_lock_spin();

	result = _delayed_call_enqueue(call, group, deadline);

	if (queue_first(&group->delayed_queue) == qe(call))
		_set_delayed_call_timer(call, group);

	call->tc_call.param1 = param1;

	thread_call_unlock();
	splx(s);

	return (result);
}
void
timer_call_shutdown(
	processor_t			processor)
{
	timer_call_t		call;
	queue_t				queue, myqueue;

	assert(processor != current_processor());

	queue = &PROCESSOR_DATA(processor, timer_call_queue);
	myqueue = &PROCESSOR_DATA(current_processor(), timer_call_queue);

	simple_lock(&timer_call_lock);

	call = TC(queue_first(queue));

	while (!queue_end(queue, qe(call))) {
		_delayed_call_dequeue(call);

		_delayed_call_enqueue(myqueue, call);

		call = TC(queue_first(queue));
	}

	call = TC(queue_first(myqueue));

	if (!queue_end(myqueue, qe(call)))
		_set_delayed_call_timer(call);

	simple_unlock(&timer_call_lock);
}
Beispiel #4
0
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;
	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->tc_call.deadline <= timestamp) {
			_pending_call_enqueue(call, group);
		}
		else
			break;

		call = TC(queue_first(&group->delayed_queue));
	}

	if (!queue_end(&group->delayed_queue, qe(call)))
		_set_delayed_call_timer(call, group);

	thread_call_unlock();
}
boolean_t
timer_call_cancel(
	timer_call_t			call)
{
	boolean_t		result = TRUE;
	spl_t			s;

	s = splclock();
	simple_lock(&timer_call_lock);

	if (call->state == DELAYED) {
		queue_t			queue = &PROCESSOR_DATA(current_processor(), timer_call_queue);

		if (queue_first(queue) == qe(call)) {
			_delayed_call_dequeue(call);

			if (!queue_empty(queue))
				_set_delayed_call_timer((timer_call_t)queue_first(queue));
		}
		else
			_delayed_call_dequeue(call);
	}
	else
		result = FALSE;

	simple_unlock(&timer_call_lock);
	splx(s);

	return (result);
}
boolean_t
timer_call_enter1(
	timer_call_t			call,
	timer_call_param_t		param1,
	uint64_t				deadline)
{
	boolean_t		result = TRUE;
	queue_t			queue;
	spl_t			s;

	s = splclock();
	simple_lock(&timer_call_lock);

	if (call->state == DELAYED)
		_delayed_call_dequeue(call);
	else
		result = FALSE;

	call->param1	= param1;
	call->deadline	= deadline;

	queue = &PROCESSOR_DATA(current_processor(), timer_call_queue);

	_delayed_call_enqueue(queue, call);

	if (queue_first(queue) == qe(call))
		_set_delayed_call_timer(call);

	simple_unlock(&timer_call_lock);
	splx(s);

	return (result);
}
Beispiel #7
0
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();
}
Beispiel #8
0
/*
 *	thread_call_enter_delayed:
 *
 *	Enqueue a callout entry to occur
 *	at the stated time.
 *
 *	Returns TRUE if the call was
 *	already on a queue.
 */
boolean_t
thread_call_enter_delayed(
    thread_call_t		call,
    uint64_t			deadline)
{
	boolean_t				result = TRUE;
	thread_call_group_t		group = &thread_call_group0;
	spl_t					s;

	s = splsched();
	thread_call_lock_spin();

	result = _delayed_call_enqueue(call, group, deadline);

	if (queue_first(&group->delayed_queue) == qe(call))
		_set_delayed_call_timer(call, group);

	call->param1 = 0;

	thread_call_unlock();
	splx(s);

	return (result);
}
static void
timer_call_interrupt(uint64_t timestamp)
{
	timer_call_t		call;
	queue_t				queue;

	simple_lock(&timer_call_lock);

	queue = &PROCESSOR_DATA(current_processor(), timer_call_queue);

	call = TC(queue_first(queue));

	while (!queue_end(queue, qe(call))) {
		if (call->deadline <= timestamp) {
			timer_call_func_t		func;
			timer_call_param_t		param0, param1;

			_delayed_call_dequeue(call);

			func = call->func;
			param0 = call->param0;
			param1 = call->param1;

			simple_unlock(&timer_call_lock);

			KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI,
							   2)
							| DBG_FUNC_START,
					      (unsigned int)func,
					      (unsigned int)param0,
					      (unsigned int)param1, 0, 0);

#if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
			DTRACE_TMR3(callout__start, timer_call_func_t, func, 
										timer_call_param_t, param0, 
										timer_call_param_t, param1);
#endif

			(*func)(param0, param1);

#if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
			DTRACE_TMR3(callout__end, timer_call_func_t, func, 
										timer_call_param_t, param0, 
										timer_call_param_t, param1);
#endif

			KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI,
							   2)
							| DBG_FUNC_END,
					      (unsigned int)func,
					      (unsigned int)param0,
					      (unsigned int)param1, 0, 0);

			simple_lock(&timer_call_lock);
		} else
			break;

		call = TC(queue_first(queue));
	}

	if (!queue_end(queue, qe(call)))
		_set_delayed_call_timer(call);

	simple_unlock(&timer_call_lock);
}