From cb1c72d36be42356a99285befde6e769dba599f5 Mon Sep 17 00:00:00 2001 From: Samy Al Bahra Date: Wed, 26 Sep 2012 12:34:51 -0400 Subject: [PATCH] ck_queue: Add CK_?LIST_MOVE operation. This operation is of format: CK_S*LIST_MOVE(a, b, linkage) and is equivalent to intializing a with the contents of b. This is done in a manner that is atomic with respect to readers. Read-only operations are still valid in b, but behavior is undefined for write-side operations on b after a MOVE operation. --- include/ck_queue.h | 11 +++++++++++ regressions/ck_queue/validate/ck_list.c | 7 +++++-- regressions/ck_queue/validate/ck_slist.c | 13 ++++++++----- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/ck_queue.h b/include/ck_queue.h index 911d5e1..4b2f91b 100644 --- a/include/ck_queue.h +++ b/include/ck_queue.h @@ -105,6 +105,7 @@ * _REMOVE_HEAD + - * _REMOVE + + * _SWAP + + + * _MOVE + + */ /* @@ -188,6 +189,10 @@ struct { \ (head)->slh_first->field.sle_next); \ } while (0) +#define CK_SLIST_MOVE(head1, head2, field) do { \ + ck_pr_store_ptr(&(head1)->slh_first, (head2)->slh_first); \ +} while (0) + /* * This operation is not applied atomically. */ @@ -265,6 +270,12 @@ struct { \ (elm)->field.le_next->field.le_prev = (elm)->field.le_prev; \ } while (0) +#define CK_LIST_MOVE(head1, head2, field) do { \ + ck_pr_store_ptr(&(head1)->lh_first, (head2)->lh_first); \ + if ((head1)->lh_first != NULL) \ + (head1)->lh_first->field.le_prev = &(head1)->lh_first; \ +} while (0) + /* * This operation is not applied atomically. */ diff --git a/regressions/ck_queue/validate/ck_list.c b/regressions/ck_queue/validate/ck_list.c index 3ee762c..bbf45c9 100644 --- a/regressions/ck_queue/validate/ck_list.c +++ b/regressions/ck_queue/validate/ck_list.c @@ -122,6 +122,7 @@ main(int argc, char *argv[]) { pthread_t *thread; struct test *n; + struct test_list target; int n_threads, i; if (argc != 3) { @@ -199,11 +200,13 @@ main(int argc, char *argv[]) assert(r == 0); } + CK_LIST_MOVE(&target, &head, list_entry); + for (i = 1; i <= goal; i++) { volatile int j; - if (CK_LIST_EMPTY(&head) == false) { - struct test *r = CK_LIST_FIRST(&head); + if (CK_LIST_EMPTY(&target) == false) { + struct test *r = CK_LIST_FIRST(&target); CK_LIST_REMOVE(r, list_entry); } diff --git a/regressions/ck_queue/validate/ck_slist.c b/regressions/ck_queue/validate/ck_slist.c index 6d167ca..6391ae3 100644 --- a/regressions/ck_queue/validate/ck_slist.c +++ b/regressions/ck_queue/validate/ck_slist.c @@ -122,6 +122,7 @@ main(int argc, char *argv[]) { pthread_t *thread; struct test *n; + struct test_list target; int n_threads, i; if (argc != 3) { @@ -199,17 +200,19 @@ main(int argc, char *argv[]) assert(r == 0); } + CK_SLIST_MOVE(&target, &head, list_entry); + for (i = 1; i <= goal; i++) { volatile int j; - if (CK_SLIST_EMPTY(&head) == false) - CK_SLIST_REMOVE_HEAD(&head, list_entry); + if (CK_SLIST_EMPTY(&target) == false) + CK_SLIST_REMOVE_HEAD(&target, list_entry); for (j = 0; j <= 1000; j++); - if (CK_SLIST_EMPTY(&head) == false) { - struct test *r = CK_SLIST_FIRST(&head); - CK_SLIST_REMOVE(&head, r, test, list_entry); + if (CK_SLIST_EMPTY(&target) == false) { + struct test *r = CK_SLIST_FIRST(&target); + CK_SLIST_REMOVE(&target, r, test, list_entry); } }