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 NO_THREAD_SAFETY_ANALYSIS 54 { 55 CHECK_ERR(pthread_mutex_lock(&mtx->lock)); 56 } 57 58 void mutex_unlock(struct mutex *mtx) 59 NO_THREAD_SAFETY_ANALYSIS 60 { 61 CHECK_ERR(pthread_mutex_unlock(&mtx->lock)); 62 } 63 64 bool 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 79 static 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 91 void cond_init(struct cond *cnd) 92 { 93 __cond_init(cnd, /*pshared=*/false); 94 } 95 96 void cond_init_pshared(struct cond *cnd) 97 { 98 __cond_init(cnd, /*pshared=*/true); 99 } 100 101 void cond_destroy(struct cond *cnd) 102 { 103 CHECK_ERR(pthread_cond_destroy(&cnd->cond)); 104 } 105 106 void cond_wait(struct cond *cnd, struct mutex *mtx) 107 { 108 CHECK_ERR(pthread_cond_wait(&cnd->cond, &mtx->lock)); 109 } 110 111 void cond_signal(struct cond *cnd) 112 { 113 CHECK_ERR(pthread_cond_signal(&cnd->cond)); 114 } 115 116 void cond_broadcast(struct cond *cnd) 117 { 118 CHECK_ERR(pthread_cond_broadcast(&cnd->cond)); 119 } 120