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.
ck_pring
Samy Al Bahra 12 years ago
parent 5df8882840
commit cb1c72d36b

@ -105,6 +105,7 @@
* _REMOVE_HEAD + - * _REMOVE_HEAD + -
* _REMOVE + + * _REMOVE + +
* _SWAP + + * _SWAP + +
* _MOVE + +
*/ */
/* /*
@ -188,6 +189,10 @@ struct { \
(head)->slh_first->field.sle_next); \ (head)->slh_first->field.sle_next); \
} while (0) } 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. * This operation is not applied atomically.
*/ */
@ -265,6 +270,12 @@ struct { \
(elm)->field.le_next->field.le_prev = (elm)->field.le_prev; \ (elm)->field.le_next->field.le_prev = (elm)->field.le_prev; \
} while (0) } 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. * This operation is not applied atomically.
*/ */

@ -122,6 +122,7 @@ main(int argc, char *argv[])
{ {
pthread_t *thread; pthread_t *thread;
struct test *n; struct test *n;
struct test_list target;
int n_threads, i; int n_threads, i;
if (argc != 3) { if (argc != 3) {
@ -199,11 +200,13 @@ main(int argc, char *argv[])
assert(r == 0); assert(r == 0);
} }
CK_LIST_MOVE(&target, &head, list_entry);
for (i = 1; i <= goal; i++) { for (i = 1; i <= goal; i++) {
volatile int j; volatile int j;
if (CK_LIST_EMPTY(&head) == false) { if (CK_LIST_EMPTY(&target) == false) {
struct test *r = CK_LIST_FIRST(&head); struct test *r = CK_LIST_FIRST(&target);
CK_LIST_REMOVE(r, list_entry); CK_LIST_REMOVE(r, list_entry);
} }

@ -122,6 +122,7 @@ main(int argc, char *argv[])
{ {
pthread_t *thread; pthread_t *thread;
struct test *n; struct test *n;
struct test_list target;
int n_threads, i; int n_threads, i;
if (argc != 3) { if (argc != 3) {
@ -199,17 +200,19 @@ main(int argc, char *argv[])
assert(r == 0); assert(r == 0);
} }
CK_SLIST_MOVE(&target, &head, list_entry);
for (i = 1; i <= goal; i++) { for (i = 1; i <= goal; i++) {
volatile int j; volatile int j;
if (CK_SLIST_EMPTY(&head) == false) if (CK_SLIST_EMPTY(&target) == false)
CK_SLIST_REMOVE_HEAD(&head, list_entry); CK_SLIST_REMOVE_HEAD(&target, list_entry);
for (j = 0; j <= 1000; j++); for (j = 0; j <= 1000; j++);
if (CK_SLIST_EMPTY(&head) == false) { if (CK_SLIST_EMPTY(&target) == false) {
struct test *r = CK_SLIST_FIRST(&head); struct test *r = CK_SLIST_FIRST(&target);
CK_SLIST_REMOVE(&head, r, test, list_entry); CK_SLIST_REMOVE(&target, r, test, list_entry);
} }
} }

Loading…
Cancel
Save