| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #ifndef NETDATA_LOCKS_H |
| 4 | #define NETDATA_LOCKS_H 1 |
| 5 | |
| 6 | #include "../libnetdata.h" |
| 7 | #include "../clocks/clocks.h" |
| 8 | |
| 9 | // #ifdef OS_WINDOWS |
| 10 | // #define SPINLOCK_IMPL_WITH_MUTEX |
| 11 | // #endif |
| 12 | |
| 13 | typedef uv_mutex_t netdata_mutex_t; |
| 14 | typedef uv_cond_t netdata_cond_t; |
| 15 | |
| 16 | #ifdef NETDATA_TRACE_RWLOCKS |
| 17 | |
| 18 | typedef enum { |
| 19 | RWLOCK_REQUEST_READ = (1 << 0), |
| 20 | RWLOCK_REQUEST_WRITE = (1 << 1), |
| 21 | RWLOCK_REQUEST_TRYREAD = (1 << 2), |
| 22 | RWLOCK_REQUEST_TRYWRITE = (1 << 3), |
| 23 | } LOCKER_REQUEST; |
| 24 | |
| 25 | typedef struct netdata_rwlock_locker { |
| 26 | LOCKER_REQUEST lock; |
| 27 | bool got_it; |
| 28 | pid_t pid; |
| 29 | size_t refcount; |
| 30 | const char *tag; |
| 31 | const char *file; |
| 32 | const char *function; |
| 33 | unsigned long line; |
| 34 | struct netdata_rwlock_locker *next, *prev; |
| 35 | } netdata_rwlock_locker; |
| 36 | |
| 37 | typedef struct netdata_rwlock_t { |
| 38 | uv_rwlock_t rwlock_t; // the lock |
| 39 | size_t readers; // the number of reader on the lock |
| 40 | size_t writers; // the number of writers on the lock |
| 41 | netdata_mutex_t lockers_mutex; // a mutex to protect the linked list of the lock holding threads |
| 42 | netdata_rwlock_locker *lockers; // the linked list of the lock holding threads |
| 43 | Pvoid_t lockers_pid_JudyL; |
| 44 | } netdata_rwlock_t; |
| 45 | |
| 46 | #define NETDATA_RWLOCK_INITIALIZER { \ |
| 47 | .rwlock_t = PTHREAD_RWLOCK_INITIALIZER, \ |
| 48 | .readers = 0, \ |
| 49 | .writers = 0, \ |
| 50 | .lockers_mutex = NETDATA_MUTEX_INITIALIZER, \ |
| 51 | .lockers = NULL, \ |
| 52 | .lockers_pid_JudyL = NULL, \ |
| 53 | } |
| 54 | |
| 55 | #else // NETDATA_TRACE_RWLOCKS |
| 56 | |
| 57 | typedef struct netdata_rwlock_t { |
| 58 | uv_rwlock_t rwlock_t; |
| 59 | } netdata_rwlock_t; |
| 60 | |
| 61 | #endif // NETDATA_TRACE_RWLOCKS |
| 62 | |
| 63 | int __netdata_cond_init(netdata_cond_t *cond); |
| 64 | void __netdata_cond_destroy(netdata_cond_t *cond); |
| 65 | void __netdata_cond_signal(netdata_cond_t *cond); |
| 66 | void __netdata_cond_wait(netdata_cond_t *cond, netdata_mutex_t *mutex); |
| 67 | int __netdata_cond_timedwait(netdata_cond_t *cond, netdata_mutex_t *mutex, uint64_t timeout_ns); |
| 68 | |
| 69 | int __netdata_mutex_init(netdata_mutex_t *mutex); |
| 70 | void __netdata_mutex_destroy(netdata_mutex_t *mutex); |
| 71 | void __netdata_mutex_lock(netdata_mutex_t *mutex); |
| 72 | int __netdata_mutex_trylock(netdata_mutex_t *mutex); |
| 73 | void __netdata_mutex_unlock(netdata_mutex_t *mutex); |
| 74 | |
| 75 | void __netdata_rwlock_destroy(netdata_rwlock_t *rwlock); |
| 76 | int __netdata_rwlock_init(netdata_rwlock_t *rwlock); |
| 77 | void __netdata_rwlock_rdlock(netdata_rwlock_t *rwlock); |
| 78 | void __netdata_rwlock_wrlock(netdata_rwlock_t *rwlock); |
| 79 | void __netdata_rwlock_rdunlock(netdata_rwlock_t *rwlock); |
| 80 | void __netdata_rwlock_wrunlock(netdata_rwlock_t *rwlock); |
| 81 | int __netdata_rwlock_tryrdlock(netdata_rwlock_t *rwlock); |
| 82 | int __netdata_rwlock_trywrlock(netdata_rwlock_t *rwlock); |
| 83 | void __netdata_cond_broadcast(netdata_cond_t *cond); |
| 84 | |
| 85 | #ifdef NETDATA_TRACE_RWLOCKS |
| 86 | |
| 87 | int netdata_mutex_init_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex); |
| 88 | int netdata_mutex_destroy_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex); |
| 89 | int netdata_mutex_lock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex); |
| 90 | int netdata_mutex_trylock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex); |
| 91 | int netdata_mutex_unlock_debug( const char *file, const char *function, const unsigned long line, netdata_mutex_t *mutex); |
| 92 | |
| 93 | int netdata_rwlock_destroy_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock); |
| 94 | int netdata_rwlock_init_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock); |
| 95 | int netdata_rwlock_rdlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock); |
| 96 | int netdata_rwlock_wrlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock); |
| 97 | int netdata_rwlock_rdunlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock); |
| 98 | int netdata_rwlock_wrunlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock); |
| 99 | int netdata_rwlock_tryrdlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock); |
| 100 | int netdata_rwlock_trywrlock_debug( const char *file, const char *function, const unsigned long line, netdata_rwlock_t *rwlock); |
| 101 | |
| 102 | #define netdata_mutex_init(mutex) netdata_mutex_init_debug(__FILE__, __FUNCTION__, __LINE__, mutex) |
| 103 | #define netdata_mutex_destroy(mutex) netdata_mutex_destroy_debug(__FILE__, __FUNCTION__, __LINE__, mutex) |
| 104 | #define netdata_mutex_lock(mutex) netdata_mutex_lock_debug(__FILE__, __FUNCTION__, __LINE__, mutex) |
| 105 | #define netdata_mutex_trylock(mutex) netdata_mutex_trylock_debug(__FILE__, __FUNCTION__, __LINE__, mutex) |
| 106 | #define netdata_mutex_unlock(mutex) netdata_mutex_unlock_debug(__FILE__, __FUNCTION__, __LINE__, mutex) |
| 107 | |
| 108 | #define netdata_rwlock_destroy(rwlock) netdata_rwlock_destroy_debug(__FILE__, __FUNCTION__, __LINE__, rwlock) |
| 109 | #define netdata_rwlock_init(rwlock) netdata_rwlock_init_debug(__FILE__, __FUNCTION__, __LINE__, rwlock) |
| 110 | #define netdata_rwlock_rdlock(rwlock) netdata_rwlock_rdlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock) |
| 111 | #define netdata_rwlock_wrlock(rwlock) netdata_rwlock_wrlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock) |
| 112 | #define netdata_rwlock_rdunlock(rwlock) netdata_rwlock_rdunlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock) |
| 113 | #define netdata_rwlock_wrunlock(rwlock) netdata_rwlock_wrunlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock) |
| 114 | #define netdata_rwlock_tryrdlock(rwlock) netdata_rwlock_tryrdlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock) |
| 115 | #define netdata_rwlock_trywrlock(rwlock) netdata_rwlock_trywrlock_debug(__FILE__, __FUNCTION__, __LINE__, rwlock) |
| 116 | |
| 117 | #else // !NETDATA_TRACE_RWLOCKS |
| 118 | |
| 119 | #define netdata_mutex_init(mutex) __netdata_mutex_init(mutex) |
| 120 | #define netdata_mutex_destroy(mutex) __netdata_mutex_destroy(mutex) |
| 121 | #define netdata_mutex_lock(mutex) __netdata_mutex_lock(mutex) |
| 122 | #define netdata_mutex_trylock(mutex) __netdata_mutex_trylock(mutex) |
| 123 | #define netdata_mutex_unlock(mutex) __netdata_mutex_unlock(mutex) |
| 124 | |
| 125 | #define netdata_rwlock_destroy(rwlock) __netdata_rwlock_destroy(rwlock) |
| 126 | #define netdata_rwlock_init(rwlock) __netdata_rwlock_init(rwlock) |
| 127 | #define netdata_rwlock_rdlock(rwlock) __netdata_rwlock_rdlock(rwlock) |
| 128 | #define netdata_rwlock_wrlock(rwlock) __netdata_rwlock_wrlock(rwlock) |
| 129 | #define netdata_rwlock_rdunlock(rwlock) __netdata_rwlock_rdunlock(rwlock) |
| 130 | #define netdata_rwlock_wrunlock(rwlock) __netdata_rwlock_wrunlock(rwlock) |
| 131 | #define netdata_rwlock_tryrdlock(rwlock) __netdata_rwlock_tryrdlock(rwlock) |
| 132 | #define netdata_rwlock_trywrlock(rwlock) __netdata_rwlock_trywrlock(rwlock) |
| 133 | |
| 134 | #endif // NETDATA_TRACE_RWLOCKS |
| 135 | |
| 136 | #define netdata_cond_init(cond) __netdata_cond_init(cond) |
| 137 | #define netdata_cond_destroy(cond) __netdata_cond_destroy(cond) |
| 138 | #define netdata_cond_signal(cond) __netdata_cond_signal(cond) |
| 139 | #define netdata_cond_broadcast(cond) __netdata_cond_broadcast(cond) |
| 140 | #define netdata_cond_wait(cond, mutex) __netdata_cond_wait(cond, mutex) |
| 141 | #define netdata_cond_timedwait(cond, mutex, tp) __netdata_cond_timedwait(cond, mutex, tp) |
| 142 | |
| 143 | #endif //NETDATA_LOCKS_H |