Пример #1
0
static int rtswitch_create_ktask(rtswitch_context_t *ctx,
                                 struct rttst_swtest_task *ptask)
{
	rtswitch_task_t *task;
	xnflags_t init_flags;
	struct taskarg arg;
	char name[30];
	int err;

	ptask->flags |= RTSWITCH_KERNEL;
	err = rtswitch_register_task(ctx, ptask);

	if (err)
		return err;

	snprintf(name, sizeof(name), "rtk%d/%u", ptask->index, ctx->cpu);

	task = &ctx->tasks[ptask->index];

	arg.ctx = ctx;
	arg.task = task;

	init_flags = (ptask->flags & RTTST_SWTEST_FPU) ? XNFPU : 0;

	/* Migrate the calling thread to the same CPU as the created task, in
	   order to be sure that the created task is suspended when this function
	   returns. This also allow us to use the stack to pass the parameters to
	   the created task. */
	set_cpus_allowed(current, cpumask_of_cpu(ctx->cpu));

	err = xnpod_init_thread(&task->ktask, rtdm_tbase, name, 1, init_flags, 0, NULL);

	if (!err)
		err = xnpod_start_thread(&task->ktask,
					 0,
					 0,
					 xnarch_cpumask_of_cpu(ctx->cpu),
					 rtswitch_ktask,
					 &arg);
	else
		/* In order to avoid calling xnpod_delete_thread with invalid
		   thread. */
		task->base.flags = 0;

	/* Putting the argument on stack is safe, because the new thread will
	   preempt the current thread immediately, and will suspend only once the
	   arguments on stack are used. */

	return err;
}
Пример #2
0
static int rtswitch_ioctl_nrt(struct rtdm_dev_context *context,
                              rtdm_user_info_t *user_info,
                              unsigned int request,
                              void *arg)
{
	rtswitch_context_t *ctx = (rtswitch_context_t *) context->dev_private;
	struct rttst_swtest_task task;
	struct rttst_swtest_dir fromto;
	unsigned long count;
	int err;

	switch (request)
		{
		case RTTST_RTIOC_SWTEST_SET_TASKS_COUNT:
			return rtswitch_set_tasks_count(ctx,
							(unsigned long) arg);

		case RTTST_RTIOC_SWTEST_SET_CPU:
			if ((unsigned long) arg > xnarch_num_online_cpus() - 1)
				return -EINVAL;

			ctx->cpu = (unsigned long) arg;
			return 0;

		case RTTST_RTIOC_SWTEST_SET_PAUSE:
			ctx->pause_us = (unsigned long) arg;
			return 0;

		case RTTST_RTIOC_SWTEST_REGISTER_UTASK:
			if (!rtdm_rw_user_ok(user_info, arg, sizeof(task)))
				return -EFAULT;

			rtdm_copy_from_user(user_info, &task, arg, sizeof(task));

			err = rtswitch_register_task(ctx, &task);

			if (!err)
				rtdm_copy_to_user(user_info,
						  arg,
						  &task,
						  sizeof(task));

			return err;

		case RTTST_RTIOC_SWTEST_CREATE_KTASK:
			if (!rtdm_rw_user_ok(user_info, arg, sizeof(task)))
				return -EFAULT;

			rtdm_copy_from_user(user_info, &task, arg, sizeof(task));

			err = rtswitch_create_ktask(ctx, &task);

			if (!err)
				rtdm_copy_to_user(user_info,
						  arg,
						  &task,
						  sizeof(task));

			return err;

		case RTTST_RTIOC_SWTEST_PEND:
			if (!rtdm_read_user_ok(user_info, arg, sizeof(task)))
				return -EFAULT;

			rtdm_copy_from_user(user_info, &task, arg, sizeof(task));

			return rtswitch_pend_nrt(ctx, task.index);

		case RTTST_RTIOC_SWTEST_SWITCH_TO:
			if (!rtdm_read_user_ok(user_info, arg, sizeof(fromto)))
				return -EFAULT;

			rtdm_copy_from_user(user_info,
					    &fromto,
					    arg,
					    sizeof(fromto));

			return rtswitch_to_nrt(ctx, fromto.from, fromto.to);

		case RTTST_RTIOC_SWTEST_GET_SWITCHES_COUNT:
			if (!rtdm_rw_user_ok(user_info, arg, sizeof(count)))
				return -EFAULT;

			count = ctx->switches_count;

			rtdm_copy_to_user(user_info, arg, &count, sizeof(count));

			return 0;

		case RTTST_RTIOC_SWTEST_GET_LAST_ERROR:
			if (!rtdm_rw_user_ok(user_info, arg, sizeof(ctx->error)))
				return -EFAULT;

			rtdm_copy_to_user(user_info,
					  arg,
					  &ctx->error,
					  sizeof(ctx->error));

			return 0;

		default:
			return -ENOTTY;
		}
}
Пример #3
0
static int rtswitch_create_ktask(rtswitch_context_t *ctx,
				 struct rttst_swtest_task *ptask)
{
	union xnsched_policy_param param;
	struct xnthread_start_attr sattr;
	struct xnthread_init_attr iattr;
	rtswitch_task_t *task;
	xnflags_t init_flags;
	struct taskarg arg;
	char name[30];
	int err;

	/*
	 * Silently disable FP tests in kernel if FPU is not supported
	 * there. Typical case is math emulation support: we can use
	 * it from userland as a synthetic FPU, but there is no sane
	 * way to use it from kernel-based threads (Xenomai or Linux).
	 */
	if (!fp_kernel_supported())
		ptask->flags &= ~RTTST_SWTEST_USE_FPU;
		
	ptask->flags |= RTSWITCH_KERNEL;
	err = rtswitch_register_task(ctx, ptask);

	if (err)
		return err;

	snprintf(name, sizeof(name), "rtk%d/%u", ptask->index, ctx->cpu);

	task = &ctx->tasks[ptask->index];

	arg.ctx = ctx;
	arg.task = task;

	init_flags = (ptask->flags & RTTST_SWTEST_FPU) ? XNFPU : 0;

	/*
	 * Migrate the calling thread to the same CPU as the created
	 * task, in order to be sure that the created task is
	 * suspended when this function returns. This also allow us to
	 * use the stack to pass the parameters to the created
	 * task.
	 */
	set_cpus_allowed(current, cpumask_of_cpu(ctx->cpu));

	iattr.tbase = rtdm_tbase;
	iattr.name = name;
	iattr.flags = init_flags;
	iattr.ops = NULL;
	iattr.stacksize = 0;
	param.rt.prio = 1;

	err = xnpod_init_thread(&task->ktask,
				&iattr, &xnsched_class_rt, &param);
	if (!err) {
		sattr.mode = 0;
		sattr.imask = 0;
		sattr.affinity = xnarch_cpumask_of_cpu(ctx->cpu);
		sattr.entry = rtswitch_ktask;
		sattr.cookie = &arg;
		err = xnpod_start_thread(&task->ktask, &sattr);
	} else
		/*
		 * In order to avoid calling xnpod_delete_thread with
		 * invalid thread.
		 */
		task->base.flags = 0;
	/*
	 * Putting the argument on stack is safe, because the new
	 * thread will preempt the current thread immediately, and
	 * will suspend only once the arguments on stack are used.
	 */

	return err;
}