Example #1
0
/*!
 * Arm/disarm timer
 * \param timerid	Timer descriptor (user descriptor)
 * \param flags		Various flags
 * \param value		Set timer values (it_value+it_period)
 * \param ovalue	Where to store time to next timer expiration (+period)
 * \return status	0 for success
 */
int sys__timer_settime ( void *p )
{
	timer_t *timerid;
	int flags;
	itimerspec_t *value;
	itimerspec_t *ovalue;

	ktimer_t *ktimer;
	int retval;
	kobject_t *kobj;

	timerid = *( (timer_t **) p );		p += sizeof (timer_t *);
	flags =	  *( (int *) p );		p += sizeof (int);
	value =	  *( (itimerspec_t **) p );	p += sizeof (itimerspec_t *);
	ovalue =  *( (itimerspec_t **) p );

	ASSERT_ERRNO_AND_EXIT ( timerid, EINVAL );
	kobj = timerid->ptr;
	ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL );
	ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ),
				EINVAL );

	ktimer = kobj->kobject;
	ASSERT_ERRNO_AND_EXIT ( ktimer && ktimer->id == timerid->id, EINVAL );

	retval = ktimer_settime ( ktimer, flags, value, ovalue );

	EXIT ( retval );
}
Example #2
0
void ksched_rr_start_timer ()
{
	sigevent_t evp;
	itimerspec_t itimer;
	int retval = 0;

	if ( rr_ktimer )
		return; /* already set */

	evp.sigev_notify = SIGEV_THREAD;
	evp.sigev_value.sival_ptr = NULL;
	evp.sigev_notify_function = ksched_rr_tick;

	retval += ktimer_create ( CLOCK_REALTIME, &evp, &rr_ktimer, NULL );
	ASSERT ( retval == EXIT_SUCCESS );

	TIME_RESET ( &itimer.it_value );
	itimer.it_value.tv_sec = 0;
	itimer.it_value.tv_nsec = SCHED_RR_TICK;
	itimer.it_interval = itimer.it_value;

	retval += ktimer_settime ( rr_ktimer, 0, &itimer, NULL );
	ASSERT ( retval == EXIT_SUCCESS );

}
Example #3
0
/*!
 * Suspend thread until given time elapses
 * \param clockid Clock to use
 * \param flags Flags (TIMER_ABSTIME)
 * \param request Suspend duration
 * \param remain Remainder time if interrupted during suspension
 * \return status
 */
