summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
ddf7eef)
Cleanup.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
void __attribute__((destructor)) rcu_bp_exit(void);
void __attribute__((destructor)) rcu_bp_exit(void);
-static pthread_mutex_t rcu_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER;
#ifdef DEBUG_YIELD
unsigned int yield_active;
#ifdef DEBUG_YIELD
unsigned int yield_active;
static void rcu_gc_registry(void);
static void rcu_gc_registry(void);
-static void internal_rcu_lock(void)
+static void mutex_lock(pthread_mutex_t *mutex)
{
int ret;
#ifndef DISTRUST_SIGNALS_EXTREME
{
int ret;
#ifndef DISTRUST_SIGNALS_EXTREME
- ret = pthread_mutex_lock(&rcu_mutex);
+ ret = pthread_mutex_lock(mutex);
if (ret) {
perror("Error in pthread mutex lock");
exit(-1);
}
#else /* #ifndef DISTRUST_SIGNALS_EXTREME */
if (ret) {
perror("Error in pthread mutex lock");
exit(-1);
}
#else /* #ifndef DISTRUST_SIGNALS_EXTREME */
- while ((ret = pthread_mutex_trylock(&rcu_mutex)) != 0) {
+ while ((ret = pthread_mutex_trylock(mutex)) != 0) {
if (ret != EBUSY && ret != EINTR) {
printf("ret = %d, errno = %d\n", ret, errno);
perror("Error in pthread mutex lock");
if (ret != EBUSY && ret != EINTR) {
printf("ret = %d, errno = %d\n", ret, errno);
perror("Error in pthread mutex lock");
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
}
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
}
-static void internal_rcu_unlock(void)
+static void mutex_unlock(pthread_mutex_t *mutex)
- ret = pthread_mutex_unlock(&rcu_mutex);
+ ret = pthread_mutex_unlock(mutex);
if (ret) {
perror("Error in pthread mutex unlock");
exit(-1);
if (ret) {
perror("Error in pthread mutex unlock");
exit(-1);
- * called with rcu_mutex held.
+ * called with rcu_gp_lock held.
*/
static void switch_next_rcu_qparity(void)
{
*/
static void switch_next_rcu_qparity(void)
{
ret = pthread_sigmask(SIG_SETMASK, &newmask, &oldmask);
assert(!ret);
ret = pthread_sigmask(SIG_SETMASK, &newmask, &oldmask);
assert(!ret);
+ mutex_lock(&rcu_gp_lock);
/* Remove old registry elements */
rcu_gc_registry();
/* All threads should read qparity before accessing data structure
/* Remove old registry elements */
rcu_gc_registry();
/* All threads should read qparity before accessing data structure
- * where new ptr points to. Must be done within internal_rcu_lock
- * because it iterates on reader threads.*/
+ * where new ptr points to. Must be done within rcu_gp_lock because it
+ * iterates on reader threads.*/
/* Write new ptr before changing the qparity */
smp_mb();
/* Write new ptr before changing the qparity */
smp_mb();
wait_for_quiescent_state(); /* Wait readers in parity 1 */
/* Finish waiting for reader threads before letting the old ptr being
wait_for_quiescent_state(); /* Wait readers in parity 1 */
/* Finish waiting for reader threads before letting the old ptr being
- * freed. Must be done within internal_rcu_lock because it iterates on
- * reader threads. */
+ * freed. Must be done within rcu_gp_lock because it iterates on reader
+ * threads. */
+ mutex_unlock(&rcu_gp_lock);
ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
assert(!ret);
}
ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
assert(!ret);
}
if (rcu_reader)
goto end;
if (rcu_reader)
goto end;
+ mutex_lock(&rcu_gp_lock);
+ mutex_unlock(&rcu_gp_lock);
end:
ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
assert(!ret);
end:
ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
assert(!ret);
static LIST_HEAD(registry);
static pthread_t tid_defer;
static LIST_HEAD(registry);
static pthread_t tid_defer;
-static void internal_rcu_lock(pthread_mutex_t *mutex)
+static void mutex_lock(pthread_mutex_t *mutex)
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
}
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
}
-static void internal_rcu_unlock(pthread_mutex_t *mutex)
+static void mutex_unlock(pthread_mutex_t *mutex)
unsigned long num_items = 0, head;
struct defer_queue *index;
unsigned long num_items = 0, head;
struct defer_queue *index;
- internal_rcu_lock(&rcu_defer_mutex);
+ mutex_lock(&rcu_defer_mutex);
list_for_each_entry(index, ®istry, list) {
head = LOAD_SHARED(index->head);
num_items += head - index->tail;
}
list_for_each_entry(index, ®istry, list) {
head = LOAD_SHARED(index->head);
num_items += head - index->tail;
}
- internal_rcu_unlock(&rcu_defer_mutex);
+ mutex_unlock(&rcu_defer_mutex);
void rcu_defer_barrier_thread(void)
{
void rcu_defer_barrier_thread(void)
{
- internal_rcu_lock(&rcu_defer_mutex);
+ mutex_lock(&rcu_defer_mutex);
_rcu_defer_barrier_thread();
_rcu_defer_barrier_thread();
- internal_rcu_unlock(&rcu_defer_mutex);
+ mutex_unlock(&rcu_defer_mutex);
if (list_empty(®istry))
return;
if (list_empty(®istry))
return;
- internal_rcu_lock(&rcu_defer_mutex);
+ mutex_lock(&rcu_defer_mutex);
list_for_each_entry(index, ®istry, list) {
index->last_head = LOAD_SHARED(index->head);
num_items += index->last_head - index->tail;
list_for_each_entry(index, ®istry, list) {
index->last_head = LOAD_SHARED(index->head);
num_items += index->last_head - index->tail;
list_for_each_entry(index, ®istry, list)
rcu_defer_barrier_queue(index, index->last_head);
end:
list_for_each_entry(index, ®istry, list)
rcu_defer_barrier_queue(index, index->last_head);
end:
- internal_rcu_unlock(&rcu_defer_mutex);
+ mutex_unlock(&rcu_defer_mutex);
assert(defer_queue.q == NULL);
defer_queue.q = malloc(sizeof(void *) * DEFER_QUEUE_SIZE);
assert(defer_queue.q == NULL);
defer_queue.q = malloc(sizeof(void *) * DEFER_QUEUE_SIZE);
- internal_rcu_lock(&defer_thread_mutex);
- internal_rcu_lock(&rcu_defer_mutex);
+ mutex_lock(&defer_thread_mutex);
+ mutex_lock(&rcu_defer_mutex);
was_empty = list_empty(®istry);
list_add(&defer_queue.list, ®istry);
was_empty = list_empty(®istry);
list_add(&defer_queue.list, ®istry);
- internal_rcu_unlock(&rcu_defer_mutex);
+ mutex_unlock(&rcu_defer_mutex);
if (was_empty)
start_defer_thread();
if (was_empty)
start_defer_thread();
- internal_rcu_unlock(&defer_thread_mutex);
+ mutex_unlock(&defer_thread_mutex);
}
void rcu_defer_unregister_thread(void)
{
int is_empty;
}
void rcu_defer_unregister_thread(void)
{
int is_empty;
- internal_rcu_lock(&defer_thread_mutex);
- internal_rcu_lock(&rcu_defer_mutex);
+ mutex_lock(&defer_thread_mutex);
+ mutex_lock(&rcu_defer_mutex);
list_del(&defer_queue.list);
_rcu_defer_barrier_thread();
free(defer_queue.q);
defer_queue.q = NULL;
is_empty = list_empty(®istry);
list_del(&defer_queue.list);
_rcu_defer_barrier_thread();
free(defer_queue.q);
defer_queue.q = NULL;
is_empty = list_empty(®istry);
- internal_rcu_unlock(&rcu_defer_mutex);
+ mutex_unlock(&rcu_defer_mutex);
if (is_empty)
stop_defer_thread();
if (is_empty)
stop_defer_thread();
- internal_rcu_unlock(&defer_thread_mutex);
+ mutex_unlock(&defer_thread_mutex);
}
void rcu_defer_exit(void)
}
void rcu_defer_exit(void)
void __attribute__((destructor)) rcu_exit(void);
void __attribute__((destructor)) rcu_exit(void);
-static pthread_mutex_t rcu_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER;
static LIST_HEAD(registry);
static LIST_HEAD(registry);
-static void internal_rcu_lock(void)
+static void mutex_lock(pthread_mutex_t *mutex)
{
int ret;
#ifndef DISTRUST_SIGNALS_EXTREME
{
int ret;
#ifndef DISTRUST_SIGNALS_EXTREME
- ret = pthread_mutex_lock(&rcu_mutex);
+ ret = pthread_mutex_lock(mutex);
if (ret) {
perror("Error in pthread mutex lock");
exit(-1);
}
#else /* #ifndef DISTRUST_SIGNALS_EXTREME */
if (ret) {
perror("Error in pthread mutex lock");
exit(-1);
}
#else /* #ifndef DISTRUST_SIGNALS_EXTREME */
- while ((ret = pthread_mutex_trylock(&rcu_mutex)) != 0) {
+ while ((ret = pthread_mutex_trylock(mutex)) != 0) {
if (ret != EBUSY && ret != EINTR) {
printf("ret = %d, errno = %d\n", ret, errno);
perror("Error in pthread mutex lock");
if (ret != EBUSY && ret != EINTR) {
printf("ret = %d, errno = %d\n", ret, errno);
perror("Error in pthread mutex lock");
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
}
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
}
-static void internal_rcu_unlock(void)
+static void mutex_unlock(pthread_mutex_t *mutex)
- ret = pthread_mutex_unlock(&rcu_mutex);
+ ret = pthread_mutex_unlock(mutex);
if (ret) {
perror("Error in pthread mutex unlock");
exit(-1);
if (ret) {
perror("Error in pthread mutex unlock");
exit(-1);
#if (BITS_PER_LONG < 64)
/*
#if (BITS_PER_LONG < 64)
/*
- * called with rcu_mutex held.
+ * called with rcu_gp_lock held.
*/
static void switch_next_rcu_qparity(void)
{
*/
static void switch_next_rcu_qparity(void)
{
if (was_online)
STORE_SHARED(rcu_reader.ctr, 0);
if (was_online)
STORE_SHARED(rcu_reader.ctr, 0);
+ mutex_lock(&rcu_gp_lock);
switch_next_rcu_qparity(); /* 0 -> 1 */
switch_next_rcu_qparity(); /* 0 -> 1 */
*/
wait_for_quiescent_state(); /* Wait readers in parity 1 */
*/
wait_for_quiescent_state(); /* Wait readers in parity 1 */
+ mutex_unlock(&rcu_gp_lock);
/*
* Finish waiting for reader threads before letting the old ptr being
/*
* Finish waiting for reader threads before letting the old ptr being
if (was_online)
STORE_SHARED(rcu_reader.ctr, 0);
if (was_online)
STORE_SHARED(rcu_reader.ctr, 0);
+ mutex_lock(&rcu_gp_lock);
STORE_SHARED(rcu_gp_ctr, rcu_gp_ctr + RCU_GP_CTR);
wait_for_quiescent_state();
STORE_SHARED(rcu_gp_ctr, rcu_gp_ctr + RCU_GP_CTR);
wait_for_quiescent_state();
+ mutex_unlock(&rcu_gp_lock);
if (was_online)
_STORE_SHARED(rcu_reader.ctr, LOAD_SHARED(rcu_gp_ctr));
if (was_online)
_STORE_SHARED(rcu_reader.ctr, LOAD_SHARED(rcu_gp_ctr));
rcu_reader.tid = pthread_self();
assert(rcu_reader.ctr == 0);
rcu_reader.tid = pthread_self();
assert(rcu_reader.ctr == 0);
+ mutex_lock(&rcu_gp_lock);
list_add(&rcu_reader.head, ®istry);
list_add(&rcu_reader.head, ®istry);
+ mutex_unlock(&rcu_gp_lock);
* with a waiting writer.
*/
_rcu_thread_offline();
* with a waiting writer.
*/
_rcu_thread_offline();
+ mutex_lock(&rcu_gp_lock);
list_del(&rcu_reader.head);
list_del(&rcu_reader.head);
+ mutex_unlock(&rcu_gp_lock);
void __attribute__((destructor)) rcu_exit(void);
#endif
void __attribute__((destructor)) rcu_exit(void);
#endif
-static pthread_mutex_t rcu_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER;
static LIST_HEAD(registry);
static LIST_HEAD(registry);
-static void internal_rcu_lock(void)
+static void mutex_lock(pthread_mutex_t *mutex)
{
int ret;
#ifndef DISTRUST_SIGNALS_EXTREME
{
int ret;
#ifndef DISTRUST_SIGNALS_EXTREME
- ret = pthread_mutex_lock(&rcu_mutex);
+ ret = pthread_mutex_lock(mutex);
if (ret) {
perror("Error in pthread mutex lock");
exit(-1);
}
#else /* #ifndef DISTRUST_SIGNALS_EXTREME */
if (ret) {
perror("Error in pthread mutex lock");
exit(-1);
}
#else /* #ifndef DISTRUST_SIGNALS_EXTREME */
- while ((ret = pthread_mutex_trylock(&rcu_mutex)) != 0) {
+ while ((ret = pthread_mutex_trylock(mutex)) != 0) {
if (ret != EBUSY && ret != EINTR) {
printf("ret = %d, errno = %d\n", ret, errno);
perror("Error in pthread mutex lock");
if (ret != EBUSY && ret != EINTR) {
printf("ret = %d, errno = %d\n", ret, errno);
perror("Error in pthread mutex lock");
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
}
#endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
}
-static void internal_rcu_unlock(void)
+static void mutex_unlock(pthread_mutex_t *mutex)
- ret = pthread_mutex_unlock(&rcu_mutex);
+ ret = pthread_mutex_unlock(mutex);
if (ret) {
perror("Error in pthread mutex unlock");
exit(-1);
if (ret) {
perror("Error in pthread mutex unlock");
exit(-1);
- * called with rcu_mutex held.
+ * called with rcu_gp_lock held.
*/
static void switch_next_rcu_qparity(void)
{
*/
static void switch_next_rcu_qparity(void)
{
void synchronize_rcu(void)
{
void synchronize_rcu(void)
{
+ mutex_lock(&rcu_gp_lock);
/* All threads should read qparity before accessing data structure
/* All threads should read qparity before accessing data structure
- * where new ptr points to. Must be done within internal_rcu_lock
- * because it iterates on reader threads.*/
+ * where new ptr points to. Must be done within rcu_gp_lock because it
+ * iterates on reader threads.*/
/* Write new ptr before changing the qparity */
smp_mb_heavy();
/* Write new ptr before changing the qparity */
smp_mb_heavy();
wait_for_quiescent_state(); /* Wait readers in parity 1 */
/* Finish waiting for reader threads before letting the old ptr being
wait_for_quiescent_state(); /* Wait readers in parity 1 */
/* Finish waiting for reader threads before letting the old ptr being
- * freed. Must be done within internal_rcu_lock because it iterates on
- * reader threads. */
+ * freed. Must be done within rcu_gp_lock because it iterates on reader
+ * threads. */
+ mutex_unlock(&rcu_gp_lock);
assert(rcu_reader.need_mb == 0);
assert(rcu_reader.ctr == 0);
assert(rcu_reader.need_mb == 0);
assert(rcu_reader.ctr == 0);
+ mutex_lock(&rcu_gp_lock);
rcu_init(); /* In case gcc does not support constructor attribute */
list_add(&rcu_reader.head, ®istry);
rcu_init(); /* In case gcc does not support constructor attribute */
list_add(&rcu_reader.head, ®istry);
+ mutex_unlock(&rcu_gp_lock);
}
void rcu_unregister_thread(void)
{
}
void rcu_unregister_thread(void)
{
+ mutex_lock(&rcu_gp_lock);
list_del(&rcu_reader.head);
list_del(&rcu_reader.head);
+ mutex_unlock(&rcu_gp_lock);
* rcu_init constructor. Called when the library is linked, but also when
* reader threads are calling rcu_register_thread().
* Should only be called by a single thread at a given time. This is ensured by
* rcu_init constructor. Called when the library is linked, but also when
* reader threads are calling rcu_register_thread().
* Should only be called by a single thread at a given time. This is ensured by
- * holing the internal_rcu_lock() from rcu_register_thread() or by running at
- * library load time, which should not be executed by multiple threads nor
- * concurrently with rcu_register_thread() anyway.
+ * holing the rcu_gp_lock from rcu_register_thread() or by running at library
+ * load time, which should not be executed by multiple threads nor concurrently
+ * with rcu_register_thread() anyway.