Make pthread mutexes more scalable

pthread_mutex_lock() now uses a better algorithm which goes much faster
in multithreaded environments that have lock contention. This comes at
the cost of adding some fixed-cost overhead to mutex invocations. That
doesn't matter for Cosmopolitan because our core libraries all encode
locking operations as NOP instructions when in single-threaded mode.
Overhead only applies starting the moment you first call clone().
This commit is contained in:
Justine Tunney 2022-09-05 13:06:34 -07:00
parent 7de2f229a7
commit 7ff0ea8c13
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
32 changed files with 410 additions and 112 deletions

View file

@ -111,6 +111,8 @@ int pthread_mutexattr_init(pthread_mutexattr_t *);
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
int pthread_mutex_lock(pthread_mutex_t *);
int pthread_mutex_unlock(pthread_mutex_t *);
@ -208,22 +210,6 @@ extern const errno_t EBUSY;
})
#endif
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407
#define pthread_mutex_lock(mutex) \
(((mutex)->attr == PTHREAD_MUTEX_NORMAL && \
!__atomic_load_n(&(mutex)->lock, __ATOMIC_RELAXED) && \
!__atomic_exchange_n(&(mutex)->lock, 1, __ATOMIC_SEQ_CST)) \
? 0 \
: pthread_mutex_lock(mutex))
#define pthread_mutex_unlock(mutex) \
((mutex)->attr == PTHREAD_MUTEX_NORMAL \
? (__atomic_store_n(&(mutex)->lock, 0, __ATOMIC_RELAXED), \
(__atomic_load_n(&(mutex)->waits, __ATOMIC_RELAXED) && \
_pthread_mutex_wake(mutex)), \
0) \
: pthread_mutex_unlock(mutex))
#endif
#define pthread_condattr_init(pAttr) (*(pAttr) = PTHREAD_PROCESS_DEFAULT, 0)
#define pthread_condattr_destroy(pAttr) (*(pAttr) = 0)
#define pthread_condattr_getpshared(pAttr, pPshared) (*(pPshared) = *(pAttr), 0)