Re: [PATCH] ALSA: seq: midi: wait for output buffer space on non-atomic delivery

From: Takashi Iwai

Date: Wed Sep 02 2026 - 10:12:02 EST


On Tue, 01 Sep 2026 16:38:03 +0200,
Junjie Cao wrote:
>
> On Tue, 01 Sep 2026 12:49:43 +0200, Takashi Iwai wrote:
> > But, the problem is that you can't take long time in
> > dump_midi() which is called from the sequencer event handler, per
> > design; the atomic=false there doesn't mean that you are allowed to
> > block for a too long time like 30 seconds.
>
> Right, dropping this one.
>
> > For working around this problem, we need a basic design change in ALSA
> > sequencer core, I'm afraid.
>
> Would you take an RFC along these lines, or do you have a different
> shape in mind?
>
> - event_input gets a way to say "port full": the core parks the event
> on a per-port FIFO instead of dropping it, copying direct/USRPTR
> payloads into the sender's pool cells (snd_seq_event_dup(),
> non-blocking). While the FIFO is non-empty, further events for
> that port queue behind it.
> - The kernel client signals readiness through a new snd_seq_kernel_*
> call and a work item re-offers the parked cells. seq_midi would
> drive that from rawmidi's transmit ack, mirroring the input-side
> runtime->event hook.
> - Backpressure stays at the sender's pool, the only place that sleeps
> today: a blocking writer with parked cells waits for pool space
> before its next direct dispatch, with ioctl_mutex dropped as
> snd_seq_cell_alloc() does; poll() already reports pool room.
> Nothing sleeps inside delivery.
> - Client exit purges its parked cells from every port, as
> snd_seq_queue_client_leave() does for queues; port deletion frees
> the FIFO.
>
> Open points: a SysEx bigger than the rawmidi buffer is consumed
> partially, so the resume offset has to live in the parked entry or in
> the driver; one event larger than the sender's pool cannot be parked
> at all (the limit queued events already have); a broadcast is
> duplicated per blocked destination. Drivers that never report "full"
> keep the current behaviour.

As mentioned, this is no new problem but a known issue (rather from
the beginning) over decades. So it's no hurry about the fix time
frame :)

In ALSA sequencer core, the event packet delivery itself must not be
blocked too long -- so waiting at callback (that happens at the
delivery) won't work well. Otherwise this will block the delivery of
other events. Although in the case of seq-midi it might work because
it's handled in a work, the same problem happens for other clients,
hence we'd have to tackle in ALSA sequencer core side more properly.

My idea has no solid shape yet, but its basic form would be something
to push-back and re-deliver of event packets. For a large data like
SysEx, it should support a partial (re-)delivery, too.

Instead of blocking the delivery, if the buffer is full, it's pushed
back, and rescheduled. Obviously, this reschedule would work only for
the queued event delivery from the pool. When it's transferred as a
direct delivery, it should just fail like the current version.
And, if the destination client gives some partial success, we'd have
to record the succeeded size, so that the re-delivery begins from the
right point, too.

So far, so good. The problem surfaced, however, when there are
multiple destination targets from a client/port; then one (or a few)
of them might block while others can process fully. Handling for this
situation has to be implemented somehow. I can imagine to extend the
struct snd_seq_subscribers and struct snd_seq_port_subs_info to track
the pending events per connection, but not sure whether this can fly
well...


thanks,

Takashi