1// SPDX-License-Identifier: GPL-2.0 2#include "mutex.h" 3 4#include "debug.h" 5#include <linux/string.h> 6#include <errno.h> 7 8static void check_err(const char *fn, int err) 9{ 10 char sbuf[STRERR_BUFSIZE]; 11 12 if (err == 0) 13 return; 14 15 pr_err("%s error: '%s'\n", fn, str_error_r(err, sbuf, sizeof(sbuf))); 16} 17 18#define CHECK_ERR(err) check_err(__func__, err) 19 20static void __mutex_init(struct mutex *mtx, bool pshared) 21{ 22 pthread_mutexattr_t attr; 23 24 CHECK_ERR(pthread_mutexattr_init(&attr)); 25 26#ifndef NDEBUG 27 /* In normal builds enable error checking, such as recursive usage. */ 28 CHECK_ERR(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)); 29#endif 30 if (pshared) 31 CHECK_ERR(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)); 32 33 CHECK_ERR(pthread_mutex_init(&mtx->lock, &attr)); 34 CHECK_ERR(pthread_mutexattr_destroy(&attr)); 35} 36 37void mutex_init(struct mutex *mtx) 38{ 39 __mutex_init(mtx, /*pshared=*/false); 40} 41 42void mutex_init_pshared(struct mutex *mtx) 43{ 44 __mutex_init(mtx, /*pshared=*/true); 45} 46 47void mutex_destroy(struct mutex *mtx) 48{ 49 CHECK_ERR(pthread_mutex_destroy(&mtx->lock)); 50} 51 52void mutex_lock(struct mutex *mtx) 53 NO_THREAD_SAFETY_ANALYSIS 54{ 55 CHECK_ERR(pthread_mutex_lock(&mtx->lock)); 56} 57 58void mutex_unlock(struct mutex *mtx) 59 NO_THREAD_SAFETY_ANALYSIS 60{ 61 CHECK_ERR(pthread_mutex_unlock(&mtx->lock)); 62} 63 64bool mutex_trylock(struct mutex *mtx) 65{ 66 int ret = pthread_mutex_trylock(&mtx->lock); 67 68 if (ret == 0) 69 return true; /* Lock acquired. */ 70 71 if (ret == EBUSY) 72 return false; /* Lock busy. */ 73 74 /* Print error. */ 75 CHECK_ERR(ret); 76 return false; 77} 78 79static void __cond_init(struct cond *cnd, bool pshared) 80{ 81 pthread_condattr_t attr; 82 83 CHECK_ERR(pthread_condattr_init(&attr)); 84 if (pshared) 85 CHECK_ERR(pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)); 86 87 CHECK_ERR(pthread_cond_init(&cnd->cond, &attr)); 88 CHECK_ERR(pthread_condattr_destroy(&attr)); 89} 90 91void cond_init(struct cond *cnd) 92{ 93 __cond_init(cnd, /*pshared=*/false); 94} 95 96void cond_init_pshared(struct cond *cnd) 97{ 98 __cond_init(cnd, /*pshared=*/true); 99} 100 101void cond_destroy(struct cond *cnd) 102{ 103 CHECK_ERR(pthread_cond_destroy(&cnd->cond)); 104} 105 106void cond_wait(struct cond *cnd, struct mutex *mtx) 107{ 108 CHECK_ERR(pthread_cond_wait(&cnd->cond, &mtx->lock)); 109} 110 111void cond_signal(struct cond *cnd) 112{ 113 CHECK_ERR(pthread_cond_signal(&cnd->cond)); 114} 115 116void cond_broadcast(struct cond *cnd) 117{ 118 CHECK_ERR(pthread_cond_broadcast(&cnd->cond)); 119} 120