Yeah I suppose a "full" lock would do. (That was what I was trying to point out. I don't really understand Pierre's message. I merely suppose you need some facility in the kernel anyway so that you can lock from userspace.) I hope that amixer the utility will at least have the capability to reschedule/wait by then though (instead of just "failing" like in your python demo).
As for the compare-and-swap part, it's just a plus. Not that "double-looping" for *each* channel doesn't work. It just again seems silly and primitive (and was once confusing to me).
On Thu, 6 Aug 2020 at 17:15, Takashi Sakamoto o-takashi@sakamocchi.jp wrote:
Hi,
On Thu, Aug 06, 2020 at 04:57:02PM +0800, Tom Yan wrote:
The problem/race I am trying to point out is, one process can get()/read before another finishing its get()+put() pair (which is required by volume setting/adjusting), so something like get1()->get2()->put1()->put2() could easily happen (where each put() relies on / is "configured" with volumes of their respective get()). The lock will need to intentionally stall further get()/read as well.
In my opinion, in the above case, it's possible to serialize each transaction which consists of get/put (read/write in userspace application) with lock/unlock mechanism.
+-----------+-----------+ | process A | process B | +-----------+-----------+ | lock | | | get | | | |lock(EPERM)| reschedule lock/get/set/unlock actions | set | | | |lock(EPERM)| reschedule lock/get/set/unlock actions | unlock | | | | lock | | | get | | | set | | | unlock | +-----------+-----------+
(Of course, the above is achieved when the series of operations is done by userspace applications. For simplicity, I don't mention about in-kernel initiators of the get/set actions. In this point, I don't address to the message Pierre posted.)
If we for some reason want to avoid using locks, put() needs to be atomic by design (like, "embed" get() in itself and use arrays for volume values, instead of requiring those to be implemented in the userspace manually / with a loop). Unfortunately that isn't the case in ALSA.
I get your intension is something like compare-and-swap[1]. At present, ALSA control core has no functionality like it, but it's worth to investigate. The ioctl request should includes a pair of 'struct snd_ctl_elem_value' in its argument. In a design of ALSA control core, the pair should be processed in each driver since ALSA control core has no 'cache' of the content of 'struct snd_ctl_elem_value' except for user-defined control element set.
Here, would I ask your opinion to the lock/get/set/unlock actions from userspace? It can really not be one of solution for the issue?
[1] https://en.wikipedia.org/wiki/Compare-and-swap
Regards
Takashi Sakamoto