Fix the spl handling. There's still the effect that the timers have

sometimes already been released at the time pcaclose() is called, but
this is now prevented from deadlocking by checking for a running timer
at the start of pca_wait().

At least, i can now play xboing again with pcaudio, this used to hang
the entire system previously within a few seconds.
This commit is contained in:
Joerg Wunsch 1996-06-09 14:23:13 +00:00
parent 2127ab9a07
commit 2e60812e3a

View File

@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: pcaudio.c,v 1.26 1995/12/22 15:27:48 bde Exp $
* $Id: pcaudio.c,v 1.27 1996/03/28 14:28:47 scrappy Exp $
*/
#include "pca.h"
@ -166,6 +166,9 @@ pca_init()
static int
pca_start(void)
{
int x = splhigh();
int rv = 0;
/* use the first buffer */
pca_status.current = 0;
pca_status.index = 0;
@ -173,21 +176,24 @@ pca_start(void)
pca_status.buffer = pca_status.buf[pca_status.current];
pca_status.oldval = inb(IO_PPI) | 0x03;
/* acquire the timers */
if (acquire_timer2(TIMER_LSB|TIMER_ONESHOT)) {
return -1;
}
if (acquire_timer0(INTERRUPT_RATE, pcaintr)) {
if (acquire_timer2(TIMER_LSB|TIMER_ONESHOT))
rv = -1;
else if (acquire_timer0(INTERRUPT_RATE, pcaintr)) {
release_timer2();
return -1;
}
pca_status.timer_on = 1;
return 0;
rv = -1;
} else
pca_status.timer_on = 1;
splx(x);
return rv;
}
static void
pca_stop(void)
{
int x = splhigh();
/* release the timers */
release_timer0();
release_timer2();
@ -198,37 +204,49 @@ pca_stop(void)
pca_status.current = 0;
pca_status.buffer = pca_status.buf[pca_status.current];
pca_status.timer_on = 0;
splx(x);
}
static void
pca_pause()
{
int x = splhigh();
release_timer0();
release_timer2();
pca_status.timer_on = 0;
splx(x);
}
static void
pca_continue()
{
int x = splhigh();
pca_status.oldval = inb(IO_PPI) | 0x03;
acquire_timer2(TIMER_LSB|TIMER_ONESHOT);
acquire_timer0(INTERRUPT_RATE, pcaintr);
pca_status.timer_on = 1;
splx(x);
}
static int
pca_wait(void)
{
int error;
int error, x;
if (!pca_status.timer_on)
return 0;
while (pca_status.in_use[0] || pca_status.in_use[1]) {
x = spltty();
pca_sleep = 1;
error = tsleep(&pca_sleep, PZERO|PCATCH, "pca_drain", 0);
pca_sleep = 0;
splx(x);
if (error != 0 && error != ERESTART) {
pca_stop();
return error;
@ -332,7 +350,7 @@ pcaclose(dev_t dev, int flags, int fmt, struct proc *p)
static int
pcawrite(dev_t dev, struct uio *uio, int flag)
{
int count, error, which;
int count, error, which, x;
/* only audio device can be written */
if (minor(dev) > 0)
@ -340,9 +358,11 @@ pcawrite(dev_t dev, struct uio *uio, int flag)
while ((count = min(BUF_SIZE, uio->uio_resid)) > 0) {
if (pca_status.in_use[0] && pca_status.in_use[1]) {
x = spltty();
pca_sleep = 1;
error = tsleep(&pca_sleep, PZERO|PCATCH, "pca_wait", 0);
pca_sleep = 0;
splx(x);
if (error != 0 && error != ERESTART) {
pca_stop();
return error;
@ -457,10 +477,8 @@ pcaintr(struct clockframe *frame)
pca_status.in_use[pca_status.current] = 0;
pca_status.current ^= 1;
pca_status.buffer = pca_status.buf[pca_status.current];
if (pca_sleep) {
if (pca_sleep)
wakeup(&pca_sleep);
pca_sleep = 0;
}
if (pca_status.wsel.si_pid) {
selwakeup((struct selinfo *)&pca_status.wsel.si_pid);
pca_status.wsel.si_pid = 0;