Esempio n. 1
0
/*! Cancel sleep
 *  - handle return values and errno;
 *  - thread must be handled elsewhere - with source of interrupt (signal?)
 */
static void kclock_interrupt_sleep ( kthread_t *kthread, void *param )
{
	ktimer_t *ktimer;
	timespec_t *remain;
	itimerspec_t irem;

	ASSERT ( kthread && param );
	ASSERT ( kthread_check_kthread ( kthread ) ); /* is this valid thread */
	ASSERT ( kthread_is_suspended ( kthread, NULL, NULL ) );

	ktimer = param;
	remain = ktimer->param;

	if ( remain )
	{
		/* save remaining time */
		timespec_t now;
		kclock_gettime ( CLOCK_REALTIME, &now );
		ktimer_gettime ( ktimer, &irem );
		*remain = irem.it_value;
		time_sub ( remain, &now );
	}

	ktimer_delete (ktimer);

	kthread_set_syscall_retval ( kthread, EXIT_FAILURE );
	kthread_set_errno ( kthread, EINTR );
}
Esempio n. 2
0
/*!
 * Get timer expiration time
 * \param ktimer	Timer
 * \param value		Where to store time to next timer expiration (+period)
 * \return status	0 for success
 */
int ktimer_gettime ( ktimer_t *ktimer, itimerspec_t *value )
{
	ASSERT( ktimer && value );
	timespec_t now;

	kclock_gettime ( ktimer->clockid, &now );

	*value = ktimer->itimer;

	/* return relative time to timer expiration */
	if ( TIME_IS_SET ( &value->it_value ) )
		time_sub ( &value->it_value, &now );

	return EXIT_SUCCESS;
}
Esempio n. 3
0
File: time.c Progetto: l30nard0/Benu
/*!
 * Get current time
 * \param clockid Clock to use
 * \param time Pointer where to store time
 * \return status (0 if successful, -1 otherwise)
 */
int sys__clock_gettime ( clockid_t clockid, timespec_t *time )
{
	int retval;

	SYS_ENTRY();

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

	retval = kclock_gettime ( clockid, time );

	SYS_EXIT ( retval, retval );
}
Esempio n. 4
0
/*! Check if task hasn't overrun its deadline */
static int edf_check_deadline ( kthread_t *kthread )
{
	/* Check if "now" is greater than "active_deadline" */
	timespec_t now;
	kthread_sched2_t *tsched = kthread_get_sched2_param ( kthread );

	kclock_gettime ( CLOCK_REALTIME, &now );

	if ( time_cmp ( &now, &tsched->params.edf.active_deadline ) > 0 )
	{
		EDF_LOG ( "%x [DEADLINE OVERRUN]", kthread );
		return EXIT_FAILURE;
	}

	return 0;
}
Esempio n. 5
0
/*!
 * Get current time
 * \param clockid Clock to use
 * \param time Pointer where to store time
 * \return status (0 if successful, -1 otherwise)
 */
int sys__clock_gettime ( void *p )
{
	clockid_t clockid;
	timespec_t *time;

	int retval;

	clockid = *( (clockid_t *) p );	p += sizeof (clockid_t);
	time = *( (void **) p );

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

	retval = kclock_gettime ( clockid, time );

	EXIT ( retval );
}
Esempio n. 6
0
/*!
 * Arm/disarm timer
 * \param ktimer	Timer
 * \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 ktimer_settime ( ktimer_t *ktimer, int flags, itimerspec_t *value,
		     itimerspec_t *ovalue )
{
	timespec_t now;

	ASSERT ( ktimer );

	kclock_gettime ( ktimer->clockid, &now );

	if ( ovalue )
	{
		*ovalue = ktimer->itimer;

		/* return relative time to timer expiration */
		if ( TIME_IS_SET ( &ovalue->it_value ) )
			time_sub ( &ovalue->it_value, &now );
	}

	/* first disarm timer, if it was armed */
	if ( TIMER_IS_ARMED ( ktimer ) )
	{
		TIMER_DISARM ( ktimer );
		list_remove ( &ktimers, 0, &ktimer->list );
	}

	if ( value && TIME_IS_SET ( &value->it_value ) )
	{
		/* arm timer */
		ktimer->itimer = *value;
		if ( !(flags & TIMER_ABSTIME) ) /* convert to absolute time */
			time_add ( &ktimer->itimer.it_value, &now );

		list_sort_add ( &ktimers, ktimer, &ktimer->list, ktimer_cmp );
	}

	ktimer_schedule ();

	return EXIT_SUCCESS;
}
Esempio n. 7
0
/*! Activate timers and reschedule threads if required */
static void ktimer_schedule ()
{
	ktimer_t *first;
	timespec_t time, ref_time;
	int resched = 0;

	kclock_gettime ( CLOCK_REALTIME, &time );
	/* should have separate "scheduler" for each clock */

	ref_time = time;
	time_add ( &ref_time, &threshold );
	/* use "ref_time" instead of "time" when looking timers to activate */

	/* should any timer be activated? */
	first = list_get ( &ktimers, FIRST );
	while ( first != NULL )
	{
		/* timers have absolute values in 'it_value' */
		if ( time_cmp ( &first->itimer.it_value, &ref_time ) <= 0 )
		{
			/* 'activate' timer */

			/* but first remove timer from list */
			first = list_remove ( &ktimers, FIRST, NULL );

			/* and add to list if period is given */
			if ( TIME_IS_SET ( &first->itimer.it_interval) )
			{
				/* calculate next activation time */
				time_add ( &first->itimer.it_value,
					   &first->itimer.it_interval );
				/* put back into list */
				list_sort_add ( &ktimers, first,
						&first->list, ktimer_cmp );
			}
			else {
				TIMER_DISARM ( first );
			}

			if ( first->owner == NULL )
			{
				/* timer set by kernel - call now, directly */
				if ( first->evp.sigev_notify_function )
					first->evp.sigev_notify_function (
						first->evp.sigev_value
					);
			}
			else {
				/* timer set by thread */
				if ( !ksignal_process_event (
					&first->evp, first->owner, SI_TIMER ) )
				{
					resched++;
				}
			}

			first = list_get ( &ktimers, FIRST );
		}
		else {
			break;
		}
	}

	first = list_get ( &ktimers, FIRST );
	if ( first )
	{
		ref_time = first->itimer.it_value;
		time_sub ( &ref_time, &time );
		arch_timer_set ( &ref_time, ktimer_schedule );
	}

	if ( resched )
		kthreads_schedule ();
}
Esempio n. 8
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;
}