at master 125 lines 2.7 kB view raw
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, 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 38void mutex_init(struct mutex *mtx) 39{ 40 __mutex_init(mtx, /*pshared=*/false, /*recursive=*/false); 41} 42 43void mutex_init_pshared(struct mutex *mtx) 44{ 45 __mutex_init(mtx, /*pshared=*/true, /*recursive=*/false); 46} 47 48void mutex_init_recursive(struct mutex *mtx) 49{ 50 __mutex_init(mtx, /*pshared=*/false, /*recursive=*/true); 51} 52 53void mutex_destroy(struct mutex *mtx) 54{ 55 CHECK_ERR(pthread_mutex_destroy(&mtx->lock)); 56} 57 58void mutex_lock(struct mutex *mtx) 59 NO_THREAD_SAFETY_ANALYSIS 60{ 61 CHECK_ERR(pthread_mutex_lock(&mtx->lock)); 62} 63 64void mutex_unlock(struct mutex *mtx) 65 NO_THREAD_SAFETY_ANALYSIS 66{ 67 CHECK_ERR(pthread_mutex_unlock(&mtx->lock)); 68} 69 70bool 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 85static 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 97void cond_init(struct cond *cnd) 98{ 99 __cond_init(cnd, /*pshared=*/false); 100} 101 102void cond_init_pshared(struct cond *cnd) 103{ 104 __cond_init(cnd, /*pshared=*/true); 105} 106 107void cond_destroy(struct cond *cnd) 108{ 109 CHECK_ERR(pthread_cond_destroy(&cnd->cond)); 110} 111 112void cond_wait(struct cond *cnd, struct mutex *mtx) 113{ 114 CHECK_ERR(pthread_cond_wait(&cnd->cond, &mtx->lock)); 115} 116 117void cond_signal(struct cond *cnd) 118{ 119 CHECK_ERR(pthread_cond_signal(&cnd->cond)); 120} 121 122void cond_broadcast(struct cond *cnd) 123{ 124 CHECK_ERR(pthread_cond_broadcast(&cnd->cond)); 125}