120 lines · c
1// SPDX-License-Identifier: GPL-2.02#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 NDEBUG27 /* In normal builds enable error checking, such as recursive usage. */28 CHECK_ERR(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));29#endif30 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_ANALYSIS54{55 CHECK_ERR(pthread_mutex_lock(&mtx->lock));56}57 58void mutex_unlock(struct mutex *mtx)59 NO_THREAD_SAFETY_ANALYSIS60{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