u_long t_getreg(u_long tid, u_long regnum, u_long *regvalue) { u_long err = SUCCESS; psostask_t *task; spl_t s; xnlock_get_irqsave(&nklock, s); if (tid == 0) task = psos_current_task(); else { task = psos_h2obj_active(tid, PSOS_TASK_MAGIC, psostask_t); if (!task) { err = psos_handle_error(tid, PSOS_TASK_MAGIC, psostask_t); goto unlock_and_exit; } } if (regnum >= PSOSTASK_NOTEPAD_REGS) { err = ERR_REGNUM; goto unlock_and_exit; } *regvalue = task->notepad[regnum]; unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
u_long t_delete(u_long tid) { u_long err = SUCCESS; psostask_t *task; spl_t s; if (tid == 0) xnpod_delete_self(); /* Never returns */ xnlock_get_irqsave(&nklock, s); task = psos_h2obj_active(tid, PSOS_TASK_MAGIC, psostask_t); if (!task) { err = psos_handle_error(tid, PSOS_TASK_MAGIC, psostask_t); goto unlock_and_exit; } xnpod_delete_thread(&task->threadbase); unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
u_long t_setpri(u_long tid, u_long newprio, u_long *oldprio) { union xnsched_policy_param param; u_long err = SUCCESS; psostask_t *task; spl_t s; xnlock_get_irqsave(&nklock, s); if (tid == 0) { if (xnpod_unblockable_p()) return -EPERM; task = psos_current_task(); } else { task = psos_h2obj_active(tid, PSOS_TASK_MAGIC, psostask_t); if (!task) { err = psos_handle_error(tid, PSOS_TASK_MAGIC, psostask_t); goto unlock_and_exit; } } *oldprio = xnthread_current_priority(&task->threadbase); if (newprio != 0) { if (newprio < 1 || newprio > 255) { err = ERR_SETPRI; goto unlock_and_exit; } if (newprio != *oldprio) { param.rt.prio = newprio; xnpod_set_thread_schedparam(&task->threadbase, &xnsched_class_rt, ¶m); xnpod_schedule(); } } unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
u_long t_start(u_long tid, u_long mode, void (*startaddr) (u_long, u_long, u_long, u_long), u_long targs[]) { u_long err = SUCCESS; xnflags_t xnmode; psostask_t *task; spl_t s; int n; /* We have no error case here: just clear out any unwanted bit. */ mode &= ~T_START_MASK; xnlock_get_irqsave(&nklock, s); task = psos_h2obj_active(tid, PSOS_TASK_MAGIC, psostask_t); if (!task) { err = psos_handle_error(tid, PSOS_TASK_MAGIC, psostask_t); goto unlock_and_exit; } if (!xnthread_test_state(&task->threadbase, XNDORMANT)) { err = ERR_ACTIVE; /* Task already started */ goto unlock_and_exit; } xnmode = psos_mode_to_xeno(mode); task->entry = startaddr; #ifdef CONFIG_XENO_OPT_PERVASIVE if (xnthread_test_state(&task->threadbase, XNSHADOW)) { memset(task->args, 0, sizeof(task->args)); /* The shadow will be returned the exact values passed * to t_start(), since the trampoline is performed at * user-space level. We just relay the information * from t_create() to t_start() here.*/ xnpod_start_thread(&task->threadbase, xnmode, (int)((mode >> 8) & 0x7), XNPOD_ALL_CPUS, (void (*)(void *))startaddr, targs); }
u_long t_suspend(u_long tid) { u_long err = SUCCESS; psostask_t *task; spl_t s; if (tid == 0) { if (xnpod_unblockable_p()) return -EPERM; xnpod_suspend_self(); if (xnthread_test_info(&psos_current_task()->threadbase, XNBREAK)) return -EINTR; return SUCCESS; } xnlock_get_irqsave(&nklock, s); task = psos_h2obj_active(tid, PSOS_TASK_MAGIC, psostask_t); if (!task) { err = psos_handle_error(tid, PSOS_TASK_MAGIC, psostask_t); goto unlock_and_exit; } if (xnthread_test_state(&task->threadbase, XNSUSP)) { err = ERR_SUSP; /* Task already suspended. */ goto unlock_and_exit; } xnpod_suspend_thread(&task->threadbase, XNSUSP, XN_INFINITE, XN_RELATIVE, NULL); if (xnthread_test_info(&task->threadbase, XNBREAK)) err = -EINTR; unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
u_long t_resume(u_long tid) { u_long err = SUCCESS; psostask_t *task; spl_t s; xnlock_get_irqsave(&nklock, s); if (tid == 0) { if (xnpod_unblockable_p()) { err = -EPERM; goto unlock_and_exit; } /* Would be admittedly silly, but silly code does * exist, and it's a matter of returning ERR_NOTSUSP * instead of ERR_OBJID. */ task = psos_current_task(); } else { task = psos_h2obj_active(tid, PSOS_TASK_MAGIC, psostask_t); if (!task) { err = psos_handle_error(tid, PSOS_TASK_MAGIC, psostask_t); goto unlock_and_exit; } } if (!xnthread_test_state(&task->threadbase, XNSUSP)) { err = ERR_NOTSUSP; /* Task not suspended. */ goto unlock_and_exit; } xnpod_resume_thread(&task->threadbase, XNSUSP); xnpod_schedule(); unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
u_long ev_send(u_long tid, u_long events) { u_long err = SUCCESS; psosevent_t *evgroup; psostask_t *task; spl_t s; xnlock_get_irqsave(&nklock, s); task = psos_h2obj_active(tid, PSOS_TASK_MAGIC, psostask_t); if (!task) { err = psos_handle_error(tid, PSOS_TASK_MAGIC, psostask_t); goto unlock_and_exit; } evgroup = &task->evgroup; evgroup->events |= events; /* Only the task to which the event group pertains can pend on it. */ if (!emptypq_p(xnsynch_wait_queue(&evgroup->synchbase))) { u_long flags = task->waitargs.evgroup.flags; u_long bits = task->waitargs.evgroup.events; if (((flags & EV_ANY) && (bits & evgroup->events) != 0) || (!(flags & EV_ANY) && ((bits & evgroup->events) == bits))) { xnsynch_wakeup_one_sleeper(&evgroup->synchbase); task->waitargs.evgroup.events = (bits & evgroup->events); evgroup->events &= ~bits; xnpod_schedule(); } } unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
u_long t_restart(u_long tid, u_long targs[]) { u_long err = SUCCESS; psostask_t *task; spl_t s; int n; if (xnpod_unblockable_p()) return -EPERM; xnlock_get_irqsave(&nklock, s); if (tid == 0) task = psos_current_task(); else { task = psos_h2obj_active(tid, PSOS_TASK_MAGIC, psostask_t); if (!task) { err = psos_handle_error(tid, PSOS_TASK_MAGIC, psostask_t); goto unlock_and_exit; } if (xnthread_test_state(&task->threadbase, XNDORMANT)) { err = ERR_NACTIVE; goto unlock_and_exit; } } for (n = 0; n < 4; n++) task->args[n] = targs ? targs[n] : 0; xnpod_restart_thread(&task->threadbase); unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
u_long t_start(u_long tid, u_long mode, void (*startaddr) (u_long, u_long, u_long, u_long), u_long targs[]) { struct xnthread_start_attr attr; u_long err = SUCCESS; xnflags_t xnmode; psostask_t *task; spl_t s; /* We have no error case here: just clear out any unwanted bit. */ mode &= ~T_START_MASK; xnlock_get_irqsave(&nklock, s); task = psos_h2obj_active(tid, PSOS_TASK_MAGIC, psostask_t); if (!task) { err = psos_handle_error(tid, PSOS_TASK_MAGIC, psostask_t); goto unlock_and_exit; } if (!xnthread_test_state(&task->threadbase, XNDORMANT)) { err = ERR_ACTIVE; /* Task already started */ goto unlock_and_exit; } xnmode = psos_mode_to_xeno(mode); if (xnmode & XNRRB) { xnpod_set_thread_tslice(&task->threadbase, psos_time_slice); xnmode &= ~XNRRB; } task->entry = startaddr; attr.mode = xnmode; attr.imask = (int)((mode >> 8) & 0x7); attr.affinity = XNPOD_ALL_CPUS; if (targs) memcpy(task->args, targs, sizeof(task->args)); else memset(task->args, 0, sizeof(task->args)); #ifdef CONFIG_XENO_OPT_PERVASIVE if (xnthread_test_state(&task->threadbase, XNSHADOW)) { attr.entry = (void (*)(void *))startaddr; attr.cookie = (void *)xnthread_handle(&task->threadbase); } else #endif /* CONFIG_XENO_OPT_PERVASIVE */ { attr.entry = psostask_trampoline; attr.cookie = task; } xnpod_start_thread(&task->threadbase, &attr); unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }