123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- #include <assert.h>
- #include <stdlib.h>
- #include "mpool.h"
- #include "queue.h"
- #include "events.h"
- #include "events_internal.h"
- struct eventq {
- struct eventrec * r;
- TAILQ_ENTRY(eventq) entries;
- int prio;
- };
- MPOOL(eventq, struct eventq, 4096);
- /* First nodes in the linked lists. */
- static TAILQ_HEAD(tailhead, eventq) heads[32] = {
- TAILQ_HEAD_INITIALIZER(heads[0]),
- TAILQ_HEAD_INITIALIZER(heads[1]),
- TAILQ_HEAD_INITIALIZER(heads[2]),
- TAILQ_HEAD_INITIALIZER(heads[3]),
- TAILQ_HEAD_INITIALIZER(heads[4]),
- TAILQ_HEAD_INITIALIZER(heads[5]),
- TAILQ_HEAD_INITIALIZER(heads[6]),
- TAILQ_HEAD_INITIALIZER(heads[7]),
- TAILQ_HEAD_INITIALIZER(heads[8]),
- TAILQ_HEAD_INITIALIZER(heads[9]),
- TAILQ_HEAD_INITIALIZER(heads[10]),
- TAILQ_HEAD_INITIALIZER(heads[11]),
- TAILQ_HEAD_INITIALIZER(heads[12]),
- TAILQ_HEAD_INITIALIZER(heads[13]),
- TAILQ_HEAD_INITIALIZER(heads[14]),
- TAILQ_HEAD_INITIALIZER(heads[15]),
- TAILQ_HEAD_INITIALIZER(heads[16]),
- TAILQ_HEAD_INITIALIZER(heads[17]),
- TAILQ_HEAD_INITIALIZER(heads[18]),
- TAILQ_HEAD_INITIALIZER(heads[19]),
- TAILQ_HEAD_INITIALIZER(heads[20]),
- TAILQ_HEAD_INITIALIZER(heads[21]),
- TAILQ_HEAD_INITIALIZER(heads[22]),
- TAILQ_HEAD_INITIALIZER(heads[23]),
- TAILQ_HEAD_INITIALIZER(heads[24]),
- TAILQ_HEAD_INITIALIZER(heads[25]),
- TAILQ_HEAD_INITIALIZER(heads[26]),
- TAILQ_HEAD_INITIALIZER(heads[27]),
- TAILQ_HEAD_INITIALIZER(heads[28]),
- TAILQ_HEAD_INITIALIZER(heads[29]),
- TAILQ_HEAD_INITIALIZER(heads[30]),
- TAILQ_HEAD_INITIALIZER(heads[31])
- };
- /* For i < minq, heads[i] == NULL. */
- static int minq = 32;
- /**
- * events_immediate_register(func, cookie, prio):
- * Register ${func}(${cookie}) to be run the next time events_run() is
- * invoked, after immediate events with smaller ${prio} values and before
- * events with larger ${prio} values. The value ${prio} must be in the range
- * [0, 31]. Return a cookie which can be passed to events_immediate_cancel().
- */
- void *
- events_immediate_register(int (* func)(void *), void * cookie, int prio)
- {
- struct eventrec * r;
- struct eventq * q;
- /* Sanity check. */
- assert((prio >= 0) && (prio < 32));
- /* Bundle into an eventrec record. */
- if ((r = events_mkrec(func, cookie)) == NULL)
- goto err0;
- /* Create a linked list node. */
- if ((q = mpool_eventq_malloc()) == NULL)
- goto err1;
- q->r = r;
- q->prio = prio;
- /* Add to the queue. */
- TAILQ_INSERT_TAIL(&heads[prio], q, entries);
- /* Update minq if necessary. */
- if (prio < minq)
- minq = prio;
- /* Success! */
- return (q);
- err1:
- events_freerec(r);
- err0:
- /* Failure! */
- return (NULL);
- }
- /**
- * events_immediate_cancel(cookie):
- * Cancel the immediate event for which the cookie ${cookie} was returned by
- * events_immediate_register().
- */
- void
- events_immediate_cancel(void * cookie)
- {
- struct eventq * q = cookie;
- int prio = q->prio;
- /* Remove it from the list. */
- TAILQ_REMOVE(&heads[prio], q, entries);
- /* Free the eventrec. */
- events_freerec(q->r);
- /* Return the node to the malloc pool. */
- mpool_eventq_free(q);
- }
- /**
- * events_immediate_get(void):
- * Remove and return an eventrec structure from the immediate event queue,
- * or return NULL if there are no such events. The caller is responsible for
- * freeing the returned memory.
- */
- struct eventrec *
- events_immediate_get(void)
- {
- struct eventq * q;
- struct eventrec * r;
- /* Advance past priorities which have no events. */
- while ((minq < 32) && (TAILQ_EMPTY(&heads[minq])))
- minq++;
- /* Are there any events? */
- if (minq == 32)
- return (NULL);
- /*
- * Remove the first node from the highest priority non-empty linked
- * list.
- */
- q = TAILQ_FIRST(&heads[minq]);
- TAILQ_REMOVE(&heads[minq], q, entries);
- /* Extract the eventrec. */
- r = q->r;
- /* Return the node to the malloc pool. */
- mpool_eventq_free(q);
- /* Return the eventrec. */
- return (r);
- }
|