#include <signal.h>
#include <assert.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <poll.h>
#include <sys/time.h>
-#include <syscall.h>
#include <unistd.h>
#include <sched.h>
#include "urcu-call-rcu.h"
#include "urcu-pointer.h"
#include "urcu/list.h"
-#include "urcu/urcu-futex.h"
+#include "urcu/futex.h"
/* Data structure that identifies a call_rcu thread. */
struct call_rcu_data {
struct cds_wfq_queue cbs;
unsigned long flags;
- int futex;
+ int32_t futex;
unsigned long qlen; /* maintained for debugging. */
pthread_t tid;
int cpu_affinity;
static struct call_rcu_data **per_cpu_call_rcu_data;
static long maxcpus;
-static void call_rcu_wait(struct call_rcu_data *crdp)
-{
- /* Read call_rcu list before read futex */
- cmm_smp_mb();
- if (uatomic_read(&crdp->futex) == -1)
- futex_async(&crdp->futex, FUTEX_WAIT, -1,
- NULL, NULL, 0);
-}
-
-static void call_rcu_wake_up(struct call_rcu_data *crdp)
-{
- /* Write to call_rcu list before reading/writing futex */
- cmm_smp_mb();
- if (unlikely(uatomic_read(&crdp->futex) == -1)) {
- uatomic_set(&crdp->futex, 0);
- futex_async(&crdp->futex, FUTEX_WAKE, 1,
- NULL, NULL, 0);
- }
-}
-
/* Allocate the array if it has not already been allocated. */
static void alloc_cpu_call_rcu_data(void)
#else /* #if defined(HAVE_SCHED_GETCPU) && defined(HAVE_SYSCONF) */
-static const struct call_rcu_data **per_cpu_call_rcu_data = NULL;
+/*
+ * per_cpu_call_rcu_data should be constant, but some functions below, used both
+ * for cases where cpu number is available and not available, assume it it not
+ * constant.
+ */
+static struct call_rcu_data **per_cpu_call_rcu_data = NULL;
static const long maxcpus = -1;
static void alloc_cpu_call_rcu_data(void)
}
#endif
+static void call_rcu_wait(struct call_rcu_data *crdp)
+{
+ /* Read call_rcu list before read futex */
+ cmm_smp_mb();
+ if (uatomic_read(&crdp->futex) == -1)
+ futex_async(&crdp->futex, FUTEX_WAIT, -1,
+ NULL, NULL, 0);
+}
+
+static void call_rcu_wake_up(struct call_rcu_data *crdp)
+{
+ /* Write to call_rcu list before reading/writing futex */
+ cmm_smp_mb();
+ if (unlikely(uatomic_read(&crdp->futex) == -1)) {
+ uatomic_set(&crdp->futex, 0);
+ futex_async(&crdp->futex, FUTEX_WAKE, 1,
+ NULL, NULL, 0);
+ }
+}
+
/* This is the code run by each call_rcu thread. */
static void *call_rcu_thread(void *arg)
exit(-1);
}
+ /*
+ * If callbacks take a read-side lock, we need to be registered.
+ */
+ rcu_register_thread();
+
thread_call_rcu_data = crdp;
if (!rt) {
uatomic_dec(&crdp->futex);
}
if (uatomic_read(&crdp->flags) & URCU_CALL_RCU_STOP)
break;
+ rcu_thread_offline();
if (!rt) {
if (&crdp->cbs.head
== _CMM_LOAD_SHARED(crdp->cbs.tail)) {
* call_rcu list.
*/
cmm_smp_mb();
+ } else {
+ poll(NULL, 0, 10);
}
} else {
poll(NULL, 0, 10);
}
+ rcu_thread_online();
}
if (!rt) {
/*
uatomic_set(&crdp->futex, 0);
}
uatomic_or(&crdp->flags, URCU_CALL_RCU_STOPPED);
+ rcu_unregister_thread();
return NULL;
}