Re: AOO plugin for PD on SGI Irix
Wolfgang Gaggl via Pd-list <[email protected]>
| Newsgroups | gmane.comp.multimedia.puredata.general |
|---|---|
| Message-ID | <[email protected]> |
>> I have been thinking: how could anyone implement synchronization
primitives without reliable atomic operations? To me, a bug in the
pthread_rwlock implementation seems more likely.
Generally, it all seems to work, including atomics.
I believe there's an issue with the GCC implementation for pthread_rwlock on this platform; as far I can observe only with the try_to_lock shared_lock. There are some mentioned differences (occasionally having to try_to_lock multiple times to get a lock on an uncontested lock) that I can also see on the native MIPSPro compiler.
But at times it fails to get a reader lock with try_to_lock when another scoped_shared_lock is active which looks like a bug.
I observed this only in GCC. Since the native MIPSPro compiler supports only C++98 I didn't fully test the exact scenario with the specific timing there.
Since you pointed out that sink.cpp may have concurrent writers active during the stream I chose another way to do this.
std::atomic<uint32_t> process_active_{0};
std::atomic<uint32_t> writer_gate_{0};
In source_desc::process():
// Writers set writer_gate_ and wait for process_active_ == 0 before mutating
// This prevents writer/process overlap without using rwlock try_lock in audio path.
if (writer_gate_.load(std::memory_order_acquire) != 0) {
if (stream_state_ != stream_state::inactive) {
LOG_DEBUG("AooSink: process blocked by writer gate");
add_xrun(1);
}
}
// process() sets process_active_ to to set writer block
sink_process_activity_guard process_guard(process_active_);
// For the extra-cautious, recheck after announcing active status to avoid race condition.
if (writer_gate_.load(std::memory_order_acquire) != 0) {
if (stream_state_ != stream_state::inactive) {
LOG_DEBUG("AooSink: process blocked by writer gate");
add_xrun(1);
}
}
// now do the processing stuff...
}
For all writer calls:
// Writer gate guard: blocks new process() entries while a writer is pending.
sink_writer_gate_guard _writer_gate(writer_gate_);
// This function loops pause_cpu() while process() is active
wait_for_sink_process_idle(process_active_);
// do write stuff...
This method does not block in the process() thread and avoids using the problematic try_to_lock.
It also uses fewer CPU cycles than looping try_to_lock in process().
As you suggested, I tested it by changing format parameters during the running stream in quick succession to see if I can break it, but it all works without issues.
---
[email protected] - the Pure Data mailinglist
https://lists.iem.at/hyperkitty/list/[email protected]/message/6323HU2BWSBL2R4RPCZBSRS3XBLWW3P5/
To unsubscribe send an email to [email protected] mailing list
UNSUBSCRIBE and account-management -> https://lists.iem.at/