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