Ejemplo n.º 1
0
/*!
 * Deactivate thread because:
 * 1. higher priority thread becomes active
 * 2. this thread time slice is expired
 * 3. this thread blocks on some queue
 */
static int rr_thread_deactivate ( kthread_t *kthread )
{
	/* Get current time and recalculate remainder */
	time_t t;
	kthread_sched_data_t *tsched = kthread_get_sched_param ( kthread );
	ksched_t *gsched = ksched_get ( tsched->sched_policy );

	if (tsched->params.rr.remainder.sec + tsched->params.rr.remainder.nsec)
	{
		/*
		 * "slice interrupted"
		 * recalculate remainder
		 */
		k_get_time ( &t );
		time_sub ( &tsched->params.rr.slice_end, &t );
		tsched->params.rr.remainder = tsched->params.rr.slice_end;

		if ( kthread_is_ready ( kthread ) )
		{
			/* is remainder too small or not? */
			if ( time_cmp ( &tsched->params.rr.remainder,
				&gsched->params.rr.threshold ) <= 0 )
			{
				kthread_move_to_ready ( kthread, LAST );
			}
			else {
				kthread_move_to_ready ( kthread, FIRST );
			}
		}
	}
	/* else = remainder is zero, thread is already enqueued in ready queue*/

	return 0;
}
Ejemplo n.º 2
0
/*! Start time slice for thread (or countinue interrupted) */
static int rr_thread_activate ( kthread_t *kthread )
{
	kthread_sched_data_t *tsched = kthread_get_sched_param ( kthread );
	ksched_t *gsched = ksched_get ( tsched->sched_policy );

	/* check remainder if needs to be replenished */
	if ( time_cmp ( &tsched->params.rr.remainder,
		&gsched->params.rr.threshold ) <= 0 )
	{
		time_add ( &tsched->params.rr.remainder,
			   &gsched->params.rr.time_slice );
	}

	/* Get current time and store it */
	k_get_time ( &tsched->params.rr.slice_start );

	/* When to wake up? */
	tsched->params.rr.slice_end = tsched->params.rr.slice_start;
	time_add ( &tsched->params.rr.slice_end, &tsched->params.rr.remainder );

	/* Set alarm for remainder time */
	gsched->params.rr.alarm.exp_time = tsched->params.rr.slice_end;
	gsched->params.rr.alarm.param = kthread;

	k_alarm_set ( gsched->params.rr.rr_alarm, &gsched->params.rr.alarm );

	return 0;
}
Ejemplo n.º 3
0
static int edf_thread_add ( kthread_t *kthread )
{
	kthread_sched_data_t *tsched = kthread_get_sched_param ( kthread );

	tsched->params.edf.edf_period_alarm = NULL;

	return 0;
}
Ejemplo n.º 4
0
/*! Add thread to RR scheduler (give him initial time slice) */
static int rr_thread_add ( kthread_t *kthread )
{
	kthread_sched_data_t *tsched = kthread_get_sched_param ( kthread );
	ksched_t *gsched = ksched_get ( tsched->sched_policy );

	tsched->params.rr.remainder = gsched->params.rr.time_slice;

	return 0;
}
Ejemplo n.º 5
0
static int edf_arm_deadline ( kthread_t *kthread )
{
	kthread_sched_data_t *tsched = kthread_get_sched_param ( kthread );
	alarm_t alarm;
	
	alarm.action = edf_deadline_timer;
	alarm.param = kthread;
	alarm.flags = 0;
	alarm.period.sec = alarm.period.nsec = 0;
	alarm.exp_time.sec = alarm.exp_time.nsec = 0;

	return k_alarm_new (	&tsched->params.edf.edf_deadline_alarm,
				&alarm,
				KERNELCALL );
}
Ejemplo n.º 6
0
static int edf_arm_period ( kthread_t *kthread )
{
	kthread_sched_data_t *tsched = kthread_get_sched_param ( kthread );
	alarm_t alarm;


	alarm.action = edf_period_timer;
	alarm.param = kthread;
	alarm.flags = ALARM_PERIODIC;
	alarm.period = tsched->params.edf.period;
	alarm.exp_time = tsched->params.edf.next_run;

	return k_alarm_new (	&tsched->params.edf.edf_period_alarm,
				&alarm,
				KERNELCALL );
}
Ejemplo n.º 7
0
/*!
 * Check if task hasn't overrun its deadline at its start
 * Handle deadline overrun, based on flags
 */
