| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: audio.c,v 1.29 2019/08/23 09:41:26 maxv Exp $ */ | | 1 | /* $NetBSD: audio.c,v 1.30 2019/08/29 13:01:07 isaki Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Andrew Doran. | | 8 | * by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -132,27 +132,27 @@ | | | @@ -132,27 +132,27 @@ |
132 | * these may be also called after attach, the thread lock is required. | | 132 | * these may be also called after attach, the thread lock is required. |
133 | * | | 133 | * |
134 | * In addition, there is an additional lock. | | 134 | * In addition, there is an additional lock. |
135 | * | | 135 | * |
136 | * - track->lock. This is an atomic variable and is similar to the | | 136 | * - track->lock. This is an atomic variable and is similar to the |
137 | * "interrupt lock". This is one for each track. If any thread context | | 137 | * "interrupt lock". This is one for each track. If any thread context |
138 | * (and software interrupt context) and hardware interrupt context who | | 138 | * (and software interrupt context) and hardware interrupt context who |
139 | * want to access some variables on this track, they must acquire this | | 139 | * want to access some variables on this track, they must acquire this |
140 | * lock before. It protects track's consistency between hardware | | 140 | * lock before. It protects track's consistency between hardware |
141 | * interrupt context and others. | | 141 | * interrupt context and others. |
142 | */ | | 142 | */ |
143 | | | 143 | |
144 | #include <sys/cdefs.h> | | 144 | #include <sys/cdefs.h> |
145 | __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.29 2019/08/23 09:41:26 maxv Exp $"); | | 145 | __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.30 2019/08/29 13:01:07 isaki Exp $"); |
146 | | | 146 | |
147 | #ifdef _KERNEL_OPT | | 147 | #ifdef _KERNEL_OPT |
148 | #include "audio.h" | | 148 | #include "audio.h" |
149 | #include "midi.h" | | 149 | #include "midi.h" |
150 | #endif | | 150 | #endif |
151 | | | 151 | |
152 | #if NAUDIO > 0 | | 152 | #if NAUDIO > 0 |
153 | | | 153 | |
154 | #ifdef _KERNEL | | 154 | #ifdef _KERNEL |
155 | | | 155 | |
156 | #include <sys/types.h> | | 156 | #include <sys/types.h> |
157 | #include <sys/param.h> | | 157 | #include <sys/param.h> |
158 | #include <sys/atomic.h> | | 158 | #include <sys/atomic.h> |
| @@ -5720,67 +5720,93 @@ audio_track_drain(struct audio_softc *sc | | | @@ -5720,67 +5720,93 @@ audio_track_drain(struct audio_softc *sc |
5720 | if (error) | | 5720 | if (error) |
5721 | return error; | | 5721 | return error; |
5722 | | | 5722 | |
5723 | /* XXX call audio_track_play here ? */ | | 5723 | /* XXX call audio_track_play here ? */ |
5724 | } | | 5724 | } |
5725 | | | 5725 | |
5726 | track->pstate = AUDIO_STATE_CLEAR; | | 5726 | track->pstate = AUDIO_STATE_CLEAR; |
5727 | TRACET(3, track, "done trk_inp=%d trk_out=%d", | | 5727 | TRACET(3, track, "done trk_inp=%d trk_out=%d", |
5728 | (int)track->inputcounter, (int)track->outputcounter); | | 5728 | (int)track->inputcounter, (int)track->outputcounter); |
5729 | return 0; | | 5729 | return 0; |
5730 | } | | 5730 | } |
5731 | | | 5731 | |
5732 | /* | | 5732 | /* |
| | | 5733 | * Send signal to process. |
| | | 5734 | * This is intended to be called only from audio_softintr_{rd,wr}. |
| | | 5735 | * Must be called with sc_lock && sc_intr_lock held. |
| | | 5736 | */ |
| | | 5737 | static inline void |
| | | 5738 | audio_psignal(struct audio_softc *sc, pid_t pid, int signum) |
| | | 5739 | { |
| | | 5740 | proc_t *p; |
| | | 5741 | |
| | | 5742 | KASSERT(mutex_owned(sc->sc_lock)); |
| | | 5743 | KASSERT(mutex_owned(sc->sc_intr_lock)); |
| | | 5744 | KASSERT(pid != 0); |
| | | 5745 | |
| | | 5746 | /* |
| | | 5747 | * psignal() must be called without spin lock held. |
| | | 5748 | * So leave intr_lock temporarily here. |
| | | 5749 | */ |
| | | 5750 | mutex_exit(sc->sc_intr_lock); |
| | | 5751 | |
| | | 5752 | mutex_enter(proc_lock); |
| | | 5753 | p = proc_find(pid); |
| | | 5754 | if (p) |
| | | 5755 | psignal(p, signum); |
| | | 5756 | mutex_exit(proc_lock); |
| | | 5757 | |
| | | 5758 | /* Enter intr_lock again */ |
| | | 5759 | mutex_enter(sc->sc_intr_lock); |
| | | 5760 | } |
| | | 5761 | |
| | | 5762 | /* |
5733 | * This is software interrupt handler for record. | | 5763 | * This is software interrupt handler for record. |
5734 | * It is called from recording hardware interrupt everytime. | | 5764 | * It is called from recording hardware interrupt everytime. |
5735 | * It does: | | 5765 | * It does: |
5736 | * - Deliver SIGIO for all async processes. | | 5766 | * - Deliver SIGIO for all async processes. |
5737 | * - Notify to audio_read() that data has arrived. | | 5767 | * - Notify to audio_read() that data has arrived. |
5738 | * - selnotify() for select/poll-ing processes. | | 5768 | * - selnotify() for select/poll-ing processes. |
5739 | */ | | 5769 | */ |
5740 | /* | | 5770 | /* |
5741 | * XXX If a process issues FIOASYNC between hardware interrupt and | | 5771 | * XXX If a process issues FIOASYNC between hardware interrupt and |
5742 | * software interrupt, (stray) SIGIO will be sent to the process | | 5772 | * software interrupt, (stray) SIGIO will be sent to the process |
5743 | * despite the fact that it has not receive recorded data yet. | | 5773 | * despite the fact that it has not receive recorded data yet. |
5744 | */ | | 5774 | */ |
5745 | static void | | 5775 | static void |
5746 | audio_softintr_rd(void *cookie) | | 5776 | audio_softintr_rd(void *cookie) |
5747 | { | | 5777 | { |
5748 | struct audio_softc *sc = cookie; | | 5778 | struct audio_softc *sc = cookie; |
5749 | audio_file_t *f; | | 5779 | audio_file_t *f; |
5750 | proc_t *p; | | | |
5751 | pid_t pid; | | 5780 | pid_t pid; |
5752 | | | 5781 | |
5753 | mutex_enter(sc->sc_lock); | | 5782 | mutex_enter(sc->sc_lock); |
5754 | mutex_enter(sc->sc_intr_lock); | | 5783 | mutex_enter(sc->sc_intr_lock); |
5755 | | | 5784 | |
5756 | SLIST_FOREACH(f, &sc->sc_files, entry) { | | 5785 | SLIST_FOREACH(f, &sc->sc_files, entry) { |
5757 | audio_track_t *track = f->rtrack; | | 5786 | audio_track_t *track = f->rtrack; |
5758 | | | 5787 | |
5759 | if (track == NULL) | | 5788 | if (track == NULL) |
5760 | continue; | | 5789 | continue; |
5761 | | | 5790 | |
5762 | TRACET(4, track, "broadcast; inp=%d/%d/%d", | | 5791 | TRACET(4, track, "broadcast; inp=%d/%d/%d", |
5763 | track->input->head, | | 5792 | track->input->head, |
5764 | track->input->used, | | 5793 | track->input->used, |
5765 | track->input->capacity); | | 5794 | track->input->capacity); |
5766 | | | 5795 | |
5767 | pid = f->async_audio; | | 5796 | pid = f->async_audio; |
5768 | if (pid != 0) { | | 5797 | if (pid != 0) { |
5769 | TRACEF(4, f, "sending SIGIO %d", pid); | | 5798 | TRACEF(4, f, "sending SIGIO %d", pid); |
5770 | mutex_enter(proc_lock); | | 5799 | audio_psignal(sc, pid, SIGIO); |
5771 | if ((p = proc_find(pid)) != NULL) | | | |
5772 | psignal(p, SIGIO); | | | |
5773 | mutex_exit(proc_lock); | | | |
5774 | } | | 5800 | } |
5775 | } | | 5801 | } |
5776 | mutex_exit(sc->sc_intr_lock); | | 5802 | mutex_exit(sc->sc_intr_lock); |
5777 | | | 5803 | |
5778 | /* Notify that data has arrived. */ | | 5804 | /* Notify that data has arrived. */ |
5779 | selnotify(&sc->sc_rsel, 0, NOTE_SUBMIT); | | 5805 | selnotify(&sc->sc_rsel, 0, NOTE_SUBMIT); |
5780 | KNOTE(&sc->sc_rsel.sel_klist, 0); | | 5806 | KNOTE(&sc->sc_rsel.sel_klist, 0); |
5781 | cv_broadcast(&sc->sc_rmixer->outcv); | | 5807 | cv_broadcast(&sc->sc_rmixer->outcv); |
5782 | | | 5808 | |
5783 | mutex_exit(sc->sc_lock); | | 5809 | mutex_exit(sc->sc_lock); |
5784 | } | | 5810 | } |
5785 | | | 5811 | |
5786 | /* | | 5812 | /* |
| @@ -5789,61 +5815,59 @@ audio_softintr_rd(void *cookie) | | | @@ -5789,61 +5815,59 @@ audio_softintr_rd(void *cookie) |
5789 | * It does: | | 5815 | * It does: |
5790 | * - Deliver SIGIO for all async and writable (used < lowat) processes. | | 5816 | * - Deliver SIGIO for all async and writable (used < lowat) processes. |
5791 | * - Notify to audio_write() that outbuf block available. | | 5817 | * - Notify to audio_write() that outbuf block available. |
5792 | * - selnotify() for select/poll-ing processes if there are any writable | | 5818 | * - selnotify() for select/poll-ing processes if there are any writable |
5793 | * (used < lowat) processes. Checking each descriptor will be done by | | 5819 | * (used < lowat) processes. Checking each descriptor will be done by |
5794 | * filt_audiowrite_event(). | | 5820 | * filt_audiowrite_event(). |
5795 | */ | | 5821 | */ |
5796 | static void | | 5822 | static void |
5797 | audio_softintr_wr(void *cookie) | | 5823 | audio_softintr_wr(void *cookie) |
5798 | { | | 5824 | { |
5799 | struct audio_softc *sc = cookie; | | 5825 | struct audio_softc *sc = cookie; |
5800 | audio_file_t *f; | | 5826 | audio_file_t *f; |
5801 | bool found; | | 5827 | bool found; |
5802 | proc_t *p; | | | |
5803 | pid_t pid; | | 5828 | pid_t pid; |
5804 | | | 5829 | |
5805 | TRACE(4, "called"); | | 5830 | TRACE(4, "called"); |
5806 | found = false; | | 5831 | found = false; |
5807 | | | 5832 | |
5808 | mutex_enter(sc->sc_lock); | | 5833 | mutex_enter(sc->sc_lock); |
5809 | mutex_enter(sc->sc_intr_lock); | | 5834 | mutex_enter(sc->sc_intr_lock); |
5810 | | | 5835 | |
5811 | SLIST_FOREACH(f, &sc->sc_files, entry) { | | 5836 | SLIST_FOREACH(f, &sc->sc_files, entry) { |
5812 | audio_track_t *track = f->ptrack; | | 5837 | audio_track_t *track = f->ptrack; |
5813 | | | 5838 | |
5814 | if (track == NULL) | | 5839 | if (track == NULL) |
5815 | continue; | | 5840 | continue; |
5816 | | | 5841 | |
5817 | TRACET(4, track, "broadcast; trseq=%d out=%d/%d/%d", | | 5842 | TRACET(4, track, "broadcast; trseq=%d out=%d/%d/%d", |
5818 | (int)track->seq, | | 5843 | (int)track->seq, |
5819 | track->outbuf.head, | | 5844 | track->outbuf.head, |
5820 | track->outbuf.used, | | 5845 | track->outbuf.used, |
5821 | track->outbuf.capacity); | | 5846 | track->outbuf.capacity); |
5822 | | | 5847 | |
5823 | /* | | 5848 | /* |
5824 | * Send a signal if the process is async mode and | | 5849 | * Send a signal if the process is async mode and |
5825 | * used is lower than lowat. | | 5850 | * used is lower than lowat. |
5826 | */ | | 5851 | */ |
5827 | if (track->usrbuf.used <= track->usrbuf_usedlow && | | 5852 | if (track->usrbuf.used <= track->usrbuf_usedlow && |
5828 | !track->is_pause) { | | 5853 | !track->is_pause) { |
| | | 5854 | /* For selnotify */ |
5829 | found = true; | | 5855 | found = true; |
| | | 5856 | /* For SIGIO */ |
5830 | pid = f->async_audio; | | 5857 | pid = f->async_audio; |
5831 | if (pid != 0) { | | 5858 | if (pid != 0) { |
5832 | TRACEF(4, f, "sending SIGIO %d", pid); | | 5859 | TRACEF(4, f, "sending SIGIO %d", pid); |
5833 | mutex_enter(proc_lock); | | 5860 | audio_psignal(sc, pid, SIGIO); |
5834 | if ((p = proc_find(pid)) != NULL) | | | |
5835 | psignal(p, SIGIO); | | | |
5836 | mutex_exit(proc_lock); | | | |
5837 | } | | 5861 | } |
5838 | } | | 5862 | } |
5839 | } | | 5863 | } |
5840 | mutex_exit(sc->sc_intr_lock); | | 5864 | mutex_exit(sc->sc_intr_lock); |
5841 | | | 5865 | |
5842 | /* | | 5866 | /* |
5843 | * Notify for select/poll when someone become writable. | | 5867 | * Notify for select/poll when someone become writable. |
5844 | * It needs sc_lock (and not sc_intr_lock). | | 5868 | * It needs sc_lock (and not sc_intr_lock). |
5845 | */ | | 5869 | */ |
5846 | if (found) { | | 5870 | if (found) { |
5847 | TRACE(4, "selnotify"); | | 5871 | TRACE(4, "selnotify"); |
5848 | selnotify(&sc->sc_wsel, 0, NOTE_SUBMIT); | | 5872 | selnotify(&sc->sc_wsel, 0, NOTE_SUBMIT); |
5849 | KNOTE(&sc->sc_wsel.sel_klist, 0); | | 5873 | KNOTE(&sc->sc_wsel.sel_klist, 0); |