mirror of
https://github.com/haproxy/haproxy.git
synced 2026-04-29 18:18:59 -04:00
MINOR: threads: Add HA_RWLOCK_TRYRDTOWR()
Add HA_RWLOCK_TRYRDTOWR(), that tries to upgrade a lock from reader to writer, and fails if any seeker or writer already holds it.
This commit is contained in:
parent
2a9436f96b
commit
ba521a1d88
2 changed files with 46 additions and 0 deletions
|
|
@ -87,6 +87,7 @@ enum { tgid = 1 };
|
|||
#define HA_RWLOCK_SKUNLOCK(lbl,l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_TRYSKLOCK(lbl,l) ({ 0; })
|
||||
#define HA_RWLOCK_TRYRDTOSK(lbl,l) ({ 0; })
|
||||
#define HA_RWLOCK_TRYRDTOWR(lbl,l) ({ 0; })
|
||||
|
||||
#define ha_sigmask(how, set, oldset) sigprocmask(how, set, oldset)
|
||||
|
||||
|
|
@ -327,6 +328,7 @@ static inline unsigned long thread_isolated()
|
|||
#define HA_RWLOCK_SKUNLOCK(lbl,l) pl_drop_s(l) /* S --> N */
|
||||
#define HA_RWLOCK_TRYSKLOCK(lbl,l) (!pl_try_s(l)) /* N -?> S */
|
||||
#define HA_RWLOCK_TRYRDTOSK(lbl,l) (!pl_try_rtos(l)) /* R -?> S */
|
||||
#define HA_RWLOCK_TRYRDTOWR(lbl, l) (!pl_try_rtow(l)) /* R -?> W */
|
||||
|
||||
#else /* !defined(DEBUG_THREAD) && !defined(DEBUG_FULL) */
|
||||
|
||||
|
|
@ -356,6 +358,7 @@ static inline unsigned long thread_isolated()
|
|||
#define __RWLOCK_SKUNLOCK(l) pl_drop_s(l) /* S --> N */
|
||||
#define __RWLOCK_TRYSKLOCK(l) (!pl_try_s(l)) /* N -?> S */
|
||||
#define __RWLOCK_TRYRDTOSK(l) (!pl_try_rtos(l)) /* R -?> S */
|
||||
#define __RWLOCK_TRYRDTOWR(l) (!pl_try_rtow(l)) /* R -?> W */
|
||||
|
||||
#define HA_SPIN_INIT(l) __spin_init(l)
|
||||
#define HA_SPIN_DESTROY(l) __spin_destroy(l)
|
||||
|
|
@ -381,6 +384,7 @@ static inline unsigned long thread_isolated()
|
|||
#define HA_RWLOCK_SKUNLOCK(lbl,l) __ha_rwlock_skunlock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_RWLOCK_TRYSKLOCK(lbl,l) __ha_rwlock_trysklock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_RWLOCK_TRYRDTOSK(lbl,l) __ha_rwlock_tryrdtosk(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_RWLOCK_TRYRDTOWR(lbl,l) __ha_rwlock_tryrdtowr(lbl, l, __func__, __FILE__, __LINE__)
|
||||
|
||||
/* Following functions are used to collect some stats about locks. We wrap
|
||||
* pthread functions to known how much time we wait in a lock. */
|
||||
|
|
@ -413,6 +417,8 @@ int __ha_rwlock_trysklock(enum lock_label lbl, struct ha_rwlock *l,
|
|||
const char *func, const char *file, int line);
|
||||
int __ha_rwlock_tryrdtosk(enum lock_label lbl, struct ha_rwlock *l,
|
||||
const char *func, const char *file, int line);
|
||||
int __ha_rwlock_tryrdtowr(enum lock_label lbl, struct ha_rwlock *l,
|
||||
const char *func, const char *file, int line);
|
||||
void __spin_init(struct ha_spinlock *l);
|
||||
void __spin_destroy(struct ha_spinlock *l);
|
||||
void __spin_lock(enum lock_label lbl, struct ha_spinlock *l,
|
||||
|
|
|
|||
40
src/thread.c
40
src/thread.c
|
|
@ -998,6 +998,46 @@ int __ha_rwlock_tryrdtosk(enum lock_label lbl, struct ha_rwlock *l,
|
|||
return r;
|
||||
}
|
||||
|
||||
int __ha_rwlock_tryrdtowr(enum lock_label lbl, struct ha_rwlock *l,
|
||||
const char *func, const char *file, int line)
|
||||
{
|
||||
ulong tbit = (ti && ti->ltid_bit) ? ti->ltid_bit : 1;
|
||||
struct ha_rwlock_state *st = &l->info.st[tgid-1];
|
||||
uint64_t start_time;
|
||||
uint bucket;
|
||||
int r;
|
||||
|
||||
if ((st->cur_writer | st->cur_seeker) & tbit)
|
||||
abort();
|
||||
|
||||
if (!(st->cur_readers & tbit))
|
||||
abort();
|
||||
|
||||
HA_ATOMIC_OR(&st->wait_writers, tbit);
|
||||
|
||||
start_time = -now_mono_time();
|
||||
r = __RWLOCK_TRYRDTOWR(&l->lock);
|
||||
start_time += now_mono_time();
|
||||
|
||||
if (likely(!r)) {
|
||||
/* got the lock ! */
|
||||
HA_ATOMIC_ADD(&lock_stats_sk[lbl].nsec_wait, start_time);
|
||||
|
||||
start_time &= 0x3fffffff; // keep values below 1 billion only
|
||||
bucket = flsnz((uint32_t)start_time ? (uint32_t)start_time : 1) - 1;
|
||||
HA_ATOMIC_INC(&lock_stats_sk[lbl].buckets[bucket]);
|
||||
HA_ATOMIC_OR(&st->cur_writer, tbit);
|
||||
HA_ATOMIC_AND(&st->cur_readers, ~tbit);
|
||||
l->info.last_location.function = func;
|
||||
l->info.last_location.file = file;
|
||||
l->info.last_location.line = line;
|
||||
}
|
||||
|
||||
HA_ATOMIC_AND(&st->wait_writers, ~tbit);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void __spin_init(struct ha_spinlock *l)
|
||||
{
|
||||
memset(l, 0, sizeof(struct ha_spinlock));
|
||||
|
|
|
|||
Loading…
Reference in a new issue