Co-authored by: meka@tilda.center
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Details
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 2998 | This function is set only in the EVFILT_READ case in dsp_kqueue(), so I suppose it is redundant to check for kn->kn_filter == EVFILT_READ here? Same for dsp_write_filter(). Or can kn->kn_filter have a different value? | |
| 2999 | From the man page description of the f_event method, I am not really sure what we want to store here. Is there a particular reason you chose sndbuf_getallocsize()? | |
I changed the code based on the comments, but I didn't add test program, yet. Give me some more time.
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 2999 | I saw what SNDCTL_DSP_GETOSPACE does and did the same. | |
I was wrong about what SNDCTL_DSP_GETOSPACE and SNDCTL_DSP_GETISPACE do, hence the update.
| share/examples/sound/oss/audio.c | ||
|---|---|---|
| 363 | The EXAMPLE_POLL case waits on POLLIN, but here we arm the EVFILT_WRITE event. It feels like it should be EVFILT_READ instead? | |
The test patch should be a separate commit. You can link to it here in the "Test Plan" section (click "Edit Revision" and you'll see it). But I'm starting to think this is becoming more of a test program than an example one. Maybe we should think about it moving it to tests, and making some more straight-forward ones for /usr/share/examples.
| share/examples/sound/oss/audio.c | ||
|---|---|---|
| 41 | Better to have this above sys/soundcard.h, as per style(9). | |
| sys/dev/sound/pcm/dsp.c | ||
| 2989 | Why do we call knlist_remove() only when CHN_F_DEAD is not set, but dsp_kqfilter() calls knlist_add() unconditionally? This is not a hint to remove the check, but to understand why the check is here in the first place. | |
| 3009 | According to kqueue.9:
Here we assign kn_data to an errno value instead. Shouldn't we assign it to 0? | |
| 3011 | Doesn't a return value of 1 indicate that there was no error? | |
| 3067 | You can assign this to 0 here and avoid setting it to 0 below for every case. | |
There are a lot of unresolved reviewer's notes. Do you really need more reviewers, at least until all existing suggestions are handled?
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3033 | I do not think that cdevpriv pointer is ever set for the context of the kqueue read or write filters. You should have enough context in the knote itself to fetch everything needed to check for the filter conditions. | |
| 3044 | Extra empty line | |
| 3105 | ||
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3033 | If that's the case, kn_hook in dsp_kqfilter() can just be the cdevpriv and we can then fetch the appropriate channel here through it. We do the same in dsp_read() and dsp_write(). | |
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 2989 | I thought that if channel was dead, it already detached the queue. I would need to think about how to test this. | |
| 3009 | If you look at kqueue(2) example, there is if (tevent.flags & EV_ERROR)
errx(EXIT_FAILURE, "Event error: %s", strerror(event.data));So I think this works according to kqueue specs. | |
| 3011 | No, it indicates if knote is still valid or not. That's how cuse does it, hence virtual_oss behaves the same. | |
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3009 | @kib Is there some kind of mismatch between kqueue.9 and kqueue.2, or do I just misunderstand something? Because kqueue.9 does not specify that, as I mentioned above. | |
| 3011 | I am not 100% sure I understand what kqueue.2's RETURN VALUES section tries to say to be honest, as in, I do not really get when we should return -1 and when !0. | |
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3009 | I had much problems figuring out how to add kqueue support and as virtual_oss uses cuse, I used cuse's implementation of kqueue support as reference. In the process I did add my notes to kqueue(9) in a separate branch in my github fork. One of my goals of this implementation is to make that man page better, but one thing at a time. | |
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3011 | Can you say exactly which sentences from kqueue.2 and kqueue.9 contradicts each other? That said, neither of man pages ever states that knote f_event returns an error. f_event should return 0 for inactive knote, and non-zero if knot was activated somehow. | |
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3011 | My comment about mismatching (not contradicting) statements between kqueue.2 and kqueue.9 is above, it does not refer to here. kqueue.9 says that kn_data holds the value of available bytes for reading/buffer spacing available for writing, but kqueue.2 shows event.data holding an errno value in case of an error, but this is not documented in kqueue.9. | |
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3011 | Practically filters never return errors. And definitely they do not set EV_ERROR, I would be curious to see an example. EV_ERROR is described conscientiously in kqueue.2. The reason why filters do not need to return error is because registered knotes must be torn down before the object they monitor is destroyed. If the object is lingering in error state, there is simply nothing to report, so knotes should be not activated. When a knote is activated, then kn_data become something that knote set according to the semantic of its filter. | |
I've been testing the patch and trying to fix the panic you mentioned in D53029, although there is one more panic in dsp_kqdetach() that I'm working on. The code needs a few changes, is it okay if I take over the revision, at least for now, so that it's easier to upload the new changes?
To be honest, I hoped you'll say that if I expose the bug in a somewhat repeatable way 😄 Anyway, go for it and good luck!
Take over revision, at least for now. All tests in D53188 pass with the new
changes.
- Fix panic in the filter functions, and do not acquire locks inside them, per kqueue.9.
- Fix a crash in dsp_kqdetach(), which was a result of unconditionally calling knlist_remove() on both channels, which means that if, for example, we set only EVFILT_WRITE (like in the test in D53188), we will call knlist_remove() on both the read and the write channels, but the read one will cause a panic inside knlist_remove_kq(), because we haven't called knlist_add() for it in dsp_kqfilter().
- Fix a hang resulting from KNOTE_LOCKED() not being called in chn_wakeup().
- Do not enter Giant in dsp_kqdetach(), but I am actually not 100% sure if we need it or not.
- s/LOCKOWNED/LOCKASSERT/
- Use chn_polltrigger() to determine whether we are ready for IO. This how chn_poll() already works for servicing poll(2) and select(2).
- Initialize and destroy the knlist in chn_init() and chn_kill() respectively, as opposed to dsp_open() and dsp_close().
- Are the return values from dsp_kqevent() correct?
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3009 | Is it actually possible to have !DSP_REGISTERED() here? Shouldn't we have drained knotes by that point? | |
| 3023 | This function should be structured so that this default case can't happen. dsp_kqfilter() can set kn->kn_ptr.p_v = ch and then this function can obtain the channel directly. | |
| 3027 | kn_data shouldn't be abused to return an error number. You can use kn_fflags to return this instead, if it's necessary. More standard would be to set EV_EOF and return 1, I suspect. | |
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3023 | Also since we can remove the DSP_REGISTERED() check, we can instead pass the channel to kn->kn_hook now. | |
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 3027 | Do we have good docs on what to return when hardware dies? I've seen a mix of ENXIO and ENODEV and kinda think the former is better since the latter indicates it's not supported (or so the error message says, with these in-kernel protocols, it's hard to say for sure). But I also know that's a storage-centric view since that's what we do there when the device is gone and is in a state where it can't come back. | |
Looks ok to me aside from the comment.
| sys/dev/sound/pcm/dsp.c | ||
|---|---|---|
| 2991 | I don't see how it's possible to have ch == NULL here. If there is no channel we won't create the knote to begin with. | |