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; } }
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; } }
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; }