diff --git a/sys/dev/speaker/spkr.c b/sys/dev/speaker/spkr.c --- a/sys/dev/speaker/spkr.c +++ b/sys/dev/speaker/spkr.c @@ -14,9 +14,12 @@ #include #include #include +#include #include #include +static struct sema spkr_sema; + static d_open_t spkropen; static d_close_t spkrclose; static d_write_t spkrwrite; @@ -24,7 +27,6 @@ static struct cdevsw spkr_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = spkropen, .d_close = spkrclose, .d_write = spkrwrite, @@ -396,7 +398,6 @@ * endtone(), and rest() functions defined above. */ -static int spkr_active = FALSE; /* exclusion flag */ static char *spkr_inbuf; /* incoming buf */ static int @@ -406,17 +407,17 @@ (void) printf("spkropen: entering with dev = %s\n", devtoname(dev)); #endif /* DEBUG */ - if (spkr_active) + int r; + + r = sema_trywait(&spkr_sema); + if (r == 0) return(EBUSY); - else { #ifdef DEBUG - (void) printf("spkropen: about to perform play initialization\n"); + (void) printf("spkropen: about to perform play initialization\n"); #endif /* DEBUG */ - playinit(); - spkr_inbuf = malloc(DEV_BSIZE, M_SPKR, M_WAITOK); - spkr_active = TRUE; - return(0); - } + playinit(); + spkr_inbuf = malloc(DEV_BSIZE, M_SPKR, M_WAITOK); + return(0); } static int @@ -455,7 +456,7 @@ wakeup(&endtone); wakeup(&endrest); free(spkr_inbuf, M_SPKR); - spkr_active = FALSE; + sema_post(&spkr_sema); return(0); } @@ -511,12 +512,14 @@ switch(type) { case MOD_LOAD: + sema_init(&spkr_sema, 1, "speaker device semaphore"); speaker_dev = make_dev(&spkr_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "speaker"); break; case MOD_SHUTDOWN: case MOD_UNLOAD: destroy_dev(speaker_dev); + sema_destroy(&spkr_sema); break; default: error = EOPNOTSUPP;