Page MenuHomeFreeBSD

D54168.diff
No OneTemporary

D54168.diff

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
@@ -10,10 +10,12 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/mutex.h>
#include <sys/uio.h>
#include <sys/conf.h>
#include <sys/ctype.h>
#include <sys/malloc.h>
+#include <machine/atomic.h>
#include <machine/clock.h>
#include <dev/speaker/speaker.h>
@@ -24,7 +26,6 @@
static struct cdevsw spkr_cdevsw = {
.d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
.d_open = spkropen,
.d_close = spkrclose,
.d_write = spkrwrite,
@@ -71,23 +72,27 @@
(void) printf("tone: thz=%d centisecs=%d\n", thz, centisecs);
#endif /* DEBUG */
- /* set timer to generate clicks at given frequency in Hertz */
+ /*
+ * Acquire the i8254 clock, configure it to drive the speaker
+ * signal, and turn on the speaker.
+ */
if (timer_spkr_acquire()) {
- /* enter list of waiting procs ??? */
return;
}
- disable_intr();
+ /* Configure the speaker with the tone frequency. */
timer_spkr_setfreq(thz);
- enable_intr();
/*
- * Set timeout to endtone function, then give up the timeslice.
- * This is so other processes can execute while the tone is being
+ * Make the current thread sleep while the tone is being
* emitted.
*/
timo = centisecs * hz / 100;
if (timo > 0)
tsleep(&endtone, SPKRPRI | PCATCH, "spkrtn", timo);
+
+ /*
+ * Turn off the speaker and release the i8254 clock.
+ */
timer_spkr_release();
}
@@ -390,7 +395,8 @@
* endtone(), and rest() functions defined above.
*/
-static bool spkr_active = false; /* exclusion flag */
+static int spkr_dev_busy = 0; /* one open at a time */
+static struct mtx spkr_op_locked; /* lock for write/ioctl */
static char *spkr_inbuf; /* incoming buf */
static int
@@ -400,7 +406,7 @@
(void) printf("spkropen: entering with dev = %s\n", devtoname(dev));
#endif /* DEBUG */
- if (spkr_active)
+ if (!atomic_cmpset_int(&spkr_dev_busy, 0, 1))
return(EBUSY);
else {
#ifdef DEBUG
@@ -408,7 +414,6 @@
#endif /* DEBUG */
playinit();
spkr_inbuf = malloc(DEV_BSIZE, M_SPKR, M_WAITOK);
- spkr_active = true;
return(0);
}
}
@@ -428,6 +433,7 @@
char *cp;
int error;
+ mtx_lock(&spkr_op_locked);
n = uio->uio_resid;
cp = spkr_inbuf;
error = uiomove(cp, n, uio);
@@ -435,7 +441,8 @@
cp[n] = '\0';
playstring(cp, n);
}
- return(error);
+ mtx_unlock(&spkr_op_locked);
+ return(error);
}
}
@@ -449,7 +456,7 @@
wakeup(&endtone);
wakeup(&endrest);
free(spkr_inbuf, M_SPKR);
- spkr_active = false;
+ (void) atomic_swap_int(&spkr_dev_busy, 0);
return(0);
}
@@ -465,20 +472,25 @@
if (cmd == SPKRTONE) {
tone_t *tp = (tone_t *)cmdarg;
+ mtx_lock(&spkr_op_locked);
if (tp->frequency == 0)
rest(tp->duration);
else
tone(tp->frequency, tp->duration);
+ mtx_unlock(&spkr_op_locked);
return 0;
} else if (cmd == SPKRTUNE) {
tone_t *tp = (tone_t *)(*(caddr_t *)cmdarg);
tone_t ttp;
int error;
+ mtx_lock(&spkr_op_locked);
for (; ; tp++) {
error = copyin(tp, &ttp, sizeof(tone_t));
- if (error)
+ if (error) {
+ mtx_unlock(&spkr_op_locked);
return(error);
+ }
if (ttp.duration == 0)
break;
@@ -488,6 +500,7 @@
else
tone(ttp.frequency, ttp.duration);
}
+ mtx_unlock(&spkr_op_locked);
return(0);
}
return(EINVAL);
@@ -504,7 +517,8 @@
int error = 0;
switch(type) {
- case MOD_LOAD:
+ case MOD_LOAD:
+ mtx_init(&spkr_op_locked, "spkr", NULL, MTX_DEF);
speaker_dev = make_dev(&spkr_cdevsw, 0,
UID_ROOT, GID_WHEEL, 0600, "speaker");
break;

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 8, 5:17 AM (16 h, 28 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27470188
Default Alt Text
D54168.diff (3 KB)

Event Timeline