From b3f374cb5589a52900ea207fa9f977ff6e5e39c6 Mon Sep 17 00:00:00 2001 From: Samy Al Bahra Date: Wed, 5 Nov 2014 18:30:31 -0500 Subject: [PATCH] ck_epoch: Allow for deferral from callbacks. This makes things much easier in cases where deferral is mixed with other reclamation mechanisms such as reference counters. --- regressions/ck_epoch/validate/Makefile | 5 +- regressions/ck_epoch/validate/ck_epoch_call.c | 64 +++++++++++++++++++ src/ck_epoch.c | 9 ++- 3 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 regressions/ck_epoch/validate/ck_epoch_call.c diff --git a/regressions/ck_epoch/validate/Makefile b/regressions/ck_epoch/validate/Makefile index 73f8e5d..c053d22 100644 --- a/regressions/ck_epoch/validate/Makefile +++ b/regressions/ck_epoch/validate/Makefile @@ -1,6 +1,6 @@ .PHONY: check clean distribution -OBJECTS=ck_stack ck_epoch_synchronize ck_epoch_poll +OBJECTS=ck_stack ck_epoch_synchronize ck_epoch_poll ck_epoch_call HALF=`expr $(CORES) / 2` all: $(OBJECTS) @@ -16,6 +16,9 @@ ck_epoch_synchronize: ck_epoch_synchronize.c ../../../include/ck_stack.h ../../. ck_epoch_poll: ck_epoch_poll.c ../../../include/ck_stack.h ../../../include/ck_epoch.h ../../../src/ck_epoch.c $(CC) $(CFLAGS) -o ck_epoch_poll ck_epoch_poll.c ../../../src/ck_epoch.c +ck_epoch_call: ck_epoch_call.c ../../../include/ck_stack.h ../../../include/ck_epoch.h ../../../src/ck_epoch.c + $(CC) $(CFLAGS) -o ck_epoch_call ck_epoch_call.c ../../../src/ck_epoch.c + ck_stack: ck_stack.c ../../../include/ck_stack.h ../../../include/ck_epoch.h ../../../src/ck_epoch.c $(CC) $(CFLAGS) -o ck_stack ck_stack.c ../../../src/ck_epoch.c diff --git a/regressions/ck_epoch/validate/ck_epoch_call.c b/regressions/ck_epoch/validate/ck_epoch_call.c new file mode 100644 index 0000000..9219ddd --- /dev/null +++ b/regressions/ck_epoch/validate/ck_epoch_call.c @@ -0,0 +1,64 @@ +/* + * Copyright 2014 Samy Al Bahra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "../../common.h" + +static ck_epoch_t epoch; +static unsigned int counter; +static ck_epoch_record_t record[2]; + +static void +cb(ck_epoch_entry_t *p) +{ + + if (counter == 0) + ck_epoch_call(&epoch, &record[1], p, cb); + + printf("Counter value: %u -> %u\n", + counter, counter + 1); + counter++; + return; +} + +int +main(void) +{ + static ck_epoch_entry_t entry; + + ck_epoch_register(&epoch, &record[0]); + ck_epoch_register(&epoch, &record[1]); + + ck_epoch_call(&epoch, &record[1], &entry, cb); + ck_epoch_barrier(&epoch, &record[1]); + ck_epoch_barrier(&epoch, &record[1]); + if (counter != 2) + ck_error("Expected counter value 2, read %u.\n", counter); + + return 0; +} diff --git a/src/ck_epoch.c b/src/ck_epoch.c index 1a51059..01320ee 100644 --- a/src/ck_epoch.c +++ b/src/ck_epoch.c @@ -257,12 +257,16 @@ static void ck_epoch_dispatch(struct ck_epoch_record *record, unsigned int e) { unsigned int epoch = e & (CK_EPOCH_LENGTH - 1); - ck_stack_entry_t *next, *cursor; + ck_stack_entry_t *head, *next, *cursor; unsigned int i = 0; - CK_STACK_FOREACH_SAFE(&record->pending[epoch], cursor, next) { + head = CK_STACK_FIRST(&record->pending[epoch]); + ck_stack_init(&record->pending[epoch]); + + for (cursor = head; cursor != NULL; cursor = next) { struct ck_epoch_entry *entry = ck_epoch_entry_container(cursor); + next = CK_STACK_NEXT(cursor); entry->function(entry); i++; } @@ -272,7 +276,6 @@ ck_epoch_dispatch(struct ck_epoch_record *record, unsigned int e) record->n_dispatch += i; record->n_pending -= i; - ck_stack_init(&record->pending[epoch]); return; }