int rt_heap_free(RT_HEAP *heap, void *block) { int err, nwake; spl_t s; if (block == NULL) return -EINVAL; xnlock_get_irqsave(&nklock, s); heap = xeno_h2obj_validate(heap, XENO_HEAP_MAGIC, RT_HEAP); if (!heap) { err = xeno_handle_error(heap, XENO_HEAP_MAGIC, RT_HEAP); goto unlock_and_exit; } if (heap->mode & H_SINGLE) { /* No-op in single-block mode. */ err = 0; goto unlock_and_exit; } err = xnheap_free(&heap->heap_base, block); if (!err && xnsynch_nsleepers(&heap->synch_base) > 0) { xnpholder_t *holder, *nholder; nholder = getheadpq(xnsynch_wait_queue(&heap->synch_base)); nwake = 0; while ((holder = nholder) != NULL) { RT_TASK *sleeper = thread2rtask(link2thread(holder, plink)); void *block; block = xnheap_alloc(&heap->heap_base, sleeper->wait_args.heap.size); if (block) { nholder = xnsynch_wakeup_this_sleeper(&heap-> synch_base, holder); sleeper->wait_args.heap.block = block; nwake++; } else nholder = nextpq(xnsynch_wait_queue (&heap->synch_base), holder); } if (nwake > 0) xnpod_schedule(); } unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
static int vfile_next(struct xnvfile_snapshot_iterator *it, void *data) { struct vfile_priv *priv = xnvfile_iterator_priv(it); RT_EVENT *event = xnvfile_priv(it->vfile); struct vfile_data *p = data; struct xnthread *thread; RT_TASK *task; priv->value = event->value; /* Refresh as we collect. */ if (priv->curr == NULL) return 0; /* We are done. */ /* Fetch current waiter, advance list cursor. */ thread = link2thread(priv->curr, plink); priv->curr = nextpq(xnsynch_wait_queue(&event->synch_base), priv->curr); /* Collect thread name to be output in ->show(). */ strncpy(p->name, xnthread_name(thread), sizeof(p->name)); task = thread2rtask(thread); p->mode = task->wait_args.event.mode; p->mask = task->wait_args.event.mask; return 1; }
static int vfile_next(struct xnvfile_snapshot_iterator *it, void *data) { struct vfile_priv *priv = xnvfile_iterator_priv(it); struct uiflag *flag = xnvfile_priv(it->vfile); struct vfile_data *p = data; struct xnthread *thread; struct uitask *task; priv->value = flag->flgvalue; /* Refresh as we collect. */ if (priv->curr == NULL) return 0; /* We are done. */ /* Fetch current waiter, advance list cursor. */ thread = link2thread(priv->curr, plink); priv->curr = nextpq(xnsynch_wait_queue(&flag->synchbase), priv->curr); /* Collect thread name to be output in ->show(). */ strncpy(p->name, xnthread_name(thread), sizeof(p->name)); task = thread2uitask(thread); p->wfmode = task->wargs.flag.wfmode; p->waiptn = task->wargs.flag.waiptn; return 1; }
static int vfile_next(struct xnvfile_snapshot_iterator *it, void *data) { struct vfile_priv *priv = xnvfile_iterator_priv(it); RT_BUFFER *bf = xnvfile_priv(it->vfile); struct vfile_data *p = data; struct xnthread *thread; struct xnpqueue *waitq; if (priv->curr == NULL) { /* Attempt to switch queues. */ if (!priv->input) /* Finished output side, we are done. */ return 0; priv->input = 0; waitq = xnsynch_wait_queue(&bf->osynch_base); priv->curr = getheadpq(waitq); if (priv->curr == NULL) return 0; } else waitq = priv->input ? xnsynch_wait_queue(&bf->isynch_base) : xnsynch_wait_queue(&bf->osynch_base); /* Fetch current waiter, advance list cursor. */ thread = link2thread(priv->curr, plink); priv->curr = nextpq(waitq, priv->curr); /* Collect thread name to be output in ->show(). */ strncpy(p->name, xnthread_name(thread), sizeof(p->name)); p->input = priv->input; return 1; }
ER set_flg(ID flgid, UINT setptn) { xnpholder_t *holder, *nholder; uiflag_t *flag; ER err = E_OK; spl_t s; if (xnpod_asynch_p()) return EN_CTXID; if (flgid <= 0 || flgid > uITRON_MAX_FLAGID) return E_ID; xnlock_get_irqsave(&nklock, s); flag = xnmap_fetch(ui_flag_idmap, flgid); if (!flag) { err = E_NOEXS; goto unlock_and_exit; } if (setptn == 0) goto unlock_and_exit; flag->flgvalue |= setptn; if (!xnsynch_pended_p(&flag->synchbase)) goto unlock_and_exit; nholder = getheadpq(xnsynch_wait_queue(&flag->synchbase)); while ((holder = nholder) != NULL) { uitask_t *sleeper = thread2uitask(link2thread(holder, plink)); UINT wfmode = sleeper->wargs.flag.wfmode; UINT waiptn = sleeper->wargs.flag.waiptn; if (((wfmode & TWF_ORW) && (waiptn & flag->flgvalue) != 0) || (!(wfmode & TWF_ORW) && ((waiptn & flag->flgvalue) == waiptn))) { nholder = xnsynch_wakeup_this_sleeper(&flag->synchbase, holder); sleeper->wargs.flag.waiptn = flag->flgvalue; if (wfmode & TWF_CLR) flag->flgvalue = 0; } else nholder = nextpq(xnsynch_wait_queue(&flag->synchbase), holder); } xnpod_schedule(); unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
/* * Detect when a thread is about to relax while holding a * synchronization object currently claimed by another thread, which * bears the TWARNSW bit (thus advertising a concern about potential * spurious relaxes and priority inversion). By relying on the claim * queue, we restrict the checks to PIP-enabled objects, but that * already covers most of the use cases anyway. */ void xnsynch_detect_claimed_relax(struct xnthread *owner) { struct xnpholder *hs, *ht; struct xnthread *sleeper; struct xnsynch *synch; for (hs = getheadpq(&owner->claimq); hs != NULL; hs = nextpq(&owner->claimq, hs)) { synch = link2synch(hs); for (ht = getheadpq(&synch->pendq); ht != NULL; ht = nextpq(&synch->pendq, ht)) { sleeper = link2thread(ht, plink); if (xnthread_test_state(sleeper, XNTRAPSW)) { xnthread_set_info(sleeper, XNSWREP); xnshadow_send_sig(sleeper, SIGDEBUG, SIGDEBUG_MIGRATE_PRIOINV, 1); } } } }
int rt_event_signal(RT_EVENT *event, unsigned long mask) { xnpholder_t *holder, *nholder; int err = 0, resched = 0; spl_t s; xnlock_get_irqsave(&nklock, s); event = xeno_h2obj_validate(event, XENO_EVENT_MAGIC, RT_EVENT); if (!event) { err = xeno_handle_error(event, XENO_EVENT_MAGIC, RT_EVENT); goto unlock_and_exit; } /* Post the flags. */ event->value |= mask; /* And wakeup any sleeper having its request fulfilled. */ nholder = getheadpq(xnsynch_wait_queue(&event->synch_base)); while ((holder = nholder) != NULL) { RT_TASK *sleeper = thread2rtask(link2thread(holder, plink)); int mode = sleeper->wait_args.event.mode; unsigned long bits = sleeper->wait_args.event.mask; if (((mode & EV_ANY) && (bits & event->value) != 0) || (!(mode & EV_ANY) && ((bits & event->value) == bits))) { sleeper->wait_args.event.mask = (bits & event->value); nholder = xnsynch_wakeup_this_sleeper(&event->synch_base, holder); resched = 1; } else nholder = nextpq(xnsynch_wait_queue(&event->synch_base), holder); } if (resched) xnpod_schedule(); unlock_and_exit: xnlock_put_irqrestore(&nklock, s); return err; }
static int __heap_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { RT_HEAP *heap = (RT_HEAP *)data; char *p = page; int len; spl_t s; p += sprintf(p, "type=%s:size=%lu:used=%lu:numaps=%d\n", (heap->mode & H_SHARED) == H_SHARED ? "shared" : (heap->mode & H_MAPPABLE) ? "mappable" : "kernel", xnheap_usable_mem(&heap->heap_base), xnheap_used_mem(&heap->heap_base), atomic_read(&heap->heap_base.archdep.numaps)); xnlock_get_irqsave(&nklock, s); if (xnsynch_nsleepers(&heap->synch_base) > 0) { xnpholder_t *holder; /* Pended heap -- dump waiters. */ holder = getheadpq(xnsynch_wait_queue(&heap->synch_base)); while (holder) { xnthread_t *sleeper = link2thread(holder, plink); RT_TASK *task = thread2rtask(sleeper); size_t size = task->wait_args.heap.size; p += sprintf(p, "+%s (size=%zd)\n", xnthread_name(sleeper), size); holder = nextpq(xnsynch_wait_queue(&heap->synch_base), holder); } } xnlock_put_irqrestore(&nklock, s); len = (p - page) - off; if (len <= off + count) *eof = 1; *start = page + off; if (len > count) len = count; if (len < 0) len = 0; return len; }
static int __event_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { RT_EVENT *event = (RT_EVENT *)data; char *p = page; int len; spl_t s; xnlock_get_irqsave(&nklock, s); p += sprintf(p, "=0x%lx\n", event->value); if (xnsynch_nsleepers(&event->synch_base) > 0) { xnpholder_t *holder; /* Pended event -- dump waiters. */ holder = getheadpq(xnsynch_wait_queue(&event->synch_base)); while (holder) { xnthread_t *sleeper = link2thread(holder, plink); RT_TASK *task = thread2rtask(sleeper); const char *mode = (task->wait_args.event. mode & EV_ANY) ? "any" : "all"; unsigned long mask = task->wait_args.event.mask; p += sprintf(p, "+%s (mask=0x%lx, %s)\n", xnthread_name(sleeper), mask, mode); holder = nextpq(xnsynch_wait_queue(&event->synch_base), holder); } } xnlock_put_irqrestore(&nklock, s); len = (p - page) - off; if (len <= off + count) *eof = 1; *start = page + off; if (len > count) len = count; if (len < 0) len = 0; return len; }
static int __intr_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { RT_INTR *intr = (RT_INTR *)data; char *p = page; int len; spl_t s; xnlock_get_irqsave(&nklock, s); #ifdef CONFIG_XENO_OPT_PERVASIVE { xnpholder_t *holder; p += sprintf(p, "hits=%lu, pending=%u, mode=0x%x\n", __intr_get_hits(intr), intr->pending, intr->mode); /* Pended interrupt -- dump waiters. */ holder = getheadpq(xnsynch_wait_queue(&intr->synch_base)); while (holder) { xnthread_t *sleeper = link2thread(holder, plink); p += sprintf(p, "+%s\n", xnthread_name(sleeper)); holder = nextpq(xnsynch_wait_queue(&intr->synch_base), holder); } } #else /* !CONFIG_XENO_OPT_PERVASIVE */ p += sprintf(p, "hits=%lu\n", __intr_get_hits(intr)); #endif /* CONFIG_XENO_OPT_PERVASIVE */ xnlock_put_irqrestore(&nklock, s); len = (p - page) - off; if (len <= off + count) *eof = 1; *start = page + off; if (len > count) len = count; if (len < 0) len = 0; return len; }
void xnsynch_release_all_ownerships(xnthread_t *thread) { xnpholder_t *holder, *nholder; for (holder = getheadpq(&thread->claimq); holder != NULL; holder = nholder) { /* Since xnsynch_wakeup_one_sleeper() alters the claim queue, we need to be conservative while scanning it. */ xnsynch_t *synch = link2synch(holder); nholder = nextpq(&thread->claimq, holder); xnsynch_wakeup_one_sleeper(synch); if (synch->cleanup) synch->cleanup(synch); } }
static int msgq_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { wind_msgq_t *queue = (wind_msgq_t *)data; char *p = page; int len; spl_t s; p += sprintf(p, "porder=%s:mlength=%u:mcount=%d\n", xnsynch_test_flags(&queue->synchbase, XNSYNCH_PRIO) ? "prio" : "fifo", queue->msg_length, countq(&queue->msgq)); xnlock_get_irqsave(&nklock, s); if (xnsynch_nsleepers(&queue->synchbase) > 0) { xnpholder_t *holder; /* Pended queue -- dump waiters. */ holder = getheadpq(xnsynch_wait_queue(&queue->synchbase)); while (holder) { xnthread_t *sleeper = link2thread(holder, plink); p += sprintf(p, "+%s\n", xnthread_name(sleeper)); holder = nextpq(xnsynch_wait_queue(&queue->synchbase), holder); } } xnlock_put_irqrestore(&nklock, s); len = (p - page) - off; if (len <= off + count) *eof = 1; *start = page + off; if (len > count) len = count; if (len < 0) len = 0; return len; }
void xnsynch_release_all_ownerships(struct xnthread *thread) { struct xnpholder *holder, *nholder; struct xnsynch *synch; for (holder = getheadpq(&thread->claimq); holder != NULL; holder = nholder) { /* * Since xnsynch_release() alters the claim queue, we * need to be conservative while scanning it. */ synch = link2synch(holder); nholder = nextpq(&thread->claimq, holder); xnsynch_release_thread(synch, thread); if (synch->cleanup) synch->cleanup(synch); } }
static int __sem_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { RT_SEM *sem = (RT_SEM *)data; char *p = page; int len; spl_t s; xnlock_get_irqsave(&nklock, s); if (xnsynch_nsleepers(&sem->synch_base) == 0) /* Idle/posted semaphore -- dump count. */ p += sprintf(p, "=%lu\n", sem->count); else { xnpholder_t *holder; /* Pended semaphore -- dump waiters. */ holder = getheadpq(xnsynch_wait_queue(&sem->synch_base)); while (holder) { xnthread_t *sleeper = link2thread(holder, plink); p += sprintf(p, "+%s\n", xnthread_name(sleeper)); holder = nextpq(xnsynch_wait_queue(&sem->synch_base), holder); } } xnlock_put_irqrestore(&nklock, s); len = (p - page) - off; if (len <= off + count) *eof = 1; *start = page + off; if (len > count) len = count; if (len < 0) len = 0; return len; }
static int vfile_next(struct xnvfile_snapshot_iterator *it, void *data) { struct vfile_priv *priv = xnvfile_iterator_priv(it); RT_COND *cond = xnvfile_priv(it->vfile); struct vfile_data *p = data; struct xnthread *thread; if (priv->curr == NULL) return 0; /* We are done. */ /* Fetch current waiter, advance list cursor. */ thread = link2thread(priv->curr, plink); priv->curr = nextpq(xnsynch_wait_queue(&cond->synch_base), priv->curr); /* Collect thread name to be output in ->show(). */ strncpy(p->name, xnthread_name(thread), sizeof(p->name)); return 1; }
static int __mbx_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { uimbx_t *mbx = (uimbx_t *)data; char *p = page; int len; spl_t s; xnlock_get_irqsave(&nklock, s); p += sprintf(p, "%d/%d message(s), attr=%s\n", mbx->mcount, mbx->bufcnt, mbx->mbxatr & TA_TPRI ? "TA_TPRI" : "TA_TFIFO"); if (xnsynch_pended_p(&mbx->synchbase)) { xnpholder_t *holder; /* Pended mbx -- dump waiters. */ holder = getheadpq(xnsynch_wait_queue(&mbx->synchbase)); while (holder) { xnthread_t *sleeper = link2thread(holder, plink); p += sprintf(p, "+%s\n", xnthread_name(sleeper)); holder = nextpq(xnsynch_wait_queue(&mbx->synchbase), holder); } } xnlock_put_irqrestore(&nklock, s); len = (p - page) - off; if (len <= off + count) *eof = 1; *start = page + off; if (len > count) len = count; if (len < 0) len = 0; return len; }
static int __flag_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { uiflag_t *flag = (uiflag_t *)data; char *p = page; int len; spl_t s; xnlock_get_irqsave(&nklock, s); p += sprintf(p, "=0x%x, attr=%s\n", flag->flgvalue, flag->flgatr & TA_WMUL ? "TA_WMUL" : "TA_WSGL"); if (xnsynch_nsleepers(&flag->synchbase) > 0) { xnpholder_t *holder; /* Pended flag -- dump waiters. */ holder = getheadpq(xnsynch_wait_queue(&flag->synchbase)); while (holder) { xnthread_t *sleeper = link2thread(holder, plink); p += sprintf(p, "+%s\n", xnthread_name(sleeper)); holder = nextpq(xnsynch_wait_queue(&flag->synchbase), holder); } } xnlock_put_irqrestore(&nklock, s); len = (p - page) - off; if (len <= off + count) *eof = 1; *start = page + off; if (len > count) len = count; if (len < 0) len = 0; return len; }