34#include <sys/kernel.h>
35#include <sys/malloc.h>
38#ifdef HAVE_KERNEL_OPTION_HEADERS
42#if defined(SND_DIAGNOSTIC) || defined(SND_DEBUG)
94#define SND_CLONE_ASSERT(x, y) do { \
99#define SND_CLONE_ASSERT(...) KASSERT(__VA_ARGS__)
111 (
"invalid typemask: 0x%08x", typemask));
114 (
"maxunit overflow: typemask=0x%08x maxunit=%d",
117 (
"invalid clone flags=0x%08x", flags));
119 c = malloc(
sizeof(*
c), M_DEVBUF, M_WAITOK | M_ZERO);
122 c->typemask = typemask;
125 c->deadline = deadline;
127 getnanouptime(&
c->tsp);
128 TAILQ_INIT(&
c->head);
143 TAILQ_FOREACH(ce, &
c->head, link) {
145 (ce->devt != NULL && ce->devt->si_threadcount != 0))
177 c->
flags &= ~SND_CLONE_ENABLE;
207 (
"maxunit overflow: typemask=0x%08x maxunit=%d",
208 c->typemask, maxunit));
221 return (
c->deadline);
229 c->deadline = deadline;
231 return (
c->deadline);
247 (
"invalid clone flags=0x%08x", flags));
277 (
"invalid clone dev flags=0x%08x", flags));
291#define SND_CLONE_ELAPSED(x, y) \
292 ((((x)->tv_sec - (y)->tv_sec) * 1000) + \
293 (((y)->tv_nsec > (x)->tv_nsec) ? \
294 (((1000000000L + (x)->tv_nsec - \
295 (y)->tv_nsec) / 1000000) - 1000) : \
296 (((x)->tv_nsec - (y)->tv_nsec) / 1000000)))
298#define SND_CLONE_EXPIRED(x, y, z) \
299 ((x)->deadline < 1 || \
300 ((y)->tv_sec - (z)->tv_sec) > ((x)->deadline / 1000) || \
301 SND_CLONE_ELAPSED(y, z) > (x)->deadline)
337 TAILQ_FOREACH_REVERSE_SAFE(ce, &
c->head, link_head, link, tce) {
342 ce->devt->si_threadcount != 0) {
343 ce->flags &= ~SND_CLONE_INVOKE;
346 TAILQ_REMOVE(&
c->head, ce, link);
347 destroy_dev(ce->devt);
366 ce = TAILQ_FIRST(&
c->head);
368 tmp = TAILQ_NEXT(ce, link);
369 if (ce->devt != NULL)
370 destroy_dev(ce->devt);
397 ce->flags &= ~SND_CLONE_INVOKE;
424 ce->flags &= ~SND_CLONE_INVOKE;
429 ce->flags &= ~SND_CLONE_BUSY;
504 (
"invalid clone alloc flags=0x%08x", ce->flags));
507 (
"invalid unit ce->unit=0x%08x dev2unit=0x%08x",
508 ce->unit, dev2unit(
dev)));
514 ce->flags &= ~SND_CLONE_ALLOC;
523 int cunit, allocunit;
529 (
"invalid tmask: typemask=0x%08x tmask=0x%08x",
530 c->typemask, tmask));
533 (
"typemask collision: typemask=0x%08x tmask=0x%08x *unit=%d",
534 c->typemask, tmask, *unit));
537 (*unit != -1 && *unit >
c->maxunit))
547 allocunit = (*unit == -1) ? 0 : *unit;
548 curpid = curthread->td_proc->p_pid;
552 TAILQ_FOREACH(ce, &
c->head, link) {
556 if (tmask > (ce->unit &
c->typemask)) {
560 }
else if (tmask < (ce->unit &
c->typemask))
567 if (*unit != -1 && *unit == (ce->unit & ~tmask))
568 goto snd_clone_alloc_out;
576 if (*unit == -1 && (ce->unit & ~tmask) == allocunit)
578 if ((ce->unit & ~tmask) < allocunit)
592 if (ce->devt != NULL && (bce == NULL ||
593 timespeccmp(&ce->tsp, &bce->tsp, <)))
597 if (ce->pid == curpid &&
598 (cce == NULL || timespeccmp(&ce->tsp, &cce->tsp, <)))
601 (nce == NULL || timespeccmp(&ce->tsp, &nce->tsp, <)))
603 else if (tce == NULL || timespeccmp(&ce->tsp, &tce->tsp, <))
607 goto snd_clone_alloc_new;
608 else if (cce != NULL) {
611 goto snd_clone_alloc_out;
612 }
else if (nce != NULL) {
617 if (allocunit < (nce->unit & ~tmask))
618 goto snd_clone_alloc_new;
620 goto snd_clone_alloc_out;
621 }
else if (allocunit >
c->maxunit) {
631 goto snd_clone_alloc_out;
632 }
else if (bce != NULL) {
634 goto snd_clone_alloc_out;
651 ce = malloc(
sizeof(*ce), M_DEVBUF,
662 goto snd_clone_alloc_out;
663 }
else if (tce != NULL) {
665 goto snd_clone_alloc_out;
666 }
else if (bce != NULL) {
668 goto snd_clone_alloc_out;
674 ce->unit = tmask | allocunit;
679 TAILQ_INSERT_AFTER(&
c->head, after, ce, link);
681 TAILQ_INSERT_HEAD(&
c->head, ce, link);
uint32_t snd_clone_getdevflags(struct cdev *dev)
int snd_clone_busy(struct snd_clone *c)
struct snd_clone * snd_clone_create(int typemask, int maxunit, int deadline, uint32_t flags)
struct snd_clone_entry * snd_clone_alloc(struct snd_clone *c, struct cdev **dev, int *unit, int tmask)
#define SND_CLONE_ASSERT(...)
uint32_t snd_clone_setflags(struct snd_clone *c, uint32_t flags)
int snd_clone_getsize(struct snd_clone *c)
int snd_clone_setmaxunit(struct snd_clone *c, int maxunit)
int snd_clone_acquire(struct cdev *dev)
int snd_clone_disable(struct snd_clone *c)
uint32_t snd_clone_getflags(struct snd_clone *c)
void snd_clone_register(struct snd_clone_entry *ce, struct cdev *dev)
int snd_clone_setdeadline(struct snd_clone *c, int deadline)
int snd_clone_enable(struct snd_clone *c)
int snd_clone_release(struct cdev *dev)
uint32_t snd_clone_setdevflags(struct cdev *dev, uint32_t flags)
int snd_clone_getdeadline(struct snd_clone *c)
int snd_clone_gc(struct snd_clone *c)
int snd_clone_getmaxunit(struct snd_clone *c)
int snd_clone_unref(struct cdev *dev)
#define SND_CLONE_EXPIRED(x, y, z)
int snd_clone_ref(struct cdev *dev)
void snd_clone_destroy(struct snd_clone *c)
#define SND_CLONE_DEVMASK
#define SND_CLONE_MAXUNIT
#define SND_CLONE_GC_UNREF
#define SND_CLONE_GC_REVOKE
#define SND_CLONE_GC_ENABLE
#define SND_CLONE_GC_LASTREF
#define SND_CLONE_GC_EXPIRED