On Fri, 19.06.09 14:31, [email protected] ([email protected]) wrote: > > > <snip> > > > for (;;) { > > > n = jack_client_wait() > > > process(n); > > > jack_cycle_signal(); > > > while (jack_frames_since_cycle_start() < threshold) { > > > if (no_private_events_to_process()) > > > break; > > > process_one_of_my_private_events(); > > > } > > > } > > > </snip> > > > > > > The early exit in the inner loop when there's nothing to do (which is > > > the usual case) is the key point here, I guess. > > > > > > Sorry for the confusion. > > this discussion seems to go away from the real issue to implementation > details of pa. > however the deeper i read into stuff which is being called, the more > malloc and mutex_lock() i see.
We use mutexes at some places and malloc at quite a few too. However, those are confined to the non-RT threads, with very few exceptions. Those exceptions usually are irrelevant for the RT case however. e.g. the writer side of our lock-free async queue actually takes a lock. Which however doesn't matter, since that's simply there to make a single-reader-single-writer queue useful for multiple writers -- it simply protects writers against each other, it's not a lock that is shared with the reader side. Now, since we allocate a seperate queue for each of our RT cases this lock in the end will never block, because there is noone else this could block against. The only reason we have this lock there is that this queue is used at various places, and for some having multi-writer queues is really useful. At least on Linux taking an uncontended lock is relatively cheap and doesn't even need a change to kernel mode. Regarding malloc(): preallocating and locking memory is not really an option for the usual PA use case: we simply cannot afford taking away all that memory from other processes all the time, since PA is just process among many on most setups. As a compromise PA uses lock-free free lists for all data that is allocated from the RT threads, in the hope we seldomly have to actually ask for memory, and in the hope to keep the memory we already allocated "hot". PA and JACK have different purposes. PA is not a textbook RT application. Far from that. We have to make compromises at many places where JACK doesn't have to. After all, on a desktop (and even more on embedded devices), PA is there to handle 'just' audio which is just something among a lot of other stuff fighting for resources. OTOH on a pro audio workstation JACK is at the center of everything, and the resources available are available only and exclusively for the use of audio applications. I mean, I am not saying PA had a flawless design, it certainly hasn't. But uh, maybe LAD is not the place to discuss those. And I think I have quite good reasons for most compromises I made. > even with jack_cycle_signal we are having a thread, which is running at > the same priority as other jack threads, so it still has a certein > potential to choke the other jack clients. Sure, but doing those things after _signal() is still better than before _signal(). > first of all.... lets assume jack is running with -p64 -n2 > (~3ms latency) > > i am not sure if lennart is aware that jack often runs with such > latencies. i dont really care for event processing inside the RT loop. > however you cant know how many clients are following in the process > cycle, so you cant know a sane threshold value. But that information could be made available, couldn't it? I mean, the Jack server has information about the graph, so it could make that information available to the clients. > what i am asking for is that events are either passed into your RT loop > via lock-free fifos As mentioned, this is what happens. that lock-free q is called pa_asyncmsgq. Lennart -- Lennart Poettering Red Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 _______________________________________________ Linux-audio-dev mailing list [email protected] http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
