mirror of
https://salsa.debian.org/ha-team/libqb
synced 2026-08-07 01:15:15 +00:00
array: More locking fixes (#400)
* array: More locking fixes helgrind threw out a couple more locking errors in the logging/array code and we also need to protect a->max_elements
This commit is contained in:
parent
08a165dc2c
commit
b2acdea2a8
30
lib/array.c
30
lib/array.c
@ -122,14 +122,19 @@ qb_array_index(struct qb_array * a, int32_t idx, void **element_out)
|
||||
if (idx < 0) {
|
||||
return -ERANGE;
|
||||
}
|
||||
(void)qb_thread_lock(a->grow_lock);
|
||||
if ((uint32_t) idx >= a->max_elements) {
|
||||
if (a->autogrow_elements == 0) {
|
||||
(void)qb_thread_unlock(a->grow_lock);
|
||||
return -ERANGE;
|
||||
} else {
|
||||
/* qb_array_grow gets the lock */
|
||||
(void)qb_thread_unlock(a->grow_lock);
|
||||
rc = qb_array_grow(a, idx + 1);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
(void)qb_thread_lock(a->grow_lock);
|
||||
}
|
||||
}
|
||||
b = BIN_NUM_GET((uint32_t) idx);
|
||||
@ -138,8 +143,6 @@ qb_array_index(struct qb_array * a, int32_t idx, void **element_out)
|
||||
if (b >= a->num_bins || a->bin[b] == NULL) {
|
||||
int32_t bin_alloced = QB_FALSE;
|
||||
|
||||
(void)qb_thread_lock(a->grow_lock);
|
||||
|
||||
if (b >= a->num_bins) {
|
||||
rc = _grow_bin_array(a, b + 1);
|
||||
if (rc < 0) {
|
||||
@ -154,11 +157,13 @@ qb_array_index(struct qb_array * a, int32_t idx, void **element_out)
|
||||
}
|
||||
bin_alloced = QB_TRUE;
|
||||
}
|
||||
|
||||
/* new_bin_cb() needs to be called unlocked so can't extend the lock after the if block */
|
||||
(void)qb_thread_unlock(a->grow_lock);
|
||||
if (bin_alloced && a->new_bin_cb) {
|
||||
a->new_bin_cb(a, b);
|
||||
}
|
||||
} else {
|
||||
(void)qb_thread_unlock(a->grow_lock);
|
||||
}
|
||||
|
||||
elem = ELEM_NUM_GET(idx);
|
||||
@ -188,10 +193,15 @@ qb_array_new_bin_cb_set(struct qb_array * a, qb_array_new_bin_cb_fn fn)
|
||||
size_t
|
||||
qb_array_num_bins_get(struct qb_array * a)
|
||||
{
|
||||
size_t bins;
|
||||
|
||||
if (a == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return a->num_bins;
|
||||
(void)qb_thread_lock(a->grow_lock);
|
||||
bins = a->num_bins;
|
||||
(void)qb_thread_unlock(a->grow_lock);
|
||||
return bins;
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -212,18 +222,20 @@ qb_array_grow(struct qb_array * a, size_t max_elements)
|
||||
if (a == NULL || max_elements > QB_ARRAY_MAX_ELEMENTS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
(void)qb_thread_lock(a->grow_lock);
|
||||
if (max_elements <= a->max_elements) {
|
||||
(void)qb_thread_unlock(a->grow_lock);
|
||||
return 0;
|
||||
}
|
||||
a->max_elements = max_elements;
|
||||
b = QB_MIN((max_elements / MAX_ELEMENTS_PER_BIN) + 1, MAX_BINS);
|
||||
if (b > a->num_bins) {
|
||||
(void)qb_thread_lock(a->grow_lock);
|
||||
if (b >= a->num_bins) {
|
||||
rc = _grow_bin_array(a, b + 1);
|
||||
}
|
||||
(void)qb_thread_unlock(a->grow_lock);
|
||||
}
|
||||
(void)qb_thread_unlock(a->grow_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -231,6 +243,12 @@ void
|
||||
qb_array_free(struct qb_array *a)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* In theory we should lock before accessing a->num_bins
|
||||
* but as we're freeing the whole array here it seems
|
||||
* a bit pointless as any other threads would segv when we
|
||||
* unlock anyway
|
||||
*/
|
||||
for (i = 0; i < a->num_bins; i++) {
|
||||
free(a->bin[i]);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user