I confirmed it is the Irix pthread implementation. 
A trylock is not guaranteed to succeed immediately even if it is uncontested. 
This is not a bug of the newer gcc implementation as I suspected earlier, but 
also true for the native MipsPro compiler as well.
 
On a MIPS4 CPU (R8k and newer) the load-linked/store-conditional (LL/SC) is not 
infallible (like the modern CAS implementation). Also context switches, 
hardware interrupts, and other stuff can cause spurious failures of trylock. I 
also found some suggestions that the M:N Hybrid user:kernel space threading for 
Posix threads on Irix increases the chance of trylock failure. 

The solution is exactly that, to try a few times (most times it works at the 
first attempt anyway). 

To avoid bombarding the OS/CPU with too many trylocks when the optimizer does 
for-loop-unrolling and the CPU applies things like speculative execution and 
runtime optimization I added a yield() once in a while, which turned out to be 
a not-so-good idea. If the thread priority is normal, overtime it might be 
deprioritized in Irix and yields can add unpredictable amounts of time. On the 
other hand increasing the priority for the AOO process made the yield mostly 
useless since it would not yield most of the time. So I replaced it by a timer 
loop instead now (code sniplet below). 

This works well, I have not had any problems since (no clicks or pops with low 
CPU usage), have PD with AOO running on an SGI Octane2 Dual-CPU as frontend, 
and an SGI Origin2200 deskside server with 8 CPUS as compute engine connected 
by dedicated GBit ethernet. 

shared_lock lock(update_mutex_, sync::try_to_lock); // reader lock!
#if defined(__sgi) && defined(__mips__)
    for (int i = 0; !lock.owns_lock() && i < kIrixReadTryLockRetries; ++i) {
        sync::pause_cpu();
        if ((i & 7) == 7) {
            struct timespec start, current;
            clock_gettime(CLOCK_SGI_CYCLE, &start);
            long elapsed = 0;
            while (elapsed < RWLOCK_WAIT_TIME) {
                sync::pause_cpu();
                clock_gettime(CLOCK_SGI_CYCLE, &current);
                elapsed = (current.tv_sec - start.tv_sec) * 1000000000L +
                          (current.tv_nsec - start.tv_nsec);
            }
        }
        lock = shared_lock(update_mutex_, sync::try_to_lock);
    }
#endif
---
[email protected] - the Pure Data mailinglist
https://lists.iem.at/hyperkitty/list/[email protected]/message/Y65QNUEXRONWASJTCUYAM3OP3ZCEJXM3/

To unsubscribe send an email to [email protected] mailing list
UNSUBSCRIBE and account-management -> https://lists.iem.at/

Reply via email to