emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: igc, macOS avoiding signals


From: Gerd Möllmann
Subject: Re: igc, macOS avoiding signals
Date: Tue, 31 Dec 2024 10:51:57 +0100
User-agent: Gnus/5.13 (Gnus v5.13)

Gerd Möllmann <gerd.moellmann@gmail.com> writes:

> Hm. Have you perhaps looked at a pthread implementation, what such a
> mutex actually is on Linux?

Unless I got lost in Apple's sources, trylock on macOS is the below.
I find it hard to tell if a signal here while being called from a signal
would do damage.

int
pthread_mutex_trylock(pthread_mutex_t *mutex)
{
        return _pthread_mutex_lock(mutex, true);
}

static inline int
_pthread_mutex_lock(pthread_mutex_t *mutex, bool trylock)
{
        if (os_unlikely(!_pthread_mutex_check_signature_fast(mutex))) {
                return _pthread_mutex_lock_init_slow(mutex, trylock);
        }

        if (os_unlikely(_pthread_mutex_is_fairshare(mutex))) {
                return _pthread_mutex_fairshare_lock(mutex, trylock);
        }

        if (os_unlikely(_pthread_mutex_uses_ulock(mutex))) {
                return _pthread_mutex_ulock_lock(mutex, trylock);
        }

#if ENABLE_USERSPACE_TRACE
        return _pthread_mutex_firstfit_lock_slow(mutex, trylock);
#elif PLOCKSTAT
        if (PLOCKSTAT_MUTEX_ACQUIRE_ENABLED() || 
PLOCKSTAT_MUTEX_ERROR_ENABLED()) {
                return _pthread_mutex_firstfit_lock_slow(mutex, trylock);
        }
#endif

        return _pthread_mutex_firstfit_lock(mutex, trylock);
}

static inline int
_pthread_mutex_firstfit_lock(pthread_mutex_t *mutex, bool trylock)
{
        /*
         * This is the first-fit fast path. The fairshare fast-ish path is in
         * _pthread_mutex_fairshare_lock()
         */
        uint64_t *tidaddr;
        MUTEX_GETTID_ADDR(mutex, &tidaddr);
        uint64_t selfid = _pthread_threadid_self_np_direct();

        mutex_seq *seqaddr;
        MUTEX_GETSEQ_ADDR(mutex, &seqaddr);

        mutex_seq oldseq, newseq;
        mutex_seq_load(seqaddr, &oldseq);

        if (os_unlikely(!trylock && (oldseq.lgenval & PTH_RWL_EBIT))) {
                return _pthread_mutex_firstfit_lock_slow(mutex, trylock);
        }

        bool gotlock;
        do {
                newseq = oldseq;
                gotlock = is_rwl_ebit_clear(oldseq.lgenval);

                if (trylock && !gotlock) {
#if __LP64__
                        // The sequence load is atomic, so we can bail here 
without writing
                        // it and avoid some unnecessary coherence traffic - 
rdar://57259033
                        os_atomic_thread_fence(acquire);
                        return EBUSY;
#else
                        // A trylock on a held lock will fail immediately. But 
since
                        // we did not load the sequence words atomically, 
perform a
                        // no-op CAS64 to ensure that nobody has unlocked 
concurrently.
#endif
                } else if (os_likely(gotlock)) {
                        // In first-fit, getting the lock simply adds the E-bit
                        newseq.lgenval |= PTH_RWL_EBIT;
                } else {
                        return _pthread_mutex_firstfit_lock_slow(mutex, 
trylock);
                }
        } while (os_unlikely(!mutex_seq_atomic_cmpxchgv(seqaddr, &oldseq, 
&newseq,
                        acquire)));

        if (os_likely(gotlock)) {
                os_atomic_store_wide(tidaddr, selfid, relaxed);
                return 0;
        } else if (trylock) {
                return EBUSY;
        } else {
                __builtin_trap();
        }
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]