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:
parent
2127ab9a07
commit
2e60812e3a
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user