commit
686ce7ab03
@ -1,58 +0,0 @@
|
||||
From 136211f67b5ba804fd0e02603bcef61ac47dbc16 Mon Sep 17 00:00:00 2001
|
||||
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
Date: Sun, 9 Dec 2018 06:31:57 -0500
|
||||
Subject: [PATCH 06/15] Cleanup: workqueue: update comments referring to
|
||||
call-rcu
|
||||
|
||||
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
---
|
||||
src/workqueue.c | 12 +++++-------
|
||||
1 file changed, 5 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/workqueue.c b/src/workqueue.c
|
||||
index 8561a7a..db0c63a 100644
|
||||
--- a/src/workqueue.c
|
||||
+++ b/src/workqueue.c
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
#include "compat-getcpu.h"
|
||||
#include "urcu/wfcqueue.h"
|
||||
-#include "urcu-call-rcu.h"
|
||||
#include "urcu-pointer.h"
|
||||
#include "urcu/list.h"
|
||||
#include "urcu/futex.h"
|
||||
@@ -55,10 +54,9 @@
|
||||
struct urcu_workqueue {
|
||||
/*
|
||||
* We do not align head on a different cache-line than tail
|
||||
- * mainly because call_rcu callback-invocation threads use
|
||||
- * batching ("splice") to get an entire list of callbacks, which
|
||||
- * effectively empties the queue, and requires to touch the tail
|
||||
- * anyway.
|
||||
+ * mainly because workqueue threads use batching ("splice") to
|
||||
+ * get an entire list of callbacks, which effectively empties
|
||||
+ * the queue, and requires to touch the tail anyway.
|
||||
*/
|
||||
struct cds_wfcq_tail cbs_tail;
|
||||
struct cds_wfcq_head cbs_head;
|
||||
@@ -244,7 +242,7 @@ static void *workqueue_thread(void *arg)
|
||||
uatomic_dec(&workqueue->futex);
|
||||
/*
|
||||
* Decrement futex before reading
|
||||
- * call_rcu list.
|
||||
+ * urcu_work list.
|
||||
*/
|
||||
cmm_smp_mb();
|
||||
} else {
|
||||
@@ -258,7 +256,7 @@ static void *workqueue_thread(void *arg)
|
||||
}
|
||||
if (!rt) {
|
||||
/*
|
||||
- * Read call_rcu list before write futex.
|
||||
+ * Read urcu_work list before write futex.
|
||||
*/
|
||||
cmm_smp_mb();
|
||||
uatomic_set(&workqueue->futex, 0);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
From b197ce865b0de8c475f3ddeadeae3a66b15ace21 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Jeanson <mjeanson@efficios.com>
|
||||
Date: Fri, 23 Nov 2018 15:27:04 -0500
|
||||
Subject: [PATCH 01/15] Fix: compat_futex_noasync on Cygwin
|
||||
|
||||
The futex_noasync compat code uses a weak symbol to share state across
|
||||
different shared object which is not possible on Windows with the
|
||||
Portable Executable format. Use the async compat code for both cases.
|
||||
|
||||
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
|
||||
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
---
|
||||
include/urcu/futex.h | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/include/urcu/futex.h b/include/urcu/futex.h
|
||||
index 0486ff6..753df62 100644
|
||||
--- a/include/urcu/futex.h
|
||||
+++ b/include/urcu/futex.h
|
||||
@@ -102,6 +102,25 @@ static inline int futex_async(int32_t *uaddr, int op, int32_t val,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#elif defined(__CYGWIN__)
|
||||
+
|
||||
+/*
|
||||
+ * The futex_noasync compat code uses a weak symbol to share state across
|
||||
+ * different shared object which is not possible on Windows with the
|
||||
+ * Portable Executable format. Use the async compat code for both cases.
|
||||
+ */
|
||||
+static inline int futex_noasync(int32_t *uaddr, int op, int32_t val,
|
||||
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
|
||||
+{
|
||||
+ return compat_futex_async(uaddr, op, val, timeout, uaddr2, val3);
|
||||
+}
|
||||
+
|
||||
+static inline int futex_async(int32_t *uaddr, int op, int32_t val,
|
||||
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
|
||||
+{
|
||||
+ return compat_futex_async(uaddr, op, val, timeout, uaddr2, val3);
|
||||
+}
|
||||
+
|
||||
#else
|
||||
|
||||
static inline int futex_noasync(int32_t *uaddr, int op, int32_t val,
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
From 79eca0929fc50a668a15937b5bf4d1cb97049de8 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Galarneau?=
|
||||
<jeremie.galarneau@efficios.com>
|
||||
Date: Fri, 7 Dec 2018 17:06:38 -0500
|
||||
Subject: [PATCH 09/15] Fix: don't wait after completion of a work queue job
|
||||
batch
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
As indicated in the previous patch of this series, waiting on
|
||||
completion of a job batch from the work queue artificially increases
|
||||
the latency of the work queue.
|
||||
|
||||
The previous patch removed the wait that is performed when the
|
||||
work queue is observed to be empty and was observed as the cause of a
|
||||
performance problem.
|
||||
|
||||
It is likely that waiting when the queue is observed to be non-empty
|
||||
is similarly unintended. Note that I have not observed such a problem
|
||||
myself.
|
||||
|
||||
If a workqueue user even need the explicit delay for batching (e.g. if
|
||||
a call-rcu implementation would ever use the workqueue worker thread),
|
||||
it can add it within the worker_before_wait_fct callback received as
|
||||
argument from workqueue creation.
|
||||
|
||||
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
|
||||
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
---
|
||||
src/workqueue.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/src/workqueue.c b/src/workqueue.c
|
||||
index 0b1a9ea..39d0e07 100644
|
||||
--- a/src/workqueue.c
|
||||
+++ b/src/workqueue.c
|
||||
@@ -244,8 +244,6 @@ static void *workqueue_thread(void *arg)
|
||||
* urcu_work list.
|
||||
*/
|
||||
cmm_smp_mb();
|
||||
- } else {
|
||||
- (void) poll(NULL, 0, 10);
|
||||
}
|
||||
} else {
|
||||
(void) poll(NULL, 0, 10);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
From d3e42beb106479eae7c234bb0aeacce92661ca7a Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Galarneau?=
|
||||
<jeremie.galarneau@efficios.com>
|
||||
Date: Fri, 7 Dec 2018 17:06:37 -0500
|
||||
Subject: [PATCH 08/15] Fix: don't wait after completion of job batch if work
|
||||
queue is empty
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On completion of a batch of jobs from the work queue, a wait of 10
|
||||
ms (using poll()) is performed if there is no work present in the
|
||||
work queue before waiting on its futex.
|
||||
|
||||
The work queue thread's structure is inspired by the call-rcu thread.
|
||||
In the context of the call-rcu thread, my understanding is that the
|
||||
intention is to ensure that the thread does not continuously wake-up
|
||||
to process a single queued item. This is fine as an application should
|
||||
not wait for a call-rcu job to be executed (or at least I don't see a
|
||||
use-case for that).
|
||||
|
||||
In the context of the work queue, waiting for more work to be available
|
||||
artificially slows down the execution of work on which an application
|
||||
may wait.
|
||||
|
||||
I have observed a case where LTTng's session daemon's shutdown is
|
||||
takes around 4 seconds as a large number of cds_lfht objects are
|
||||
destroyed. Removing the wait reduces the duration of this phase of the
|
||||
shut-down to almost ~10ms.
|
||||
|
||||
If a workqueue user even need the explicit delay for batching (e.g. if
|
||||
a call-rcu implementation would ever use the workqueue worker thread),
|
||||
it can add it within the worker_before_wait_fct callback received as
|
||||
argument from workqueue creation.
|
||||
|
||||
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
|
||||
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
---
|
||||
src/workqueue.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/src/workqueue.c b/src/workqueue.c
|
||||
index 6707ffe..0b1a9ea 100644
|
||||
--- a/src/workqueue.c
|
||||
+++ b/src/workqueue.c
|
||||
@@ -238,7 +238,6 @@ static void *workqueue_thread(void *arg)
|
||||
if (cds_wfcq_empty(&workqueue->cbs_head,
|
||||
&workqueue->cbs_tail)) {
|
||||
futex_wait(&workqueue->futex);
|
||||
- (void) poll(NULL, 0, 10);
|
||||
uatomic_dec(&workqueue->futex);
|
||||
/*
|
||||
* Decrement futex before reading
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
From 0aa1fccd3aff5f5a7717c166f7bfbe864d041f23 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Galarneau?=
|
||||
<jeremie.galarneau@efficios.com>
|
||||
Date: Fri, 7 Dec 2018 17:06:36 -0500
|
||||
Subject: [PATCH 05/15] Fix: mixup between URCU_WORKQUEUE_RT and
|
||||
URCU_CALL_RCU_RT
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The work queue implementation is derived from the call-rcu thread. A
|
||||
number of references seem to have been left in place when adapting the
|
||||
code for its new purpose.
|
||||
|
||||
The URCU_CALL_RCU_RT flag is used by wake_worker_thread() while the
|
||||
rest of the workqueue.c code uses URCU_WORKQUEUE_RT to determine if
|
||||
the work queue was configured in real-time mode. Both flags are defined
|
||||
to the same value (0x1) and the current internal user of the
|
||||
work queue (lfht) never specifies any flags.
|
||||
|
||||
In practice, this does not cause any problem, but this mixup should
|
||||
be fixed nevertheless.
|
||||
|
||||
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
|
||||
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
---
|
||||
src/workqueue.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/workqueue.c b/src/workqueue.c
|
||||
index 17ea835..8561a7a 100644
|
||||
--- a/src/workqueue.c
|
||||
+++ b/src/workqueue.c
|
||||
@@ -309,7 +309,7 @@ struct urcu_workqueue *urcu_workqueue_create(unsigned long flags,
|
||||
|
||||
static void wake_worker_thread(struct urcu_workqueue *workqueue)
|
||||
{
|
||||
- if (!(_CMM_LOAD_SHARED(workqueue->flags) & URCU_CALL_RCU_RT))
|
||||
+ if (!(_CMM_LOAD_SHARED(workqueue->flags) & URCU_WORKQUEUE_RT))
|
||||
futex_wake_up(&workqueue->futex);
|
||||
}
|
||||
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
From 803e59362b6d94edff3a36f47a9da3e8dca4bde2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Galarneau?=
|
||||
<jeremie.galarneau@efficios.com>
|
||||
Date: Fri, 7 Dec 2018 17:06:39 -0500
|
||||
Subject: [PATCH 10/15] Fix: only wait if work queue is empty in real-time mode
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Unconditionally waiting for 10 ms after the completion of every batch
|
||||
of jobs of the work queue in real-time mode appears to be a behaviour
|
||||
inherited from the call-rcu thread.
|
||||
|
||||
While this is a fair trade-off in the context of call-rcu, it is less
|
||||
evident that it is desirable in the context of a general-purpose
|
||||
work queue. Waiting when work is available artificially degrades the
|
||||
latency characteristics of the work queue.
|
||||
|
||||
If a workqueue user even need the explicit delay for batching (e.g. if
|
||||
a call-rcu implementation would ever use the workqueue worker thread),
|
||||
it can add it within the worker_before_wait_fct callback received as
|
||||
argument from workqueue creation.
|
||||
|
||||
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
|
||||
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
---
|
||||
src/workqueue.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/workqueue.c b/src/workqueue.c
|
||||
index 39d0e07..14957a0 100644
|
||||
--- a/src/workqueue.c
|
||||
+++ b/src/workqueue.c
|
||||
@@ -246,7 +246,10 @@ static void *workqueue_thread(void *arg)
|
||||
cmm_smp_mb();
|
||||
}
|
||||
} else {
|
||||
- (void) poll(NULL, 0, 10);
|
||||
+ if (cds_wfcq_empty(&workqueue->cbs_head,
|
||||
+ &workqueue->cbs_tail)) {
|
||||
+ (void) poll(NULL, 0, 10);
|
||||
+ }
|
||||
}
|
||||
if (workqueue->worker_after_wake_up_fct)
|
||||
workqueue->worker_after_wake_up_fct(workqueue, workqueue->priv);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,224 +0,0 @@
|
||||
From eec2f6a5c353f28bb74e4a3f96a3da5a50f25574 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Jeanson <mjeanson@efficios.com>
|
||||
Date: Fri, 23 Nov 2018 16:47:18 -0500
|
||||
Subject: [PATCH 02/15] Fix: pthread_rwlock initialization on Cygwin
|
||||
|
||||
On Cygwin the PTHREAD_RWLOCK_INITIALIZER macro is not
|
||||
sufficient to get a properly initialized pthread_rwlock_t
|
||||
struct. Use the pthread_rwlock_init function instead which
|
||||
should work on all platforms.
|
||||
|
||||
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
|
||||
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
---
|
||||
tests/benchmark/test_rwlock.c | 51 ++++++++++++++++++++++++----
|
||||
tests/benchmark/test_rwlock_timing.c | 50 +++++++++++++++++++++++----
|
||||
2 files changed, 88 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/tests/benchmark/test_rwlock.c b/tests/benchmark/test_rwlock.c
|
||||
index 4448597..f95e4e1 100644
|
||||
--- a/tests/benchmark/test_rwlock.c
|
||||
+++ b/tests/benchmark/test_rwlock.c
|
||||
@@ -48,7 +48,11 @@ struct test_array {
|
||||
int a;
|
||||
};
|
||||
|
||||
-pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||
+/*
|
||||
+ * static rwlock initializer is broken on Cygwin. Use runtime
|
||||
+ * initialization.
|
||||
+ */
|
||||
+pthread_rwlock_t lock;
|
||||
|
||||
static volatile int test_go, test_stop;
|
||||
|
||||
@@ -173,14 +177,25 @@ void *thr_reader(void *_count)
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
- int a;
|
||||
+ int a, ret;
|
||||
+
|
||||
+ ret = pthread_rwlock_rdlock(&lock);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "reader pthread_rwlock_rdlock: %s\n", strerror(ret));
|
||||
+ abort();
|
||||
+ }
|
||||
|
||||
- pthread_rwlock_rdlock(&lock);
|
||||
a = test_array.a;
|
||||
assert(a == 8);
|
||||
if (caa_unlikely(rduration))
|
||||
loop_sleep(rduration);
|
||||
- pthread_rwlock_unlock(&lock);
|
||||
+
|
||||
+ ret = pthread_rwlock_unlock(&lock);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "reader pthread_rwlock_unlock: %s\n", strerror(ret));
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
URCU_TLS(nr_reads)++;
|
||||
if (caa_unlikely(!test_duration_read()))
|
||||
break;
|
||||
@@ -208,12 +223,25 @@ void *thr_writer(void *_count)
|
||||
cmm_smp_mb();
|
||||
|
||||
for (;;) {
|
||||
- pthread_rwlock_wrlock(&lock);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = pthread_rwlock_wrlock(&lock);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "writer pthread_rwlock_wrlock: %s\n", strerror(ret));
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
test_array.a = 0;
|
||||
test_array.a = 8;
|
||||
if (caa_unlikely(wduration))
|
||||
loop_sleep(wduration);
|
||||
- pthread_rwlock_unlock(&lock);
|
||||
+
|
||||
+ ret = pthread_rwlock_unlock(&lock);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "writer pthread_rwlock_unlock: %s\n", strerror(ret));
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
URCU_TLS(nr_writes)++;
|
||||
if (caa_unlikely(!test_duration_write()))
|
||||
break;
|
||||
@@ -321,6 +349,12 @@ int main(int argc, char **argv)
|
||||
printf_verbose("thread %-6s, tid %lu\n",
|
||||
"main", urcu_get_thread_id());
|
||||
|
||||
+ err = pthread_rwlock_init(&lock, NULL);
|
||||
+ if (err != 0) {
|
||||
+ fprintf(stderr, "pthread_rwlock_init: (%d) %s\n", err, strerror(err));
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
tid_reader = calloc(nr_readers, sizeof(*tid_reader));
|
||||
tid_writer = calloc(nr_writers, sizeof(*tid_writer));
|
||||
count_reader = calloc(nr_readers, sizeof(*count_reader));
|
||||
@@ -371,6 +405,11 @@ int main(int argc, char **argv)
|
||||
nr_writers, wdelay, tot_reads, tot_writes,
|
||||
tot_reads + tot_writes);
|
||||
|
||||
+ err = pthread_rwlock_destroy(&lock);
|
||||
+ if (err != 0) {
|
||||
+ fprintf(stderr, "pthread_rwlock_destroy: (%d) %s\n", err, strerror(err));
|
||||
+ exit(1);
|
||||
+ }
|
||||
free(tid_reader);
|
||||
free(tid_writer);
|
||||
free(count_reader);
|
||||
diff --git a/tests/benchmark/test_rwlock_timing.c b/tests/benchmark/test_rwlock_timing.c
|
||||
index a52da38..bc51c45 100644
|
||||
--- a/tests/benchmark/test_rwlock_timing.c
|
||||
+++ b/tests/benchmark/test_rwlock_timing.c
|
||||
@@ -42,7 +42,11 @@ struct test_array {
|
||||
int a;
|
||||
};
|
||||
|
||||
-pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||
+/*
|
||||
+ * static rwlock initializer is broken on Cygwin. Use runtime
|
||||
+ * initialization.
|
||||
+ */
|
||||
+pthread_rwlock_t lock;
|
||||
|
||||
static struct test_array test_array = { 8 };
|
||||
|
||||
@@ -65,7 +69,7 @@ static caa_cycles_t __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *writer_time;
|
||||
|
||||
void *thr_reader(void *arg)
|
||||
{
|
||||
- int i, j;
|
||||
+ int i, j, ret;
|
||||
caa_cycles_t time1, time2;
|
||||
|
||||
printf("thread_begin %s, tid %lu\n",
|
||||
@@ -75,9 +79,19 @@ void *thr_reader(void *arg)
|
||||
time1 = caa_get_cycles();
|
||||
for (i = 0; i < OUTER_READ_LOOP; i++) {
|
||||
for (j = 0; j < INNER_READ_LOOP; j++) {
|
||||
- pthread_rwlock_rdlock(&lock);
|
||||
+ ret = pthread_rwlock_rdlock(&lock);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "reader pthread_rwlock_rdlock: %s\n", strerror(ret));
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
assert(test_array.a == 8);
|
||||
- pthread_rwlock_unlock(&lock);
|
||||
+
|
||||
+ ret = pthread_rwlock_unlock(&lock);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "reader pthread_rwlock_unlock: %s\n", strerror(ret));
|
||||
+ abort();
|
||||
+ }
|
||||
}
|
||||
}
|
||||
time2 = caa_get_cycles();
|
||||
@@ -93,7 +107,7 @@ void *thr_reader(void *arg)
|
||||
|
||||
void *thr_writer(void *arg)
|
||||
{
|
||||
- int i, j;
|
||||
+ int i, j, ret;
|
||||
caa_cycles_t time1, time2;
|
||||
|
||||
printf("thread_begin %s, tid %lu\n",
|
||||
@@ -103,9 +117,20 @@ void *thr_writer(void *arg)
|
||||
for (i = 0; i < OUTER_WRITE_LOOP; i++) {
|
||||
for (j = 0; j < INNER_WRITE_LOOP; j++) {
|
||||
time1 = caa_get_cycles();
|
||||
- pthread_rwlock_wrlock(&lock);
|
||||
+ ret = pthread_rwlock_wrlock(&lock);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "writer pthread_rwlock_wrlock: %s\n", strerror(ret));
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
test_array.a = 8;
|
||||
- pthread_rwlock_unlock(&lock);
|
||||
+
|
||||
+ ret = pthread_rwlock_unlock(&lock);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "writer pthread_rwlock_unlock: %s\n", strerror(ret));
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
time2 = caa_get_cycles();
|
||||
writer_time[(unsigned long)arg] += time2 - time1;
|
||||
usleep(1);
|
||||
@@ -133,6 +158,12 @@ int main(int argc, char **argv)
|
||||
num_read = atoi(argv[1]);
|
||||
num_write = atoi(argv[2]);
|
||||
|
||||
+ err = pthread_rwlock_init(&lock, NULL);
|
||||
+ if (err != 0) {
|
||||
+ fprintf(stderr, "pthread_rwlock_init: (%d) %s\n", err, strerror(err));
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
reader_time = calloc(num_read, sizeof(*reader_time));
|
||||
writer_time = calloc(num_write, sizeof(*writer_time));
|
||||
tid_reader = calloc(num_read, sizeof(*tid_reader));
|
||||
@@ -173,6 +204,11 @@ int main(int argc, char **argv)
|
||||
printf("Time per write : %g cycles\n",
|
||||
(double)tot_wtime / ((double)NR_WRITE * (double)WRITE_LOOP));
|
||||
|
||||
+ err = pthread_rwlock_destroy(&lock);
|
||||
+ if (err != 0) {
|
||||
+ fprintf(stderr, "pthread_rwlock_destroy: (%d) %s\n", err, strerror(err));
|
||||
+ exit(1);
|
||||
+ }
|
||||
free(reader_time);
|
||||
free(writer_time);
|
||||
free(tid_reader);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
From f3a942e30e3a217cfbf987d5e6bec1d89c394963 Mon Sep 17 00:00:00 2001
|
||||
From: root <root@localhost.localdomain>
|
||||
Date: Thu, 25 Jun 2020 07:20:38 +0800
|
||||
Subject: [PATCH] fix-make-test-error
|
||||
|
||||
---
|
||||
tests/Makefile.am | 1 -
|
||||
tests/benchmark/Makefile.am | 4 +---
|
||||
2 files changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||
index 03f3f29..7e91a71 100644
|
||||
--- a/tests/Makefile.am
|
||||
+++ b/tests/Makefile.am
|
||||
@@ -8,4 +8,3 @@ long_bench:
|
||||
cd benchmark && $(MAKE) $(AM_MAKEFLAGS) long_bench
|
||||
regtest:
|
||||
cd regression && $(MAKE) $(AM_MAKEFLAGS) regtest
|
||||
- cd benchmark && $(MAKE) $(AM_MAKEFLAGS) regtest
|
||||
diff --git a/tests/benchmark/Makefile.am b/tests/benchmark/Makefile.am
|
||||
index 216d013..35e2db6 100644
|
||||
--- a/tests/benchmark/Makefile.am
|
||||
+++ b/tests/benchmark/Makefile.am
|
||||
@@ -226,7 +226,7 @@ clean-local:
|
||||
done; \
|
||||
fi
|
||||
|
||||
-.PHONY: short_bench long_bench regtest
|
||||
+.PHONY: short_bench long_bench
|
||||
|
||||
short_bench:
|
||||
./run.sh short_bench_tests
|
||||
@@ -234,5 +234,3 @@ short_bench:
|
||||
long_bench:
|
||||
./run.sh long_bench_tests
|
||||
|
||||
-regtest:
|
||||
- ./run.sh regression_tests
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
From 9e19a6b0d350ffb70e9f29d8eea371c6b7ffad72 Mon Sep 17 00:00:00 2001
|
||||
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
Date: Sun, 9 Dec 2018 06:37:09 -0500
|
||||
Subject: [PATCH 07/15] Fix: workqueue: struct urcu_work vs rcu_head mixup
|
||||
|
||||
The workqueue code was derived from call-rcu, and its API
|
||||
expects a struct urcu_work for work items, but it internally iterates
|
||||
over struct rcu_head.
|
||||
|
||||
This is not an issue at runtime because both structures have the
|
||||
exact same layout and content, but it is a type mixup nevertheless.
|
||||
|
||||
Use the right type in the implementation.
|
||||
|
||||
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
---
|
||||
src/workqueue.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/workqueue.c b/src/workqueue.c
|
||||
index db0c63a..6707ffe 100644
|
||||
--- a/src/workqueue.c
|
||||
+++ b/src/workqueue.c
|
||||
@@ -221,11 +221,11 @@ static void *workqueue_thread(void *arg)
|
||||
cbcount = 0;
|
||||
__cds_wfcq_for_each_blocking_safe(&cbs_tmp_head,
|
||||
&cbs_tmp_tail, cbs, cbs_tmp_n) {
|
||||
- struct rcu_head *rhp;
|
||||
+ struct urcu_work *uwp;
|
||||
|
||||
- rhp = caa_container_of(cbs,
|
||||
- struct rcu_head, next);
|
||||
- rhp->func(rhp);
|
||||
+ uwp = caa_container_of(cbs,
|
||||
+ struct urcu_work, next);
|
||||
+ uwp->func(uwp);
|
||||
cbcount++;
|
||||
}
|
||||
uatomic_sub(&workqueue->qlen, cbcount);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
From 6c249cd8c0a48370bac8511216c166e98104d699 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Jeanson <mjeanson@efficios.com>
|
||||
Date: Fri, 23 Nov 2018 15:27:07 -0500
|
||||
Subject: [PATCH 04/15] test_rwlock: Add per-thread count to verbose output
|
||||
|
||||
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
|
||||
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
---
|
||||
tests/benchmark/test_rwlock.c | 12 +++++++-----
|
||||
1 file changed, 7 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/tests/benchmark/test_rwlock.c b/tests/benchmark/test_rwlock.c
|
||||
index f95e4e1..827c117 100644
|
||||
--- a/tests/benchmark/test_rwlock.c
|
||||
+++ b/tests/benchmark/test_rwlock.c
|
||||
@@ -202,8 +202,9 @@ void *thr_reader(void *_count)
|
||||
}
|
||||
|
||||
*count = URCU_TLS(nr_reads);
|
||||
- printf_verbose("thread_end %s, tid %lu\n",
|
||||
- "reader", urcu_get_thread_id());
|
||||
+
|
||||
+ printf_verbose("thread_end %s, tid %lu, count %llu\n",
|
||||
+ "reader", urcu_get_thread_id(), *count);
|
||||
return ((void*)1);
|
||||
|
||||
}
|
||||
@@ -248,10 +249,10 @@ void *thr_writer(void *_count)
|
||||
if (caa_unlikely(wdelay))
|
||||
loop_sleep(wdelay);
|
||||
}
|
||||
-
|
||||
- printf_verbose("thread_end %s, tid %lu\n",
|
||||
- "writer", urcu_get_thread_id());
|
||||
*count = URCU_TLS(nr_writes);
|
||||
+
|
||||
+ printf_verbose("thread_end %s, tid %lu, count %llu\n",
|
||||
+ "writer", urcu_get_thread_id(), *count);
|
||||
return ((void*)2);
|
||||
}
|
||||
|
||||
@@ -345,6 +346,7 @@ int main(int argc, char **argv)
|
||||
printf_verbose("running test for %lu seconds, %u readers, %u writers.\n",
|
||||
duration, nr_readers, nr_writers);
|
||||
printf_verbose("Writer delay : %lu loops.\n", wdelay);
|
||||
+ printf_verbose("Writer duration : %lu loops.\n", wduration);
|
||||
printf_verbose("Reader duration : %lu loops.\n", rduration);
|
||||
printf_verbose("thread %-6s, tid %lu\n",
|
||||
"main", urcu_get_thread_id());
|
||||
--
|
||||
2.19.1
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
From 11dcfc5e044f55941ffd3f1155bbda51ed05aff7 Mon Sep 17 00:00:00 2001
|
||||
From: hewenliang <hewenliang4@huawei.com>
|
||||
Date: Mon, 12 Aug 2019 22:30:20 +0000
|
||||
Subject: [PATCH] urcu: fix deadlock issue using SIG_RCU
|
||||
|
||||
reason:
|
||||
1.use a seperate thread(cds_lfht_workqueue) to handle hash table auto resize,
|
||||
and this thread block all signal at initialization.
|
||||
2.While in urcu-signal flavor, call_rcu_thread will send SIGRCU signal to all
|
||||
the registed thread to make them do cmm_smp_mb.
|
||||
3.Based on above, call_rcu_thread and workqueue thread will trapped into a dead
|
||||
loop: where call_rcu_thread hold the rcu_registry_lock to waiting all the registed
|
||||
thread to do cmm_smp_mb, while workqueue thread nerver do cmm_smp_mb and waiting to
|
||||
get rcu_registry_lock to unregiter from rcu.
|
||||
so we should not block SIGRCU in workqueue thread to avoid the dead lock.
|
||||
|
||||
Signed-off-by: hewenliang <hewenliang4@huawei.com>
|
||||
---
|
||||
src/rculfhash.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/rculfhash.c b/src/rculfhash.c
|
||||
index fed33e4..fc3d610 100644
|
||||
--- a/src/rculfhash.c
|
||||
+++ b/src/rculfhash.c
|
||||
@@ -273,6 +273,7 @@
|
||||
#include <urcu/uatomic.h>
|
||||
#include <urcu/compiler.h>
|
||||
#include <urcu/rculfhash.h>
|
||||
+#include <urcu.h>
|
||||
#include <rculfhash-internal.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
@@ -2112,7 +2113,7 @@ static void cds_lfht_worker_init(struct urcu_workqueue *workqueue,
|
||||
{
|
||||
int ret;
|
||||
sigset_t mask;
|
||||
-
|
||||
+ sigset_t set;
|
||||
/* Block signal for entire process, so only our thread processes it. */
|
||||
ret = sigfillset(&mask);
|
||||
if (ret)
|
||||
@@ -2120,6 +2121,11 @@ static void cds_lfht_worker_init(struct urcu_workqueue *workqueue,
|
||||
ret = pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
||||
if (ret)
|
||||
urcu_die(ret);
|
||||
+ sigemptyset(&set);
|
||||
+ sigaddset(&set, SIGRCU);
|
||||
+ ret = pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
||||
+ if (ret)
|
||||
+ urcu_die(ret);
|
||||
}
|
||||
|
||||
static void cds_lfht_init_worker(const struct rcu_flavor_struct *flavor)
|
||||
--
|
||||
2.19.1
|
||||
|
||||
Binary file not shown.
BIN
userspace-rcu-0.12.1.tar.bz2
Normal file
BIN
userspace-rcu-0.12.1.tar.bz2
Normal file
Binary file not shown.
@ -1,24 +1,11 @@
|
||||
Name: userspace-rcu
|
||||
Version: 0.10.1
|
||||
Release: 10
|
||||
Version: 0.12.1
|
||||
Release: 1
|
||||
Summary: Userspace read-copy-update library
|
||||
License: LGPLv2+
|
||||
URL: http://liburcu.org
|
||||
Source0: http://lttng.org/files/urcu/%{name}-%{version}.tar.bz2
|
||||
|
||||
Patch6000: fix-compat_futex_noasync-on-Cygwin.patch
|
||||
Patch6001: fix-pthread_rwlock-initialization-on-Cygwin.patch
|
||||
Patch6002: test_rwlock-Add-per-thread-count-to-verbose-output.patch
|
||||
Patch6003: fix-mixup-between-URCU_WORKQUEUE_RT-and-URCU_CALL_RC.patch
|
||||
Patch6004: cleanup-workqueue-update-comments-referring-to-call-.patch
|
||||
Patch6005: fix-workqueue-struct-urcu_work-vs-rcu_head-mixup.patch
|
||||
Patch6006: fix-don-t-wait-after-completion-of-job-batch-if-work.patch
|
||||
Patch6007: fix-don-t-wait-after-completion-of-a-work-queue-job-.patch
|
||||
Patch6008: fix-only-wait-if-work-queue-is-empty-in-real-time-mo.patch
|
||||
Patch6009: fix-regtest-without-bench.patch
|
||||
|
||||
Patch9000: urcu-fix-deadlock-issue-using-SIG_RCU.patch
|
||||
|
||||
BuildRequires: pkgconfig perl-Test-Harness autoconf automake libtool
|
||||
|
||||
%description
|
||||
@ -77,6 +64,9 @@ make check
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Jul 21 2020 jinzhimin <jinzhimin2@huawei.com> - 0.12.1-1
|
||||
- upgrade to 0.12.1
|
||||
|
||||
* Thu Jun 29 2020 xinghe <xinghe1@huawei.com> - 0.10.1-10
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user