static int edf_check_deadline ( kthread_t *kthread )
{
	/* 
	 * Check if "now" is greater than "active_deadline"
	 */

	time_t now;
	kthread_sched_data_t *tsched = kthread_get_sched_param ( kthread );

	k_get_time ( &now );

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

	return 0;
}
Ejemplo n.º 8
0
static int edf_thread_remove ( kthread_t *kthread )
{
	kthread_sched_data_t *tsched = kthread_get_sched_param ( kthread );
	ksched_t *gsched = ksched_get ( tsched->sched_policy );

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

	if ( tsched->params.edf.edf_period_alarm )
	{
		k_alarm_remove ( tsched->params.edf.edf_period_alarm );
		tsched->params.edf.edf_period_alarm = NULL;
	}

	tsched->sched_policy = SCHED_FIFO;

	k_edf_schedule ();

	return 0;
}
Ejemplo n.º 9
0
/*! Timer interrupt for Round Robin */
static void rr_timer ( void *p )
{
	kthread_t *kthread = p;
	kthread_sched_data_t *tsched;

	if ( kthread_get_active () != kthread )
	{
		/* bug or rr thread got canceled! Let asume second :) */
		return;
	}

	tsched = kthread_get_sched_param ( kthread );

	/* given time is elapsed, set remainder to zero */
	tsched->params.rr.remainder.sec = tsched->params.rr.remainder.nsec = 0;

	/* move thread to ready queue - as last in coresponding queue */
	kthread_move_to_ready ( kthread, LAST );

	kthreads_schedule ();
}
Ejemplo n.º 10
0
static void edf_deadline_timer ( void *p )
{
	alarm_t alarm;
	kthread_t *kthread = p, *test;
	kthread_sched_data_t *tsched  = kthread_get_sched_param ( kthread );


	ASSERT ( kthread );

	test = kthreadq_remove ( &ksched_edf.params.edf.wait, kthread );

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

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

			kthread_set_syscall_retval ( kthread, -1 );
			kthread_move_to_ready ( kthread, LAST );

			if ( tsched->params.edf.flags & EDF_TERMINATE )
			{
				LOG( DEBUG, "%x [EDF_TERMINATE]", kthread );
				tsched = kthread_get_sched_param ( kthread );
				k_alarm_remove ( tsched->params.edf.edf_period_alarm );
				k_alarm_remove ( tsched->params.edf.edf_deadline_alarm );
				tsched->params.edf.edf_period_alarm = NULL;
				kthread_cancel ( kthread, -E_DEADLINE );
			}

			kthreads_schedule ();
		}
	}
	else {
		/*
		 * thread is not in edf.wait queue, but might be running or its
		 * blocked - it is probable (sure?) it missed deadline
		 */
		LOG( DEBUG, "%x [Not in edf.wait. Missed deadline?]", kthread );

		if ( edf_check_deadline ( kthread ) )
		{
			/* what to do if its missed? kill thread? */
			tsched = kthread_get_sched_param ( kthread );
			if ( tsched->params.edf.flags & EDF_TERMINATE )
			{
				LOG( DEBUG, "%x [EDF_TERMINATE]", kthread );
				k_alarm_remove ( tsched->params.edf.edf_period_alarm );
				k_alarm_remove ( tsched->params.edf.edf_deadline_alarm );
				tsched->params.edf.edf_period_alarm = NULL;
				kthread_cancel ( kthread, -E_DEADLINE );
			}
			else if ( tsched->params.edf.flags & EDF_CONTINUE )
			{
				/* continue as deadline is not missed */
				LOG( DEBUG, "%x [EDF_CONTINUE]", kthread );
			}
			else if ( tsched->params.edf.flags & EDF_SKIP )
			{
				/* skip deadline */
				/* set times for next period */
				LOG( DEBUG, "%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_edf.params.edf.active )
					ksched_edf.params.edf.active = NULL;

				alarm.action = edf_deadline_timer;
				alarm.param = kthread;
				alarm.flags = 0;
				alarm.period.sec = alarm.period.nsec = 0;
				alarm.exp_time = tsched->params.edf.active_deadline;

				k_alarm_set ( tsched->params.edf.edf_deadline_alarm, &alarm );

				alarm.action = edf_period_timer;
				alarm.param = kthread;
				alarm.flags = ALARM_PERIODIC;
				alarm.period = tsched->params.edf.period;
				alarm.exp_time = tsched->params.edf.next_run;

				k_alarm_set ( tsched->params.edf.edf_period_alarm, &alarm );

				kthread_enqueue ( kthread, &ksched_edf.params.edf.ready );
				kthreads_schedule (); /* will call edf_schedule() */
			}
		}
	}
}
Ejemplo n.º 11
0
static int k_edf_schedule ()
{
	kthread_t *first, *next, *edf_active;
	kthread_sched_data_t *sch_first, *sch_next;
	ksched_t *gsched = ksched_get ( SCHED_EDF );
	int retval = 0;

	edf_active = gsched->params.edf.active;
	first = kthreadq_get ( &gsched->params.edf.ready );

	LOG( DEBUG, "%x [active]", edf_active );
	LOG( DEBUG, "%x [first]", first );
	//LOG( DEBUG, "%x [next]", next );

	if ( !first )
		return 0; /* no threads in edf.ready queue, edf.active unch. */

	if ( edf_active )
	{
		next = first;
		first = edf_active;
		LOG( DEBUG, "%x [next]", kthreadq_get_next ( next ) );
	}
	else {
		next = kthreadq_get_next ( first );
		LOG( DEBUG, "%x [next]", next );
	}

	while ( first && next )
	{

		sch_first = kthread_get_sched_param ( first );
		sch_next = kthread_get_sched_param ( next );

		if ( time_cmp ( &sch_first->params.edf.active_deadline,
			&sch_next->params.edf.active_deadline ) > 0 )
		{
			first = next;
		}

		next = kthreadq_get_next ( next );
	}

	if ( first && first != edf_active )
	{
		next = kthreadq_remove ( &gsched->params.edf.ready, first );
		LOG ( DEBUG, "%x removed, %x is now first", next, kthreadq_get ( &gsched->params.edf.ready ) );

		if ( edf_active )
		{
			LOG( DEBUG, "%x=>%x [EDF_SCHED_PREEMPT]",
			     edf_active, first );

			/*
			 * change active EDF thread:
			 * -remove it from active/ready list
			 * -put it into edf.ready list
			 */
			if ( kthread_is_ready (edf_active) )
			{
				if ( !kthread_is_active (edf_active) )
				{
					kthread_remove_from_ready (edf_active);

					/*
					 * set "deactivated" flag, don't need
					 * another call to "edf_schedule"
					 */
				}
				else {
					kthread_get_sched_param (edf_active)
						->activated = 0;
				}

				kthread_enqueue ( edf_active,
						  &gsched->params.edf.ready );
			}
			/* else = thread is blocked - leave it there */
		}

		gsched->params.edf.active = first;
		LOG( DEBUG, "%x [new active]", first );

		kthread_move_to_ready ( first, LAST );
		retval = 1;
	}

	return retval;
}
Ejemplo n.º 12
0
static int edf_set_thread_sched_parameters (kthread_t *kthread, sched_t *params)
{
	time_t now;
	alarm_t alarm;
	kthread_sched_data_t *tsched = kthread_get_sched_param ( kthread );
	ksched_t *gsched = ksched_get ( SCHED_EDF );


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

	k_get_time ( &now );

	if ( params->edf.flags & EDF_SET )
	{
		/*LOG( DEBUG, "%x [SET]", kthread ); */
		tsched->params.edf.period = params->edf.period;
		tsched->params.edf.relative_deadline = params->edf.deadline;
		tsched->params.edf.flags = params->edf.flags;

		/* set periodic alarm */
		tsched->params.edf.next_run = now;
		time_add ( &tsched->params.edf.next_run, &params->edf.period );
		edf_arm_deadline ( kthread );
		edf_arm_period ( kthread );

		/*
		 * 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 );

		tsched->params.edf.active_deadline = now;
		time_add ( &tsched->params.edf.active_deadline,
			   &params->edf.deadline );
	}
	else if ( params->edf.flags & EDF_WAIT )
	{
		if ( edf_check_deadline ( kthread ) )
			return -1;

		/* 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 == gsched->params.edf.active )
				gsched->params.edf.active = NULL;

			/* set (separate) alarm for deadline */

			alarm.action = edf_deadline_timer;
			alarm.param = kthread;
			alarm.flags = 0;
			alarm.period.sec = alarm.period.nsec = 0;
			alarm.exp_time = tsched->params.edf.active_deadline;

			k_alarm_set ( tsched->params.edf.edf_deadline_alarm, &alarm );

		}

		/* 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" */
			LOG( DEBUG, "%x [EDF WAIT]", kthread );
			kthread_enqueue ( kthread, &gsched->params.edf.wait );
			kthreads_schedule (); /* will call edf_schedule() */
		}
		else {
			/* "next_run" has already come,
			 * activate task => move it to "EDF ready tasks"
			 */
			LOG( DEBUG, "%x [EDF READY]", kthread );
			LOG( DEBUG, "%x [1st READY]", kthreadq_get ( &gsched->params.edf.ready ) );
			kthread_enqueue ( kthread, &gsched->params.edf.ready );
			kthreads_schedule (); /* will call edf_schedule() */
		}
	}
	else if ( params->edf.flags & EDF_EXIT )
	{
		if ( kthread == gsched->params.edf.active )
			gsched->params.edf.active = NULL;

		//LOG( DEBUG, "%x [EXIT]", kthread );
		if ( edf_check_deadline ( kthread ) )
		{
			LOG( DEBUG, "%x [EXIT-error]", kthread );
			return -1;
		}

		LOG( DEBUG, "%x [EXIT-normal]", kthread );
		if ( tsched->params.edf.edf_period_alarm )
			k_alarm_remove ( tsched->params.edf.edf_period_alarm );

		if ( tsched->params.edf.edf_deadline_alarm )
			k_alarm_remove ( tsched->params.edf.edf_deadline_alarm );

		tsched->sched_policy = SCHED_FIFO;

		LOG( DEBUG, "%x [EXIT]", kthread );
		if ( k_edf_schedule () )
		{
			LOG( DEBUG, "%x [EXIT]", kthread );

			kthreads_schedule (); /* will NOT call edf_schedule() */
		}

		LOG( DEBUG, "%x [EXIT]", kthread );
	}

	return 0;
}