int sys__clock_nanosleep ( void *p )
{
	clockid_t clockid;
	int flags;
	timespec_t *request;
	timespec_t *remain;

	int retval = EXIT_SUCCESS;
	kthread_t *kthread = kthread_get_active ();
	ktimer_t *ktimer;
	sigevent_t evp;
	itimerspec_t itimer;

	clockid =	*( (clockid_t *) p );	p += sizeof (clockid_t);
	flags =		*( (int *) p );		p += sizeof (int);
	request =	*( (timespec_t **) p );	p += sizeof (timespec_t *);
	remain =	*( (timespec_t **) p );

	ASSERT_ERRNO_AND_EXIT (
	    (clockid==CLOCK_REALTIME || clockid==CLOCK_MONOTONIC) &&
	    request && TIME_IS_SET(request),
	    EINVAL
	);

	/* Timers are used for "sleep" operations through steps 1-4 */

	/* 1. create timer, but not arm it yet */
	evp.sigev_notify = SIGEV_WAKE_THREAD;
	evp.sigev_value.sival_ptr = kthread;
	evp.sigev_notify_function = kclock_wake_thread;

	retval += ktimer_create ( clockid, &evp, &ktimer, kthread );
	ASSERT ( retval == EXIT_SUCCESS );

	/* save remainder location, if provided */
	ktimer->param = remain;

	/* 2. suspend thread */
	kthread_set_private_param ( kthread, ktimer );
	retval += kthread_suspend ( kthread, kclock_interrupt_sleep, ktimer );
	ASSERT ( retval == EXIT_SUCCESS );

	/* 3. arm timer */
	TIME_RESET ( &itimer.it_interval );
	itimer.it_value = *request;

	retval += ktimer_settime ( ktimer, flags, &itimer, NULL );
	ASSERT ( retval == EXIT_SUCCESS );

	/* 4. pick other thread as active */
	kthreads_schedule ();

	EXIT ( retval );
}
Example #4
0
static void edf_deadline_alarm ( sigval_t sigev_value )
{
	kthread_t *kthread = sigev_value.sival_ptr, *test;
	kthread_sched2_t *tsched;
	ksched_t *ksched;
	itimerspec_t alarm;

	ASSERT ( kthread );

	ksched = ksched2_get ( kthread_get_sched_policy (kthread) );
	tsched = kthread_get_sched2_param ( kthread );

	test = kthreadq_remove ( &ksched->params.edf.wait, kthread );

	EDF_LOG ( "%x %x [Deadline alarm]", kthread, test );

	if( test == kthread )
	{
		EDF_LOG ( "%x [Waked, but too late]", kthread );

		kthread_set_syscall_retval ( kthread, EXIT_FAILURE );
		kthread_move_to_ready ( kthread, LAST );

		if ( tsched->params.edf.flags & EDF_TERMINATE )
		{
			EDF_LOG ( "%x [EDF_TERMINATE]", kthread );
			ktimer_delete ( tsched->params.edf.period_alarm );
			tsched->params.edf.period_alarm = NULL;
			ktimer_delete ( tsched->params.edf.deadline_alarm );
			tsched->params.edf.deadline_alarm = NULL;
			kthread_set_errno ( kthread, ETIMEDOUT );
			kthread_exit ( kthread, NULL, TRUE );
		}
		else {
			edf_schedule (ksched);
		}
	}
	else {
	/*
	 * thread is not in edf.wait queue, but might be running or its
	 * blocked - it is probable (almost certain) that it missed deadline
	 */
	EDF_LOG ( "%x [Not in edf.wait. Missed deadline?]", kthread );

	if ( edf_check_deadline ( kthread ) )
	{
		/* what to do if its missed? kill thread? */
		if ( tsched->params.edf.flags & EDF_TERMINATE )
		{
			EDF_LOG ( "%x [EDF_TERMINATE]", kthread );
			ktimer_delete (tsched->params.edf.period_alarm);
			tsched->params.edf.period_alarm = NULL;
			ktimer_delete ( tsched->params.edf.deadline_alarm );
			tsched->params.edf.deadline_alarm = NULL;
			kthread_set_errno ( kthread, ETIMEDOUT );
			kthread_exit ( kthread, NULL, TRUE );
		}
		else if ( tsched->params.edf.flags & EDF_CONTINUE )
		{
			/* continue as deadline is not missed */
			EDF_LOG ( "%x [EDF_CONTINUE]", kthread );
		}
		else if ( tsched->params.edf.flags & EDF_SKIP )
		{
			/* skip deadline */
			/* set times for next period */
			EDF_LOG ( "%x [EDF_SKIP]", kthread );

			time_add ( &tsched->params.edf.next_run,
				   &tsched->params.edf.period );

			tsched->params.edf.active_deadline =
					tsched->params.edf.next_run;
			time_add ( &tsched->params.edf.active_deadline,
					&tsched->params.edf.relative_deadline );

			if ( kthread == ksched->params.edf.active )
				ksched->params.edf.active = NULL;

			TIME_RESET ( &alarm.it_interval );
			alarm.it_value = tsched->params.edf.active_deadline;
			ktimer_settime ( tsched->params.edf.deadline_alarm,
					 TIMER_ABSTIME, &alarm, NULL );

			alarm.it_interval = tsched->params.edf.period;
			alarm.it_value = tsched->params.edf.next_run;
			ktimer_settime ( tsched->params.edf.period_alarm,
					 TIMER_ABSTIME, &alarm, NULL );

			kthread_enqueue (kthread, &ksched->params.edf.ready);
			edf_schedule (ksched);
		}
	} /* moved 1 tab left for readability */
	}
}
Example #5
0
static int edf_set_thread_sched_parameters ( ksched_t *ksched,
					     kthread_t *kthread,
					     sched_supp_t *params )
{
	timespec_t now;
	itimerspec_t alarm;
	kthread_sched2_t *tsched = kthread_get_sched2_param ( kthread );

	if ( ksched->params.edf.active == kthread )
		ksched->params.edf.active = NULL;

	kclock_gettime ( CLOCK_REALTIME, &now );

	if ( params->edf.flags & EDF_SET )
	{
		tsched->params.edf.period = params->edf.period;
		tsched->params.edf.relative_deadline = params->edf.deadline;
		tsched->params.edf.flags = params->edf.flags ^ EDF_SET;

		/* create and set periodic alarm */
		edf_create_alarm ( kthread, edf_period_alarm,
				   &tsched->params.edf.period_alarm );
		tsched->params.edf.next_run = now;
		time_add ( &tsched->params.edf.next_run, &params->edf.period );
		alarm.it_interval = tsched->params.edf.period;
		alarm.it_value = tsched->params.edf.next_run;
		ktimer_settime ( tsched->params.edf.period_alarm, TIMER_ABSTIME,
				 &alarm, NULL );

		/* adjust "next_run" and "deadline" for "0" period
		 * first "edf_wait" will set correct values for first period */
		tsched->params.edf.next_run = now;
		time_sub ( &tsched->params.edf.next_run, &params->edf.period );

		/* create and set deadline alarm */
		edf_create_alarm ( kthread, edf_deadline_alarm,
				   &tsched->params.edf.deadline_alarm );
		tsched->params.edf.active_deadline = now;
		time_add ( &tsched->params.edf.active_deadline,
			   &params->edf.deadline );
		TIME_RESET ( &alarm.it_interval );
		alarm.it_value = tsched->params.edf.active_deadline;
		ktimer_settime ( tsched->params.edf.deadline_alarm,
				 TIMER_ABSTIME, &alarm, NULL );

		/* move thread to edf scheduler */
		kthread_enqueue ( kthread, &ksched->params.edf.ready );
		edf_schedule (ksched);
	}
	else if ( params->edf.flags & EDF_WAIT )
	{
		if ( edf_check_deadline ( kthread ) )
			return EXIT_FAILURE;

		/* set times for next period */
		if ( time_cmp ( &now, &tsched->params.edf.next_run ) > 0 )
		{
			time_add ( &tsched->params.edf.next_run,
				   &tsched->params.edf.period );

			tsched->params.edf.active_deadline =
				tsched->params.edf.next_run;
			time_add ( &tsched->params.edf.active_deadline,
				   &tsched->params.edf.relative_deadline );

			if ( kthread == ksched->params.edf.active )
				ksched->params.edf.active = NULL;

			/* set (separate) alarm for deadline
			 * (periodic alarm is set only once as periodic) */

			TIME_RESET ( &alarm.it_interval );
			alarm.it_value = tsched->params.edf.active_deadline;
			ktimer_settime ( tsched->params.edf.deadline_alarm,
					 TIMER_ABSTIME, &alarm, NULL );
		}

		/* is task ready for execution, or must wait until next period*/
		if ( time_cmp ( &tsched->params.edf.next_run, &now ) > 0 )
		{
			/* wait till "next_run" */
			EDF_LOG ( "%x [EDF WAIT]", kthread );
			kthread_enqueue ( kthread, &ksched->params.edf.wait );
			edf_schedule (ksched);
		}
		else {
			/* "next_run" has already come,
			 * activate task => move it to "EDF ready tasks"
			 */
			EDF_LOG ( "%x [EDF READY]", kthread );
			kthread_enqueue ( kthread, &ksched->params.edf.ready );
			edf_schedule (ksched);
		}
	}
	else if ( params->edf.flags & EDF_EXIT )
	{
		if ( kthread == ksched->params.edf.active )
			ksched->params.edf.active = NULL;

		if ( edf_check_deadline ( kthread ) )
		{
			EDF_LOG ( "%x [EXIT-error]", kthread );
			return EXIT_FAILURE;
		}

		EDF_LOG ( "%x [EXIT-normal]", kthread );

		if ( tsched->params.edf.period_alarm )
		{
			/* disarm timer */
			TIME_RESET ( &alarm.it_interval );
			TIME_RESET ( &alarm.it_value );
			ktimer_settime ( tsched->params.edf.period_alarm, 0,
					 &alarm, NULL );
		}

		if ( tsched->params.edf.deadline_alarm )
		{
			/* disarm timer */
			TIME_RESET ( &alarm.it_interval );
			TIME_RESET ( &alarm.it_value );
			ktimer_settime ( tsched->params.edf.deadline_alarm, 0,
					 &alarm, NULL );
		}

		kthread_setschedparam ( kthread, SCHED_FIFO, NULL );
	}

	return 0;
}