/** * Bind a file descriptor (represented by its @a xnselect structure) to a * selector block. * * @param select_block pointer to the @a struct @a xnselect to be bound; * * @param binding pointer to a newly allocated (using xnmalloc) @a struct * @a xnselect_binding; * * @param selector pointer to the selector structure; * * @param type type of events (@a XNSELECT_READ, @a XNSELECT_WRITE, or @a * XNSELECT_EXCEPT); * * @param index index of the file descriptor (represented by @a select_block) in the bit fields used by the @a selector structure; * * @param state current state of the file descriptor>. * * @a select_block must have been initialized with xnselect_init(), * the @a xnselector structure must have been initialized with * xnselector_init(), @a binding may be uninitialized. * * This service must be called with nklock locked, irqs off. For this reason, * the @a binding parameter must have been allocated by the caller outside the * locking section. * * @retval -EINVAL if @a type or @a index is invalid; * @retval 0 otherwise. */ int xnselect_bind(struct xnselect *select_block, struct xnselect_binding *binding, struct xnselector *selector, unsigned type, unsigned index, unsigned state) { if (type >= XNSELECT_MAX_TYPES || index > __FD_SETSIZE) return -EINVAL; binding->selector = selector; binding->fd = select_block; binding->type = type; binding->bit_index = index; inith(&binding->link); inith(&binding->slink); appendq(&selector->bindings, &binding->slink); appendq(&select_block->bindings, &binding->link); __FD_SET__(index, &selector->fds[type].expected); if (state) { __FD_SET__(index, &selector->fds[type].pending); if (xnselect_wakeup(selector)) xnpod_schedule(); } else __FD_CLR__(index, &selector->fds[type].pending); return 0; }
void xntimer_adjust_all_aperiodic(xnsticks_t delta) { unsigned cpu, nr_cpus; xnqueue_t adjq; initq(&adjq); delta = xnarch_ns_to_tsc(delta); for (cpu = 0, nr_cpus = xnarch_num_online_cpus(); cpu < nr_cpus; cpu++) { xnsched_t *sched = xnpod_sched_slot(cpu); xntimerq_t *q = &sched->timerqueue; xnholder_t *adjholder; xntimerh_t *holder; xntimerq_it_t it; for (holder = xntimerq_it_begin(q, &it); holder; holder = xntimerq_it_next(q, &it, holder)) { xntimer_t *timer = aplink2timer(holder); if (testbits(timer->status, XNTIMER_REALTIME)) { inith(&timer->adjlink); appendq(&adjq, &timer->adjlink); } } while ((adjholder = getq(&adjq))) { xntimer_t *timer = adjlink2timer(adjholder); xntimer_dequeue_aperiodic(timer); xntimer_adjust_aperiodic(timer, delta); } if (sched != xnpod_current_sched()) xntimer_next_remote_shot(sched); else xntimer_next_local_shot(sched); } }
void xntslave_adjust(xntslave_t *slave, xnsticks_t delta) { int nr_cpus, cpu, n; xnqueue_t adjq; initq(&adjq); for (cpu = 0, nr_cpus = xnarch_num_online_cpus(); cpu < nr_cpus; cpu++) { struct percpu_cascade *pc = &slave->cascade[cpu]; xnholder_t *adjholder; for (n = 0; n < XNTIMER_WHEELSIZE; n++) { xnqueue_t *q = &pc->wheel[n]; xntlholder_t *holder; for (holder = xntlist_head(q); holder; holder = xntlist_next(q, holder)) { xntimer_t *timer = plink2timer(holder); if (testbits(timer->status, XNTIMER_REALTIME)) { inith(&timer->adjlink); appendq(&adjq, &timer->adjlink); } } } while ((adjholder = getq(&adjq))) { xntimer_t *timer = adjlink2timer(adjholder); xntimer_dequeue_periodic(timer); xntimer_adjust_periodic(timer, delta); } } }
void xnmod_alloc_glinks(xnqueue_t *freehq) { xngholder_t *sholder, *eholder; sholder = xnheap_alloc(&kheap, sizeof(xngholder_t) * XNMOD_GHOLDER_REALLOC); if (!sholder) { /* If we are running out of memory but still have some free holders, just return silently, hoping that the contention will disappear before we have no other choice than allocating memory eventually. Otherwise, we have to raise a fatal error right now. */ if (emptyq_p(freehq)) xnpod_fatal("cannot allocate generic holders"); return; } for (eholder = sholder + XNMOD_GHOLDER_REALLOC; sholder < eholder; sholder++) { inith(&sholder->glink.plink); appendq(freehq, &sholder->glink.plink); } }
static inline void xnpipe_enqueue_wait(struct xnpipe_state *state, int mask) { if (state->wcount != 0x7fffffff && state->wcount++ == 0) appendq(&xnpipe_sleepq, &state->slink); __setbits(state->status, mask); }
MSG_Q_ID msgQCreate(int nb_msgs, int length, int flags) { static unsigned long msgq_ids; wind_msgq_t *queue; xnflags_t bflags = 0; int i, msg_size; char *msgs_mem; spl_t s; check_NOT_ISR_CALLABLE(return 0); error_check(nb_msgs <= 0, S_msgQLib_INVALID_QUEUE_TYPE, return 0); error_check(flags & ~WIND_MSG_Q_OPTION_MASK, S_msgQLib_INVALID_QUEUE_TYPE, return 0); error_check(length < 0, S_msgQLib_INVALID_MSG_LENGTH, return 0); msgs_mem = xnmalloc(sizeof(wind_msgq_t) + nb_msgs * (sizeof(wind_msg_t) + length)); error_check(msgs_mem == NULL, S_memLib_NOT_ENOUGH_MEMORY, return 0); queue = (wind_msgq_t *)msgs_mem; msgs_mem += sizeof(wind_msgq_t); queue->magic = WIND_MSGQ_MAGIC; queue->msg_length = length; queue->free_list = NULL; initq(&queue->msgq); inith(&queue->rlink); queue->rqueue = &wind_get_rholder()->msgQq; /* init of the synch object : */ if (flags & MSG_Q_PRIORITY) bflags |= XNSYNCH_PRIO; xnsynch_init(&queue->synchbase, bflags, NULL); msg_size = sizeof(wind_msg_t) + length; for (i = 0; i < nb_msgs; ++i, msgs_mem += msg_size) free_msg(queue, (wind_msg_t *)msgs_mem); xnlock_get_irqsave(&nklock, s); appendq(queue->rqueue, &queue->rlink); xnlock_put_irqrestore(&nklock, s); sprintf(queue->name, "mq%lu", msgq_ids++); if (xnregistry_enter(queue->name, queue, &queue->handle, &msgq_pnode)) { wind_errnoset(S_objLib_OBJ_ID_ERROR); msgQDelete((MSG_Q_ID)queue); return 0; } return (MSG_Q_ID)queue; }
ssize_t xnpipe_send(int minor, struct xnpipe_mh *mh, size_t size, int flags) { struct xnpipe_state *state; int need_sched = 0; spl_t s; if (minor < 0 || minor >= XNPIPE_NDEVS) return -ENODEV; if (size <= sizeof(*mh)) return -EINVAL; state = &xnpipe_states[minor]; xnlock_get_irqsave(&nklock, s); if (!testbits(state->status, XNPIPE_KERN_CONN)) { xnlock_put_irqrestore(&nklock, s); return -EBADF; } inith(xnpipe_m_link(mh)); xnpipe_m_size(mh) = size - sizeof(*mh); xnpipe_m_rdoff(mh) = 0; state->ionrd += xnpipe_m_size(mh); if (flags & XNPIPE_URGENT) prependq(&state->outq, xnpipe_m_link(mh)); else appendq(&state->outq, xnpipe_m_link(mh)); if (!testbits(state->status, XNPIPE_USER_CONN)) { xnlock_put_irqrestore(&nklock, s); return (ssize_t) size; } if (testbits(state->status, XNPIPE_USER_WREAD)) { /* * Wake up the regular Linux task waiting for input * from the Xenomai side. */ __setbits(state->status, XNPIPE_USER_WREAD_READY); need_sched = 1; } if (state->asyncq) { /* Schedule asynch sig. */ __setbits(state->status, XNPIPE_USER_SIGIO); need_sched = 1; } if (need_sched) xnpipe_schedule_request(); xnlock_put_irqrestore(&nklock, s); return (ssize_t) size; }
/* * _shm_alloc allocs chunk from Fusion kheap or alloc a new heap */ void *_shm_alloc(unsigned long name, int size, int suprt, int in_kheap, unsigned long *opaque) { void *ret = NULL; xnholder_t *holder; xnshm_a_t *p; spl_t s; xnlock_get_irqsave(&nklock, s); holder = getheadq(&xnshm_allocq); while (holder != NULL) { p = link2shma(holder); if (p->name == name) { /* assert(size==p->size); */ p->ref++; ret = p->chunk; *opaque = (unsigned long)p->heap; goto unlock_and_exit; } holder = nextq(&xnshm_allocq, holder); } if (in_kheap) { p = kalloc_new_shm(name, size); } else { /* create new heap can suspend */ xnlock_put_irqrestore(&nklock, s); p = create_new_heap(name, size, suprt); xnlock_get_irqsave(&nklock, s); } if (!p) goto unlock_and_exit; *opaque = (unsigned long)p->heap; appendq(&xnshm_allocq, &p->link); #ifdef CONFIG_XENO_OPT_REGISTRY { p->handle = 0; num2nam(p->name, p->szName); xnregistry_enter(p->szName, p, &p->handle, &__shm_pnode); } #endif /* CONFIG_XENO_OPT_REGISTRY */ ret = p->chunk; unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return ret; }
void __wind_wd_handler(void *cookie) { wind_wd_t *wd = (wind_wd_t *)cookie; if (wd->plink.last == wd->plink.next) { /* Not linked? */ appendq(&wd->rh->wdpending, &wd->plink); if (countq(&wd->rh->wdpending) == 1) xnsynch_flush(&wd->rh->wdsynch, 0); } }
static void pse51_shm_init(pse51_shm_t * shm) { shm->addr = NULL; shm->size = 0; sema_init(&shm->maplock, 1); initq(&shm->mappings); inith(&shm->link); appendq(&pse51_shmq, &shm->link); }
/** * Destroy a selector block. * * All bindings with file descriptor are destroyed. * * @param selector the selector block to be destroyed */ void xnselector_destroy(struct xnselector *selector) { spl_t s; inith(&selector->destroy_link); xnlock_get_irqsave(&nklock, s); appendq(&xnselectors, &selector->destroy_link); xnlock_put_irqrestore(&nklock, s); rthal_apc_schedule(xnselect_apc); }
int rt_buffer_create(RT_BUFFER *bf, const char *name, size_t bufsz, int mode) { int ret = 0; spl_t s; if (xnpod_asynch_p()) return -EPERM; if (bufsz == 0) return -EINVAL; bf->bufmem = xnarch_alloc_host_mem(bufsz); if (bf->bufmem == NULL) return -ENOMEM; xnsynch_init(&bf->isynch_base, mode & B_PRIO, NULL); xnsynch_init(&bf->osynch_base, mode & B_PRIO, NULL); bf->handle = 0; /* i.e. (still) unregistered buffer. */ xnobject_copy_name(bf->name, name); inith(&bf->rlink); bf->rqueue = &xeno_get_rholder()->bufferq; xnlock_get_irqsave(&nklock, s); appendq(bf->rqueue, &bf->rlink); xnlock_put_irqrestore(&nklock, s); bf->mode = mode; bf->bufsz = bufsz; bf->rdoff = 0; bf->wroff = 0; bf->fillsz = 0; bf->rdtoken = 0; bf->wrtoken = 0; #ifndef __XENO_SIM__ bf->cpid = 0; #endif bf->magic = XENO_BUFFER_MAGIC; /* * <!> Since xnregister_enter() may reschedule, only register * complete objects, so that the registry cannot return * handles to half-baked objects... */ if (name) { ret = xnregistry_enter(bf->name, bf, &bf->handle, &__buffer_pnode.node); if (ret) rt_buffer_delete(bf); } return ret; }
int rt_event_create(RT_EVENT *event, const char *name, unsigned long ivalue, int mode) { int err = 0; spl_t s; if (xnpod_asynch_p()) return -EPERM; xnsynch_init(&event->synch_base, mode & EV_PRIO); event->value = ivalue; event->handle = 0; /* i.e. (still) unregistered event. */ event->magic = XENO_EVENT_MAGIC; xnobject_copy_name(event->name, name); inith(&event->rlink); event->rqueue = &xeno_get_rholder()->eventq; xnlock_get_irqsave(&nklock, s); appendq(event->rqueue, &event->rlink); xnlock_put_irqrestore(&nklock, s); #ifdef CONFIG_XENO_OPT_PERVASIVE event->cpid = 0; #endif /* CONFIG_XENO_OPT_PERVASIVE */ #ifdef CONFIG_XENO_OPT_REGISTRY /* <!> Since xnregister_enter() may reschedule, only register complete objects, so that the registry cannot return handles to half-baked objects... */ if (name) { xnpnode_t *pnode = &__event_pnode; if (!*name) { /* Since this is an anonymous object (empty name on entry) from user-space, it gets registered under an unique internal name but is not exported through /proc. */ xnobject_create_name(event->name, sizeof(event->name), (void *)event); pnode = NULL; } err = xnregistry_enter(event->name, event, &event->handle, pnode); if (err) rt_event_delete(event); } #endif /* CONFIG_XENO_OPT_REGISTRY */ return err; }
int sc_screate(unsigned initval, int opt, int *errp) { int bflags = 0, semid; vrtxsem_t *sem; spl_t s; if (opt & ~1) { *errp = ER_IIP; return -1; } sem = (vrtxsem_t *)xnmalloc(sizeof(*sem)); if (!sem) { *errp = ER_NOCB; return -1; } semid = xnmap_enter(vrtx_sem_idmap, -1, sem); if (semid < 0) { *errp = ER_NOCB; xnfree(sem); return -1; } if (opt == 0) bflags = XNSYNCH_PRIO; else bflags = XNSYNCH_FIFO; xnsynch_init(&sem->synchbase, bflags | XNSYNCH_DREORD); inith(&sem->link); sem->semid = semid; sem->magic = VRTX_SEM_MAGIC; sem->count = initval; xnlock_get_irqsave(&nklock, s); appendq(&vrtx_sem_q, &sem->link); xnlock_put_irqrestore(&nklock, s); #ifdef CONFIG_XENO_OPT_REGISTRY sprintf(sem->name, "sem%d", semid); xnregistry_enter(sem->name, sem, &sem->handle, &__sem_pnode); #endif /* CONFIG_XENO_OPT_REGISTRY */ *errp = RET_OK; return semid; }
int sc_mcreate(unsigned int opt, int *errp) { int bflags, mid; vrtxmx_t *mx; spl_t s; switch (opt) { case 0: bflags = XNSYNCH_PRIO; break; case 1: bflags = XNSYNCH_FIFO; break; case 2: bflags = XNSYNCH_PRIO | XNSYNCH_PIP; break; default: *errp = ER_IIP; return 0; } mx = xnmalloc(sizeof(*mx)); if (mx == NULL) { *errp = ER_NOCB; return -1; } mid = xnmap_enter(vrtx_mx_idmap, -1, mx); if (mid < 0) { xnfree(mx); return -1; } inith(&mx->link); mx->mid = mid; xnsynch_init(&mx->synchbase, bflags | XNSYNCH_DREORD | XNSYNCH_OWNER, NULL); xnlock_get_irqsave(&nklock, s); appendq(&vrtx_mx_q, &mx->link); xnlock_put_irqrestore(&nklock, s); sprintf(mx->name, "mx%d", mid); xnregistry_enter(mx->name, mx, &mx->handle, &__mutex_pnode.node); *errp = RET_OK; return mid; }
int xntbase_alloc(const char *name, u_long period, u_long flags, xntbase_t **basep) { xntslave_t *slave; xntbase_t *base; spl_t s; if (flags & ~XNTBISO) return -EINVAL; if (period == XN_APERIODIC_TICK) { *basep = &nktbase; xnarch_declare_tbase(&nktbase); return 0; } slave = (xntslave_t *)xnarch_alloc_host_mem(sizeof(*slave)); if (!slave) return -ENOMEM; base = &slave->base; base->tickvalue = period; base->ticks2sec = 1000000000UL / period; base->wallclock_offset = 0; base->jiffies = 0; base->hook = NULL; base->ops = &nktimer_ops_periodic; base->name = name; inith(&base->link); xntslave_init(slave); /* Set initial status: Not running, no time set, unlocked, isolated if requested. */ base->status = flags; *basep = base; #ifdef CONFIG_XENO_OPT_STATS initq(&base->timerq); #endif /* CONFIG_XENO_OPT_TIMING_PERIODIC */ xntbase_declare_proc(base); xnlock_get_irqsave(&nklock, s); appendq(&nktimebaseq, &base->link); xnlock_put_irqrestore(&nklock, s); xnarch_declare_tbase(base); return 0; }
/* Called with nklock locked, irq off. */ static int pse51_sem_init_inner(pse51_sem_t * sem, int pshared, unsigned value) { if (value > (unsigned)SEM_VALUE_MAX) return EINVAL; sem->magic = PSE51_SEM_MAGIC; inith(&sem->link); appendq(&pse51_kqueues(pshared)->semq, &sem->link); xnsynch_init(&sem->synchbase, XNSYNCH_PRIO, NULL); sem->value = value; sem->pshared = pshared; sem->is_named = 0; sem->owningq = pse51_kqueues(pshared); return 0; }
int rt_intr_create(RT_INTR *intr, const char *name, unsigned irq, rt_isr_t isr, rt_iack_t iack, int mode) { int err; spl_t s; if (xnpod_asynch_p()) return -EPERM; if (name) xnobject_copy_name(intr->name, name); else /* Kernel-side "anonymous" objects (name == NULL) get unique names. * Nevertheless, they will not be exported via the registry. */ xnobject_create_name(intr->name, sizeof(intr->name), isr); xnintr_init(&intr->intr_base, intr->name, irq, isr, iack, mode); #ifdef CONFIG_XENO_OPT_PERVASIVE xnsynch_init(&intr->synch_base, XNSYNCH_PRIO, NULL); intr->pending = 0; intr->cpid = 0; intr->mode = 0; #endif /* CONFIG_XENO_OPT_PERVASIVE */ intr->magic = XENO_INTR_MAGIC; intr->handle = 0; /* i.e. (still) unregistered interrupt. */ inith(&intr->rlink); intr->rqueue = &xeno_get_rholder()->intrq; xnlock_get_irqsave(&nklock, s); appendq(intr->rqueue, &intr->rlink); xnlock_put_irqrestore(&nklock, s); err = xnintr_attach(&intr->intr_base, intr); /* * <!> Since xnregister_enter() may reschedule, only register * complete objects, so that the registry cannot return * handles to half-baked objects... */ if (!err && name) err = xnregistry_enter(intr->name, intr, &intr->handle, &__intr_pnode); if (err) rt_intr_delete(intr); return err; }
void addmlq(struct xnsched_mlq *q, struct xnpholder *h, int idx, int lifo) { struct xnqueue *queue = &q->queue[idx]; int hi = idx / BITS_PER_LONG; int lo = idx % BITS_PER_LONG; if (lifo) prependq(queue, &h->plink); else appendq(queue, &h->plink); h->prio = idx; q->elems++; __setbits(q->himap, 1UL << hi); __setbits(q->lomap[hi], 1UL << lo); }
void __xntimer_init(xntimer_t *timer, xntbase_t *base, void (*handler) (xntimer_t *timer)) { /* CAUTION: Setup from xntimer_init() must not depend on the periodic/aperiodic timing mode. */ xntimerh_init(&timer->aplink); xntimerh_date(&timer->aplink) = XN_INFINITE; #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC timer->base = base; xntlholder_init(&timer->plink); xntlholder_date(&timer->plink) = XN_INFINITE; #endif /* CONFIG_XENO_OPT_TIMING_PERIODIC */ xntimer_set_priority(timer, XNTIMER_STDPRIO); timer->status = XNTIMER_DEQUEUED; timer->handler = handler; timer->interval = 0; timer->sched = xnpod_current_sched(); #ifdef CONFIG_XENO_OPT_STATS { spl_t s; if (!xnpod_current_thread() || xnpod_shadow_p()) snprintf(timer->name, XNOBJECT_NAME_LEN, "%d/%s", current->pid, current->comm); else xnobject_copy_name(timer->name, xnpod_current_thread()->name); inith(&timer->tblink); xnstat_counter_set(&timer->scheduled, 0); xnstat_counter_set(&timer->fired, 0); xnlock_get_irqsave(&nklock, s); appendq(&base->timerq, &timer->tblink); base->timerq_rev++; xnlock_put_irqrestore(&nklock, s); } #endif /* CONFIG_XENO_OPT_TIMING_PERIODIC */ xnarch_init_display_context(timer); }
int rt_sem_create(RT_SEM *sem, const char *name, unsigned long icount, int mode) { int err = 0; spl_t s; if (xnpod_asynch_p()) return -EPERM; if ((mode & S_PULSE) && icount > 0) return -EINVAL; xnsynch_init(&sem->synch_base, mode & S_PRIO, NULL); sem->count = icount; sem->mode = mode; sem->handle = 0; /* i.e. (still) unregistered semaphore. */ sem->magic = XENO_SEM_MAGIC; xnobject_copy_name(sem->name, name); inith(&sem->rlink); sem->rqueue = &xeno_get_rholder()->semq; xnlock_get_irqsave(&nklock, s); appendq(sem->rqueue, &sem->rlink); xnlock_put_irqrestore(&nklock, s); #ifdef CONFIG_XENO_OPT_PERVASIVE sem->cpid = 0; #endif /* CONFIG_XENO_OPT_PERVASIVE */ /* * <!> Since xnregister_enter() may reschedule, only register * complete objects, so that the registry cannot return * handles to half-baked objects... */ if (name) { err = xnregistry_enter(sem->name, sem, &sem->handle, &__sem_pnode); if (err) rt_sem_delete(sem); } return err; }
int rt_event_create(RT_EVENT *event, const char *name, unsigned long ivalue, int mode) { int err = 0; spl_t s; if (xnpod_asynch_p()) return -EPERM; xnsynch_init(&event->synch_base, mode & EV_PRIO, NULL); event->value = ivalue; event->handle = 0; /* i.e. (still) unregistered event. */ event->magic = XENO_EVENT_MAGIC; xnobject_copy_name(event->name, name); inith(&event->rlink); event->rqueue = &xeno_get_rholder()->eventq; xnlock_get_irqsave(&nklock, s); appendq(event->rqueue, &event->rlink); xnlock_put_irqrestore(&nklock, s); #ifdef CONFIG_XENO_OPT_PERVASIVE event->cpid = 0; #endif /* CONFIG_XENO_OPT_PERVASIVE */ /* * <!> Since xnregister_enter() may reschedule, only register * complete objects, so that the registry cannot return * handles to half-baked objects... */ if (name) { err = xnregistry_enter(event->name, event, &event->handle, &__event_pnode); if (err) rt_event_delete(event); } return err; }
static int xnpipe_fasync(int fd, struct file *file, int on) { struct xnpipe_state *state = file->private_data; int ret, queued; spl_t s; queued = (state->asyncq != NULL); ret = fasync_helper(fd, file, on, &state->asyncq); if (state->asyncq) { if (!queued) { xnlock_get_irqsave(&nklock, s); appendq(&xnpipe_asyncq, &state->alink); xnlock_put_irqrestore(&nklock, s); } } else if (queued) { xnlock_get_irqsave(&nklock, s); removeq(&xnpipe_asyncq, &state->alink); xnlock_put_irqrestore(&nklock, s); } return ret; }
int rt_cond_create(RT_COND *cond, const char *name) { int err = 0; spl_t s; if (xnpod_asynch_p()) return -EPERM; xnsynch_init(&cond->synch_base, XNSYNCH_PRIO, NULL); cond->handle = 0; /* i.e. (still) unregistered cond. */ cond->magic = XENO_COND_MAGIC; xnobject_copy_name(cond->name, name); inith(&cond->rlink); cond->rqueue = &xeno_get_rholder()->condq; xnlock_get_irqsave(&nklock, s); appendq(cond->rqueue, &cond->rlink); xnlock_put_irqrestore(&nklock, s); #ifndef __XENO_SIM__ cond->cpid = 0; #endif /* * <!> Since xnregister_enter() may reschedule, only register * complete objects, so that the registry cannot return * handles to half-baked objects... */ if (name) { err = xnregistry_enter(cond->name, cond, &cond->handle, &__cond_pnode.node); if (err) rt_cond_delete(cond); } return err; }
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; }
int rt_heap_create(RT_HEAP *heap, const char *name, size_t heapsize, int mode) { int err; spl_t s; if (!xnpod_root_p()) return -EPERM; if (heapsize == 0) return -EINVAL; /* Make sure we won't hit trivial argument errors when calling xnheap_init(). */ heap->csize = heapsize; /* Record this for SBA management and inquiry. */ #ifdef __KERNEL__ if (mode & H_MAPPABLE) { if (!name || !*name) return -EINVAL; heapsize = xnheap_rounded_size(heapsize, PAGE_SIZE); err = xnheap_init_mapped(&heap->heap_base, heapsize, ((mode & H_DMA) ? GFP_DMA : 0) | ((mode & H_DMA32) ? GFP_DMA32 : 0) | ((mode & H_NONCACHED) ? XNHEAP_GFP_NONCACHED : 0)); if (err) return err; heap->cpid = 0; } else #endif /* __KERNEL__ */ { void *heapmem; heapsize = xnheap_rounded_size(heapsize, XNHEAP_PAGE_SIZE); heapmem = xnarch_alloc_host_mem(heapsize); if (!heapmem) return -ENOMEM; err = xnheap_init(&heap->heap_base, heapmem, heapsize, XNHEAP_PAGE_SIZE); if (err) { xnarch_free_host_mem(heapmem, heapsize); return err; } } xnheap_set_label(&heap->heap_base, "rt_heap: %s", name); xnsynch_init(&heap->synch_base, mode & (H_PRIO | H_FIFO), NULL); heap->handle = 0; /* i.e. (still) unregistered heap. */ heap->magic = XENO_HEAP_MAGIC; heap->mode = mode; heap->sba = NULL; xnobject_copy_name(heap->name, name); inith(&heap->rlink); heap->rqueue = &xeno_get_rholder()->heapq; xnlock_get_irqsave(&nklock, s); appendq(heap->rqueue, &heap->rlink); xnlock_put_irqrestore(&nklock, s); /* * <!> Since xnregister_enter() may reschedule, only register * complete objects, so that the registry cannot return * handles to half-baked objects... */ if (name) { err = xnregistry_enter(heap->name, heap, &heap->handle, &__heap_pnode.node); if (err) rt_heap_delete(heap); } return err; }
int doname(nameblkp p, int reclevel, time_t *tval, int nowait) { int errstat; int okdel1; int didwork; int len; time_t td, td1, tdep, ptime, ptime1; depblkp q; depblkp qtemp, suffp, suffp1; nameblkp p1, p2; struct shblock *implcom, *explcom; lineblkp lp; lineblkp lp1, lp2; char sourcename[100], prefix[100], temp[100], concsuff[20]; char *stem; char *pnamep, *p1namep; chainp allchain, qchain; char qbuf[QBUFMAX], tgsbuf[QBUFMAX]; wildp wp; int nproc1; char *lastslash, *s; if(p == 0) { *tval = 0; return 0; } if(dbgflag) { printf("doname(%s,%d)\n",p->namep,reclevel); fflush(stdout); } if(p->done > 0) { *tval = p->modtime; return (p->done == 3); } errstat = 0; tdep = 0; implcom = 0; explcom = 0; ptime = exists(p->namep); ptime1 = 0; didwork = NO; p->done = 1; /* avoid infinite loops */ nproc1 = nproc; /* current depth of process stack */ qchain = NULL; allchain = NULL; /* define values of Bradford's $$@ and $$/ macros */ for(s = lastslash = p->namep; *s; ++s) if(*s == '/') lastslash = s; setvar("$@", p->namep, YES); setvar("$/", lastslash, YES); /* expand any names that have embedded metacharacters */ for(lp = p->linep ; lp ; lp = lp->nxtlineblock) for(q = lp->depp ; q ; q=qtemp ) { qtemp = q->nxtdepblock; expand(q); } /* make sure all dependents are up to date */ for(lp = p->linep ; lp ; lp = lp->nxtlineblock) { td = 0; for(q = lp->depp ; q ; q = q->nxtdepblock) if(q->depname) { errstat += doname(q->depname, reclevel+1, &td1, q->nowait); if(dbgflag) printf("TIME(%s)=%ld\n",q->depname->namep, td1); if(td1 > td) td = td1; if(ptime < td1) qchain = appendq(qchain, q->depname->namep); allchain = appendq(allchain, q->depname->namep); } if(p->septype == SOMEDEPS) { if(lp->shp) if( ptime<td || (ptime==0 && td==0) || lp->depp==0) { okdel1 = okdel; okdel = NO; set3var("@", p->namep); setvar("?", mkqlist(qchain,qbuf), YES); setvar("^", mkqlist(allchain,tgsbuf), YES); qchain = NULL; if( !questflag ) errstat += docom(lp->shp, nowait, nproc1); set3var("@", CHNULL); okdel = okdel1; ptime1 = prestime(); didwork = YES; } } else { if(lp->shp != 0) { if(explcom) fprintf(stderr, "Too many command lines for `%s'\n", p->namep); else explcom = lp->shp; } if(td > tdep) tdep = td; } } /* Look for implicit dependents, using suffix rules */ for(lp = sufflist ; lp ; lp = lp->nxtlineblock) for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock) { pnamep = suffp->depname->namep; if(suffix(p->namep , pnamep , prefix)) { (void)srchdir(concat(prefix,"*",temp), NO, (depblkp) NULL); for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock) for(suffp1=lp1->depp; suffp1 ; suffp1 = suffp1->nxtdepblock) { p1namep = suffp1->depname->namep; if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) && (p2=srchname(concat(prefix, p1namep ,sourcename))) ) { errstat += doname(p2, reclevel+1, &td, NO); if(ptime < td) qchain = appendq(qchain, p2->namep); if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td); if(td > tdep) tdep = td; set3var("*", prefix); set3var("<", copys(sourcename)); for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) if(implcom = lp2->shp) break; goto endloop; } } } } /* Look for implicit dependents, using pattern matching rules */ len = strlen(p->namep); for(wp = firstwild ; wp ; wp = wp->next) if(stem = wildmatch(wp, p->namep, len) ) { lp = wp->linep; for(q = lp->depp; q; q = q->nxtdepblock) { if(dbgflag>1 && q->depname) fprintf(stderr,"check dep of %s on %s\n", p->namep, wildsub(q->depname->namep,stem)); if(q->depname && ! chkname(wildsub(q->depname->namep,stem))) break; } if(q) /* some name not found, go to next line */ continue; for(q = lp->depp; q; q = q->nxtdepblock) { nameblkp tamep; if(q->depname == NULL) continue; tamep = srchname( wildsub(q->depname->namep,stem)); /*TEMP fprintf(stderr,"check dep %s on %s =>%s\n",p->namep,q->depname->namep,tamep->namep);*/ /*TEMP*/if(dbgflag) printf("%s depends on %s. stem=%s\n", p->namep,tamep->namep, stem); errstat += doname(tamep, reclevel+1, &td, q->nowait); if(ptime < td) qchain = appendq(qchain, tamep->namep); allchain = appendq(allchain, tamep->namep); if(dbgflag) printf("TIME(%s)=%ld\n", tamep->namep, td); if(td > tdep) tdep = td; set3var("<", copys(tamep->namep) ); } set3var("*", stem); setvar("%", stem, YES); implcom = lp->shp; goto endloop; } endloop: if(errstat==0 && (ptime<tdep || (ptime==0 && tdep==0) ) ) { ptime = (tdep>0 ? tdep : prestime() ); set3var("@", p->namep); setvar("?", mkqlist(qchain,qbuf), YES); setvar("^", mkqlist(allchain,tgsbuf), YES); if(explcom) errstat += docom(explcom, nowait, nproc1); else if(implcom) errstat += docom(implcom, nowait, nproc1); else if(p->septype == 0) if(p1=srchname(".DEFAULT")) { set3var("<", p->namep); for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) if(implcom = lp2->shp) { errstat += docom(implcom, nowait,nproc1); break; } } else if(keepgoing) { printf("Don't know how to make %s\n", p->namep); ++errstat; } else fatal1(" Don't know how to make %s", p->namep); set3var("@", CHNULL); if(noexflag || nowait || (ptime = exists(p->namep)) == 0 ) ptime = prestime(); } else if(errstat!=0 && reclevel==0) printf("`%s' not remade because of errors\n", p->namep); else if(!questflag && reclevel==0 && didwork==NO) printf("`%s' is up to date.\n", p->namep); if(questflag && reclevel==0) exit(ndocoms>0 ? -1 : 0); p->done = (errstat ? 3 : 2); if(ptime1 > ptime) ptime = ptime1; p->modtime = ptime; *tval = ptime; return errstat; }
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; }
static ssize_t xnpipe_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct xnpipe_state *state = file->private_data; struct xnpipe_mh *mh; int pollnum, ret; spl_t s; if (count == 0) return 0; if (!access_ok(VERIFY_READ, buf, count)) return -EFAULT; xnlock_get_irqsave(&nklock, s); retry: if (!testbits(state->status, XNPIPE_KERN_CONN)) { xnlock_put_irqrestore(&nklock, s); return -EPIPE; } pollnum = countq(&state->inq) + countq(&state->outq); xnlock_put_irqrestore(&nklock, s); mh = state->ops.alloc_ibuf(count + sizeof(*mh), state->xstate); if (mh == (struct xnpipe_mh *)-1) return -ENOMEM; if (mh == NULL) { if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK; xnlock_get_irqsave(&nklock, s); if (xnpipe_wait(state, XNPIPE_USER_WSYNC, s, pollnum > countq(&state->inq) + countq(&state->outq))) { xnlock_put_irqrestore(&nklock, s); return -ERESTARTSYS; } goto retry; } inith(xnpipe_m_link(mh)); xnpipe_m_size(mh) = count; xnpipe_m_rdoff(mh) = 0; if (copy_from_user(xnpipe_m_data(mh), buf, count)) { state->ops.free_ibuf(mh, state->xstate); return -EFAULT; } xnlock_get_irqsave(&nklock, s); appendq(&state->inq, &mh->link); /* Wake up a Xenomai sleeper if any. */ if (xnsynch_wakeup_one_sleeper(&state->synchbase)) xnpod_schedule(); if (state->ops.input) { ret = state->ops.input(mh, 0, state->xstate); if (ret) count = (size_t)ret; } if (file->f_flags & O_SYNC) { if (!emptyq_p(&state->inq)) { if (xnpipe_wait(state, XNPIPE_USER_WSYNC, s, emptyq_p(&state->inq))) count = -ERESTARTSYS; } } xnlock_put_irqrestore(&nklock, s); return (ssize_t)count; }
int rt_heap_create(RT_HEAP *heap, const char *name, size_t heapsize, int mode) { int err; spl_t s; if (!xnpod_root_p()) return -EPERM; if (heapsize == 0) return -EINVAL; /* Make sure we won't hit trivial argument errors when calling xnheap_init(). */ heap->csize = heapsize; /* Record this for SBA management and inquiry. */ #ifdef __KERNEL__ if (mode & H_MAPPABLE) { if (!name || !*name) return -EINVAL; #ifdef CONFIG_XENO_OPT_PERVASIVE heapsize = xnheap_rounded_size(heapsize, PAGE_SIZE); err = xnheap_init_mapped(&heap->heap_base, heapsize, ((mode & H_DMA) ? GFP_DMA : 0) | ((mode & H_NONCACHED) ? XNHEAP_GFP_NONCACHED : 0)); if (err) return err; heap->cpid = 0; #else /* !CONFIG_XENO_OPT_PERVASIVE */ return -ENOSYS; #endif /* CONFIG_XENO_OPT_PERVASIVE */ } else #endif /* __KERNEL__ */ { void *heapmem; heapsize = xnheap_rounded_size(heapsize, XNCORE_PAGE_SIZE); heapmem = xnarch_alloc_host_mem(heapsize); if (!heapmem) return -ENOMEM; err = xnheap_init(&heap->heap_base, heapmem, heapsize, XNCORE_PAGE_SIZE); if (err) { xnarch_free_host_mem(heapmem, heapsize); return err; } } xnsynch_init(&heap->synch_base, mode & (H_PRIO | H_FIFO)); heap->handle = 0; /* i.e. (still) unregistered heap. */ heap->magic = XENO_HEAP_MAGIC; heap->mode = mode; heap->sba = NULL; xnobject_copy_name(heap->name, name); inith(&heap->rlink); heap->rqueue = &xeno_get_rholder()->heapq; xnlock_get_irqsave(&nklock, s); appendq(heap->rqueue, &heap->rlink); xnlock_put_irqrestore(&nklock, s); #ifdef CONFIG_XENO_OPT_REGISTRY /* <!> Since xnregister_enter() may reschedule, only register complete objects, so that the registry cannot return handles to half-baked objects... */ if (name) { xnpnode_t *pnode = &__heap_pnode; if (!*name) { /* Since this is an anonymous object (empty name on entry) from user-space, it gets registered under an unique internal name but is not exported through /proc. */ xnobject_create_name(heap->name, sizeof(heap->name), (void *)heap); pnode = NULL; } err = xnregistry_enter(heap->name, heap, &heap->handle, pnode); if (err) rt_heap_delete(heap); } #endif /* CONFIG_XENO_OPT_REGISTRY */ return err; }