int rt_task_init(RT_TASK *task, void (*body) (int), int cookie, int stack_size, int priority, int uses_fpu, void (*sigfn) (void)) { union xnsched_policy_param param; struct xnthread_start_attr sattr; struct xnthread_init_attr iattr; xnflags_t bflags = 0; int ret; spl_t s; if (priority < XNSCHED_LOW_PRIO || priority > XNSCHED_HIGH_PRIO || task->magic == RTAI_TASK_MAGIC) return -EINVAL; priority = XNSCHED_HIGH_PRIO - priority + 1; /* Normalize. */ if (uses_fpu) #ifdef CONFIG_XENO_HW_FPU bflags |= XNFPU; #else /* !CONFIG_XENO_HW_FPU */ return -EINVAL; #endif /* CONFIG_XENO_HW_FPU */ iattr.tbase = rtai_tbase; iattr.name = NULL; iattr.flags = bflags; iattr.ops = &__rtai_task_ops; iattr.stacksize = stack_size; param.rt.prio = priority; if (xnpod_init_thread(&task->thread_base, &iattr, &xnsched_class_rt, ¶m) != 0) /* Assume this is the only possible failure. */ return -ENOMEM; xnarch_cpus_clear(task->affinity); inith(&task->link); task->suspend_depth = 1; task->cookie = cookie; task->body = body; task->sigfn = sigfn; if (xnarch_cpus_empty(task->affinity)) task->affinity = XNPOD_ALL_CPUS; xnlock_get_irqsave(&nklock, s); sattr.mode = XNSUSP; /* Suspend on startup. */ sattr.imask = 0; sattr.affinity = task->affinity; sattr.entry = rt_task_trampoline; sattr.cookie = task; ret = xnpod_start_thread(&task->thread_base, &sattr); if (ret) goto unlock_and_exit; task->magic = RTAI_TASK_MAGIC; appendq(&__rtai_task_q, &task->link); #ifdef CONFIG_XENO_FASTSYNCH /* We need an anonymous registry entry to obtain a handle for fast mutex locking. */ ret = xnthread_register(&task->thread_base, ""); if (ret) { xnpod_abort_thread(&task->thread_base); goto unlock_and_exit; } #endif /* CONFIG_XENO_FASTSYNCH */ /* Add a switch hook only if a signal function has been declared at least once for some created task. */ if (sigfn != NULL && __rtai_task_sig++ == 0) xnpod_add_hook(XNHOOK_THREAD_SWITCH, &__task_switch_hook); unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return ret ? -EINVAL : 0; }
u_long t_create(const char *name, u_long prio, u_long sstack, u_long ustack, u_long flags, u_long *tid_r) { union xnsched_policy_param param; struct xnthread_init_attr attr; xnflags_t bflags = 0; psostask_t *task; u_long err; spl_t s; int n; /* Xenomai extension: we accept priority level #0 for creating non-RT tasks (i.e. underlaid by SCHED_NORMAL pthreads), which are allowed to call into the pSOS emulator, usually for synchronization services. */ if (prio > 255) return ERR_PRIOR; task = (psostask_t *)xnmalloc(sizeof(*task)); if (!task) return ERR_NOTCB; if (flags & T_FPU) bflags |= XNFPU; #ifdef CONFIG_XENO_OPT_PERVASIVE if (flags & T_SHADOW) bflags |= XNSHADOW; #endif /* CONFIG_XENO_OPT_PERVASIVE */ ustack += sstack; if (!(flags & T_SHADOW) && ustack < 1024) { xnfree(task); return ERR_TINYSTK; } if (name && *name) xnobject_copy_name(task->name, name); else /* i.e. Anonymous object which must be accessible from user-space. */ sprintf(task->name, "anon_task%lu", psos_task_ids++); attr.tbase = psos_tbase; attr.name = task->name; attr.flags = bflags; attr.ops = &psos_task_ops; attr.stacksize = ustack; param.rt.prio = prio; if (xnpod_init_thread(&task->threadbase, &attr, &xnsched_class_rt, ¶m) != 0) { xnfree(task); return ERR_NOSTK; /* Assume this is the only possible failure */ } xnthread_time_slice(&task->threadbase) = psos_time_slice; taskev_init(&task->evgroup); inith(&task->link); for (n = 0; n < PSOSTASK_NOTEPAD_REGS; n++) task->notepad[n] = 0; initgq(&task->alarmq, &xnmod_glink_queue, xnmod_alloc_glinks, XNMOD_GHOLDER_THRESHOLD); task->magic = PSOS_TASK_MAGIC; xnlock_get_irqsave(&nklock, s); appendq(&psostaskq, &task->link); *tid_r = (u_long)task; xnlock_put_irqrestore(&nklock, s); err = xnthread_register(&task->threadbase, task->name); if (err) { t_delete((u_long)task); return err; } xnarch_create_display(&task->threadbase, task->name, psostask); return SUCCESS; }