Example #1
0
static void rtswitch_ktask(void *cookie)
{
	struct taskarg *arg = (struct taskarg *) cookie;
	rtswitch_context_t *ctx = arg->ctx;
	rtswitch_task_t *task = arg->task;
	unsigned to, i = 0;

	to = task->base.index;

	rtswitch_pend_rt(ctx, task->base.index);

	for(;;) {
		if (task->base.flags & RTTST_SWTEST_USE_FPU)
			fp_regs_set(task->base.index + i * 1000);

		switch(i % 3) {
		case 0:
			/* to == from means "return to last task" */
			rtswitch_to_rt(ctx, task->base.index, task->base.index);
			break;
		case 1:
			if (++to == task->base.index)
				++to;
			if (to > ctx->tasks_count - 1)
				to = 0;
			if (to == task->base.index)
				++to;

			/* Fall through. */
		case 2:
			rtswitch_to_rt(ctx, task->base.index, to);
		}

		if (task->base.flags & RTTST_SWTEST_USE_FPU) {
			unsigned fp_val, expected;

			expected = task->base.index + i * 1000;
			fp_val = fp_regs_check(expected);

			if (fp_val != expected) {
				if (task->base.flags & RTTST_SWTEST_FREEZE)
					xntrace_user_freeze(0, 0);
				handle_ktask_error(ctx, fp_val);
			}
		}

		if (++i == 4000000)
			i = 0;
	}
}
Example #2
0
static void rtswitch_ktask(void *cookie)
{
	struct taskarg *arg = (struct taskarg *) cookie;
	rtswitch_context_t *ctx = arg->ctx;
	rtswitch_task_t *task = arg->task;
	unsigned to, i = 0;

	to = task->base.index;

	rtswitch_pend_rt(ctx, task->base.index);

	for(;;) {
		if (++to == task->base.index)
			++to;
		if (to > ctx->tasks_count - 1)
			to = 0;
		if (to == task->base.index)
			++to;

		if (task->base.flags & RTTST_SWTEST_USE_FPU)
			fp_regs_set(task->base.index + i * 1000);
		rtswitch_to_rt(ctx, task->base.index, to);
		if (task->base.flags & RTTST_SWTEST_USE_FPU) {
			unsigned fp_val, expected;

			expected = task->base.index + i * 1000;
			fp_val = fp_regs_check(expected);

			if (fp_val != expected)
				handle_ktask_error(ctx, fp_val);
		}
				
		if (++i == 4000000)
			i = 0;
	}
}
Example #3
0
static int rtswitch_to_nrt(rtswitch_context_t *ctx,
			   unsigned from_idx,
			   unsigned to_idx)
{
	rtswitch_task_t *from, *to;
	unsigned expected, fp_val;
	int fp_check;

	if (from_idx > ctx->tasks_count || to_idx > ctx->tasks_count)
		return -EINVAL;

	/* to == from is a special case which means
	   "return to the previous task". */
	if (to_idx == from_idx)
		to_idx = ctx->error.last_switch.from;

	from = &ctx->tasks[from_idx];
	to = &ctx->tasks[to_idx];

	fp_check = ctx->switches_count == from->last_switch + 1
		&& ctx->error.last_switch.from == to_idx
		&& ctx->error.last_switch.to == from_idx;

	from->base.flags &= ~RTSWITCH_RT;
	from->last_switch = ++ctx->switches_count;
	ctx->error.last_switch.from = from_idx;
	ctx->error.last_switch.to = to_idx;
	barrier();

	if (ctx->pause_us) {
		ctx->next_task = to_idx;
		barrier();
		rtdm_timer_start(&ctx->wake_up_delay,
				 ctx->pause_us * 1000, 0,
				 RTDM_TIMERMODE_RELATIVE);
	} else
		switch (to->base.flags & RTSWITCH_RT) {
		case RTSWITCH_NRT:
		switch_to_nrt:
			up(&to->nrt_synch);
			break;

		case RTSWITCH_RT:

			if (!fp_check || fp_linux_begin() < 0) {
				fp_check = 0;
				goto signal_nofp;
			}

			expected = from_idx + 500 +
				(ctx->switches_count % 4000000) * 1000;

			fp_regs_set(expected);
			rtdm_event_signal(&to->rt_synch);
			fp_val = fp_regs_check(expected);
			fp_linux_end();

			if(down_interruptible(&from->nrt_synch))
				return -EINTR;
			if (ctx->failed)
				return 1;
			if (fp_val != expected) {
				handle_ktask_error(ctx, fp_val);
				return 1;
			}

			from->base.flags &= ~RTSWITCH_RT;
			from->last_switch = ++ctx->switches_count;
			ctx->error.last_switch.from = from_idx;
			ctx->error.last_switch.to = to_idx;
			if ((to->base.flags & RTSWITCH_RT) == RTSWITCH_NRT)
				goto switch_to_nrt;
			expected = from_idx + 500 +
				(ctx->switches_count % 4000000) * 1000;
			barrier();

			fp_linux_begin();
			fp_regs_set(expected);
			rtdm_event_signal(&to->rt_synch);
			fp_val = fp_regs_check(expected);
			fp_linux_end();

			if (down_interruptible(&from->nrt_synch))
				return -EINTR;
			if (ctx->failed)
				return 1;
			if (fp_val != expected) {
				handle_ktask_error(ctx, fp_val);
				return 1;
			}

			from->base.flags &= ~RTSWITCH_RT;
			from->last_switch = ++ctx->switches_count;
			ctx->error.last_switch.from = from_idx;
			ctx->error.last_switch.to = to_idx;
			barrier();
			if ((to->base.flags & RTSWITCH_RT) == RTSWITCH_NRT)
				goto switch_to_nrt;

		signal_nofp:
			rtdm_event_signal(&to->rt_synch);
			break;

		default:
			return -EINVAL;
		}

	if (down_interruptible(&from->nrt_synch))
		return -EINTR;

	if (ctx->failed)
		return 1;

	return 0;
}