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 8 static 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 20 static 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 37 void mutex_init(struct mutex *mtx) 38 { 39 __mutex_init(mtx, /*pshared=*/false); 40 } 41 42 void mutex_init_pshared(struct mutex *mtx) 43 { 44 __mutex_init(mtx, /*pshared=*/true); 45 } 46 47 void mutex_destroy(struct mutex *mtx) 48 { 49 CHECK_ERR(pthread_mutex_destroy(&mtx->lock)); 50 } 51 52 void mutex_lock(struct mutex *mtx) 53 { 54 CHECK_ERR(pthread_mutex_lock(&mtx->lock)); 55 } 56 57 void mutex_unlock(struct mutex *mtx) 58 { 59 CHECK_ERR(pthread_mutex_unlock(&mtx->lock)); 60 } 61 62 bool mutex_trylock(struct mutex *mtx) 63 { 64 int ret = pthread_mutex_trylock(&mtx->lock); 65 66 if (ret == 0) 67 return true; /* Lock acquired. */ 68 69 if (ret == EBUSY) 70 return false; /* Lock busy. */ 71 72 /* Print error. */ 73 CHECK_ERR(ret); 74 return false; 75 } 76 77 static void __cond_init(struct cond *cnd, bool pshared) 78 { 79 pthread_condattr_t attr; 80 81 CHECK_ERR(pthread_condattr_init(&attr)); 82 if (pshared) 83 CHECK_ERR(pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)); 84 85 CHECK_ERR(pthread_cond_init(&cnd->cond, &attr)); 86 CHECK_ERR(pthread_condattr_destroy(&attr)); 87 } 88 89 void cond_init(struct cond *cnd) 90 { 91 __cond_init(cnd, /*pshared=*/false); 92 } 93 94 void cond_init_pshared(struct cond *cnd) 95 { 96 __cond_init(cnd, /*pshared=*/true); 97 } 98 99 void cond_destroy(struct cond *cnd) 100 { 101 CHECK_ERR(pthread_cond_destroy(&cnd->cond)); 102 } 103 104 void cond_wait(struct cond *cnd, struct mutex *mtx) 105 { 106 CHECK_ERR(pthread_cond_wait(&cnd->cond, &mtx->lock)); 107 } 108 109 void cond_signal(struct cond *cnd) 110 { 111 CHECK_ERR(pthread_cond_signal(&cnd->cond)); 112 } 113 114 void cond_broadcast(struct cond *cnd) 115 { 116 CHECK_ERR(pthread_cond_broadcast(&cnd->cond)); 117 } 118