コード例 #1
0
ファイル: sched_edf.c プロジェクト: mi44099/diplomski_rad
/*! Timer interrupt for edf */
static void edf_period_timer ( void *p )
{
	kthread_t *kthread = p, *test;

	ASSERT ( kthread );

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

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

	if( test == kthread )
	{
		if ( !edf_check_deadline ( kthread ) )
		{
			//LOG( DEBUG, "%x [Waked, moved to edf.ready]", kthread );
			kthread_enqueue ( kthread, &ksched_edf.params.edf.ready );

			if ( k_edf_schedule () )
				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 );
	}
}
コード例 #2
0
ファイル: sched_edf.c プロジェクト: bkolobara/Benu-pi
/*! Timer interrupt for edf */
static void edf_period_alarm ( sigval_t sigev_value )
{
	kthread_t *kthread = sigev_value.sival_ptr, *test;
	ksched_t *ksched;

	ASSERT ( kthread );

	ksched = ksched2_get ( kthread_get_sched_policy (kthread) );

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

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

	if( test == kthread )
	{
		if ( !edf_check_deadline ( kthread ) )
		{
			EDF_LOG ( "%x [Waked, moved to edf.ready]", kthread );
			kthread_enqueue ( kthread, &ksched->params.edf.ready );

			edf_schedule (ksched);
		}
		/* else => missed deadline -- handle with deadline timer */
	}
	else {
		/*
		 * thread is not in edf.wait queue, but might be running or its
		 * blocked - it is probable it missed its deadline, but that
		 * will be handled with different timer
		 */
		EDF_LOG ( "%x [Not in edf.wait. Missed deadline?]", kthread );
	}
}
コード例 #3
0
ファイル: sched_edf.c プロジェクト: mi44099/diplomski_rad
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() */
			}
		}
	}
}
コード例 #4
0
ファイル: sched_edf.c プロジェクト: mi44099/diplomski_rad
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;
}
コード例 #5
0
ファイル: sched_edf.c プロジェクト: bkolobara/Benu-pi
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 */
	}
}
コード例 #6
0
ファイル: sched_edf.c プロジェクト: bkolobara/Benu-pi
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;
}