Adding upstream version 0.6.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
c49a9029dc
commit
7f70a05c55
465 changed files with 60158 additions and 0 deletions
128
regressions/Makefile
Normal file
128
regressions/Makefile
Normal file
|
@ -0,0 +1,128 @@
|
|||
DIR=array \
|
||||
backoff \
|
||||
barrier \
|
||||
bitmap \
|
||||
brlock \
|
||||
bytelock \
|
||||
cohort \
|
||||
epoch \
|
||||
fifo \
|
||||
hp \
|
||||
hs \
|
||||
rhs \
|
||||
ht \
|
||||
pflock \
|
||||
pr \
|
||||
queue \
|
||||
ring \
|
||||
rwlock \
|
||||
swlock \
|
||||
sequence \
|
||||
spinlock \
|
||||
stack \
|
||||
swlock \
|
||||
tflock
|
||||
|
||||
.PHONY: all clean check
|
||||
|
||||
all:
|
||||
$(MAKE) -C ./ck_array/validate all
|
||||
$(MAKE) -C ./ck_cohort/validate all
|
||||
$(MAKE) -C ./ck_cohort/benchmark all
|
||||
$(MAKE) -C ./ck_bitmap/validate all
|
||||
$(MAKE) -C ./ck_backoff/validate all
|
||||
$(MAKE) -C ./ck_queue/validate all
|
||||
$(MAKE) -C ./ck_brlock/validate all
|
||||
$(MAKE) -C ./ck_ht/validate all
|
||||
$(MAKE) -C ./ck_ht/benchmark all
|
||||
$(MAKE) -C ./ck_brlock/benchmark all
|
||||
$(MAKE) -C ./ck_spinlock/validate all
|
||||
$(MAKE) -C ./ck_spinlock/benchmark all
|
||||
$(MAKE) -C ./ck_fifo/validate all
|
||||
$(MAKE) -C ./ck_fifo/benchmark all
|
||||
$(MAKE) -C ./ck_pr/validate all
|
||||
$(MAKE) -C ./ck_pr/benchmark all
|
||||
$(MAKE) -C ./ck_hs/benchmark all
|
||||
$(MAKE) -C ./ck_hs/validate all
|
||||
$(MAKE) -C ./ck_rhs/benchmark all
|
||||
$(MAKE) -C ./ck_rhs/validate all
|
||||
$(MAKE) -C ./ck_barrier/validate all
|
||||
$(MAKE) -C ./ck_barrier/benchmark all
|
||||
$(MAKE) -C ./ck_bytelock/validate all
|
||||
$(MAKE) -C ./ck_bytelock/benchmark all
|
||||
$(MAKE) -C ./ck_epoch/validate all
|
||||
$(MAKE) -C ./ck_rwcohort/validate all
|
||||
$(MAKE) -C ./ck_rwcohort/benchmark all
|
||||
$(MAKE) -C ./ck_sequence/validate all
|
||||
$(MAKE) -C ./ck_sequence/benchmark all
|
||||
$(MAKE) -C ./ck_stack/validate all
|
||||
$(MAKE) -C ./ck_stack/benchmark all
|
||||
$(MAKE) -C ./ck_ring/validate all
|
||||
$(MAKE) -C ./ck_ring/benchmark all
|
||||
$(MAKE) -C ./ck_rwlock/validate all
|
||||
$(MAKE) -C ./ck_rwlock/benchmark all
|
||||
$(MAKE) -C ./ck_tflock/validate all
|
||||
$(MAKE) -C ./ck_tflock/benchmark all
|
||||
$(MAKE) -C ./ck_swlock/validate all
|
||||
$(MAKE) -C ./ck_swlock/benchmark all
|
||||
$(MAKE) -C ./ck_pflock/validate all
|
||||
$(MAKE) -C ./ck_pflock/benchmark all
|
||||
$(MAKE) -C ./ck_hp/validate all
|
||||
$(MAKE) -C ./ck_hp/benchmark all
|
||||
|
||||
clean:
|
||||
$(MAKE) -C ./ck_array/validate clean
|
||||
$(MAKE) -C ./ck_pflock/validate clean
|
||||
$(MAKE) -C ./ck_pflock/benchmark clean
|
||||
$(MAKE) -C ./ck_tflock/validate clean
|
||||
$(MAKE) -C ./ck_tflock/benchmark clean
|
||||
$(MAKE) -C ./ck_rwcohort/validate clean
|
||||
$(MAKE) -C ./ck_rwcohort/benchmark clean
|
||||
$(MAKE) -C ./ck_backoff/validate clean
|
||||
$(MAKE) -C ./ck_bitmap/validate clean
|
||||
$(MAKE) -C ./ck_queue/validate clean
|
||||
$(MAKE) -C ./ck_cohort/validate clean
|
||||
$(MAKE) -C ./ck_cohort/benchmark clean
|
||||
$(MAKE) -C ./ck_brlock/validate clean
|
||||
$(MAKE) -C ./ck_ht/validate clean
|
||||
$(MAKE) -C ./ck_ht/benchmark clean
|
||||
$(MAKE) -C ./ck_hs/validate clean
|
||||
$(MAKE) -C ./ck_hs/benchmark clean
|
||||
$(MAKE) -C ./ck_rhs/validate clean
|
||||
$(MAKE) -C ./ck_rhs/benchmark clean
|
||||
$(MAKE) -C ./ck_brlock/benchmark clean
|
||||
$(MAKE) -C ./ck_spinlock/validate clean
|
||||
$(MAKE) -C ./ck_spinlock/benchmark clean
|
||||
$(MAKE) -C ./ck_fifo/validate clean
|
||||
$(MAKE) -C ./ck_fifo/benchmark clean
|
||||
$(MAKE) -C ./ck_pr/validate clean
|
||||
$(MAKE) -C ./ck_pr/benchmark clean
|
||||
$(MAKE) -C ./ck_barrier/validate clean
|
||||
$(MAKE) -C ./ck_barrier/benchmark clean
|
||||
$(MAKE) -C ./ck_bytelock/validate clean
|
||||
$(MAKE) -C ./ck_bytelock/benchmark clean
|
||||
$(MAKE) -C ./ck_epoch/validate clean
|
||||
$(MAKE) -C ./ck_sequence/validate clean
|
||||
$(MAKE) -C ./ck_sequence/benchmark clean
|
||||
$(MAKE) -C ./ck_stack/validate clean
|
||||
$(MAKE) -C ./ck_stack/benchmark clean
|
||||
$(MAKE) -C ./ck_ring/validate clean
|
||||
$(MAKE) -C ./ck_ring/benchmark clean
|
||||
$(MAKE) -C ./ck_rwlock/validate clean
|
||||
$(MAKE) -C ./ck_rwlock/benchmark clean
|
||||
$(MAKE) -C ./ck_swlock/validate clean
|
||||
$(MAKE) -C ./ck_swlock/benchmark clean
|
||||
$(MAKE) -C ./ck_pflock/validate clean
|
||||
$(MAKE) -C ./ck_pflock/benchmark clean
|
||||
$(MAKE) -C ./ck_hp/validate clean
|
||||
$(MAKE) -C ./ck_hp/benchmark clean
|
||||
|
||||
check: all
|
||||
rc=0; \
|
||||
for d in $(DIR) ; do \
|
||||
echo "----[ Testing $$d...."; \
|
||||
$(MAKE) -C ./ck_$$d/validate check || rc=1; \
|
||||
echo; \
|
||||
done; \
|
||||
exit $$rc
|
||||
|
9
regressions/Makefile.unsupported
Normal file
9
regressions/Makefile.unsupported
Normal file
|
@ -0,0 +1,9 @@
|
|||
.PHONY: all clean check
|
||||
|
||||
all:
|
||||
@echo Regressions are currently unsupported for out-of-source builds
|
||||
|
||||
clean: all
|
||||
|
||||
check: all
|
||||
|
17
regressions/ck_array/validate/Makefile
Normal file
17
regressions/ck_array/validate/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=serial
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
serial: serial.c ../../../include/ck_array.h ../../../src/ck_array.c
|
||||
$(CC) $(CFLAGS) -o serial serial.c ../../../src/ck_array.c
|
||||
|
||||
check: all
|
||||
./serial
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o $(OBJECTS) *.dSYM *.exe
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=-D_GNU_SOURCE -ggdb
|
178
regressions/ck_array/validate/serial.c
Normal file
178
regressions/ck_array/validate/serial.c
Normal file
|
@ -0,0 +1,178 @@
|
|||
#include <ck_array.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATION
|
||||
#define ITERATION 128
|
||||
#endif
|
||||
|
||||
static void
|
||||
my_free(void *p, size_t m, bool d)
|
||||
{
|
||||
|
||||
(void)m;
|
||||
(void)d;
|
||||
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
my_malloc(size_t b)
|
||||
{
|
||||
|
||||
return malloc(b);
|
||||
}
|
||||
|
||||
static void *
|
||||
my_realloc(void *r, size_t a, size_t b, bool d)
|
||||
{
|
||||
|
||||
(void)a;
|
||||
(void)d;
|
||||
|
||||
return realloc(r, b);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
void *r;
|
||||
uintptr_t i;
|
||||
ck_array_t array;
|
||||
ck_array_iterator_t iterator;
|
||||
struct ck_malloc m = {
|
||||
.malloc = my_malloc,
|
||||
.free = NULL,
|
||||
.realloc = my_realloc
|
||||
};
|
||||
|
||||
if (ck_array_init(&array, CK_ARRAY_MODE_SPMC, &m, 4) == true)
|
||||
ck_error("ck_array_init with NULL free succeeded\n");
|
||||
|
||||
m.free = my_free;
|
||||
if (ck_array_init(&array, CK_ARRAY_MODE_SPMC, &m, 4) == false)
|
||||
ck_error("ck_array_init\n");
|
||||
|
||||
for (i = 0; i < ITERATION; i++) {
|
||||
if (ck_array_put(&array, (void *)i) == false)
|
||||
ck_error("ck_error_put\n");
|
||||
|
||||
if (ck_array_remove(&array, (void *)i) == false)
|
||||
ck_error("ck_error_remove after put\n");
|
||||
}
|
||||
|
||||
i = 0; CK_ARRAY_FOREACH(&array, &iterator, &r) i++;
|
||||
if (i != 0)
|
||||
ck_error("Non-empty array after put -> remove workload.\n");
|
||||
|
||||
ck_array_commit(&array);
|
||||
|
||||
i = 0; CK_ARRAY_FOREACH(&array, &iterator, &r) i++;
|
||||
if (i != 0)
|
||||
ck_error("Non-empty array after put -> remove -> commit workload.\n");
|
||||
|
||||
for (i = 0; i < ITERATION; i++) {
|
||||
if (ck_array_put(&array, (void *)i) == false)
|
||||
ck_error("ck_error_put\n");
|
||||
}
|
||||
|
||||
i = 0; CK_ARRAY_FOREACH(&array, &iterator, &r) i++;
|
||||
if (i != 0)
|
||||
ck_error("Non-empty array after put workload.\n");
|
||||
|
||||
for (i = 0; i < ITERATION; i++) {
|
||||
if (ck_array_remove(&array, (void *)i) == false)
|
||||
ck_error("ck_error_remove after put\n");
|
||||
}
|
||||
|
||||
i = 0; CK_ARRAY_FOREACH(&array, &iterator, &r) i++;
|
||||
if (i != 0)
|
||||
ck_error("Non-empty array after put -> remove workload.\n");
|
||||
|
||||
ck_array_commit(&array);
|
||||
|
||||
i = 0; CK_ARRAY_FOREACH(&array, &iterator, &r) i++;
|
||||
if (i != 0)
|
||||
ck_error("Non-empty array after put -> remove -> commit workload.\n");
|
||||
|
||||
for (i = 0; i < ITERATION; i++) {
|
||||
if (ck_array_put(&array, (void *)i) == false)
|
||||
ck_error("ck_error_put\n");
|
||||
}
|
||||
|
||||
ck_array_commit(&array);
|
||||
|
||||
i = 0;
|
||||
CK_ARRAY_FOREACH(&array, &iterator, &r) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i != ITERATION)
|
||||
ck_error("Incorrect item count in iteration\n");
|
||||
|
||||
ck_array_remove(&array, (void *)(uintptr_t)0);
|
||||
ck_array_remove(&array, (void *)(uintptr_t)1);
|
||||
ck_array_commit(&array);
|
||||
i = 0; CK_ARRAY_FOREACH(&array, &iterator, &r) i++;
|
||||
if (i != ITERATION - 2 || ck_array_length(&array) != ITERATION - 2)
|
||||
ck_error("Incorrect item count in iteration after remove\n");
|
||||
|
||||
if (ck_array_put_unique(&array, (void *)UINTPTR_MAX) != 0)
|
||||
ck_error("Unique value put failed.\n");
|
||||
|
||||
if (ck_array_put_unique(&array, (void *)(uintptr_t)4) != 1)
|
||||
ck_error("put of 4 not detected as non-unique.\n");
|
||||
|
||||
if (ck_array_put_unique(&array, (void *)UINTPTR_MAX) != 1)
|
||||
ck_error("put of UINTPTR_MAX not detected as non-unique.\n");
|
||||
|
||||
ck_array_commit(&array);
|
||||
i = 0;
|
||||
CK_ARRAY_FOREACH(&array, &iterator, &r) {
|
||||
i++;
|
||||
}
|
||||
if (i != ITERATION - 1 || ck_array_length(&array) != ITERATION - 1)
|
||||
ck_error("Incorrect item count in iteration after unique put\n");
|
||||
|
||||
if (ck_array_initialized(&array) == false)
|
||||
ck_error("Error, expected array to be initialized.\n");
|
||||
|
||||
for (i = 0; i < ITERATION * 4; i++) {
|
||||
ck_array_remove(&array, (void *)i);
|
||||
}
|
||||
|
||||
for (i = 0; i < ITERATION * 16; i++) {
|
||||
ck_array_put(&array, (void *)i);
|
||||
}
|
||||
|
||||
ck_array_commit(&array);
|
||||
|
||||
for (i = 0; i < ITERATION * 128; i++) {
|
||||
ck_array_put(&array, (void *)i);
|
||||
if (ck_array_put_unique(&array, (void *)i) != 1)
|
||||
ck_error("put_unique for non-unique value should fail.\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < ITERATION * 64; i++) {
|
||||
bool f = ck_array_remove(&array, (void *)i);
|
||||
|
||||
if (f == false && i < ITERATION * 144)
|
||||
ck_error("Remove failed for existing entry.\n");
|
||||
|
||||
if (f == true && i > ITERATION * 144)
|
||||
ck_error("Remove succeeded for non-existing entry.\n");
|
||||
}
|
||||
|
||||
ck_array_commit(&array);
|
||||
ck_array_deinit(&array, false);
|
||||
|
||||
if (ck_array_initialized(&array) == true)
|
||||
ck_error("Error, expected array to be uninitialized.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
15
regressions/ck_backoff/validate/Makefile
Normal file
15
regressions/ck_backoff/validate/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
.PHONY: check clean
|
||||
|
||||
all: validate
|
||||
|
||||
validate: validate.c ../../../include/ck_backoff.h
|
||||
$(CC) $(CFLAGS) -o validate validate.c
|
||||
|
||||
check: all
|
||||
./validate
|
||||
|
||||
clean:
|
||||
rm -rf validate *.dSYM *.exe
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=-D_GNU_SOURCE
|
60
regressions/ck_backoff/validate/validate.c
Normal file
60
regressions/ck_backoff/validate/validate.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ck_backoff.h>
|
||||
#include "../../common.h"
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
ck_backoff_t backoff = CK_BACKOFF_INITIALIZER;
|
||||
const ck_backoff_t ceiling = CK_BACKOFF_CEILING + 1;
|
||||
unsigned int i = 0;
|
||||
|
||||
fprintf(stderr, "Ceiling is: %u (%#x)\n", CK_BACKOFF_CEILING, CK_BACKOFF_CEILING);
|
||||
|
||||
for (;;) {
|
||||
ck_backoff_t previous = backoff;
|
||||
ck_backoff_eb(&backoff);
|
||||
|
||||
printf("EB %u\n", backoff);
|
||||
if (previous == ceiling) {
|
||||
if (backoff != ceiling)
|
||||
ck_error("[C] GB: expected %u, got %u\n", ceiling, backoff);
|
||||
|
||||
if (i++ >= 1)
|
||||
break;
|
||||
} else if (previous != backoff >> 1) {
|
||||
ck_error("[N] GB: expected %u (%u), got %u\n", previous << 1, previous, backoff);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
14
regressions/ck_barrier/benchmark/Makefile
Normal file
14
regressions/ck_barrier/benchmark/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
.PHONY: clean distribution
|
||||
|
||||
OBJECTS=throughput
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
throughput: throughput.c ../../../include/ck_barrier.h ../../../src/ck_barrier_centralized.c
|
||||
$(CC) $(CFLAGS) -o throughput throughput.c ../../../src/ck_barrier_centralized.c
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
136
regressions/ck_barrier/benchmark/throughput.c
Normal file
136
regressions/ck_barrier/benchmark/throughput.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <ck_stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_barrier.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#if defined(CK_F_PR_INC_64) && defined(CK_F_PR_LOAD_64)
|
||||
static int done = 0;
|
||||
static struct affinity a;
|
||||
static int nthr;
|
||||
static int tid;
|
||||
static ck_barrier_centralized_t barrier = CK_BARRIER_CENTRALIZED_INITIALIZER;
|
||||
struct counter {
|
||||
uint64_t value;
|
||||
} CK_CC_CACHELINE;
|
||||
struct counter *counters;
|
||||
|
||||
static void *
|
||||
thread(void *null CK_CC_UNUSED)
|
||||
{
|
||||
ck_barrier_centralized_state_t state = CK_BARRIER_CENTRALIZED_STATE_INITIALIZER;
|
||||
int id;
|
||||
|
||||
id = ck_pr_faa_int(&tid, 1);
|
||||
aff_iterate(&a);
|
||||
|
||||
while (ck_pr_load_int(&done) == 0) {
|
||||
ck_barrier_centralized(&barrier, &state, nthr);
|
||||
ck_pr_inc_64(&counters[id].value);
|
||||
ck_barrier_centralized(&barrier, &state, nthr);
|
||||
ck_pr_inc_64(&counters[id].value);
|
||||
ck_barrier_centralized(&barrier, &state, nthr);
|
||||
ck_pr_inc_64(&counters[id].value);
|
||||
ck_barrier_centralized(&barrier, &state, nthr);
|
||||
ck_pr_inc_64(&counters[id].value);
|
||||
ck_barrier_centralized(&barrier, &state, nthr);
|
||||
ck_pr_inc_64(&counters[id].value);
|
||||
ck_barrier_centralized(&barrier, &state, nthr);
|
||||
ck_pr_inc_64(&counters[id].value);
|
||||
ck_barrier_centralized(&barrier, &state, nthr);
|
||||
ck_pr_inc_64(&counters[id].value);
|
||||
ck_barrier_centralized(&barrier, &state, nthr);
|
||||
ck_pr_inc_64(&counters[id].value);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t *threads;
|
||||
uint64_t count;
|
||||
int i;
|
||||
|
||||
if (argc != 3) {
|
||||
ck_error("Correct usage: <number of threads> <affinity delta>\n");
|
||||
}
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
counters = calloc(sizeof(struct counter), nthr);
|
||||
if (counters == NULL) {
|
||||
ck_error("ERROR: Could not allocate counters\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
fprintf(stderr, "Creating threads (barrier)...");
|
||||
for (i = 0; i < nthr; ++i) {
|
||||
if (pthread_create(&threads[i], NULL, thread, NULL)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
common_sleep(10);
|
||||
|
||||
count = 0;
|
||||
ck_pr_store_int(&done, 1);
|
||||
for (i = 0; i < nthr; ++i)
|
||||
count += ck_pr_load_64(&counters[i].value);
|
||||
printf("%d %16" PRIu64 "\n", nthr, count);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#else
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
fputs("Unsupported.", stderr);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
34
regressions/ck_barrier/validate/Makefile
Normal file
34
regressions/ck_barrier/validate/Makefile
Normal file
|
@ -0,0 +1,34 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=barrier_centralized barrier_combining barrier_dissemination barrier_tournament barrier_mcs
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
barrier_centralized: barrier_centralized.c ../../../include/ck_barrier.h ../../../src/ck_barrier_centralized.c
|
||||
$(CC) $(CFLAGS) -o barrier_centralized barrier_centralized.c ../../../src/ck_barrier_centralized.c
|
||||
|
||||
barrier_combining: barrier_combining.c ../../../include/ck_barrier.h ../../../src/ck_barrier_combining.c
|
||||
$(CC) $(CFLAGS) -o barrier_combining barrier_combining.c ../../../src/ck_barrier_combining.c
|
||||
|
||||
barrier_dissemination: barrier_dissemination.c ../../../include/ck_barrier.h ../../../src/ck_barrier_dissemination.c
|
||||
$(CC) $(CFLAGS) -o barrier_dissemination barrier_dissemination.c ../../../src/ck_barrier_dissemination.c
|
||||
|
||||
barrier_tournament: barrier_tournament.c ../../../include/ck_barrier.h ../../../src/ck_barrier_tournament.c
|
||||
$(CC) $(CFLAGS) -o barrier_tournament barrier_tournament.c ../../../src/ck_barrier_tournament.c
|
||||
|
||||
barrier_mcs: barrier_mcs.c ../../../include/ck_barrier.h ../../../src/ck_barrier_mcs.c
|
||||
$(CC) $(CFLAGS) -o barrier_mcs barrier_mcs.c ../../../src/ck_barrier_mcs.c
|
||||
|
||||
check: all
|
||||
rc=0; \
|
||||
for d in $(OBJECTS) ; do \
|
||||
echo $$d; \
|
||||
./$$d $(CORES) 1 1 || rc=1; \
|
||||
done; \
|
||||
exit $$rc
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
121
regressions/ck_barrier/validate/barrier_centralized.c
Normal file
121
regressions/ck_barrier/validate/barrier_centralized.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_barrier.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATE
|
||||
#define ITERATE 5000000
|
||||
#endif
|
||||
|
||||
#ifndef ENTRIES
|
||||
#define ENTRIES 512
|
||||
#endif
|
||||
|
||||
static struct affinity a;
|
||||
static int nthr;
|
||||
static int counters[ENTRIES];
|
||||
static ck_barrier_centralized_t barrier = CK_BARRIER_CENTRALIZED_INITIALIZER;
|
||||
static int barrier_wait;
|
||||
|
||||
static void *
|
||||
thread(void *null CK_CC_UNUSED)
|
||||
{
|
||||
ck_barrier_centralized_state_t state = CK_BARRIER_CENTRALIZED_STATE_INITIALIZER;
|
||||
int j, counter;
|
||||
int i = 0;
|
||||
|
||||
aff_iterate(&a);
|
||||
|
||||
ck_pr_inc_int(&barrier_wait);
|
||||
while (ck_pr_load_int(&barrier_wait) != nthr)
|
||||
ck_pr_stall();
|
||||
|
||||
for (j = 0; j < ITERATE; j++) {
|
||||
i = j++ & (ENTRIES - 1);
|
||||
ck_pr_inc_int(&counters[i]);
|
||||
ck_barrier_centralized(&barrier, &state, nthr);
|
||||
counter = ck_pr_load_int(&counters[i]);
|
||||
if (counter != nthr * (j / ENTRIES + 1)) {
|
||||
ck_error("FAILED [%d:%d]: %d != %d\n", i, j - 1, counter, nthr);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t *threads;
|
||||
int i;
|
||||
|
||||
if (argc < 3) {
|
||||
ck_error("Usage: correct <number of threads> <affinity delta>\n");
|
||||
}
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
fprintf(stderr, "Creating threads (barrier)...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
if (pthread_create(&threads[i], NULL, thread, NULL)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish correctness regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done (passed)\n");
|
||||
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
143
regressions/ck_barrier/validate/barrier_combining.c
Normal file
143
regressions/ck_barrier/validate/barrier_combining.c
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright 2011-2015 Samy Al Bahra.
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_barrier.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATE
|
||||
#define ITERATE 5000000
|
||||
#endif
|
||||
|
||||
#ifndef ENTRIES
|
||||
#define ENTRIES 512
|
||||
#endif
|
||||
|
||||
static struct affinity a;
|
||||
static int nthr;
|
||||
static int ngroups;
|
||||
static int counters[ENTRIES];
|
||||
static ck_barrier_combining_t barrier;
|
||||
static int barrier_wait;
|
||||
|
||||
static void *
|
||||
thread(void *group)
|
||||
{
|
||||
ck_barrier_combining_state_t state = CK_BARRIER_COMBINING_STATE_INITIALIZER;
|
||||
int j, counter;
|
||||
int i = 0;
|
||||
|
||||
aff_iterate(&a);
|
||||
|
||||
ck_pr_inc_int(&barrier_wait);
|
||||
while (ck_pr_load_int(&barrier_wait) != (nthr * ngroups))
|
||||
ck_pr_stall();
|
||||
|
||||
for (j = 0; j < ITERATE; j++) {
|
||||
i = j++ & (ENTRIES - 1);
|
||||
ck_pr_inc_int(&counters[i]);
|
||||
ck_barrier_combining(&barrier, group, &state);
|
||||
counter = ck_pr_load_int(&counters[i]);
|
||||
if (counter != nthr * ngroups * (j / ENTRIES + 1)) {
|
||||
ck_error("FAILED [%d:%d]: %d != %d\n", i, j - 1, counter, nthr * ngroups);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t *threads;
|
||||
ck_barrier_combining_group_t *groupings;
|
||||
ck_barrier_combining_group_t *init_root;
|
||||
int i;
|
||||
|
||||
init_root = malloc(sizeof(ck_barrier_combining_group_t));
|
||||
if (init_root == NULL) {
|
||||
ck_error("ERROR: Could not allocate initial barrier structure\n");
|
||||
}
|
||||
ck_barrier_combining_init(&barrier, init_root);
|
||||
|
||||
if (argc < 4) {
|
||||
ck_error("Usage: correct <total groups> <threads per group> <affinity delta>\n");
|
||||
}
|
||||
|
||||
ngroups = atoi(argv[1]);
|
||||
if (ngroups <= 0) {
|
||||
ck_error("ERROR: Number of groups must be greater than 0\n");
|
||||
}
|
||||
|
||||
nthr = atoi(argv[2]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
|
||||
groupings = malloc(sizeof(ck_barrier_combining_group_t) * ngroups);
|
||||
if (groupings == NULL) {
|
||||
ck_error("Could not allocate thread barrier grouping structures\n");
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr * ngroups);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[3]);
|
||||
|
||||
for (i = 0; i < ngroups; i++)
|
||||
ck_barrier_combining_group_init(&barrier, groupings + i, nthr);
|
||||
|
||||
fprintf(stderr, "Creating threads (barrier)...");
|
||||
for (i = 0; i < (nthr * ngroups); i++) {
|
||||
if (pthread_create(&threads[i], NULL, thread, groupings + (i % ngroups))) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish correctness regression...");
|
||||
for (i = 0; i < (nthr * ngroups); i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done (passed)\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
144
regressions/ck_barrier/validate/barrier_dissemination.c
Normal file
144
regressions/ck_barrier/validate/barrier_dissemination.c
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright 2011-2015 Samy Al Bahra.
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_barrier.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATE
|
||||
#define ITERATE 5000000
|
||||
#endif
|
||||
|
||||
#ifndef ENTRIES
|
||||
#define ENTRIES 512
|
||||
#endif
|
||||
|
||||
static struct affinity a;
|
||||
static int nthr;
|
||||
static int counters[ENTRIES];
|
||||
static int barrier_wait;
|
||||
|
||||
static void *
|
||||
thread(void *b)
|
||||
{
|
||||
ck_barrier_dissemination_t *barrier = b;
|
||||
ck_barrier_dissemination_state_t state;
|
||||
int j, k, counter;
|
||||
int i = 0;
|
||||
|
||||
aff_iterate(&a);
|
||||
ck_barrier_dissemination_subscribe(barrier, &state);
|
||||
|
||||
ck_pr_inc_int(&barrier_wait);
|
||||
while (ck_pr_load_int(&barrier_wait) != nthr)
|
||||
ck_pr_stall();
|
||||
|
||||
for (j = 0, k = 0; j < ITERATE; j++, k++) {
|
||||
i = j++ & (ENTRIES - 1);
|
||||
ck_pr_inc_int(&counters[i]);
|
||||
ck_barrier_dissemination(barrier, &state);
|
||||
counter = ck_pr_load_int(&counters[i]);
|
||||
if (counter != nthr * (j / ENTRIES + 1)) {
|
||||
ck_error("FAILED [%d:%d]: %d != %d\n", i, j - 1, counter, nthr);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
ck_barrier_dissemination_t *barrier;
|
||||
ck_barrier_dissemination_flag_t **barrier_internal;
|
||||
pthread_t *threads;
|
||||
int i, size;
|
||||
|
||||
if (argc < 3) {
|
||||
ck_error("Usage: correct <number of threads> <affinity delta>\n");
|
||||
}
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
barrier = malloc(sizeof(ck_barrier_dissemination_t) * nthr);
|
||||
if (barrier == NULL) {
|
||||
ck_error("ERROR: Could not allocate barrier structures\n");
|
||||
}
|
||||
|
||||
barrier_internal = malloc(sizeof(ck_barrier_dissemination_flag_t *) * nthr);
|
||||
if (barrier_internal == NULL) {
|
||||
ck_error("ERROR: Could not allocate barrier structures\n");
|
||||
}
|
||||
|
||||
size = ck_barrier_dissemination_size(nthr);
|
||||
for (i = 0; i < nthr; ++i) {
|
||||
barrier_internal[i] = malloc(sizeof(ck_barrier_dissemination_flag_t) * size);
|
||||
if (barrier_internal[i] == NULL) {
|
||||
ck_error("ERROR: Could not allocate barrier structures\n");
|
||||
}
|
||||
}
|
||||
ck_barrier_dissemination_init(barrier, barrier_internal, nthr);
|
||||
|
||||
fprintf(stderr, "Creating threads (barrier)...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
if (pthread_create(&threads[i], NULL, thread, barrier)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish correctness regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done (passed)\n");
|
||||
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
131
regressions/ck_barrier/validate/barrier_mcs.c
Normal file
131
regressions/ck_barrier/validate/barrier_mcs.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 2011-2015 Samy Al Bahra.
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_barrier.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATE
|
||||
#define ITERATE 5000000
|
||||
#endif
|
||||
|
||||
#ifndef ENTRIES
|
||||
#define ENTRIES 512
|
||||
#endif
|
||||
|
||||
static struct affinity a;
|
||||
static int nthr;
|
||||
static int counters[ENTRIES];
|
||||
static int barrier_wait;
|
||||
|
||||
static void *
|
||||
thread(void *b)
|
||||
{
|
||||
ck_barrier_mcs_t *barrier = b;
|
||||
ck_barrier_mcs_state_t state;
|
||||
int j, counter;
|
||||
int i = 0;
|
||||
|
||||
aff_iterate(&a);
|
||||
|
||||
ck_barrier_mcs_subscribe(barrier, &state);
|
||||
|
||||
ck_pr_inc_int(&barrier_wait);
|
||||
while (ck_pr_load_int(&barrier_wait) != nthr)
|
||||
ck_pr_stall();
|
||||
|
||||
for (j = 0; j < ITERATE; j++) {
|
||||
i = j++ & (ENTRIES - 1);
|
||||
ck_pr_inc_int(&counters[i]);
|
||||
ck_barrier_mcs(barrier, &state);
|
||||
counter = ck_pr_load_int(&counters[i]);
|
||||
if (counter != nthr * (j / ENTRIES + 1)) {
|
||||
ck_error("FAILED [%d:%d]: %d != %d\n", i, j - 1, counter, nthr);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t *threads;
|
||||
ck_barrier_mcs_t *barrier;
|
||||
int i;
|
||||
|
||||
if (argc < 3) {
|
||||
ck_error("Usage: correct <number of threads> <affinity delta>\n");
|
||||
}
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
barrier = malloc(sizeof(ck_barrier_mcs_t) * nthr);
|
||||
if (barrier == NULL) {
|
||||
ck_error("ERROR: Could not allocate barrier structures\n");
|
||||
}
|
||||
ck_barrier_mcs_init(barrier, nthr);
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
fprintf(stderr, "Creating threads (barrier)...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
if (pthread_create(&threads[i], NULL, thread, barrier)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish correctness regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done (passed)\n");
|
||||
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
142
regressions/ck_barrier/validate/barrier_tournament.c
Normal file
142
regressions/ck_barrier/validate/barrier_tournament.c
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright 2011-2015 Samy Al Bahra.
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_barrier.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATE
|
||||
#define ITERATE 5000000
|
||||
#endif
|
||||
|
||||
#ifndef ENTRIES
|
||||
#define ENTRIES 512
|
||||
#endif
|
||||
|
||||
static struct affinity a;
|
||||
static int nthr;
|
||||
static int counters[ENTRIES];
|
||||
static int barrier_wait;
|
||||
static ck_barrier_tournament_t barrier;
|
||||
|
||||
static void *
|
||||
thread(CK_CC_UNUSED void *unused)
|
||||
{
|
||||
ck_barrier_tournament_state_t state;
|
||||
int j, counter;
|
||||
int i = 0;
|
||||
|
||||
aff_iterate(&a);
|
||||
ck_barrier_tournament_subscribe(&barrier, &state);
|
||||
|
||||
ck_pr_inc_int(&barrier_wait);
|
||||
while (ck_pr_load_int(&barrier_wait) != nthr)
|
||||
ck_pr_stall();
|
||||
|
||||
for (j = 0; j < ITERATE; j++) {
|
||||
i = j++ & (ENTRIES - 1);
|
||||
ck_pr_inc_int(&counters[i]);
|
||||
ck_barrier_tournament(&barrier, &state);
|
||||
counter = ck_pr_load_int(&counters[i]);
|
||||
if (counter != nthr * (j / ENTRIES + 1)) {
|
||||
ck_error("FAILED [%d:%d]: %d != %d\n", i, j - 1, counter, nthr);
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_inc_int(&barrier_wait);
|
||||
while (ck_pr_load_int(&barrier_wait) != nthr * 2)
|
||||
ck_pr_stall();
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t *threads;
|
||||
ck_barrier_tournament_round_t **rounds;
|
||||
int i;
|
||||
unsigned int size;
|
||||
|
||||
if (argc < 3) {
|
||||
ck_error("Usage: correct <number of threads> <affinity delta>\n");
|
||||
}
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
rounds = malloc(sizeof(ck_barrier_tournament_round_t *) * nthr);
|
||||
if (rounds == NULL) {
|
||||
ck_error("ERROR: Could not allocate barrier structures\n");
|
||||
}
|
||||
|
||||
size = ck_barrier_tournament_size(nthr);
|
||||
for (i = 0; i < nthr; ++i) {
|
||||
rounds[i] = malloc(sizeof(ck_barrier_tournament_round_t) * size);
|
||||
if (rounds[i] == NULL) {
|
||||
ck_error("ERROR: Could not allocate barrier structures\n");
|
||||
}
|
||||
}
|
||||
|
||||
ck_barrier_tournament_init(&barrier, rounds, nthr);
|
||||
|
||||
fprintf(stderr, "Creating threads (barrier)...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
if (pthread_create(&threads[i], NULL, thread, NULL)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish correctness regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done (passed)\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
17
regressions/ck_bitmap/validate/Makefile
Normal file
17
regressions/ck_bitmap/validate/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: check clean
|
||||
|
||||
OBJECTS=serial
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
serial: serial.c ../../../include/ck_bitmap.h
|
||||
$(CC) $(CFLAGS) -o serial serial.c
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o $(OBJECTS) *.dSYM *.exe
|
||||
|
||||
check: all
|
||||
./serial
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=-D_GNU_SOURCE
|
372
regressions/ck_bitmap/validate/serial.c
Normal file
372
regressions/ck_bitmap/validate/serial.c
Normal file
|
@ -0,0 +1,372 @@
|
|||
/*
|
||||
* Copyright 2012-2015 Samy Al Bahra.
|
||||
* Copyright 2012-2014 AppNexus, Inc.
|
||||
* Copyright 2012 Shreyas Prasad.
|
||||
* Copyright 2014 Paul Khuong.
|
||||
* 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 <ck_bitmap.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef STATIC_LENGTH
|
||||
#define STATIC_LENGTH 256
|
||||
#endif
|
||||
|
||||
static unsigned int length = 256;
|
||||
static ck_bitmap_t *g_bits;
|
||||
|
||||
static void
|
||||
check_iteration(ck_bitmap_t *bits, unsigned int len, bool initial)
|
||||
{
|
||||
ck_bitmap_iterator_t iter;
|
||||
unsigned int i = 0, j;
|
||||
|
||||
len += 1;
|
||||
if (initial == true) {
|
||||
if (bits == g_bits)
|
||||
len = length;
|
||||
else
|
||||
len = STATIC_LENGTH;
|
||||
}
|
||||
|
||||
ck_bitmap_iterator_init(&iter, bits);
|
||||
for (j = 0; ck_bitmap_next(bits, &iter, &i) == true; j++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
ck_error("[4] ERROR: Expected bit %u, got bit %u\n", j, i);
|
||||
}
|
||||
|
||||
if (j != len) {
|
||||
ck_error("[5] ERROR: Expected length %u, got length %u\n", len, j);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test(ck_bitmap_t *bits, unsigned int n_length, bool initial)
|
||||
{
|
||||
bool r;
|
||||
unsigned int i;
|
||||
CK_BITMAP_INSTANCE(8) u;
|
||||
|
||||
CK_BITMAP_INIT(&u, 8, false);
|
||||
CK_BITMAP_SET(&u, 1);
|
||||
CK_BITMAP_SET(&u, 4);
|
||||
|
||||
for (i = 0; i < n_length; i++) {
|
||||
if (ck_bitmap_test(bits, i) == !initial) {
|
||||
ck_error("[0] ERROR [%u]: Expected %u got %u\n", i,
|
||||
initial, !initial);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n_length; i++) {
|
||||
ck_bitmap_set(bits, i);
|
||||
if (ck_bitmap_test(bits, i) == false) {
|
||||
ck_error("[1] ERROR: Expected bit to be set: %u\n", i);
|
||||
}
|
||||
|
||||
ck_bitmap_reset(bits, i);
|
||||
if (ck_bitmap_test(bits, i) == true) {
|
||||
ck_error("[2] ERROR: Expected bit to be cleared: %u\n", i);
|
||||
}
|
||||
|
||||
r = ck_bitmap_bts(bits, i);
|
||||
if (r == true) {
|
||||
ck_error("[3] ERROR: Expected bit to be cleared before 1st bts: %u\n", i);
|
||||
}
|
||||
if (ck_bitmap_test(bits, i) == false) {
|
||||
ck_error("[4] ERROR: Expected bit to be set: %u\n", i);
|
||||
}
|
||||
r = ck_bitmap_bts(bits, i);
|
||||
if (r == false) {
|
||||
ck_error("[5] ERROR: Expected bit to be set before 2nd bts: %u\n", i);
|
||||
}
|
||||
if (ck_bitmap_test(bits, i) == false) {
|
||||
ck_error("[6] ERROR: Expected bit to be set: %u\n", i);
|
||||
}
|
||||
|
||||
ck_bitmap_reset(bits, i);
|
||||
if (ck_bitmap_test(bits, i) == true) {
|
||||
ck_error("[7] ERROR: Expected bit to be cleared: %u\n", i);
|
||||
}
|
||||
|
||||
ck_bitmap_set(bits, i);
|
||||
if (ck_bitmap_test(bits, i) == false) {
|
||||
ck_error("[8] ERROR: Expected bit to be set: %u\n", i);
|
||||
}
|
||||
|
||||
check_iteration(bits, i, initial);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_length; i++) {
|
||||
if (ck_bitmap_test(bits, i) == false) {
|
||||
ck_error("[9] ERROR: Expected bit to be set: %u\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
ck_bitmap_clear(bits);
|
||||
|
||||
for (i = 0; i < n_length; i++) {
|
||||
if (ck_bitmap_test(bits, i) == true) {
|
||||
ck_error("[10] ERROR: Expected bit to be reset: %u\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
ck_bitmap_union(bits, CK_BITMAP(&u));
|
||||
if (ck_bitmap_test(bits, 1) == false ||
|
||||
ck_bitmap_test(bits, 4) == false) {
|
||||
ck_error("ERROR: Expected union semantics.\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_init(bool init)
|
||||
{
|
||||
ck_bitmap_t *bitmap;
|
||||
size_t bytes;
|
||||
unsigned int i;
|
||||
|
||||
bytes = ck_bitmap_size(length);
|
||||
bitmap = malloc(bytes);
|
||||
memset(bitmap, random(), bytes);
|
||||
|
||||
ck_bitmap_init(bitmap, length, init);
|
||||
|
||||
if (ck_bitmap_bits(bitmap) != length) {
|
||||
ck_error("ERROR: Expected length %u got %u\n",
|
||||
length, ck_bitmap_bits(bitmap));
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (ck_bitmap_test(bitmap, i) != init) {
|
||||
ck_error("ERROR: Expected bit %i at index %u, got %i\n",
|
||||
(int)init, i, (int)(!init));
|
||||
}
|
||||
}
|
||||
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
static ck_bitmap_t *
|
||||
random_init(void)
|
||||
{
|
||||
ck_bitmap_t *bitmap;
|
||||
unsigned int i;
|
||||
|
||||
bitmap = malloc(ck_bitmap_size(length));
|
||||
ck_bitmap_init(bitmap, length, false);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (random() & 1) {
|
||||
ck_bitmap_set(bitmap, i);
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static ck_bitmap_t *
|
||||
copy(const ck_bitmap_t *src)
|
||||
{
|
||||
ck_bitmap_t *bitmap;
|
||||
size_t bytes = ck_bitmap_size(ck_bitmap_bits(src));
|
||||
|
||||
bitmap = malloc(bytes);
|
||||
memcpy(bitmap, src, bytes);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static void
|
||||
test_counts(const ck_bitmap_t *x, const ck_bitmap_t *y)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
unsigned int count_intersect = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i <= length * 2; i++) {
|
||||
unsigned actual_limit = i;
|
||||
unsigned int r;
|
||||
bool check;
|
||||
|
||||
if (actual_limit > ck_bitmap_bits(x))
|
||||
actual_limit = ck_bitmap_bits(x);
|
||||
|
||||
check = ck_bitmap_empty(x, i);
|
||||
if (check != (count == 0)) {
|
||||
ck_error("ck_bitmap_empty(%u): got %i expected %i\n",
|
||||
i, (int)check, (int)(count == 0));
|
||||
}
|
||||
|
||||
check = ck_bitmap_full(x, i);
|
||||
if (check != (count == actual_limit)) {
|
||||
ck_error("ck_bitmap_full(%u): got %i expected %i\n",
|
||||
i, (int)check, (int)(count == i));
|
||||
}
|
||||
|
||||
r = ck_bitmap_count(x, i);
|
||||
if (r != count) {
|
||||
ck_error("ck_bitmap_count(%u): got %u expected %u\n",
|
||||
i, r, count);
|
||||
}
|
||||
|
||||
r = ck_bitmap_count_intersect(x, y, i);
|
||||
if (r != count_intersect) {
|
||||
ck_error("ck_bitmap_count_intersect(%u): got %u expected %u\n",
|
||||
i, r, count_intersect);
|
||||
}
|
||||
|
||||
if (i < length) {
|
||||
count += ck_bitmap_test(x, i);
|
||||
count_intersect += ck_bitmap_test(x, i) & ck_bitmap_test(y, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
random_test(unsigned int seed)
|
||||
{
|
||||
ck_bitmap_t *x, *x_copy, *y;
|
||||
unsigned int i;
|
||||
|
||||
srandom(seed);
|
||||
|
||||
test_init(false);
|
||||
test_init(true);
|
||||
|
||||
x = random_init();
|
||||
y = random_init();
|
||||
|
||||
#define TEST(routine, expected) do { \
|
||||
x_copy = copy(x); \
|
||||
routine(x_copy, y); \
|
||||
for (i = 0; i < length; i++) { \
|
||||
bool xi = ck_bitmap_test(x, i); \
|
||||
bool yi = ck_bitmap_test(y, i); \
|
||||
bool ri = ck_bitmap_test(x_copy, i); \
|
||||
bool wanted = expected(xi, yi); \
|
||||
\
|
||||
if (ri != wanted) { \
|
||||
ck_error("In " #routine " at %u: " \
|
||||
"got %i expected %i\n", \
|
||||
i, ri, wanted); \
|
||||
} \
|
||||
} \
|
||||
free(x_copy); \
|
||||
} while (0)
|
||||
|
||||
#define OR(x, y) (x | y)
|
||||
#define AND(x, y) (x & y)
|
||||
#define ANDC2(x, y) (x & (~y))
|
||||
|
||||
TEST(ck_bitmap_union, OR);
|
||||
TEST(ck_bitmap_intersection, AND);
|
||||
TEST(ck_bitmap_intersection_negate, ANDC2);
|
||||
|
||||
#undef ANDC2
|
||||
#undef AND
|
||||
#undef OR
|
||||
#undef TEST
|
||||
|
||||
test_counts(x, y);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
ck_bitmap_init(x, length, i & 1);
|
||||
ck_bitmap_init(y, length, i >> 1);
|
||||
test_counts(x, y);
|
||||
}
|
||||
|
||||
free(y);
|
||||
free(x);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int bytes, base;
|
||||
size_t i, j;
|
||||
|
||||
if (argc >= 2) {
|
||||
length = atoi(argv[1]);
|
||||
}
|
||||
|
||||
base = ck_bitmap_base(length);
|
||||
bytes = ck_bitmap_size(length);
|
||||
fprintf(stderr, "Configuration: %u bytes\n",
|
||||
bytes);
|
||||
|
||||
g_bits = malloc(bytes);
|
||||
memset(g_bits->map, 0xFF, base);
|
||||
ck_bitmap_init(g_bits, length, false);
|
||||
test(g_bits, length, false);
|
||||
|
||||
memset(g_bits->map, 0x00, base);
|
||||
ck_bitmap_init(g_bits, length, true);
|
||||
test(g_bits, length, true);
|
||||
|
||||
ck_bitmap_test(g_bits, length - 1);
|
||||
|
||||
CK_BITMAP_INSTANCE(STATIC_LENGTH) sb;
|
||||
fprintf(stderr, "Static configuration: %zu bytes\n",
|
||||
sizeof(sb));
|
||||
memset(CK_BITMAP_BUFFER(&sb), 0xFF, ck_bitmap_base(STATIC_LENGTH));
|
||||
CK_BITMAP_INIT(&sb, STATIC_LENGTH, false);
|
||||
test(CK_BITMAP(&sb), STATIC_LENGTH, false);
|
||||
memset(CK_BITMAP_BUFFER(&sb), 0x00, ck_bitmap_base(STATIC_LENGTH));
|
||||
CK_BITMAP_INIT(&sb, STATIC_LENGTH, true);
|
||||
test(CK_BITMAP(&sb), STATIC_LENGTH, true);
|
||||
|
||||
CK_BITMAP_CLEAR(&sb);
|
||||
if (CK_BITMAP_TEST(&sb, 1) == true) {
|
||||
ck_error("ERROR: Expected bit to be reset.\n");
|
||||
}
|
||||
|
||||
CK_BITMAP_SET(&sb, 1);
|
||||
if (CK_BITMAP_TEST(&sb, 1) == false) {
|
||||
ck_error("ERROR: Expected bit to be set.\n");
|
||||
}
|
||||
|
||||
CK_BITMAP_RESET(&sb, 1);
|
||||
if (CK_BITMAP_TEST(&sb, 1) == true) {
|
||||
ck_error("ERROR: Expected bit to be reset.\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < 4 * sizeof(unsigned int) * CHAR_BIT; i++) {
|
||||
length = i;
|
||||
for (j = 0; j < 10; j++) {
|
||||
random_test(i * 10 + j);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
17
regressions/ck_brlock/benchmark/Makefile
Normal file
17
regressions/ck_brlock/benchmark/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: clean distribution
|
||||
|
||||
OBJECTS=latency throughput
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
latency: latency.c ../../../include/ck_brlock.h
|
||||
$(CC) $(CFLAGS) -o latency latency.c
|
||||
|
||||
throughput: throughput.c ../../../include/ck_brlock.h
|
||||
$(CC) $(CFLAGS) -o throughput throughput.c
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
103
regressions/ck_brlock/benchmark/latency.c
Normal file
103
regressions/ck_brlock/benchmark/latency.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <ck_brlock.h>
|
||||
#include <ck_rwlock.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef STEPS
|
||||
#define STEPS 1000000
|
||||
#endif
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
uint64_t s_b, e_b, i;
|
||||
ck_brlock_t brlock = CK_BRLOCK_INITIALIZER;
|
||||
ck_brlock_reader_t r[8];
|
||||
ck_rwlock_t naive;
|
||||
|
||||
for (i = 0; i < sizeof(r) / sizeof(*r); i++)
|
||||
ck_brlock_read_register(&brlock, &r[i]);
|
||||
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_brlock_write_lock(&brlock);
|
||||
ck_brlock_write_unlock(&brlock);
|
||||
}
|
||||
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_brlock_write_lock(&brlock);
|
||||
ck_brlock_write_unlock(&brlock);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("WRITE: brlock %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
ck_rwlock_init(&naive);
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_rwlock_write_lock(&naive);
|
||||
ck_rwlock_write_unlock(&naive);
|
||||
}
|
||||
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_rwlock_write_lock(&naive);
|
||||
ck_rwlock_write_unlock(&naive);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("WRITE: naive %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_brlock_read_lock(&brlock, &r[0]);
|
||||
ck_brlock_read_unlock(&r[0]);
|
||||
}
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_brlock_read_lock(&brlock, &r[0]);
|
||||
ck_brlock_read_unlock(&r[0]);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("READ: brlock %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_rwlock_read_lock(&naive);
|
||||
ck_rwlock_read_unlock(&naive);
|
||||
}
|
||||
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_rwlock_read_lock(&naive);
|
||||
ck_rwlock_read_unlock(&naive);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("READ: naive %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
164
regressions/ck_brlock/benchmark/throughput.c
Normal file
164
regressions/ck_brlock/benchmark/throughput.c
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <ck_brlock.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef STEPS
|
||||
#define STEPS 1000000
|
||||
#endif
|
||||
|
||||
static int barrier;
|
||||
static int threads;
|
||||
static unsigned int flag CK_CC_CACHELINE;
|
||||
static ck_brlock_t brlock = CK_BRLOCK_INITIALIZER;
|
||||
static struct affinity affinity;
|
||||
|
||||
static void *
|
||||
thread_brlock(void *pun)
|
||||
{
|
||||
uint64_t s_b, e_b, a, i;
|
||||
ck_brlock_reader_t r;
|
||||
uint64_t *value = pun;
|
||||
|
||||
if (aff_iterate(&affinity) != 0) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_brlock_read_register(&brlock, &r);
|
||||
ck_pr_inc_int(&barrier);
|
||||
while (ck_pr_load_int(&barrier) != threads)
|
||||
ck_pr_stall();
|
||||
|
||||
for (i = 1, a = 0;; i++) {
|
||||
s_b = rdtsc();
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
ck_brlock_read_lock(&brlock, &r);
|
||||
ck_brlock_read_unlock(&r);
|
||||
e_b = rdtsc();
|
||||
|
||||
a += (e_b - s_b) >> 4;
|
||||
|
||||
if (ck_pr_load_uint(&flag) == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
ck_pr_inc_int(&barrier);
|
||||
while (ck_pr_load_int(&barrier) != threads * 2)
|
||||
ck_pr_stall();
|
||||
|
||||
*value = (a / i);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int t;
|
||||
pthread_t *p;
|
||||
uint64_t *latency;
|
||||
|
||||
if (argc != 3) {
|
||||
ck_error("Usage: throughput <delta> <threads>\n");
|
||||
}
|
||||
|
||||
threads = atoi(argv[2]);
|
||||
if (threads <= 0) {
|
||||
ck_error("ERROR: Threads must be a value > 0.\n");
|
||||
}
|
||||
|
||||
p = malloc(sizeof(pthread_t) * threads);
|
||||
if (p == NULL) {
|
||||
ck_error("ERROR: Failed to initialize thread.\n");
|
||||
}
|
||||
|
||||
latency = malloc(sizeof(uint64_t) * threads);
|
||||
if (latency == NULL) {
|
||||
ck_error("ERROR: Failed to create latency buffer.\n");
|
||||
}
|
||||
|
||||
affinity.delta = atoi(argv[1]);
|
||||
affinity.request = 0;
|
||||
|
||||
fprintf(stderr, "Creating threads (brlock)...");
|
||||
for (t = 0; t < threads; t++) {
|
||||
if (pthread_create(&p[t], NULL, thread_brlock, latency + t) != 0) {
|
||||
ck_error("ERROR: Could not create thread %d\n", t);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
common_sleep(10);
|
||||
ck_pr_store_uint(&flag, 1);
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish acquisition regression...");
|
||||
for (t = 0; t < threads; t++)
|
||||
pthread_join(p[t], NULL);
|
||||
fprintf(stderr, "done\n\n");
|
||||
|
||||
for (t = 1; t <= threads; t++)
|
||||
printf("%10u %20" PRIu64 "\n", t, latency[t - 1]);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
17
regressions/ck_brlock/validate/Makefile
Normal file
17
regressions/ck_brlock/validate/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=validate
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
validate: validate.c ../../../include/ck_brlock.h
|
||||
$(CC) $(CFLAGS) -o validate validate.c
|
||||
|
||||
check: all
|
||||
./validate $(CORES) 1
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
155
regressions/ck_brlock/validate/validate.c
Normal file
155
regressions/ck_brlock/validate/validate.c
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_brlock.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATE
|
||||
#define ITERATE 1000000
|
||||
#endif
|
||||
|
||||
static struct affinity a;
|
||||
static unsigned int locked = 0;
|
||||
static int nthr;
|
||||
static ck_brlock_t lock = CK_BRLOCK_INITIALIZER;
|
||||
|
||||
static void *
|
||||
thread(void *null CK_CC_UNUSED)
|
||||
{
|
||||
ck_brlock_reader_t r;
|
||||
int i = ITERATE;
|
||||
unsigned int l;
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_brlock_read_register(&lock, &r);
|
||||
|
||||
while (i--) {
|
||||
ck_brlock_write_lock(&lock);
|
||||
{
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 8) {
|
||||
ck_error("ERROR [WR:%d]: %u != 2\n", __LINE__, l);
|
||||
}
|
||||
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
}
|
||||
ck_brlock_write_unlock(&lock);
|
||||
|
||||
ck_brlock_read_lock(&lock, &r);
|
||||
{
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [RD:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
}
|
||||
ck_brlock_read_unlock(&r);
|
||||
}
|
||||
|
||||
ck_brlock_read_unregister(&lock, &r);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t *threads;
|
||||
int i;
|
||||
|
||||
if (argc != 3) {
|
||||
ck_error("Usage: validate <number of threads> <affinity delta>\n");
|
||||
}
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
fprintf(stderr, "Creating threads (mutual exclusion)...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
if (pthread_create(&threads[i], NULL, thread, NULL)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish correctness regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done (passed)\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
14
regressions/ck_bytelock/benchmark/Makefile
Normal file
14
regressions/ck_bytelock/benchmark/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
.PHONY: clean distribution
|
||||
|
||||
OBJECTS=latency
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
latency: latency.c
|
||||
$(CC) $(CFLAGS) -o latency latency.c
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
99
regressions/ck_bytelock/benchmark/latency.c
Normal file
99
regressions/ck_bytelock/benchmark/latency.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <ck_bytelock.h>
|
||||
#include <ck_rwlock.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef STEPS
|
||||
#define STEPS 1000000
|
||||
#endif
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
uint64_t s_b, e_b, i;
|
||||
ck_bytelock_t bytelock = CK_BYTELOCK_INITIALIZER;
|
||||
ck_rwlock_t naive;
|
||||
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_bytelock_write_lock(&bytelock, 1);
|
||||
ck_bytelock_write_unlock(&bytelock);
|
||||
}
|
||||
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_bytelock_write_lock(&bytelock, 1);
|
||||
ck_bytelock_write_unlock(&bytelock);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("WRITE: bytelock %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
ck_rwlock_init(&naive);
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_rwlock_write_lock(&naive);
|
||||
ck_rwlock_write_unlock(&naive);
|
||||
}
|
||||
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_rwlock_write_lock(&naive);
|
||||
ck_rwlock_write_unlock(&naive);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("WRITE: naive %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_bytelock_read_lock(&bytelock, 1);
|
||||
ck_bytelock_read_unlock(&bytelock, 1);
|
||||
}
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_bytelock_read_lock(&bytelock, 1);
|
||||
ck_bytelock_read_unlock(&bytelock, 1);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("READ: bytelock %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_rwlock_read_lock(&naive);
|
||||
ck_rwlock_read_unlock(&naive);
|
||||
}
|
||||
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_rwlock_read_lock(&naive);
|
||||
ck_rwlock_read_unlock(&naive);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("READ: naive %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
17
regressions/ck_bytelock/validate/Makefile
Normal file
17
regressions/ck_bytelock/validate/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=validate
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
validate: validate.c ../../../include/ck_bytelock.h
|
||||
$(CC) $(CFLAGS) -o validate validate.c
|
||||
|
||||
check: all
|
||||
./validate $(CORES) 1
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
166
regressions/ck_bytelock/validate/validate.c
Normal file
166
regressions/ck_bytelock/validate/validate.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_bytelock.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATE
|
||||
#define ITERATE 5000000
|
||||
#endif
|
||||
|
||||
struct block {
|
||||
unsigned int tid;
|
||||
};
|
||||
|
||||
static struct affinity a;
|
||||
static unsigned int locked = 0;
|
||||
static int nthr;
|
||||
static ck_bytelock_t lock CK_CC_CACHELINE = CK_BYTELOCK_INITIALIZER;
|
||||
|
||||
static void *
|
||||
thread(void *null)
|
||||
{
|
||||
struct block *context = null;
|
||||
int i = ITERATE;
|
||||
unsigned int l;
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (context->tid == (unsigned int)nthr - 1)
|
||||
context->tid = sizeof(lock.readers) + 1;
|
||||
|
||||
while (i--) {
|
||||
ck_bytelock_write_lock(&lock, context->tid);
|
||||
{
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 8) {
|
||||
ck_error("ERROR [WR:%d]: %u != 2\n", __LINE__, l);
|
||||
}
|
||||
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
}
|
||||
ck_bytelock_write_unlock(&lock);
|
||||
|
||||
ck_bytelock_read_lock(&lock, context->tid);
|
||||
{
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [RD:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
}
|
||||
ck_bytelock_read_unlock(&lock, context->tid);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t *threads;
|
||||
struct block *context;
|
||||
int i;
|
||||
|
||||
if (argc != 3) {
|
||||
ck_error("Usage: correct <number of threads> <affinity delta>\n");
|
||||
}
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
context = malloc(sizeof(struct block) * nthr);
|
||||
if (context == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread contexts\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
fprintf(stderr, "Creating threads (mutual exclusion)...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
context[i].tid = i + 1;
|
||||
if (pthread_create(&threads[i], NULL, thread, context + i)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish correctness regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done (passed)\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
17
regressions/ck_cohort/benchmark/Makefile
Normal file
17
regressions/ck_cohort/benchmark/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: all clean
|
||||
|
||||
OBJECTS=ck_cohort.THROUGHPUT ck_cohort.LATENCY
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
ck_cohort.THROUGHPUT: ck_cohort.c
|
||||
$(CC) $(CFLAGS) -o ck_cohort.THROUGHPUT throughput.c -lm
|
||||
|
||||
ck_cohort.LATENCY: ck_cohort.c
|
||||
$(CC) -DLATENCY $(CFLAGS) -o ck_cohort.LATENCY ck_cohort.c
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE -lm
|
8
regressions/ck_cohort/benchmark/ck_cohort.c
Normal file
8
regressions/ck_cohort/benchmark/ck_cohort.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include "../ck_cohort.h"
|
||||
|
||||
#include <ck_cohort.h>
|
||||
#ifdef THROUGHPUT
|
||||
#include "../../ck_spinlock/benchmark/throughput.h"
|
||||
#elif defined(LATENCY)
|
||||
#include "../../ck_spinlock/benchmark/latency.h"
|
||||
#endif
|
239
regressions/ck_cohort/benchmark/throughput.c
Normal file
239
regressions/ck_cohort/benchmark/throughput.c
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Copyright 2013-2015 Samy Al Bahra.
|
||||
* Copyright 2013 Brendon Scheinman.
|
||||
* 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_cohort.h>
|
||||
#include <ck_md.h>
|
||||
#include <ck_spinlock.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
||||
|
||||
static struct affinity a;
|
||||
static unsigned int ready;
|
||||
|
||||
struct counters {
|
||||
uint64_t value;
|
||||
} CK_CC_CACHELINE;
|
||||
|
||||
static struct counters *count;
|
||||
static uint64_t nthr;
|
||||
static unsigned int n_cohorts;
|
||||
static unsigned int barrier;
|
||||
static int critical CK_CC_CACHELINE;
|
||||
|
||||
static void
|
||||
ck_spinlock_fas_lock_with_context(ck_spinlock_fas_t *lock, void *context)
|
||||
{
|
||||
|
||||
(void)context;
|
||||
ck_spinlock_fas_lock(lock);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ck_spinlock_fas_unlock_with_context(ck_spinlock_fas_t *lock, void *context)
|
||||
{
|
||||
|
||||
(void)context;
|
||||
ck_spinlock_fas_unlock(lock);
|
||||
return;
|
||||
}
|
||||
|
||||
static bool
|
||||
ck_spinlock_fas_locked_with_context(ck_spinlock_fas_t *lock, void *context)
|
||||
{
|
||||
|
||||
(void)context;
|
||||
return ck_spinlock_fas_locked(lock);
|
||||
}
|
||||
|
||||
CK_COHORT_PROTOTYPE(basic,
|
||||
ck_spinlock_fas_lock_with_context, ck_spinlock_fas_unlock_with_context, ck_spinlock_fas_locked_with_context,
|
||||
ck_spinlock_fas_lock_with_context, ck_spinlock_fas_unlock_with_context, ck_spinlock_fas_locked_with_context)
|
||||
|
||||
struct cohort_record {
|
||||
CK_COHORT_INSTANCE(basic) cohort;
|
||||
} CK_CC_CACHELINE;
|
||||
static struct cohort_record *cohorts;
|
||||
|
||||
static ck_spinlock_t global_lock = CK_SPINLOCK_INITIALIZER;
|
||||
|
||||
struct block {
|
||||
unsigned int tid;
|
||||
};
|
||||
|
||||
static void *
|
||||
fairness(void *null)
|
||||
{
|
||||
struct block *context = null;
|
||||
unsigned int i = context->tid;
|
||||
volatile int j;
|
||||
long int base;
|
||||
unsigned int core;
|
||||
CK_COHORT_INSTANCE(basic) *cohort;
|
||||
|
||||
|
||||
if (aff_iterate_core(&a, &core)) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cohort = &((cohorts + (core / (int)(a.delta)) % n_cohorts)->cohort);
|
||||
|
||||
while (ck_pr_load_uint(&ready) == 0);
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) != nthr);
|
||||
|
||||
while (ck_pr_load_uint(&ready)) {
|
||||
CK_COHORT_LOCK(basic, cohort, NULL, NULL);
|
||||
|
||||
count[i].value++;
|
||||
if (critical) {
|
||||
base = common_lrand48() % critical;
|
||||
for (j = 0; j < base; j++);
|
||||
}
|
||||
|
||||
CK_COHORT_UNLOCK(basic, cohort, NULL, NULL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
uint64_t v, d;
|
||||
unsigned int i;
|
||||
pthread_t *threads;
|
||||
struct block *context;
|
||||
ck_spinlock_t *local_lock;
|
||||
|
||||
if (argc != 5) {
|
||||
ck_error("Usage: ck_cohort <number of cohorts> <threads per cohort> "
|
||||
"<affinity delta> <critical section>\n");
|
||||
}
|
||||
|
||||
n_cohorts = atoi(argv[1]);
|
||||
if (n_cohorts <= 0) {
|
||||
ck_error("ERROR: Number of cohorts must be greater than 0\n");
|
||||
}
|
||||
|
||||
nthr = n_cohorts * atoi(argv[2]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
|
||||
critical = atoi(argv[4]);
|
||||
if (critical < 0) {
|
||||
ck_error("ERROR: critical section cannot be negative\n");
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
cohorts = malloc(sizeof(struct cohort_record) * n_cohorts);
|
||||
if (cohorts == NULL) {
|
||||
ck_error("ERROR: Could not allocate cohort structures\n");
|
||||
}
|
||||
|
||||
context = malloc(sizeof(struct block) * nthr);
|
||||
if (context == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread contexts\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
a.request = 0;
|
||||
|
||||
count = malloc(sizeof(*count) * nthr);
|
||||
if (count == NULL) {
|
||||
ck_error("ERROR: Could not create acquisition buffer\n");
|
||||
}
|
||||
memset(count, 0, sizeof(*count) * nthr);
|
||||
|
||||
fprintf(stderr, "Creating cohorts...");
|
||||
for (i = 0 ; i < n_cohorts ; i++) {
|
||||
local_lock = malloc(max(CK_MD_CACHELINE, sizeof(ck_spinlock_t)));
|
||||
if (local_lock == NULL) {
|
||||
ck_error("ERROR: Could not allocate local lock\n");
|
||||
}
|
||||
CK_COHORT_INIT(basic, &((cohorts + i)->cohort), &global_lock, local_lock,
|
||||
CK_COHORT_DEFAULT_LOCAL_PASS_LIMIT);
|
||||
local_lock = NULL;
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Creating threads (fairness)...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
context[i].tid = i;
|
||||
if (pthread_create(&threads[i], NULL, fairness, context + i)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
ck_pr_store_uint(&ready, 1);
|
||||
common_sleep(10);
|
||||
ck_pr_store_uint(&ready, 0);
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish acquisition regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done\n\n");
|
||||
|
||||
for (i = 0, v = 0; i < nthr; i++) {
|
||||
printf("%d %15" PRIu64 "\n", i, count[i].value);
|
||||
v += count[i].value;
|
||||
}
|
||||
|
||||
printf("\n# total : %15" PRIu64 "\n", v);
|
||||
printf("# throughput : %15" PRIu64 " a/s\n", (v /= nthr) / 10);
|
||||
|
||||
for (i = 0, d = 0; i < nthr; i++)
|
||||
d += (count[i].value - v) * (count[i].value - v);
|
||||
|
||||
printf("# average : %15" PRIu64 "\n", v);
|
||||
printf("# deviation : %.2f (%.2f%%)\n\n", sqrt(d / nthr), (sqrt(d / nthr) / v) * 100.00);
|
||||
|
||||
return 0;
|
||||
}
|
35
regressions/ck_cohort/ck_cohort.h
Normal file
35
regressions/ck_cohort/ck_cohort.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#define LOCK_NAME "ck_cohort"
|
||||
#define LOCK_DEFINE \
|
||||
static ck_spinlock_fas_t global_fas_lock = CK_SPINLOCK_FAS_INITIALIZER; \
|
||||
static ck_spinlock_fas_t local_fas_lock = CK_SPINLOCK_FAS_INITIALIZER; \
|
||||
static void \
|
||||
ck_spinlock_fas_lock_with_context(ck_spinlock_fas_t *lock, void *context) \
|
||||
{ \
|
||||
(void)context; \
|
||||
ck_spinlock_fas_lock(lock); \
|
||||
} \
|
||||
\
|
||||
static void \
|
||||
ck_spinlock_fas_unlock_with_context(ck_spinlock_fas_t *lock, void *context) \
|
||||
{ \
|
||||
(void)context; \
|
||||
ck_spinlock_fas_unlock(lock); \
|
||||
} \
|
||||
\
|
||||
static bool \
|
||||
ck_spinlock_fas_locked_with_context(ck_spinlock_fas_t *lock, void *context) \
|
||||
{ \
|
||||
(void)context; \
|
||||
return ck_spinlock_fas_locked(lock); \
|
||||
} \
|
||||
CK_COHORT_PROTOTYPE(fas_fas, \
|
||||
ck_spinlock_fas_lock_with_context, ck_spinlock_fas_unlock_with_context, \
|
||||
ck_spinlock_fas_locked_with_context, ck_spinlock_fas_lock_with_context, \
|
||||
ck_spinlock_fas_unlock_with_context, ck_spinlock_fas_locked_with_context) \
|
||||
static CK_COHORT_INSTANCE(fas_fas) CK_CC_CACHELINE cohort = CK_COHORT_INITIALIZER
|
||||
|
||||
|
||||
#define LOCK_INIT CK_COHORT_INIT(fas_fas, &cohort, &global_fas_lock, &local_fas_lock, \
|
||||
CK_COHORT_DEFAULT_LOCAL_PASS_LIMIT)
|
||||
#define LOCK CK_COHORT_LOCK(fas_fas, &cohort, NULL, NULL)
|
||||
#define UNLOCK CK_COHORT_UNLOCK(fas_fas, &cohort, NULL, NULL)
|
17
regressions/ck_cohort/validate/Makefile
Normal file
17
regressions/ck_cohort/validate/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=validate
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
validate: validate.c ../../../include/ck_cohort.h
|
||||
$(CC) $(CFLAGS) -o validate validate.c
|
||||
|
||||
check: all
|
||||
./validate `expr $(CORES) / 2` 2 1
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
205
regressions/ck_cohort/validate/validate.c
Normal file
205
regressions/ck_cohort/validate/validate.c
Normal file
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright 2013-2015 Samy Al Bahra.
|
||||
* Copyright 2013 Brendon Scheinman.
|
||||
* 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 <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_cohort.h>
|
||||
#include <ck_spinlock.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATE
|
||||
#define ITERATE 1000000
|
||||
#endif
|
||||
|
||||
static struct affinity a;
|
||||
static unsigned int locked;
|
||||
static int nthr;
|
||||
static ck_spinlock_fas_t global_fas_lock = CK_SPINLOCK_FAS_INITIALIZER;
|
||||
|
||||
static void
|
||||
ck_spinlock_fas_lock_with_context(ck_spinlock_fas_t *lock, void *context)
|
||||
{
|
||||
(void)context;
|
||||
ck_spinlock_fas_lock(lock);
|
||||
}
|
||||
|
||||
static void
|
||||
ck_spinlock_fas_unlock_with_context(ck_spinlock_fas_t *lock, void *context)
|
||||
{
|
||||
(void)context;
|
||||
ck_spinlock_fas_unlock(lock);
|
||||
}
|
||||
|
||||
static bool
|
||||
ck_spinlock_fas_locked_with_context(ck_spinlock_fas_t *lock, void *context)
|
||||
{
|
||||
(void)context;
|
||||
return ck_spinlock_fas_locked(lock);
|
||||
}
|
||||
|
||||
static bool
|
||||
ck_spinlock_fas_trylock_with_context(ck_spinlock_fas_t *lock, void *context)
|
||||
{
|
||||
(void)context;
|
||||
return ck_spinlock_fas_trylock(lock);
|
||||
}
|
||||
|
||||
CK_COHORT_TRYLOCK_PROTOTYPE(fas_fas,
|
||||
ck_spinlock_fas_lock_with_context, ck_spinlock_fas_unlock_with_context,
|
||||
ck_spinlock_fas_locked_with_context, ck_spinlock_fas_trylock_with_context,
|
||||
ck_spinlock_fas_lock_with_context, ck_spinlock_fas_unlock_with_context,
|
||||
ck_spinlock_fas_locked_with_context, ck_spinlock_fas_trylock_with_context)
|
||||
static CK_COHORT_INSTANCE(fas_fas) *cohorts;
|
||||
static int n_cohorts;
|
||||
|
||||
static void *
|
||||
thread(void *null CK_CC_UNUSED)
|
||||
{
|
||||
int i = ITERATE;
|
||||
unsigned int l;
|
||||
unsigned int core;
|
||||
CK_COHORT_INSTANCE(fas_fas) *cohort;
|
||||
|
||||
if (aff_iterate_core(&a, &core)) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cohort = cohorts + (core / (int)(a.delta)) % n_cohorts;
|
||||
|
||||
while (i--) {
|
||||
|
||||
if (i & 1) {
|
||||
CK_COHORT_LOCK(fas_fas, cohort, NULL, NULL);
|
||||
} else {
|
||||
while (CK_COHORT_TRYLOCK(fas_fas, cohort, NULL, NULL, NULL) == false) {
|
||||
ck_pr_stall();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 8) {
|
||||
ck_error("ERROR [WR:%d]: %u != 2\n", __LINE__, l);
|
||||
}
|
||||
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
}
|
||||
CK_COHORT_UNLOCK(fas_fas, cohort, NULL, NULL);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t *threads;
|
||||
int threads_per_cohort;
|
||||
ck_spinlock_fas_t *local_lock;
|
||||
int i;
|
||||
|
||||
if (argc != 4) {
|
||||
ck_error("Usage: validate <number of cohorts> <threads per cohort> <affinity delta>\n");
|
||||
}
|
||||
|
||||
n_cohorts = atoi(argv[1]);
|
||||
if (n_cohorts <= 0) {
|
||||
fprintf(stderr, "setting number of cohorts per thread to 1\n");
|
||||
n_cohorts = 1;
|
||||
}
|
||||
|
||||
threads_per_cohort = atoi(argv[2]);
|
||||
if (threads_per_cohort <= 0) {
|
||||
ck_error("ERROR: Threads per cohort must be greater than 0\n");
|
||||
}
|
||||
|
||||
nthr = n_cohorts * threads_per_cohort;
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[3]);
|
||||
|
||||
fprintf(stderr, "Creating cohorts...");
|
||||
cohorts = malloc(sizeof(CK_COHORT_INSTANCE(fas_fas)) * n_cohorts);
|
||||
for (i = 0 ; i < n_cohorts ; i++) {
|
||||
local_lock = malloc(sizeof(ck_spinlock_fas_t));
|
||||
CK_COHORT_INIT(fas_fas, cohorts + i, &global_fas_lock, local_lock,
|
||||
CK_COHORT_DEFAULT_LOCAL_PASS_LIMIT);
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Creating threads...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
if (pthread_create(&threads[i], NULL, thread, NULL)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish correctness regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done (passed)\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
42
regressions/ck_epoch/validate/Makefile
Normal file
42
regressions/ck_epoch/validate/Makefile
Normal file
|
@ -0,0 +1,42 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=ck_stack ck_epoch_synchronize ck_epoch_poll ck_epoch_call \
|
||||
ck_epoch_section ck_epoch_section_2 torture
|
||||
HALF=`expr $(CORES) / 2`
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
check: all
|
||||
./ck_stack $(CORES) 1
|
||||
./ck_epoch_synchronize $(HALF) $(HALF) 1
|
||||
./ck_epoch_poll $(CORES) 1 1
|
||||
./ck_epoch_section
|
||||
./ck_epoch_section_2 $(HALF) $(HALF) 1
|
||||
./torture $(HALF) $(HALF) 1
|
||||
|
||||
ck_epoch_synchronize: ck_epoch_synchronize.c ../../../include/ck_stack.h ../../../include/ck_epoch.h ../../../src/ck_epoch.c
|
||||
$(CC) $(CFLAGS) -o ck_epoch_synchronize ck_epoch_synchronize.c ../../../src/ck_epoch.c
|
||||
|
||||
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
|
||||
|
||||
torture: torture.c ../../../include/ck_epoch.h ../../../src/ck_epoch.c
|
||||
$(CC) $(CFLAGS) -o torture torture.c ../../../src/ck_epoch.c
|
||||
|
||||
ck_epoch_section: ck_epoch_section.c ../../../include/ck_epoch.h ../../../src/ck_epoch.c
|
||||
$(CC) $(CFLAGS) -o ck_epoch_section ck_epoch_section.c ../../../src/ck_epoch.c
|
||||
|
||||
ck_epoch_section_2: ck_epoch_section_2.c ../../../include/ck_epoch.h ../../../src/ck_epoch.c
|
||||
$(CC) $(CFLAGS) -o ck_epoch_section_2 ck_epoch_section_2.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
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o $(OBJECTS) *.dSYM *.exe
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
64
regressions/ck_epoch/validate/ck_epoch_call.c
Normal file
64
regressions/ck_epoch/validate/ck_epoch_call.c
Normal file
|
@ -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 <stdio.h>
|
||||
#include <ck_epoch.h>
|
||||
|
||||
#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(&record[1], p, cb);
|
||||
|
||||
printf("Counter value: %u -> %u\n",
|
||||
counter, counter + 1);
|
||||
counter++;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
ck_epoch_entry_t entry;
|
||||
|
||||
ck_epoch_register(&epoch, &record[0]);
|
||||
ck_epoch_register(&epoch, &record[1]);
|
||||
|
||||
ck_epoch_call(&record[1], &entry, cb);
|
||||
ck_epoch_barrier(&record[1]);
|
||||
ck_epoch_barrier(&record[1]);
|
||||
if (counter != 2)
|
||||
ck_error("Expected counter value 2, read %u.\n", counter);
|
||||
|
||||
return 0;
|
||||
}
|
236
regressions/ck_epoch/validate/ck_epoch_poll.c
Normal file
236
regressions/ck_epoch/validate/ck_epoch_poll.c
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright 2010-2015 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_backoff.h>
|
||||
#include <ck_cc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ck_epoch.h>
|
||||
#include <ck_stack.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static unsigned int n_rd;
|
||||
static unsigned int n_wr;
|
||||
static unsigned int n_threads;
|
||||
static unsigned int barrier;
|
||||
static unsigned int e_barrier;
|
||||
static unsigned int readers;
|
||||
static unsigned int writers;
|
||||
|
||||
#ifndef PAIRS_S
|
||||
#define PAIRS_S 100000
|
||||
#endif
|
||||
|
||||
#ifndef ITERATE_S
|
||||
#define ITERATE_S 20
|
||||
#endif
|
||||
|
||||
struct node {
|
||||
unsigned int value;
|
||||
ck_stack_entry_t stack_entry;
|
||||
ck_epoch_entry_t epoch_entry;
|
||||
};
|
||||
static ck_stack_t stack = CK_STACK_INITIALIZER;
|
||||
static ck_epoch_t stack_epoch;
|
||||
CK_STACK_CONTAINER(struct node, stack_entry, stack_container)
|
||||
CK_EPOCH_CONTAINER(struct node, epoch_entry, epoch_container)
|
||||
static struct affinity a;
|
||||
static const char animate[] = "-/|\\";
|
||||
|
||||
static void
|
||||
destructor(ck_epoch_entry_t *p)
|
||||
{
|
||||
struct node *e = epoch_container(p);
|
||||
|
||||
free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
read_thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
unsigned int j;
|
||||
ck_epoch_record_t record CK_CC_CACHELINE;
|
||||
ck_stack_entry_t *cursor, *n;
|
||||
|
||||
ck_epoch_register(&stack_epoch, &record);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads);
|
||||
|
||||
while (CK_STACK_ISEMPTY(&stack) == true) {
|
||||
if (ck_pr_load_uint(&readers) != 0)
|
||||
break;
|
||||
|
||||
ck_pr_stall();
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (;;) {
|
||||
ck_epoch_begin(&record, NULL);
|
||||
CK_STACK_FOREACH(&stack, cursor) {
|
||||
if (cursor == NULL)
|
||||
continue;
|
||||
|
||||
n = CK_STACK_NEXT(cursor);
|
||||
j += ck_pr_load_ptr(&n) != NULL;
|
||||
}
|
||||
ck_epoch_end(&record, NULL);
|
||||
|
||||
if (j != 0 && ck_pr_load_uint(&readers) == 0)
|
||||
ck_pr_store_uint(&readers, 1);
|
||||
|
||||
if (CK_STACK_ISEMPTY(&stack) == true &&
|
||||
ck_pr_load_uint(&e_barrier) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < n_threads);
|
||||
|
||||
fprintf(stderr, "[R] Observed entries: %u\n", j);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void *
|
||||
write_thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
struct node **entry, *e;
|
||||
unsigned int i, j, tid;
|
||||
ck_epoch_record_t record;
|
||||
ck_stack_entry_t *s;
|
||||
|
||||
ck_epoch_register(&stack_epoch, &record);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tid = ck_pr_faa_uint(&writers, 1);
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads);
|
||||
|
||||
entry = malloc(sizeof(struct node *) * PAIRS_S);
|
||||
if (entry == NULL) {
|
||||
ck_error("Failed allocation.\n");
|
||||
}
|
||||
|
||||
for (j = 0; j < ITERATE_S; j++) {
|
||||
for (i = 0; i < PAIRS_S; i++) {
|
||||
entry[i] = malloc(sizeof(struct node));
|
||||
if (entry == NULL) {
|
||||
ck_error("Failed individual allocation\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < PAIRS_S; i++) {
|
||||
ck_stack_push_upmc(&stack, &entry[i]->stack_entry);
|
||||
}
|
||||
|
||||
while (ck_pr_load_uint(&readers) == 0)
|
||||
ck_pr_stall();
|
||||
|
||||
if (tid == 0) {
|
||||
fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b[W] %2.2f: %c",
|
||||
(double)j / ITERATE_S, animate[i % strlen(animate)]);
|
||||
}
|
||||
|
||||
for (i = 0; i < PAIRS_S; i++) {
|
||||
ck_epoch_begin(&record, NULL);
|
||||
s = ck_stack_pop_upmc(&stack);
|
||||
e = stack_container(s);
|
||||
ck_epoch_end(&record, NULL);
|
||||
|
||||
ck_epoch_call(&record, &e->epoch_entry, destructor);
|
||||
ck_epoch_poll(&record);
|
||||
}
|
||||
}
|
||||
|
||||
ck_epoch_barrier(&record);
|
||||
|
||||
if (tid == 0) {
|
||||
fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b[W] Peak: %u (%2.2f%%)\n Reclamations: %lu\n\n",
|
||||
record.n_peak,
|
||||
(double)record.n_peak / ((double)PAIRS_S * ITERATE_S) * 100,
|
||||
record.n_dispatch);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < n_threads);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
pthread_t *threads;
|
||||
|
||||
if (argc != 4) {
|
||||
ck_error("Usage: stack <#readers> <#writers> <affinity delta>\n");
|
||||
}
|
||||
|
||||
n_rd = atoi(argv[1]);
|
||||
n_wr = atoi(argv[2]);
|
||||
n_threads = n_wr + n_rd;
|
||||
|
||||
a.delta = atoi(argv[3]);
|
||||
a.request = 0;
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * n_threads);
|
||||
ck_epoch_init(&stack_epoch);
|
||||
|
||||
for (i = 0; i < n_rd; i++)
|
||||
pthread_create(threads + i, NULL, read_thread, NULL);
|
||||
|
||||
do {
|
||||
pthread_create(threads + i, NULL, write_thread, NULL);
|
||||
} while (++i < n_wr + n_rd);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
return (0);
|
||||
}
|
311
regressions/ck_epoch/validate/ck_epoch_section.c
Normal file
311
regressions/ck_epoch/validate/ck_epoch_section.c
Normal file
|
@ -0,0 +1,311 @@
|
|||
/*
|
||||
* Copyright 2015 John Esmet.
|
||||
* 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 <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_epoch.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static ck_epoch_t epc;
|
||||
static ck_epoch_record_t record, record2;
|
||||
static unsigned int cleanup_calls;
|
||||
|
||||
static void
|
||||
setup_test(void)
|
||||
{
|
||||
|
||||
ck_epoch_init(&epc);
|
||||
ck_epoch_register(&epc, &record);
|
||||
ck_epoch_register(&epc, &record2);
|
||||
cleanup_calls = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
teardown_test(void)
|
||||
{
|
||||
|
||||
memset(&epc, 0, sizeof(ck_epoch_t));
|
||||
ck_epoch_unregister(&record);
|
||||
memset(&record, 0, sizeof(ck_epoch_record_t));
|
||||
memset(&record2, 0, sizeof(ck_epoch_record_t));
|
||||
cleanup_calls = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup(ck_epoch_entry_t *e)
|
||||
{
|
||||
(void) e;
|
||||
|
||||
cleanup_calls++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_simple_read_section(void)
|
||||
{
|
||||
ck_epoch_entry_t entry;
|
||||
ck_epoch_section_t section;
|
||||
|
||||
memset(&entry, 0, sizeof(ck_epoch_entry_t));
|
||||
setup_test();
|
||||
|
||||
ck_epoch_begin(&record, §ion);
|
||||
ck_epoch_call(&record, &entry, cleanup);
|
||||
assert(cleanup_calls == 0);
|
||||
ck_epoch_end(&record, §ion);
|
||||
ck_epoch_barrier(&record);
|
||||
assert(cleanup_calls == 1);
|
||||
|
||||
teardown_test();
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_nested_read_section(void)
|
||||
{
|
||||
ck_epoch_entry_t entry1, entry2;
|
||||
ck_epoch_section_t section1, section2;
|
||||
|
||||
memset(&entry1, 0, sizeof(ck_epoch_entry_t));
|
||||
memset(&entry2, 0, sizeof(ck_epoch_entry_t));
|
||||
setup_test();
|
||||
|
||||
ck_epoch_begin(&record, §ion1);
|
||||
ck_epoch_call(&record, &entry1, cleanup);
|
||||
assert(cleanup_calls == 0);
|
||||
|
||||
ck_epoch_begin(&record, §ion2);
|
||||
ck_epoch_call(&record, &entry2, cleanup);
|
||||
assert(cleanup_calls == 0);
|
||||
|
||||
ck_epoch_end(&record, §ion2);
|
||||
assert(cleanup_calls == 0);
|
||||
|
||||
ck_epoch_end(&record, §ion1);
|
||||
assert(cleanup_calls == 0);
|
||||
|
||||
ck_epoch_barrier(&record);
|
||||
assert(cleanup_calls == 2);
|
||||
|
||||
teardown_test();
|
||||
return;
|
||||
}
|
||||
|
||||
struct obj {
|
||||
ck_epoch_entry_t entry;
|
||||
unsigned int destroyed;
|
||||
};
|
||||
|
||||
static void *
|
||||
barrier_work(void *arg)
|
||||
{
|
||||
unsigned int *run;
|
||||
|
||||
run = (unsigned int *)arg;
|
||||
while (ck_pr_load_uint(run) != 0) {
|
||||
/*
|
||||
* Need to use record2, as record is local
|
||||
* to the test thread.
|
||||
*/
|
||||
ck_epoch_barrier(&record2);
|
||||
usleep(5 * 1000);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
reader_work(void *arg)
|
||||
{
|
||||
ck_epoch_record_t local_record;
|
||||
ck_epoch_section_t section;
|
||||
struct obj *o;
|
||||
|
||||
ck_epoch_register(&epc, &local_record);
|
||||
|
||||
o = (struct obj *)arg;
|
||||
|
||||
/*
|
||||
* Begin a read section. The calling thread has an open read section,
|
||||
* so the object should not be destroyed for the lifetime of this
|
||||
* thread.
|
||||
*/
|
||||
ck_epoch_begin(&local_record, §ion);
|
||||
usleep((common_rand() % 100) * 1000);
|
||||
assert(ck_pr_load_uint(&o->destroyed) == 0);
|
||||
ck_epoch_end(&local_record, §ion);
|
||||
|
||||
ck_epoch_unregister(&local_record);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
obj_destroy(ck_epoch_entry_t *e)
|
||||
{
|
||||
struct obj *o;
|
||||
|
||||
o = (struct obj *)e;
|
||||
ck_pr_fas_uint(&o->destroyed, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_single_reader_with_barrier_thread(void)
|
||||
{
|
||||
const int num_sections = 10;
|
||||
struct obj o;
|
||||
unsigned int run;
|
||||
pthread_t thread;
|
||||
ck_epoch_section_t sections[num_sections];
|
||||
int shuffled[num_sections];
|
||||
|
||||
run = 1;
|
||||
memset(&o, 0, sizeof(struct obj));
|
||||
common_srand(time(NULL));
|
||||
setup_test();
|
||||
|
||||
if (pthread_create(&thread, NULL, barrier_work, &run) != 0) {
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Start a bunch of sections. */
|
||||
for (int i = 0; i < num_sections; i++) {
|
||||
ck_epoch_begin(&record, §ions[i]);
|
||||
shuffled[i] = i;
|
||||
if (i == num_sections / 2) {
|
||||
usleep(1 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate a shuffle. */
|
||||
for (int i = num_sections - 1; i >= 0; i--) {
|
||||
int k = common_rand() % (i + 1);
|
||||
int tmp = shuffled[k];
|
||||
shuffled[k] = shuffled[i];
|
||||
shuffled[i] = tmp;
|
||||
}
|
||||
|
||||
ck_epoch_call(&record, &o.entry, obj_destroy);
|
||||
|
||||
/* Close the sections in shuffle-order. */
|
||||
for (int i = 0; i < num_sections; i++) {
|
||||
ck_epoch_end(&record, §ions[shuffled[i]]);
|
||||
if (i != num_sections - 1) {
|
||||
assert(ck_pr_load_uint(&o.destroyed) == 0);
|
||||
usleep(3 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_store_uint(&run, 0);
|
||||
if (pthread_join(thread, NULL) != 0) {
|
||||
abort();
|
||||
}
|
||||
|
||||
ck_epoch_barrier(&record);
|
||||
assert(ck_pr_load_uint(&o.destroyed) == 1);
|
||||
|
||||
teardown_test();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_multiple_readers_with_barrier_thread(void)
|
||||
{
|
||||
const int num_readers = 10;
|
||||
struct obj o;
|
||||
unsigned int run;
|
||||
ck_epoch_section_t section;
|
||||
pthread_t threads[num_readers + 1];
|
||||
|
||||
run = 1;
|
||||
memset(&o, 0, sizeof(struct obj));
|
||||
memset(§ion, 0, sizeof(ck_epoch_section_t));
|
||||
common_srand(time(NULL));
|
||||
setup_test();
|
||||
|
||||
/* Create a thread to call barrier() while we create reader threads.
|
||||
* Each barrier will attempt to move the global epoch forward so
|
||||
* it will make the read section code coverage more interesting. */
|
||||
if (pthread_create(&threads[num_readers], NULL,
|
||||
barrier_work, &run) != 0) {
|
||||
abort();
|
||||
}
|
||||
|
||||
ck_epoch_begin(&record, §ion);
|
||||
ck_epoch_call(&record, &o.entry, obj_destroy);
|
||||
|
||||
for (int i = 0; i < num_readers; i++) {
|
||||
if (pthread_create(&threads[i], NULL, reader_work, &o) != 0) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
ck_epoch_end(&record, §ion);
|
||||
|
||||
ck_pr_store_uint(&run, 0);
|
||||
if (pthread_join(threads[num_readers], NULL) != 0) {
|
||||
abort();
|
||||
}
|
||||
|
||||
/* After the barrier, the object should be destroyed and readers
|
||||
* should return. */
|
||||
for (int i = 0; i < num_readers; i++) {
|
||||
if (pthread_join(threads[i], NULL) != 0) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
teardown_test();
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
test_simple_read_section();
|
||||
test_nested_read_section();
|
||||
test_single_reader_with_barrier_thread();
|
||||
test_multiple_readers_with_barrier_thread();
|
||||
|
||||
return 0;
|
||||
}
|
195
regressions/ck_epoch/validate/ck_epoch_section_2.c
Normal file
195
regressions/ck_epoch/validate/ck_epoch_section_2.c
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright 2010-2015 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 <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ck_cc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ck_epoch.h>
|
||||
#include <ck_stack.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static unsigned int n_rd;
|
||||
static unsigned int n_wr;
|
||||
static unsigned int n_threads;
|
||||
static unsigned int barrier;
|
||||
static unsigned int leave;
|
||||
|
||||
#ifndef PAIRS_S
|
||||
#define PAIRS_S 10000
|
||||
#endif
|
||||
|
||||
#ifndef CK_EPOCH_T_DEPTH
|
||||
#define CK_EPOCH_T_DEPTH 8
|
||||
#endif
|
||||
|
||||
static ck_epoch_t epoch;
|
||||
static struct affinity a;
|
||||
|
||||
static void *
|
||||
read_thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
ck_epoch_record_t *record;
|
||||
unsigned long long i = 0;
|
||||
|
||||
record = malloc(sizeof *record);
|
||||
assert(record != NULL);
|
||||
ck_epoch_register(&epoch, record);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads);
|
||||
|
||||
for (;;) {
|
||||
ck_epoch_section_t section[2];
|
||||
ck_epoch_section_t junk[CK_EPOCH_T_DEPTH];
|
||||
unsigned int j;
|
||||
|
||||
ck_epoch_begin(record, §ion[0]);
|
||||
|
||||
for (j = 0; j < CK_EPOCH_T_DEPTH; j++)
|
||||
ck_epoch_begin(record, &junk[j]);
|
||||
for (j = 0; j < CK_EPOCH_T_DEPTH; j++)
|
||||
ck_epoch_end(record, &junk[j]);
|
||||
|
||||
if (i > 0)
|
||||
ck_epoch_end(record, §ion[1]);
|
||||
|
||||
/* Wait for the next synchronize operation. */
|
||||
while ((ck_pr_load_uint(&epoch.epoch) & 1) ==
|
||||
section[0].bucket) {
|
||||
i++;
|
||||
|
||||
if (!(i % 10000000)) {
|
||||
fprintf(stderr, "%u %u %u\n",
|
||||
ck_pr_load_uint(&epoch.epoch),
|
||||
section[0].bucket, record->epoch);
|
||||
}
|
||||
|
||||
while ((ck_pr_load_uint(&epoch.epoch) & 1) ==
|
||||
section[0].bucket) {
|
||||
if (ck_pr_load_uint(&leave) == 1)
|
||||
break;
|
||||
|
||||
ck_pr_stall();
|
||||
}
|
||||
}
|
||||
|
||||
ck_epoch_begin(record, §ion[1]);
|
||||
|
||||
assert(section[0].bucket != section[1].bucket);
|
||||
ck_epoch_end(record, §ion[0]);
|
||||
|
||||
assert(ck_pr_load_uint(&record->active) > 0);
|
||||
|
||||
if (ck_pr_load_uint(&leave) == 1) {
|
||||
ck_epoch_end(record, §ion[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
write_thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
ck_epoch_record_t record;
|
||||
unsigned long iterations = 0;
|
||||
|
||||
ck_epoch_register(&epoch, &record);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads);
|
||||
|
||||
for (;;) {
|
||||
if (!(iterations % 1048575))
|
||||
fprintf(stderr, ".");
|
||||
|
||||
ck_epoch_synchronize(&record);
|
||||
iterations++;
|
||||
|
||||
if (ck_pr_load_uint(&leave) == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%lu iterations\n", iterations);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
pthread_t *threads;
|
||||
|
||||
if (argc != 4) {
|
||||
ck_error("Usage: stack <#readers> <#writers> <affinity delta>\n");
|
||||
}
|
||||
|
||||
n_rd = atoi(argv[1]);
|
||||
n_wr = atoi(argv[2]);
|
||||
n_threads = n_wr + n_rd;
|
||||
|
||||
a.delta = atoi(argv[3]);
|
||||
a.request = 0;
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * n_threads);
|
||||
ck_epoch_init(&epoch);
|
||||
|
||||
for (i = 0; i < n_rd; i++)
|
||||
pthread_create(threads + i, NULL, read_thread, NULL);
|
||||
|
||||
do {
|
||||
pthread_create(threads + i, NULL, write_thread, NULL);
|
||||
} while (++i < n_wr + n_rd);
|
||||
|
||||
common_sleep(10);
|
||||
ck_pr_store_uint(&leave, 1);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
return (0);
|
||||
}
|
249
regressions/ck_epoch/validate/ck_epoch_synchronize.c
Normal file
249
regressions/ck_epoch/validate/ck_epoch_synchronize.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* Copyright 2010-2015 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_backoff.h>
|
||||
#include <ck_cc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ck_epoch.h>
|
||||
#include <ck_stack.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static unsigned int n_rd;
|
||||
static unsigned int n_wr;
|
||||
static unsigned int n_threads;
|
||||
static unsigned int barrier;
|
||||
static unsigned int e_barrier;
|
||||
static unsigned int readers;
|
||||
static unsigned int writers;
|
||||
|
||||
#ifndef PAIRS_S
|
||||
#define PAIRS_S 10000
|
||||
#endif
|
||||
|
||||
#ifndef ITERATE_S
|
||||
#define ITERATE_S 20
|
||||
#endif
|
||||
|
||||
struct node {
|
||||
unsigned int value;
|
||||
ck_stack_entry_t stack_entry;
|
||||
ck_epoch_entry_t epoch_entry;
|
||||
};
|
||||
static ck_stack_t stack = CK_STACK_INITIALIZER;
|
||||
static ck_epoch_t stack_epoch;
|
||||
CK_STACK_CONTAINER(struct node, stack_entry, stack_container)
|
||||
CK_EPOCH_CONTAINER(struct node, epoch_entry, epoch_container)
|
||||
static struct affinity a;
|
||||
static const char animate[] = "-/|\\";
|
||||
|
||||
static void
|
||||
destructor(ck_epoch_entry_t *p)
|
||||
{
|
||||
struct node *e = epoch_container(p);
|
||||
|
||||
free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
read_thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
unsigned int j;
|
||||
ck_epoch_record_t record CK_CC_CACHELINE;
|
||||
ck_stack_entry_t *cursor;
|
||||
ck_stack_entry_t *n;
|
||||
unsigned int i;
|
||||
|
||||
ck_epoch_register(&stack_epoch, &record);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads);
|
||||
|
||||
while (CK_STACK_ISEMPTY(&stack) == true) {
|
||||
if (ck_pr_load_uint(&readers) != 0)
|
||||
break;
|
||||
|
||||
ck_pr_stall();
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (;;) {
|
||||
i = 0;
|
||||
|
||||
ck_epoch_begin(&record, NULL);
|
||||
CK_STACK_FOREACH(&stack, cursor) {
|
||||
if (cursor == NULL)
|
||||
continue;
|
||||
|
||||
n = CK_STACK_NEXT(cursor);
|
||||
j += ck_pr_load_ptr(&n) != NULL;
|
||||
|
||||
if (i++ > 4098)
|
||||
break;
|
||||
}
|
||||
ck_epoch_end(&record, NULL);
|
||||
|
||||
if (j != 0 && ck_pr_load_uint(&readers) == 0)
|
||||
ck_pr_store_uint(&readers, 1);
|
||||
|
||||
if (CK_STACK_ISEMPTY(&stack) == true &&
|
||||
ck_pr_load_uint(&e_barrier) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < n_threads);
|
||||
|
||||
fprintf(stderr, "[R] Observed entries: %u\n", j);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void *
|
||||
write_thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
struct node **entry, *e;
|
||||
unsigned int i, j, tid;
|
||||
ck_epoch_record_t record;
|
||||
ck_stack_entry_t *s;
|
||||
|
||||
ck_epoch_register(&stack_epoch, &record);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tid = ck_pr_faa_uint(&writers, 1);
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads);
|
||||
|
||||
entry = malloc(sizeof(struct node *) * PAIRS_S);
|
||||
if (entry == NULL) {
|
||||
ck_error("Failed allocation.\n");
|
||||
}
|
||||
|
||||
for (j = 0; j < ITERATE_S; j++) {
|
||||
for (i = 0; i < PAIRS_S; i++) {
|
||||
entry[i] = malloc(sizeof(struct node));
|
||||
if (entry == NULL) {
|
||||
ck_error("Failed individual allocation\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < PAIRS_S; i++) {
|
||||
ck_stack_push_upmc(&stack, &entry[i]->stack_entry);
|
||||
}
|
||||
|
||||
while (ck_pr_load_uint(&readers) == 0)
|
||||
ck_pr_stall();
|
||||
|
||||
for (i = 0; i < PAIRS_S; i++) {
|
||||
ck_epoch_begin(&record, NULL);
|
||||
s = ck_stack_pop_upmc(&stack);
|
||||
e = stack_container(s);
|
||||
ck_epoch_end(&record, NULL);
|
||||
|
||||
if (i & 1) {
|
||||
ck_epoch_synchronize(&record);
|
||||
ck_epoch_reclaim(&record);
|
||||
ck_epoch_call(&record, &e->epoch_entry, destructor);
|
||||
} else {
|
||||
ck_epoch_barrier(&record);
|
||||
destructor(&e->epoch_entry);
|
||||
}
|
||||
|
||||
if (tid == 0 && (i % 16384) == 0) {
|
||||
fprintf(stderr, "[W] %2.2f: %c\n",
|
||||
(double)j / ITERATE_S, animate[i % strlen(animate)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ck_epoch_synchronize(&record);
|
||||
|
||||
if (tid == 0) {
|
||||
fprintf(stderr, "[W] Peak: %u (%2.2f%%)\n Reclamations: %lu\n\n",
|
||||
record.n_peak,
|
||||
(double)record.n_peak / ((double)PAIRS_S * ITERATE_S) * 100,
|
||||
record.n_dispatch);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < n_threads);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
pthread_t *threads;
|
||||
|
||||
if (argc != 4) {
|
||||
ck_error("Usage: stack <#readers> <#writers> <affinity delta>\n");
|
||||
}
|
||||
|
||||
n_rd = atoi(argv[1]);
|
||||
n_wr = atoi(argv[2]);
|
||||
n_threads = n_wr + n_rd;
|
||||
|
||||
a.delta = atoi(argv[3]);
|
||||
a.request = 0;
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * n_threads);
|
||||
ck_epoch_init(&stack_epoch);
|
||||
|
||||
for (i = 0; i < n_rd; i++)
|
||||
pthread_create(threads + i, NULL, read_thread, NULL);
|
||||
|
||||
do {
|
||||
pthread_create(threads + i, NULL, write_thread, NULL);
|
||||
} while (++i < n_wr + n_rd);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
return (0);
|
||||
}
|
164
regressions/ck_epoch/validate/ck_stack.c
Normal file
164
regressions/ck_epoch/validate/ck_stack.c
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright 2010-2015 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_backoff.h>
|
||||
#include <ck_cc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <ck_epoch.h>
|
||||
#include <ck_stack.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static unsigned int n_threads;
|
||||
static unsigned int barrier;
|
||||
static unsigned int e_barrier;
|
||||
|
||||
#ifndef PAIRS
|
||||
#define PAIRS 5000000
|
||||
#endif
|
||||
|
||||
struct node {
|
||||
unsigned int value;
|
||||
ck_epoch_entry_t epoch_entry;
|
||||
ck_stack_entry_t stack_entry;
|
||||
};
|
||||
static ck_stack_t stack = {NULL, NULL};
|
||||
static ck_epoch_t stack_epoch;
|
||||
CK_STACK_CONTAINER(struct node, stack_entry, stack_container)
|
||||
CK_EPOCH_CONTAINER(struct node, epoch_entry, epoch_container)
|
||||
static struct affinity a;
|
||||
|
||||
static void
|
||||
destructor(ck_epoch_entry_t *p)
|
||||
{
|
||||
struct node *e = epoch_container(p);
|
||||
|
||||
free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
struct node **entry, *e;
|
||||
ck_epoch_record_t record;
|
||||
ck_stack_entry_t *s;
|
||||
unsigned long smr = 0;
|
||||
unsigned int i;
|
||||
|
||||
ck_epoch_register(&stack_epoch, &record);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
entry = malloc(sizeof(struct node *) * PAIRS);
|
||||
if (entry == NULL) {
|
||||
ck_error("Failed allocation.\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < PAIRS; i++) {
|
||||
entry[i] = malloc(sizeof(struct node));
|
||||
if (entry == NULL) {
|
||||
ck_error("Failed individual allocation\n");
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads);
|
||||
|
||||
for (i = 0; i < PAIRS; i++) {
|
||||
ck_epoch_begin(&record, NULL);
|
||||
ck_stack_push_upmc(&stack, &entry[i]->stack_entry);
|
||||
s = ck_stack_pop_upmc(&stack);
|
||||
ck_epoch_end(&record, NULL);
|
||||
|
||||
e = stack_container(s);
|
||||
ck_epoch_call(&record, &e->epoch_entry, destructor);
|
||||
smr += ck_epoch_poll(&record) == false;
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < n_threads);
|
||||
|
||||
fprintf(stderr, "Deferrals: %lu (%2.2f)\n", smr, (double)smr / PAIRS);
|
||||
fprintf(stderr, "Peak: %u (%2.2f%%), %u pending\nReclamations: %lu\n\n",
|
||||
record.n_peak,
|
||||
(double)record.n_peak / PAIRS * 100,
|
||||
record.n_pending,
|
||||
record.n_dispatch);
|
||||
|
||||
ck_epoch_barrier(&record);
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < (n_threads << 1));
|
||||
|
||||
if (record.n_pending != 0) {
|
||||
ck_error("ERROR: %u pending, expecting none.\n",
|
||||
record.n_pending);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
pthread_t *threads;
|
||||
|
||||
if (argc != 3) {
|
||||
ck_error("Usage: stack <threads> <affinity delta>\n");
|
||||
}
|
||||
|
||||
n_threads = atoi(argv[1]);
|
||||
a.delta = atoi(argv[2]);
|
||||
a.request = 0;
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * n_threads);
|
||||
|
||||
ck_epoch_init(&stack_epoch);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_create(threads + i, NULL, thread, NULL);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
return (0);
|
||||
}
|
234
regressions/ck_epoch/validate/torture.c
Normal file
234
regressions/ck_epoch/validate/torture.c
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* Copyright 2010-2015 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 <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ck_cc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ck_epoch.h>
|
||||
#include <ck_stack.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static unsigned int n_rd;
|
||||
static unsigned int n_wr;
|
||||
static unsigned int n_threads;
|
||||
static unsigned int barrier;
|
||||
static unsigned int leave;
|
||||
static unsigned int first;
|
||||
|
||||
struct {
|
||||
unsigned int value;
|
||||
} valid CK_CC_CACHELINE = { 1 };
|
||||
|
||||
struct {
|
||||
unsigned int value;
|
||||
} invalid CK_CC_CACHELINE;
|
||||
|
||||
#ifndef PAIRS_S
|
||||
#define PAIRS_S 10000
|
||||
#endif
|
||||
|
||||
#ifndef CK_EPOCH_T_DEPTH
|
||||
#define CK_EPOCH_T_DEPTH 8
|
||||
#endif
|
||||
|
||||
static ck_epoch_t epoch;
|
||||
static struct affinity a;
|
||||
|
||||
static void
|
||||
test(struct ck_epoch_record *record)
|
||||
{
|
||||
unsigned int j[3];
|
||||
unsigned int b, c;
|
||||
const unsigned int r = 100;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
ck_epoch_begin(record, NULL);
|
||||
c = ck_pr_load_uint(&invalid.value);
|
||||
ck_pr_fence_load();
|
||||
b = ck_pr_load_uint(&valid.value);
|
||||
ck_test(c > b, "Invalid value: %u > %u\n", c, b);
|
||||
ck_epoch_end(record, NULL);
|
||||
}
|
||||
|
||||
ck_epoch_begin(record, NULL);
|
||||
|
||||
/* This implies no early load of epoch occurs. */
|
||||
j[0] = record->epoch;
|
||||
|
||||
|
||||
/* We should observe up to one epoch migration. */
|
||||
do {
|
||||
ck_pr_fence_load();
|
||||
j[1] = ck_pr_load_uint(&epoch.epoch);
|
||||
|
||||
if (ck_pr_load_uint(&leave) == 1) {
|
||||
ck_epoch_end(record, NULL);
|
||||
return;
|
||||
}
|
||||
} while (j[1] == j[0]);
|
||||
|
||||
/* No more epoch migrations should occur */
|
||||
for (i = 0; i < r; i++) {
|
||||
ck_pr_fence_strict_load();
|
||||
j[2] = ck_pr_load_uint(&epoch.epoch);
|
||||
|
||||
ck_test(j[2] != j[1], "Inconsistency detected: %u %u %u\n",
|
||||
j[0], j[1], j[2]);
|
||||
}
|
||||
|
||||
ck_epoch_end(record, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
read_thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
ck_epoch_record_t *record;
|
||||
|
||||
record = malloc(sizeof *record);
|
||||
assert(record != NULL);
|
||||
ck_epoch_register(&epoch, record);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads);
|
||||
|
||||
do {
|
||||
test(record);
|
||||
test(record);
|
||||
test(record);
|
||||
test(record);
|
||||
} while (ck_pr_load_uint(&leave) == 0);
|
||||
|
||||
ck_pr_dec_uint(&n_rd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
write_thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
ck_epoch_record_t *record;
|
||||
unsigned long iterations = 0;
|
||||
bool c = ck_pr_faa_uint(&first, 1);
|
||||
|
||||
record = malloc(sizeof *record);
|
||||
assert(record != NULL);
|
||||
ck_epoch_register(&epoch, record);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads);
|
||||
|
||||
do {
|
||||
/*
|
||||
* A thread should never observe invalid.value > valid.value.
|
||||
* inside a protected section. Only
|
||||
* invalid.value <= valid.value is valid.
|
||||
*/
|
||||
if (!c) ck_pr_store_uint(&valid.value, 1);
|
||||
ck_epoch_synchronize(record);
|
||||
if (!c) ck_pr_store_uint(&invalid.value, 1);
|
||||
|
||||
ck_pr_fence_store();
|
||||
if (!c) ck_pr_store_uint(&valid.value, 2);
|
||||
ck_epoch_synchronize(record);
|
||||
if (!c) ck_pr_store_uint(&invalid.value, 2);
|
||||
|
||||
ck_pr_fence_store();
|
||||
if (!c) ck_pr_store_uint(&valid.value, 3);
|
||||
ck_epoch_synchronize(record);
|
||||
if (!c) ck_pr_store_uint(&invalid.value, 3);
|
||||
|
||||
ck_pr_fence_store();
|
||||
if (!c) ck_pr_store_uint(&valid.value, 4);
|
||||
ck_epoch_synchronize(record);
|
||||
if (!c) ck_pr_store_uint(&invalid.value, 4);
|
||||
|
||||
ck_epoch_synchronize(record);
|
||||
if (!c) ck_pr_store_uint(&invalid.value, 0);
|
||||
ck_epoch_synchronize(record);
|
||||
|
||||
iterations += 4;
|
||||
} while (ck_pr_load_uint(&leave) == 0 &&
|
||||
ck_pr_load_uint(&n_rd) > 0);
|
||||
|
||||
fprintf(stderr, "%lu iterations\n", iterations);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
pthread_t *threads;
|
||||
|
||||
if (argc != 4) {
|
||||
ck_error("Usage: stack <#readers> <#writers> <affinity delta>\n");
|
||||
}
|
||||
|
||||
n_rd = atoi(argv[1]);
|
||||
n_wr = atoi(argv[2]);
|
||||
n_threads = n_wr + n_rd;
|
||||
|
||||
a.delta = atoi(argv[3]);
|
||||
a.request = 0;
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * n_threads);
|
||||
ck_epoch_init(&epoch);
|
||||
|
||||
for (i = 0; i < n_rd; i++)
|
||||
pthread_create(threads + i, NULL, read_thread, NULL);
|
||||
|
||||
do {
|
||||
pthread_create(threads + i, NULL, write_thread, NULL);
|
||||
} while (++i < n_wr + n_rd);
|
||||
|
||||
common_sleep(30);
|
||||
ck_pr_store_uint(&leave, 1);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
return 0;
|
||||
}
|
14
regressions/ck_fifo/benchmark/Makefile
Normal file
14
regressions/ck_fifo/benchmark/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
.PHONY: clean distribution
|
||||
|
||||
OBJECTS=latency
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
latency: latency.c
|
||||
$(CC) $(CFLAGS) -o latency latency.c
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o *.dSYM *.exe $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
157
regressions/ck_fifo/benchmark/latency.c
Normal file
157
regressions/ck_fifo/benchmark/latency.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <ck_fifo.h>
|
||||
#include <ck_spinlock.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ENTRIES
|
||||
#define ENTRIES 4096
|
||||
#endif
|
||||
|
||||
#ifndef STEPS
|
||||
#define STEPS 40000
|
||||
#endif
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
ck_spinlock_fas_t mutex = CK_SPINLOCK_FAS_INITIALIZER;
|
||||
void *r;
|
||||
uint64_t s, e, a;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
|
||||
#if defined(CK_F_FIFO_SPSC)
|
||||
ck_fifo_spsc_t spsc_fifo;
|
||||
ck_fifo_spsc_entry_t spsc_entry[ENTRIES];
|
||||
ck_fifo_spsc_entry_t spsc_stub;
|
||||
#endif
|
||||
|
||||
#if defined(CK_F_FIFO_MPMC)
|
||||
ck_fifo_mpmc_t mpmc_fifo;
|
||||
ck_fifo_mpmc_entry_t mpmc_entry[ENTRIES];
|
||||
ck_fifo_mpmc_entry_t mpmc_stub;
|
||||
ck_fifo_mpmc_entry_t *garbage;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_FIFO_SPSC
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_fifo_spsc_init(&spsc_fifo, &spsc_stub);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++) {
|
||||
ck_spinlock_fas_lock(&mutex);
|
||||
ck_fifo_spsc_enqueue(&spsc_fifo, spsc_entry + j, NULL);
|
||||
ck_spinlock_fas_unlock(&mutex);
|
||||
}
|
||||
e = rdtsc();
|
||||
|
||||
a += e - s;
|
||||
}
|
||||
printf(" spinlock_enqueue: %16" PRIu64 "\n", a / STEPS / (sizeof(spsc_entry) / sizeof(*spsc_entry)));
|
||||
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_fifo_spsc_init(&spsc_fifo, &spsc_stub);
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_fifo_spsc_enqueue(&spsc_fifo, spsc_entry + j, NULL);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++) {
|
||||
ck_spinlock_fas_lock(&mutex);
|
||||
ck_fifo_spsc_dequeue(&spsc_fifo, &r);
|
||||
ck_spinlock_fas_unlock(&mutex);
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
printf(" spinlock_dequeue: %16" PRIu64 "\n", a / STEPS / (sizeof(spsc_entry) / sizeof(*spsc_entry)));
|
||||
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_fifo_spsc_init(&spsc_fifo, &spsc_stub);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_fifo_spsc_enqueue(&spsc_fifo, spsc_entry + j, NULL);
|
||||
e = rdtsc();
|
||||
|
||||
a += e - s;
|
||||
}
|
||||
printf("ck_fifo_spsc_enqueue: %16" PRIu64 "\n", a / STEPS / (sizeof(spsc_entry) / sizeof(*spsc_entry)));
|
||||
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_fifo_spsc_init(&spsc_fifo, &spsc_stub);
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_fifo_spsc_enqueue(&spsc_fifo, spsc_entry + j, NULL);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_fifo_spsc_dequeue(&spsc_fifo, &r);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
printf("ck_fifo_spsc_dequeue: %16" PRIu64 "\n", a / STEPS / (sizeof(spsc_entry) / sizeof(*spsc_entry)));
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_FIFO_MPMC
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_fifo_mpmc_init(&mpmc_fifo, &mpmc_stub);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_fifo_mpmc_enqueue(&mpmc_fifo, mpmc_entry + j, NULL);
|
||||
e = rdtsc();
|
||||
|
||||
a += e - s;
|
||||
}
|
||||
printf("ck_fifo_mpmc_enqueue: %16" PRIu64 "\n", a / STEPS / (sizeof(mpmc_entry) / sizeof(*mpmc_entry)));
|
||||
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_fifo_mpmc_init(&mpmc_fifo, &mpmc_stub);
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_fifo_mpmc_enqueue(&mpmc_fifo, mpmc_entry + j, NULL);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_fifo_mpmc_dequeue(&mpmc_fifo, &r, &garbage);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
printf("ck_fifo_mpmc_dequeue: %16" PRIu64 "\n", a / STEPS / (sizeof(mpmc_entry) / sizeof(*mpmc_entry)));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
29
regressions/ck_fifo/validate/Makefile
Normal file
29
regressions/ck_fifo/validate/Makefile
Normal file
|
@ -0,0 +1,29 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=ck_fifo_spsc ck_fifo_mpmc ck_fifo_spsc_iterator ck_fifo_mpmc_iterator
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
check: all
|
||||
./ck_fifo_spsc $(CORES) 1 64000
|
||||
./ck_fifo_mpmc $(CORES) 1 16000
|
||||
./ck_fifo_spsc_iterator
|
||||
./ck_fifo_mpmc_iterator
|
||||
|
||||
ck_fifo_spsc: ck_fifo_spsc.c ../../../include/ck_fifo.h
|
||||
$(CC) $(CFLAGS) -o ck_fifo_spsc ck_fifo_spsc.c
|
||||
|
||||
ck_fifo_mpmc: ck_fifo_mpmc.c ../../../include/ck_fifo.h
|
||||
$(CC) $(CFLAGS) -o ck_fifo_mpmc ck_fifo_mpmc.c
|
||||
|
||||
ck_fifo_spsc_iterator: ck_fifo_spsc_iterator.c ../../../include/ck_fifo.h
|
||||
$(CC) $(CFLAGS) -o ck_fifo_spsc_iterator ck_fifo_spsc_iterator.c
|
||||
|
||||
ck_fifo_mpmc_iterator: ck_fifo_mpmc_iterator.c ../../../include/ck_fifo.h
|
||||
$(CC) $(CFLAGS) -o ck_fifo_mpmc_iterator ck_fifo_mpmc_iterator.c
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
168
regressions/ck_fifo/validate/ck_fifo_mpmc.c
Normal file
168
regressions/ck_fifo/validate/ck_fifo_mpmc.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <ck_fifo.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifdef CK_F_FIFO_MPMC
|
||||
#ifndef ITERATIONS
|
||||
#define ITERATIONS 128
|
||||
#endif
|
||||
|
||||
struct context {
|
||||
unsigned int tid;
|
||||
unsigned int previous;
|
||||
unsigned int next;
|
||||
};
|
||||
|
||||
struct entry {
|
||||
int tid;
|
||||
int value;
|
||||
};
|
||||
|
||||
static int nthr;
|
||||
|
||||
#ifdef CK_F_FIFO_MPMC
|
||||
static ck_fifo_mpmc_t fifo CK_CC_CACHELINE;
|
||||
#endif
|
||||
|
||||
static struct affinity a;
|
||||
static int size;
|
||||
static unsigned int barrier;
|
||||
|
||||
static void *
|
||||
test(void *c)
|
||||
{
|
||||
#ifdef CK_F_FIFO_MPMC
|
||||
struct context *context = c;
|
||||
struct entry *entry;
|
||||
ck_fifo_mpmc_entry_t *fifo_entry, *garbage;
|
||||
int i, j;
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < (unsigned int)nthr);
|
||||
|
||||
for (i = 0; i < ITERATIONS; i++) {
|
||||
for (j = 0; j < size; j++) {
|
||||
fifo_entry = malloc(sizeof(ck_fifo_mpmc_entry_t));
|
||||
entry = malloc(sizeof(struct entry));
|
||||
entry->tid = context->tid;
|
||||
ck_fifo_mpmc_enqueue(&fifo, fifo_entry, entry);
|
||||
if (ck_fifo_mpmc_dequeue(&fifo, &entry, &garbage) == false) {
|
||||
ck_error("ERROR [%u] Queue should never be empty.\n", context->tid);
|
||||
}
|
||||
|
||||
if (entry->tid < 0 || entry->tid >= nthr) {
|
||||
ck_error("ERROR [%u] Incorrect value in entry.\n", entry->tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ITERATIONS; i++) {
|
||||
for (j = 0; j < size; j++) {
|
||||
fifo_entry = malloc(sizeof(ck_fifo_mpmc_entry_t));
|
||||
entry = malloc(sizeof(struct entry));
|
||||
entry->tid = context->tid;
|
||||
while (ck_fifo_mpmc_tryenqueue(&fifo, fifo_entry, entry) == false)
|
||||
ck_pr_stall();
|
||||
|
||||
while (ck_fifo_mpmc_trydequeue(&fifo, &entry, &garbage) == false)
|
||||
ck_pr_stall();
|
||||
|
||||
if (entry->tid < 0 || entry->tid >= nthr) {
|
||||
ck_error("ERROR [%u] Incorrect value in entry when using try interface.\n", entry->tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, r;
|
||||
struct context *context;
|
||||
ck_fifo_mpmc_entry_t *garbage;
|
||||
pthread_t *thread;
|
||||
|
||||
if (argc != 4) {
|
||||
ck_error("Usage: validate <threads> <affinity delta> <size>\n");
|
||||
}
|
||||
|
||||
a.request = 0;
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
assert(nthr >= 1);
|
||||
|
||||
size = atoi(argv[3]);
|
||||
assert(size > 0);
|
||||
|
||||
context = malloc(sizeof(*context) * nthr);
|
||||
assert(context);
|
||||
|
||||
thread = malloc(sizeof(pthread_t) * nthr);
|
||||
assert(thread);
|
||||
|
||||
ck_fifo_mpmc_init(&fifo, malloc(sizeof(ck_fifo_mpmc_entry_t)));
|
||||
ck_fifo_mpmc_deinit(&fifo, &garbage);
|
||||
if (garbage == NULL)
|
||||
ck_error("ERROR: Expected non-NULL stub node on deinit.\n");
|
||||
free(garbage);
|
||||
ck_fifo_mpmc_init(&fifo, malloc(sizeof(ck_fifo_mpmc_entry_t)));
|
||||
|
||||
for (i = 0; i < nthr; i++) {
|
||||
context[i].tid = i;
|
||||
r = pthread_create(thread + i, NULL, test, context + i);
|
||||
assert(r == 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(thread[i], NULL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#else
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
fprintf(stderr, "Unsupported.\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
90
regressions/ck_fifo/validate/ck_fifo_mpmc_iterator.c
Normal file
90
regressions/ck_fifo/validate/ck_fifo_mpmc_iterator.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <ck_fifo.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef CK_F_FIFO_MPMC
|
||||
struct example {
|
||||
int x;
|
||||
};
|
||||
|
||||
static ck_fifo_mpmc_t mpmc_fifo;
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int i, length = 3;
|
||||
struct example *examples;
|
||||
ck_fifo_mpmc_entry_t *stub, *entries, *entry, *next;
|
||||
|
||||
stub = malloc(sizeof(ck_fifo_mpmc_entry_t));
|
||||
if (stub == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
ck_fifo_mpmc_init(&mpmc_fifo, stub);
|
||||
|
||||
entries = malloc(sizeof(ck_fifo_mpmc_entry_t) * length);
|
||||
if (entries == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
examples = malloc(sizeof(struct example) * length);
|
||||
/* Need these for this unit test. */
|
||||
if (examples == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
examples[i].x = i;
|
||||
ck_fifo_mpmc_enqueue(&mpmc_fifo, entries + i, examples + i);
|
||||
}
|
||||
|
||||
puts("Testing CK_FIFO_MPMC_FOREACH.");
|
||||
CK_FIFO_MPMC_FOREACH(&mpmc_fifo, entry) {
|
||||
printf("Next value in fifo: %d\n", ((struct example *)entry->value)->x);
|
||||
}
|
||||
|
||||
puts("Testing CK_FIFO_MPMC_FOREACH_SAFE.");
|
||||
CK_FIFO_MPMC_FOREACH_SAFE(&mpmc_fifo, entry, next) {
|
||||
if (entry->next.pointer != next)
|
||||
exit(EXIT_FAILURE);
|
||||
printf("Next value in fifo: %d\n", ((struct example *)entry->value)->x);
|
||||
}
|
||||
|
||||
free(examples);
|
||||
free(entries);
|
||||
free(stub);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#else
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
#endif
|
177
regressions/ck_fifo/validate/ck_fifo_spsc.c
Normal file
177
regressions/ck_fifo/validate/ck_fifo_spsc.c
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <ck_fifo.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATIONS
|
||||
#define ITERATIONS 128
|
||||
#endif
|
||||
|
||||
struct context {
|
||||
unsigned int tid;
|
||||
unsigned int previous;
|
||||
unsigned int next;
|
||||
};
|
||||
|
||||
struct entry {
|
||||
int tid;
|
||||
int value;
|
||||
};
|
||||
|
||||
static int nthr;
|
||||
static ck_fifo_spsc_t *fifo;
|
||||
static struct affinity a;
|
||||
static int size;
|
||||
static unsigned int barrier;
|
||||
|
||||
static void *
|
||||
test(void *c)
|
||||
{
|
||||
struct context *context = c;
|
||||
struct entry *entry;
|
||||
ck_fifo_spsc_entry_t *fifo_entry;
|
||||
int i, j;
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%p %u: %u -> %u\n", fifo+context->tid, context->tid, context->previous, context->tid);
|
||||
#endif
|
||||
|
||||
if (context->tid == 0) {
|
||||
struct entry *entries;
|
||||
|
||||
entries = malloc(sizeof(struct entry) * size);
|
||||
assert(entries != NULL);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
entries[i].value = i;
|
||||
entries[i].tid = 0;
|
||||
|
||||
fifo_entry = malloc(sizeof(ck_fifo_spsc_entry_t));
|
||||
ck_fifo_spsc_enqueue(fifo + context->tid, fifo_entry, entries + i);
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < (unsigned int)nthr);
|
||||
|
||||
for (i = 0; i < ITERATIONS; i++) {
|
||||
for (j = 0; j < size; j++) {
|
||||
while (ck_fifo_spsc_dequeue(fifo + context->previous, &entry) == false);
|
||||
if (context->previous != (unsigned int)entry->tid) {
|
||||
ck_error("T [%u:%p] %u != %u\n",
|
||||
context->tid, (void *)entry, entry->tid, context->previous);
|
||||
}
|
||||
|
||||
if (entry->value != j) {
|
||||
ck_error("V [%u:%p] %u != %u\n",
|
||||
context->tid, (void *)entry, entry->value, j);
|
||||
}
|
||||
|
||||
entry->tid = context->tid;
|
||||
fifo_entry = ck_fifo_spsc_recycle(fifo + context->tid);
|
||||
if (fifo_entry == NULL)
|
||||
fifo_entry = malloc(sizeof(ck_fifo_spsc_entry_t));
|
||||
|
||||
ck_fifo_spsc_enqueue(fifo + context->tid, fifo_entry, entry);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, r;
|
||||
struct context *context;
|
||||
pthread_t *thread;
|
||||
|
||||
if (argc != 4) {
|
||||
ck_error("Usage: validate <threads> <affinity delta> <size>\n");
|
||||
}
|
||||
|
||||
a.request = 0;
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
assert(nthr >= 1);
|
||||
|
||||
size = atoi(argv[3]);
|
||||
assert(size > 0);
|
||||
|
||||
fifo = malloc(sizeof(ck_fifo_spsc_t) * nthr);
|
||||
assert(fifo);
|
||||
|
||||
context = malloc(sizeof(*context) * nthr);
|
||||
assert(context);
|
||||
|
||||
thread = malloc(sizeof(pthread_t) * nthr);
|
||||
assert(thread);
|
||||
|
||||
for (i = 0; i < nthr; i++) {
|
||||
ck_fifo_spsc_entry_t *garbage;
|
||||
|
||||
context[i].tid = i;
|
||||
if (i == 0) {
|
||||
context[i].previous = nthr - 1;
|
||||
context[i].next = i + 1;
|
||||
} else if (i == nthr - 1) {
|
||||
context[i].next = 0;
|
||||
context[i].previous = i - 1;
|
||||
} else {
|
||||
context[i].next = i + 1;
|
||||
context[i].previous = i - 1;
|
||||
}
|
||||
|
||||
ck_fifo_spsc_init(fifo + i, malloc(sizeof(ck_fifo_spsc_entry_t)));
|
||||
ck_fifo_spsc_deinit(fifo + i, &garbage);
|
||||
if (garbage == NULL)
|
||||
ck_error("ERROR: Expected non-NULL stub node on deinit.\n");
|
||||
|
||||
free(garbage);
|
||||
ck_fifo_spsc_init(fifo + i, malloc(sizeof(ck_fifo_spsc_entry_t)));
|
||||
r = pthread_create(thread + i, NULL, test, context + i);
|
||||
assert(r == 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(thread[i], NULL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
83
regressions/ck_fifo/validate/ck_fifo_spsc_iterator.c
Normal file
83
regressions/ck_fifo/validate/ck_fifo_spsc_iterator.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <ck_fifo.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct example {
|
||||
int x;
|
||||
};
|
||||
|
||||
static ck_fifo_spsc_t spsc_fifo;
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int i, length = 3;
|
||||
struct example *examples;
|
||||
ck_fifo_spsc_entry_t *stub, *entries, *entry, *next;
|
||||
|
||||
stub = malloc(sizeof(ck_fifo_spsc_entry_t));
|
||||
if (stub == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
ck_fifo_spsc_init(&spsc_fifo, stub);
|
||||
|
||||
entries = malloc(sizeof(ck_fifo_spsc_entry_t) * length);
|
||||
if (entries == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
examples = malloc(sizeof(struct example) * length);
|
||||
/* Need these for this unit test. */
|
||||
if (examples == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
examples[i].x = i;
|
||||
ck_fifo_spsc_enqueue(&spsc_fifo, entries + i, examples + i);
|
||||
}
|
||||
|
||||
puts("Testing CK_FIFO_SPSC_FOREACH.");
|
||||
CK_FIFO_SPSC_FOREACH(&spsc_fifo, entry) {
|
||||
printf("Next value in fifo: %d\n", ((struct example *)entry->value)->x);
|
||||
}
|
||||
|
||||
puts("Testing CK_FIFO_SPSC_FOREACH_SAFE.");
|
||||
CK_FIFO_SPSC_FOREACH_SAFE(&spsc_fifo, entry, next) {
|
||||
if (entry->next != next)
|
||||
exit(EXIT_FAILURE);
|
||||
printf("Next value in fifo: %d\n", ((struct example *)entry->value)->x);
|
||||
}
|
||||
|
||||
free(examples);
|
||||
free(entries);
|
||||
free(stub);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
17
regressions/ck_hp/benchmark/Makefile
Normal file
17
regressions/ck_hp/benchmark/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: clean distribution
|
||||
|
||||
OBJECTS=fifo_latency stack_latency
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
fifo_latency: fifo_latency.c
|
||||
$(CC) $(CFLAGS) -o fifo_latency ../../../src/ck_hp.c fifo_latency.c
|
||||
|
||||
stack_latency: stack_latency.c
|
||||
$(CC) $(CFLAGS) -o stack_latency ../../../src/ck_hp.c stack_latency.c
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o *.dSYM *.exe $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
94
regressions/ck_hp/benchmark/fifo_latency.c
Normal file
94
regressions/ck_hp/benchmark/fifo_latency.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <ck_hp.h>
|
||||
#include <ck_hp_fifo.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ENTRIES
|
||||
#define ENTRIES 4096
|
||||
#endif
|
||||
|
||||
#ifndef STEPS
|
||||
#define STEPS 40000
|
||||
#endif
|
||||
|
||||
static ck_hp_fifo_t fifo;
|
||||
static ck_hp_t fifo_hp;
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
void *r;
|
||||
uint64_t s, e, a;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
ck_hp_fifo_entry_t hp_entry[ENTRIES];
|
||||
ck_hp_fifo_entry_t hp_stub;
|
||||
ck_hp_record_t record;
|
||||
|
||||
ck_hp_init(&fifo_hp, CK_HP_FIFO_SLOTS_COUNT, 1000000, NULL);
|
||||
|
||||
r = malloc(CK_HP_FIFO_SLOTS_SIZE);
|
||||
if (r == NULL) {
|
||||
ck_error("ERROR: Failed to allocate slots.\n");
|
||||
}
|
||||
ck_hp_register(&fifo_hp, &record, r);
|
||||
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_hp_fifo_init(&fifo, &hp_stub);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_hp_fifo_enqueue_mpmc(&record, &fifo, hp_entry + j, NULL);
|
||||
e = rdtsc();
|
||||
|
||||
a += e - s;
|
||||
}
|
||||
printf("ck_hp_fifo_enqueue_mpmc: %16" PRIu64 "\n", a / STEPS / ENTRIES);
|
||||
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_hp_fifo_init(&fifo, &hp_stub);
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_hp_fifo_enqueue_mpmc(&record, &fifo, hp_entry + j, NULL);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_hp_fifo_dequeue_mpmc(&record, &fifo, &r);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
printf("ck_hp_fifo_dequeue_mpmc: %16" PRIu64 "\n", a / STEPS / ENTRIES);
|
||||
|
||||
return 0;
|
||||
}
|
95
regressions/ck_hp/benchmark/stack_latency.c
Normal file
95
regressions/ck_hp/benchmark/stack_latency.c
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <ck_hp.h>
|
||||
#include <ck_hp_stack.h>
|
||||
#include <ck_stack.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ENTRIES
|
||||
#define ENTRIES 4096
|
||||
#endif
|
||||
|
||||
#ifndef STEPS
|
||||
#define STEPS 40000
|
||||
#endif
|
||||
|
||||
static ck_stack_t stack;
|
||||
static ck_hp_t stack_hp;
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
ck_hp_record_t record;
|
||||
ck_stack_entry_t entry[ENTRIES];
|
||||
uint64_t s, e, a;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
void *r;
|
||||
|
||||
ck_hp_init(&stack_hp, CK_HP_STACK_SLOTS_COUNT, 1000000, NULL);
|
||||
r = malloc(CK_HP_STACK_SLOTS_SIZE);
|
||||
if (r == NULL) {
|
||||
ck_error("ERROR: Failed to allocate slots.\n");
|
||||
}
|
||||
ck_hp_register(&stack_hp, &record, (void *)r);
|
||||
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_stack_init(&stack);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_hp_stack_push_mpmc(&stack, entry + j);
|
||||
e = rdtsc();
|
||||
|
||||
a += e - s;
|
||||
}
|
||||
printf("ck_hp_stack_push_mpmc: %16" PRIu64 "\n", a / STEPS / ENTRIES);
|
||||
|
||||
a = 0;
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_stack_init(&stack);
|
||||
|
||||
for (j = 0; j < ENTRIES; j++)
|
||||
ck_hp_stack_push_mpmc(&stack, entry + j);
|
||||
|
||||
s = rdtsc();
|
||||
for (j = 0; j < ENTRIES; j++) {
|
||||
r = ck_hp_stack_pop_mpmc(&record, &stack);
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
printf(" ck_hp_stack_pop_mpmc: %16" PRIu64 "\n", a / STEPS / ENTRIES);
|
||||
|
||||
return 0;
|
||||
}
|
33
regressions/ck_hp/validate/Makefile
Normal file
33
regressions/ck_hp/validate/Makefile
Normal file
|
@ -0,0 +1,33 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=ck_hp_stack nbds_haz_test serial ck_hp_fifo ck_hp_fifo_donner
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
check: all
|
||||
./serial
|
||||
./ck_hp_stack $(CORES) 100 1
|
||||
./ck_hp_fifo $(CORES) 1 16384 100
|
||||
./nbds_haz_test $(CORES) 15 1
|
||||
./ck_hp_fifo_donner $(CORES) 16384
|
||||
|
||||
ck_hp_stack: ../../../src/ck_hp.c ck_hp_stack.c ../../../include/ck_hp_stack.h
|
||||
$(CC) $(CFLAGS) ../../../src/ck_hp.c -o ck_hp_stack ck_hp_stack.c
|
||||
|
||||
ck_hp_fifo: ../../../src/ck_hp.c ck_hp_fifo.c ../../../include/ck_hp_fifo.h
|
||||
$(CC) $(CFLAGS) ../../../src/ck_hp.c -o ck_hp_fifo ck_hp_fifo.c
|
||||
|
||||
ck_hp_fifo_donner: ../../../src/ck_hp.c ck_hp_fifo_donner.c ../../../include/ck_hp_fifo.h
|
||||
$(CC) $(CFLAGS) ../../../src/ck_hp.c -o ck_hp_fifo_donner ck_hp_fifo_donner.c
|
||||
|
||||
serial: ../../../src/ck_hp.c serial.c ../../../include/ck_hp_stack.h
|
||||
$(CC) $(CFLAGS) ../../../src/ck_hp.c -o serial serial.c
|
||||
|
||||
nbds_haz_test: ../../../src/ck_hp.c nbds_haz_test.c
|
||||
$(CC) $(CFLAGS) ../../../src/ck_hp.c -o nbds_haz_test nbds_haz_test.c
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o *.dSYM *.exe $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
187
regressions/ck_hp/validate/ck_hp_fifo.c
Normal file
187
regressions/ck_hp/validate/ck_hp_fifo.c
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright 2011-2015 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 <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <ck_hp_fifo.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATIONS
|
||||
#define ITERATIONS 128
|
||||
#endif
|
||||
|
||||
struct context {
|
||||
unsigned int tid;
|
||||
unsigned int previous;
|
||||
unsigned int next;
|
||||
};
|
||||
|
||||
struct entry {
|
||||
int tid;
|
||||
int value;
|
||||
};
|
||||
|
||||
static ck_hp_fifo_t fifo;
|
||||
static ck_hp_t fifo_hp;
|
||||
static int nthr;
|
||||
|
||||
static struct affinity a;
|
||||
static int size;
|
||||
static unsigned int barrier;
|
||||
static unsigned int e_barrier;
|
||||
|
||||
static void *
|
||||
test(void *c)
|
||||
{
|
||||
struct context *context = c;
|
||||
struct entry *entry;
|
||||
ck_hp_fifo_entry_t *fifo_entry;
|
||||
ck_hp_record_t record;
|
||||
int i, j;
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_hp_register(&fifo_hp, &record, malloc(sizeof(void *) * 2));
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < (unsigned int)nthr);
|
||||
|
||||
for (i = 0; i < ITERATIONS; i++) {
|
||||
for (j = 0; j < size; j++) {
|
||||
fifo_entry = malloc(sizeof(ck_hp_fifo_entry_t));
|
||||
entry = malloc(sizeof(struct entry));
|
||||
entry->tid = context->tid;
|
||||
ck_hp_fifo_enqueue_mpmc(&record, &fifo, fifo_entry, entry);
|
||||
|
||||
ck_pr_barrier();
|
||||
|
||||
fifo_entry = ck_hp_fifo_dequeue_mpmc(&record, &fifo, &entry);
|
||||
if (fifo_entry == NULL) {
|
||||
ck_error("ERROR [%u] Queue should never be empty.\n", context->tid);
|
||||
}
|
||||
|
||||
ck_pr_barrier();
|
||||
|
||||
if (entry->tid < 0 || entry->tid >= nthr) {
|
||||
ck_error("ERROR [%u] Incorrect value in entry.\n", entry->tid);
|
||||
}
|
||||
|
||||
ck_hp_free(&record, &fifo_entry->hazard, fifo_entry, fifo_entry);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ITERATIONS; i++) {
|
||||
for (j = 0; j < size; j++) {
|
||||
fifo_entry = malloc(sizeof(ck_hp_fifo_entry_t));
|
||||
entry = malloc(sizeof(struct entry));
|
||||
entry->tid = context->tid;
|
||||
|
||||
while (ck_hp_fifo_tryenqueue_mpmc(&record, &fifo, fifo_entry, entry) == false)
|
||||
ck_pr_stall();
|
||||
|
||||
while (fifo_entry = ck_hp_fifo_trydequeue_mpmc(&record, &fifo, &entry), fifo_entry == NULL)
|
||||
ck_pr_stall();
|
||||
|
||||
if (entry->tid < 0 || entry->tid >= nthr) {
|
||||
ck_error("ERROR [%u] Incorrect value in entry.\n", entry->tid);
|
||||
}
|
||||
|
||||
ck_hp_free(&record, &fifo_entry->hazard, fifo_entry, fifo_entry);
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < (unsigned int)nthr);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
destructor(void *p)
|
||||
{
|
||||
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, r;
|
||||
struct context *context;
|
||||
pthread_t *thread;
|
||||
int threshold;
|
||||
|
||||
if (argc != 5) {
|
||||
ck_error("Usage: validate <threads> <affinity delta> <size> <threshold>\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
assert(nthr >= 1);
|
||||
|
||||
size = atoi(argv[3]);
|
||||
assert(size > 0);
|
||||
|
||||
threshold = atoi(argv[4]);
|
||||
assert(threshold > 0);
|
||||
|
||||
context = malloc(sizeof(*context) * nthr);
|
||||
assert(context);
|
||||
|
||||
thread = malloc(sizeof(pthread_t) * nthr);
|
||||
assert(thread);
|
||||
|
||||
ck_hp_init(&fifo_hp, 2, threshold, destructor);
|
||||
ck_hp_fifo_init(&fifo, malloc(sizeof(ck_hp_fifo_entry_t)));
|
||||
|
||||
ck_hp_fifo_entry_t *entry;
|
||||
ck_hp_fifo_deinit(&fifo, &entry);
|
||||
|
||||
if (entry == NULL)
|
||||
ck_error("ERROR: Expected non-NULL stub node.\n");
|
||||
|
||||
free(entry);
|
||||
ck_hp_fifo_init(&fifo, malloc(sizeof(ck_hp_fifo_entry_t)));
|
||||
|
||||
for (i = 0; i < nthr; i++) {
|
||||
context[i].tid = i;
|
||||
r = pthread_create(thread + i, NULL, test, context + i);
|
||||
assert(r == 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(thread[i], NULL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
213
regressions/ck_hp/validate/ck_hp_fifo_donner.c
Normal file
213
regressions/ck_hp/validate/ck_hp_fifo_donner.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright 2012 Hendrik Donner
|
||||
* Copyright 2012-2015 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 <ck_hp.h>
|
||||
#include <ck_hp_fifo.h>
|
||||
#include <ck_pr.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
#include "../../common.h"
|
||||
|
||||
/* FIFO queue */
|
||||
static ck_hp_fifo_t fifo;
|
||||
|
||||
/* Hazard pointer global */
|
||||
static ck_hp_t fifo_hp;
|
||||
|
||||
/* thread local element count */
|
||||
static unsigned long *count;
|
||||
|
||||
static unsigned long thread_count;
|
||||
|
||||
static unsigned int start_barrier;
|
||||
static unsigned int end_barrier;
|
||||
|
||||
/* destructor for FIFO queue */
|
||||
static void
|
||||
destructor(void *p)
|
||||
{
|
||||
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
/* entry struct for FIFO queue entries */
|
||||
struct entry {
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
/* function for thread */
|
||||
static void *
|
||||
queue_50_50(void *elements)
|
||||
{
|
||||
struct entry *entry;
|
||||
ck_hp_fifo_entry_t *fifo_entry;
|
||||
ck_hp_record_t *record;
|
||||
void *slots;
|
||||
unsigned long j, element_count = *(unsigned long *)elements;
|
||||
unsigned int seed;
|
||||
|
||||
record = malloc(sizeof(ck_hp_record_t));
|
||||
assert(record);
|
||||
|
||||
slots = malloc(CK_HP_FIFO_SLOTS_SIZE);
|
||||
assert(slots);
|
||||
|
||||
/* different seed for each thread */
|
||||
seed = 1337; /*(unsigned int) pthread_self(); */
|
||||
|
||||
/*
|
||||
* This subscribes the thread to the fifo_hp state using the thread-owned
|
||||
* record.
|
||||
* FIFO queue needs 2 hazard pointers.
|
||||
*/
|
||||
ck_hp_register(&fifo_hp, record, slots);
|
||||
|
||||
/* start barrier */
|
||||
ck_pr_inc_uint(&start_barrier);
|
||||
while (ck_pr_load_uint(&start_barrier) < thread_count + 1)
|
||||
ck_pr_stall();
|
||||
|
||||
/* 50/50 enqueue-dequeue */
|
||||
for(j = 0; j < element_count; j++) {
|
||||
/* rand_r with thread local state should be thread safe */
|
||||
if( 50 < (1+(int) (100.0*common_rand_r(&seed)/(RAND_MAX+1.0)))) {
|
||||
/* This is the container for the enqueued data. */
|
||||
fifo_entry = malloc(sizeof(ck_hp_fifo_entry_t));
|
||||
|
||||
if (fifo_entry == NULL) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* This is the data. */
|
||||
entry = malloc(sizeof(struct entry));
|
||||
if (entry != NULL) {
|
||||
entry->value = j;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enqueue the value of the pointer entry into FIFO queue using the
|
||||
* container fifo_entry.
|
||||
*/
|
||||
ck_hp_fifo_enqueue_mpmc(record, &fifo, fifo_entry, entry);
|
||||
} else {
|
||||
/*
|
||||
* ck_hp_fifo_dequeue_mpmc will return a pointer to the first unused node and store
|
||||
* the value of the first pointer in the FIFO queue in entry.
|
||||
*/
|
||||
fifo_entry = ck_hp_fifo_dequeue_mpmc(record, &fifo, &entry);
|
||||
if (fifo_entry != NULL) {
|
||||
/*
|
||||
* Safely reclaim memory associated with fifo_entry.
|
||||
* This inserts garbage into a local list. Once the list (plist) reaches
|
||||
* a length of 100, ck_hp_free will attempt to reclaim all references
|
||||
* to objects on the list.
|
||||
*/
|
||||
ck_hp_free(record, &fifo_entry->hazard, fifo_entry, fifo_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* end barrier */
|
||||
ck_pr_inc_uint(&end_barrier);
|
||||
while (ck_pr_load_uint(&end_barrier) < thread_count + 1)
|
||||
ck_pr_stall();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
ck_hp_fifo_entry_t *stub;
|
||||
unsigned long element_count, i;
|
||||
pthread_t *thr;
|
||||
|
||||
if (argc != 3) {
|
||||
ck_error("Usage: cktest <thread_count> <element_count>\n");
|
||||
}
|
||||
|
||||
/* Get element count from argument */
|
||||
element_count = atoi(argv[2]);
|
||||
|
||||
/* Get element count from argument */
|
||||
thread_count = atoi(argv[1]);
|
||||
|
||||
/* pthread handles */
|
||||
thr = malloc(sizeof(pthread_t) * thread_count);
|
||||
|
||||
/* array for local operation count */
|
||||
count = malloc(sizeof(unsigned long *) * thread_count);
|
||||
|
||||
/*
|
||||
* Initialize global hazard pointer safe memory reclamation to execute free()
|
||||
* when a fifo_entry is safe to be deleted.
|
||||
* Hazard pointer scan routine will be called when the thread local intern plist's
|
||||
* size exceed 100 entries.
|
||||
*/
|
||||
|
||||
/* FIFO queue needs 2 hazard pointers */
|
||||
ck_hp_init(&fifo_hp, CK_HP_FIFO_SLOTS_COUNT, 100, destructor);
|
||||
|
||||
/* The FIFO requires one stub entry on initialization. */
|
||||
stub = malloc(sizeof(ck_hp_fifo_entry_t));
|
||||
|
||||
/* Behavior is undefined if stub is NULL. */
|
||||
if (stub == NULL) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* This is called once to initialize the fifo. */
|
||||
ck_hp_fifo_init(&fifo, stub);
|
||||
|
||||
/* Create threads */
|
||||
for (i = 0; i < thread_count; i++) {
|
||||
count[i] = (element_count + i) / thread_count;
|
||||
if (pthread_create(&thr[i], NULL, queue_50_50, (void *) &count[i]) != 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* start barrier */
|
||||
ck_pr_inc_uint(&start_barrier);
|
||||
while (ck_pr_load_uint(&start_barrier) < thread_count + 1);
|
||||
|
||||
/* end barrier */
|
||||
ck_pr_inc_uint(&end_barrier);
|
||||
while (ck_pr_load_uint(&end_barrier) < thread_count + 1);
|
||||
|
||||
/* Join threads */
|
||||
for (i = 0; i < thread_count; i++)
|
||||
pthread_join(thr[i], NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
165
regressions/ck_hp/validate/ck_hp_stack.c
Normal file
165
regressions/ck_hp/validate/ck_hp_stack.c
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright 2010-2015 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_backoff.h>
|
||||
#include <ck_cc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <ck_hp.h>
|
||||
#include <ck_stack.h>
|
||||
#include <ck_hp_stack.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static unsigned int threshold;
|
||||
static unsigned int n_threads;
|
||||
static unsigned int barrier;
|
||||
static unsigned int e_barrier;
|
||||
|
||||
#ifndef PAIRS
|
||||
#define PAIRS 5000000
|
||||
#endif
|
||||
|
||||
struct node {
|
||||
unsigned int value;
|
||||
ck_hp_hazard_t hazard;
|
||||
ck_stack_entry_t stack_entry;
|
||||
};
|
||||
static ck_stack_t stack = {NULL, NULL};
|
||||
static ck_hp_t stack_hp;
|
||||
CK_STACK_CONTAINER(struct node, stack_entry, stack_container)
|
||||
static struct affinity a;
|
||||
|
||||
static void *
|
||||
thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
struct node **entry, *e;
|
||||
unsigned int i;
|
||||
ck_hp_record_t record;
|
||||
void **pointers;
|
||||
ck_stack_entry_t *s;
|
||||
|
||||
unused = NULL;
|
||||
pointers = malloc(sizeof(void *));
|
||||
ck_hp_register(&stack_hp, &record, pointers);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
entry = malloc(sizeof(struct node *) * PAIRS);
|
||||
if (entry == NULL) {
|
||||
ck_error("Failed allocation.\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < PAIRS; i++) {
|
||||
entry[i] = malloc(sizeof(struct node));
|
||||
if (entry == NULL) {
|
||||
ck_error("Failed individual allocation\n");
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads)
|
||||
ck_pr_stall();
|
||||
|
||||
for (i = 0; i < PAIRS; i++) {
|
||||
ck_hp_stack_push_mpmc(&stack, &entry[i]->stack_entry);
|
||||
s = ck_hp_stack_pop_mpmc(&record, &stack);
|
||||
e = stack_container(s);
|
||||
ck_hp_free(&record, &e->hazard, e, s);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < n_threads)
|
||||
ck_pr_stall();
|
||||
|
||||
fprintf(stderr, "Peak: %u (%2.2f%%)\nReclamations: %" PRIu64 "\n\n",
|
||||
record.n_peak,
|
||||
(double)record.n_peak / PAIRS * 100,
|
||||
record.n_reclamations);
|
||||
|
||||
ck_hp_clear(&record);
|
||||
ck_hp_purge(&record);
|
||||
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < (n_threads << 1));
|
||||
|
||||
if (record.n_pending != 0) {
|
||||
ck_error("ERROR: %u pending, expecting none.\n",
|
||||
record.n_pending);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
destructor(void *p)
|
||||
{
|
||||
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
pthread_t *threads;
|
||||
|
||||
if (argc != 4) {
|
||||
ck_error("Usage: stack <threads> <threshold> <delta>\n");
|
||||
}
|
||||
|
||||
n_threads = atoi(argv[1]);
|
||||
threshold = atoi(argv[2]);
|
||||
a.delta = atoi(argv[3]);
|
||||
a.request = 0;
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * n_threads);
|
||||
|
||||
ck_hp_init(&stack_hp, 1, threshold, destructor);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_create(threads + i, NULL, thread, NULL);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
return (0);
|
||||
}
|
226
regressions/ck_hp/validate/nbds_haz_test.c
Normal file
226
regressions/ck_hp/validate/nbds_haz_test.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* Copyright 2010-2015 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a unit test similar to the implementation in John Dybnis's nbds
|
||||
* test.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include <ck_backoff.h>
|
||||
#include <ck_cc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <ck_hp.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#define STACK_CONTAINER(T, M, N) CK_CC_CONTAINER(stack_entry_t, T, M, N)
|
||||
|
||||
struct stack_entry {
|
||||
struct stack_entry *next;
|
||||
} CK_CC_ALIGN(8);
|
||||
typedef struct stack_entry stack_entry_t;
|
||||
|
||||
struct stack {
|
||||
struct stack_entry *head;
|
||||
char *generation;
|
||||
} CK_CC_PACKED CK_CC_ALIGN(16);
|
||||
typedef struct stack hp_stack_t;
|
||||
|
||||
static unsigned int threshold;
|
||||
static unsigned int n_threads;
|
||||
static unsigned int barrier;
|
||||
static unsigned int e_barrier;
|
||||
static unsigned int global_tid;
|
||||
static unsigned int pops;
|
||||
static unsigned int pushs;
|
||||
|
||||
#ifndef PAIRS
|
||||
#define PAIRS 1000000
|
||||
#endif
|
||||
|
||||
struct node {
|
||||
unsigned int value;
|
||||
ck_hp_hazard_t hazard;
|
||||
stack_entry_t stack_entry;
|
||||
};
|
||||
hp_stack_t stack = {NULL, NULL};
|
||||
ck_hp_t stack_hp;
|
||||
|
||||
STACK_CONTAINER(struct node, stack_entry, stack_container)
|
||||
static struct affinity a;
|
||||
|
||||
/*
|
||||
* Stack producer operation safe for multiple unique producers and multiple consumers.
|
||||
*/
|
||||
CK_CC_INLINE static void
|
||||
stack_push_mpmc(struct stack *target, struct stack_entry *entry)
|
||||
{
|
||||
struct stack_entry *lstack;
|
||||
ck_backoff_t backoff = CK_BACKOFF_INITIALIZER;
|
||||
|
||||
lstack = ck_pr_load_ptr(&target->head);
|
||||
ck_pr_store_ptr(&entry->next, lstack);
|
||||
ck_pr_fence_store();
|
||||
|
||||
while (ck_pr_cas_ptr_value(&target->head, lstack, entry, &lstack) == false) {
|
||||
ck_pr_store_ptr(&entry->next, lstack);
|
||||
ck_pr_fence_store();
|
||||
ck_backoff_eb(&backoff);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stack consumer operation safe for multiple unique producers and multiple consumers.
|
||||
*/
|
||||
CK_CC_INLINE static struct stack_entry *
|
||||
stack_pop_mpmc(ck_hp_record_t *record, struct stack *target)
|
||||
{
|
||||
struct stack_entry *entry;
|
||||
ck_backoff_t backoff = CK_BACKOFF_INITIALIZER;
|
||||
|
||||
do {
|
||||
entry = ck_pr_load_ptr(&target->head);
|
||||
if (entry == NULL)
|
||||
return (NULL);
|
||||
|
||||
ck_hp_set_fence(record, 0, entry);
|
||||
} while (entry != ck_pr_load_ptr(&target->head));
|
||||
|
||||
while (ck_pr_cas_ptr_value(&target->head, entry, entry->next, &entry) == false) {
|
||||
if (ck_pr_load_ptr(&entry) == NULL)
|
||||
break;
|
||||
|
||||
ck_hp_set_fence(record, 0, entry);
|
||||
if (entry != ck_pr_load_ptr(&target->head))
|
||||
continue;
|
||||
|
||||
ck_backoff_eb(&backoff);
|
||||
}
|
||||
|
||||
return (entry);
|
||||
}
|
||||
|
||||
static void *
|
||||
thread(void *unused CK_CC_UNUSED)
|
||||
{
|
||||
struct node *entry, *e;
|
||||
unsigned int i;
|
||||
ck_hp_record_t record;
|
||||
void **pointers;
|
||||
stack_entry_t *s;
|
||||
unsigned int tid = ck_pr_faa_uint(&global_tid, 1) + 1;
|
||||
unsigned int r = (unsigned int)(tid + 1) * 0x5bd1e995;
|
||||
|
||||
unused = NULL;
|
||||
pointers = malloc(sizeof(void *));
|
||||
ck_hp_register(&stack_hp, &record, pointers);
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: failed to affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&barrier);
|
||||
while (ck_pr_load_uint(&barrier) < n_threads)
|
||||
ck_pr_stall();
|
||||
|
||||
for (i = 0; i < PAIRS; i++) {
|
||||
r ^= r << 6; r ^= r >> 21; r ^= r << 7;
|
||||
|
||||
if (r & 0x1000) {
|
||||
entry = malloc(sizeof(struct node));
|
||||
assert(entry);
|
||||
stack_push_mpmc(&stack, &entry->stack_entry);
|
||||
ck_pr_inc_uint(&pushs);
|
||||
} else {
|
||||
s = stack_pop_mpmc(&record, &stack);
|
||||
if (s == NULL)
|
||||
continue;
|
||||
|
||||
e = stack_container(s);
|
||||
ck_hp_free(&record, &e->hazard, e, s);
|
||||
ck_pr_inc_uint(&pops);
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&e_barrier);
|
||||
while (ck_pr_load_uint(&e_barrier) < n_threads);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
destructor(void *p)
|
||||
{
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
pthread_t *threads;
|
||||
|
||||
if (argc != 4) {
|
||||
ck_error("Usage: stack <threads> <threshold> <delta>\n");
|
||||
}
|
||||
|
||||
n_threads = atoi(argv[1]);
|
||||
threshold = atoi(argv[2]);
|
||||
a.delta = atoi(argv[3]);
|
||||
a.request = 0;
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * n_threads);
|
||||
|
||||
ck_hp_init(&stack_hp, 1, threshold, destructor);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_create(threads + i, NULL, thread, NULL);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
fprintf(stderr, "Push: %u\nPop: %u\n", pushs, pops);
|
||||
return (0);
|
||||
}
|
127
regressions/ck_hp/validate/serial.c
Normal file
127
regressions/ck_hp/validate/serial.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright 2010-2015 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <ck_hp.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
struct entry {
|
||||
unsigned int value;
|
||||
ck_hp_hazard_t hazard;
|
||||
};
|
||||
|
||||
static void
|
||||
destructor(void *pointer)
|
||||
{
|
||||
|
||||
fprintf(stderr, "Free %p\n", pointer);
|
||||
free(pointer);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
ck_hp_t state;
|
||||
ck_hp_record_t record[2];
|
||||
void **pointers;
|
||||
struct entry *entry, *other;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
ck_hp_init(&state, 1, 1, destructor);
|
||||
|
||||
pointers = malloc(sizeof(void *));
|
||||
if (pointers == NULL) {
|
||||
ck_error("ERROR: Failed to allocate slot.\n");
|
||||
}
|
||||
ck_hp_register(&state, &record[0], pointers);
|
||||
ck_hp_reclaim(&record[0]);
|
||||
|
||||
entry = malloc(sizeof *entry);
|
||||
ck_hp_set(&record[0], 0, entry);
|
||||
ck_hp_reclaim(&record[0]);
|
||||
ck_hp_free(&record[0], &entry->hazard, entry, entry);
|
||||
ck_hp_reclaim(&record[0]);
|
||||
ck_hp_set(&record[0], 0, NULL);
|
||||
ck_hp_reclaim(&record[0]);
|
||||
|
||||
entry = malloc(sizeof *entry);
|
||||
ck_hp_set(&record[0], 0, entry);
|
||||
ck_hp_reclaim(&record[0]);
|
||||
ck_hp_free(&record[0], &entry->hazard, entry, entry);
|
||||
ck_hp_reclaim(&record[0]);
|
||||
ck_hp_set(&record[0], 0, NULL);
|
||||
ck_hp_reclaim(&record[0]);
|
||||
|
||||
pointers = malloc(sizeof(void *));
|
||||
if (pointers == NULL) {
|
||||
ck_error("ERROR: Failed to allocate slot.\n");
|
||||
}
|
||||
ck_hp_register(&state, &record[1], pointers);
|
||||
ck_hp_reclaim(&record[1]);
|
||||
|
||||
entry = malloc(sizeof *entry);
|
||||
ck_hp_set(&record[1], 0, entry);
|
||||
ck_hp_reclaim(&record[1]);
|
||||
ck_hp_free(&record[1], &entry->hazard, entry, entry);
|
||||
ck_hp_reclaim(&record[1]);
|
||||
ck_hp_set(&record[1], 0, NULL);
|
||||
ck_hp_reclaim(&record[1]);
|
||||
|
||||
printf("Allocating entry and freeing in other HP record...\n");
|
||||
entry = malloc(sizeof *entry);
|
||||
entry->value = 42;
|
||||
ck_hp_set(&record[0], 0, entry);
|
||||
ck_hp_free(&record[1], &entry->hazard, entry, entry);
|
||||
ck_pr_store_uint(&entry->value, 1);
|
||||
|
||||
other = malloc(sizeof *other);
|
||||
other->value = 24;
|
||||
ck_hp_set(&record[1], 0, other);
|
||||
ck_hp_free(&record[0], &other->hazard, other, other);
|
||||
ck_pr_store_uint(&other->value, 32);
|
||||
ck_hp_set(&record[0], 0, NULL);
|
||||
ck_hp_reclaim(&record[1]);
|
||||
ck_hp_set(&record[1], 0, NULL);
|
||||
ck_hp_reclaim(&record[0]);
|
||||
ck_hp_reclaim(&record[1]);
|
||||
|
||||
return 0;
|
||||
}
|
23
regressions/ck_hs/benchmark/Makefile
Normal file
23
regressions/ck_hs/benchmark/Makefile
Normal file
|
@ -0,0 +1,23 @@
|
|||
.PHONY: clean distribution
|
||||
|
||||
OBJECTS=serial parallel_bytestring parallel_bytestring.delete apply
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
serial: serial.c ../../../include/ck_hs.h ../../../src/ck_hs.c
|
||||
$(CC) $(CFLAGS) -o serial serial.c ../../../src/ck_hs.c
|
||||
|
||||
apply: apply.c ../../../include/ck_hs.h ../../../src/ck_hs.c
|
||||
$(CC) $(CFLAGS) -o apply apply.c ../../../src/ck_hs.c
|
||||
|
||||
parallel_bytestring: parallel_bytestring.c ../../../include/ck_hs.h ../../../src/ck_hs.c ../../../src/ck_epoch.c
|
||||
$(CC) $(PTHREAD_CFLAGS) $(CFLAGS) -o parallel_bytestring parallel_bytestring.c ../../../src/ck_hs.c ../../../src/ck_epoch.c
|
||||
|
||||
parallel_bytestring.delete: parallel_bytestring.c ../../../include/ck_hs.h ../../../src/ck_hs.c ../../../src/ck_epoch.c
|
||||
$(CC) $(PTHREAD_CFLAGS) $(CFLAGS) -DHS_DELETE -o parallel_bytestring.delete parallel_bytestring.c ../../../src/ck_hs.c ../../../src/ck_epoch.c
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o $(OBJECTS) *.dSYM *.exe
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=-D_GNU_SOURCE
|
260
regressions/ck_hs/benchmark/apply.c
Normal file
260
regressions/ck_hs/benchmark/apply.c
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright 2014 Samy Al Bahra.
|
||||
* Copyright 2014 Backtrace I/O, Inc.
|
||||
* 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 copyrighs
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyrighs
|
||||
* 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 <ck_hs.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ck_malloc.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#include "../../../src/ck_ht_hash.h"
|
||||
|
||||
static ck_hs_t hs;
|
||||
static char **keys;
|
||||
static size_t keys_length = 0;
|
||||
static size_t keys_capacity = 128;
|
||||
static unsigned long global_seed;
|
||||
|
||||
static void *
|
||||
hs_malloc(size_t r)
|
||||
{
|
||||
|
||||
return malloc(r);
|
||||
}
|
||||
|
||||
static void
|
||||
hs_free(void *p, size_t b, bool r)
|
||||
{
|
||||
|
||||
(void)b;
|
||||
(void)r;
|
||||
|
||||
free(p);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ck_malloc my_allocator = {
|
||||
.malloc = hs_malloc,
|
||||
.free = hs_free
|
||||
};
|
||||
|
||||
static unsigned long
|
||||
hs_hash(const void *object, unsigned long seed)
|
||||
{
|
||||
const char *c = object;
|
||||
unsigned long h;
|
||||
|
||||
h = (unsigned long)MurmurHash64A(c, strlen(c), seed);
|
||||
return h;
|
||||
}
|
||||
|
||||
static bool
|
||||
hs_compare(const void *previous, const void *compare)
|
||||
{
|
||||
|
||||
return strcmp(previous, compare) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_destroy(void)
|
||||
{
|
||||
|
||||
ck_hs_destroy(&hs);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
set_init(unsigned int size, unsigned int mode)
|
||||
{
|
||||
|
||||
if (ck_hs_init(&hs, CK_HS_MODE_OBJECT | CK_HS_MODE_SPMC | mode, hs_hash, hs_compare,
|
||||
&my_allocator, size, global_seed) == false) {
|
||||
perror("ck_hs_init");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static size_t
|
||||
set_count(void)
|
||||
{
|
||||
|
||||
return ck_hs_count(&hs);
|
||||
}
|
||||
|
||||
static bool
|
||||
set_reset(void)
|
||||
{
|
||||
|
||||
return ck_hs_reset(&hs);
|
||||
}
|
||||
|
||||
static void *
|
||||
test_apply(void *key, void *closure)
|
||||
{
|
||||
|
||||
(void)key;
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
static void
|
||||
run_test(const char *file, size_t r, unsigned int size, unsigned int mode)
|
||||
{
|
||||
FILE *fp;
|
||||
char buffer[512];
|
||||
size_t i, j;
|
||||
unsigned int d = 0;
|
||||
uint64_t s, e, a, gp, agp;
|
||||
struct ck_hs_stat st;
|
||||
char **t;
|
||||
|
||||
keys = malloc(sizeof(char *) * keys_capacity);
|
||||
assert(keys != NULL);
|
||||
|
||||
fp = fopen(file, "r");
|
||||
assert(fp != NULL);
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
buffer[strlen(buffer) - 1] = '\0';
|
||||
keys[keys_length++] = strdup(buffer);
|
||||
assert(keys[keys_length - 1] != NULL);
|
||||
|
||||
if (keys_length == keys_capacity) {
|
||||
t = realloc(keys, sizeof(char *) * (keys_capacity *= 2));
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
}
|
||||
}
|
||||
|
||||
t = realloc(keys, sizeof(char *) * keys_length);
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
|
||||
set_init(size, mode);
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
unsigned long h = CK_HS_HASH(&hs, hs_hash, keys[i]);
|
||||
|
||||
if (ck_hs_get(&hs, h, keys[i]) == false) {
|
||||
if (ck_hs_put(&hs, h, keys[i]) == false)
|
||||
ck_error("ERROR: Failed get to put workload.\n");
|
||||
} else {
|
||||
d++;
|
||||
}
|
||||
}
|
||||
ck_hs_stat(&hs, &st);
|
||||
|
||||
fprintf(stderr, "# %zu entries stored, %u duplicates, %u probe.\n",
|
||||
set_count(), d, st.probe_maximum);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
if (set_reset() == false)
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
unsigned long h = CK_HS_HASH(&hs, hs_hash, keys[i]);
|
||||
|
||||
if (ck_hs_get(&hs, h, keys[i]) == false &&
|
||||
ck_hs_put(&hs, h, keys[i]) == false) {
|
||||
ck_error("ERROR: Failed get to put workload.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
gp = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
if (set_reset() == false)
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
unsigned long h = CK_HS_HASH(&hs, hs_hash, keys[i]);
|
||||
|
||||
if (ck_hs_apply(&hs, h, keys[i], test_apply, (void *)keys[i]) == false)
|
||||
ck_error("ERROR: Failed in apply workload.\n");
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
agp = a / (r * keys_length);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
free(keys[i]);
|
||||
}
|
||||
|
||||
printf("Get to put: %" PRIu64 " ticks\n", gp);
|
||||
printf(" Apply: %" PRIu64 " ticks\n", agp);
|
||||
|
||||
free(keys);
|
||||
keys_length = 0;
|
||||
set_destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int r, size;
|
||||
|
||||
common_srand48((long int)time(NULL));
|
||||
if (argc < 2) {
|
||||
ck_error("Usage: ck_hs <dictionary> [<repetitions> <initial size>]\n");
|
||||
}
|
||||
|
||||
r = 16;
|
||||
if (argc >= 3)
|
||||
r = atoi(argv[2]);
|
||||
|
||||
size = 8;
|
||||
if (argc >= 4)
|
||||
size = atoi(argv[3]);
|
||||
|
||||
global_seed = common_lrand48();
|
||||
run_test(argv[1], r, size, 0);
|
||||
|
||||
printf("\n==============================================\n"
|
||||
"Delete mode\n"
|
||||
"==============================================\n");
|
||||
run_test(argv[1], r, size, CK_HS_MODE_DELETE);
|
||||
return 0;
|
||||
}
|
||||
|
602
regressions/ck_hs/benchmark/parallel_bytestring.c
Normal file
602
regressions/ck_hs/benchmark/parallel_bytestring.c
Normal file
|
@ -0,0 +1,602 @@
|
|||
/*
|
||||
* Copyright 2012 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 copyrighs
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyrighs
|
||||
* 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 "../../common.h"
|
||||
#include <ck_hs.h>
|
||||
#include "../../../src/ck_ht_hash.h"
|
||||
#include <assert.h>
|
||||
#include <ck_epoch.h>
|
||||
#include <ck_malloc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <ck_spinlock.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static ck_hs_t hs CK_CC_CACHELINE;
|
||||
static char **keys;
|
||||
static size_t keys_length = 0;
|
||||
static size_t keys_capacity = 128;
|
||||
static ck_epoch_t epoch_hs;
|
||||
static ck_epoch_record_t epoch_wr;
|
||||
static int n_threads;
|
||||
static bool next_stage;
|
||||
|
||||
enum state {
|
||||
HS_STATE_STOP = 0,
|
||||
HS_STATE_GET,
|
||||
HS_STATE_STRICT_REPLACEMENT,
|
||||
HS_STATE_DELETION,
|
||||
HS_STATE_REPLACEMENT,
|
||||
HS_STATE_COUNT
|
||||
};
|
||||
|
||||
static ck_spinlock_t mtx = CK_SPINLOCK_INITIALIZER;
|
||||
static struct affinity affinerator = AFFINITY_INITIALIZER;
|
||||
static uint64_t accumulator[HS_STATE_COUNT];
|
||||
static int barrier[HS_STATE_COUNT];
|
||||
static int state;
|
||||
|
||||
struct hs_epoch {
|
||||
ck_epoch_entry_t epoch_entry;
|
||||
};
|
||||
|
||||
COMMON_ALARM_DECLARE_GLOBAL(hs_alarm, alarm_event, next_stage)
|
||||
|
||||
static void
|
||||
alarm_handler(int s)
|
||||
{
|
||||
|
||||
(void)s;
|
||||
next_stage = true;
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
hs_hash(const void *object, unsigned long seed)
|
||||
{
|
||||
const char *c = object;
|
||||
unsigned long h;
|
||||
|
||||
h = (unsigned long)MurmurHash64A(c, strlen(c), seed);
|
||||
return h;
|
||||
}
|
||||
|
||||
static bool
|
||||
hs_compare(const void *previous, const void *compare)
|
||||
{
|
||||
|
||||
return strcmp(previous, compare) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hs_destroy(ck_epoch_entry_t *e)
|
||||
{
|
||||
|
||||
free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
hs_malloc(size_t r)
|
||||
{
|
||||
ck_epoch_entry_t *b;
|
||||
|
||||
b = malloc(sizeof(*b) + r);
|
||||
return b + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
hs_free(void *p, size_t b, bool r)
|
||||
{
|
||||
struct hs_epoch *e = p;
|
||||
|
||||
(void)b;
|
||||
|
||||
if (r == true) {
|
||||
/* Destruction requires safe memory reclamation. */
|
||||
ck_epoch_call(&epoch_wr, &(--e)->epoch_entry, hs_destroy);
|
||||
} else {
|
||||
free(--e);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ck_malloc my_allocator = {
|
||||
.malloc = hs_malloc,
|
||||
.free = hs_free
|
||||
};
|
||||
|
||||
static void
|
||||
set_init(void)
|
||||
{
|
||||
unsigned int mode = CK_HS_MODE_OBJECT | CK_HS_MODE_SPMC;
|
||||
|
||||
#ifdef HS_DELETE
|
||||
mode |= CK_HS_MODE_DELETE;
|
||||
#endif
|
||||
|
||||
ck_epoch_init(&epoch_hs);
|
||||
ck_epoch_register(&epoch_hs, &epoch_wr);
|
||||
common_srand48((long int)time(NULL));
|
||||
if (ck_hs_init(&hs, mode, hs_hash, hs_compare, &my_allocator, 65536, common_lrand48()) == false) {
|
||||
perror("ck_hs_init");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static bool
|
||||
set_remove(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
return (bool)ck_hs_remove(&hs, h, value);
|
||||
}
|
||||
|
||||
static bool
|
||||
set_replace(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
void *previous;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
return ck_hs_set(&hs, h, value, &previous);
|
||||
}
|
||||
|
||||
static bool
|
||||
set_swap(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
void *previous;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
return ck_hs_fas(&hs, h, value, &previous);
|
||||
}
|
||||
|
||||
static void *
|
||||
set_get(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
void *v;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
v = ck_hs_get(&hs, h, value);
|
||||
return v;
|
||||
}
|
||||
|
||||
static bool
|
||||
set_insert(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
return ck_hs_put(&hs, h, value);
|
||||
}
|
||||
|
||||
static size_t
|
||||
set_count(void)
|
||||
{
|
||||
|
||||
return ck_hs_count(&hs);
|
||||
}
|
||||
|
||||
static bool
|
||||
set_reset(void)
|
||||
{
|
||||
|
||||
return ck_hs_reset(&hs);
|
||||
}
|
||||
|
||||
static void *
|
||||
reader(void *unused)
|
||||
{
|
||||
size_t i;
|
||||
ck_epoch_record_t epoch_record;
|
||||
int state_previous = HS_STATE_STOP;
|
||||
int n_state = 0;
|
||||
uint64_t s, j, a;
|
||||
|
||||
(void)unused;
|
||||
if (aff_iterate(&affinerator) != 0)
|
||||
perror("WARNING: Failed to affine thread");
|
||||
|
||||
s = j = a = 0;
|
||||
ck_epoch_register(&epoch_hs, &epoch_record);
|
||||
for (;;) {
|
||||
j++;
|
||||
ck_epoch_begin(&epoch_record, NULL);
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
char *r;
|
||||
|
||||
r = set_get(keys[i]);
|
||||
if (r == NULL) {
|
||||
if (n_state == HS_STATE_STRICT_REPLACEMENT) {
|
||||
ck_error("ERROR: Did not find during replacement: %s\n", keys[i]);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(r, keys[i]) == 0)
|
||||
continue;
|
||||
|
||||
ck_error("ERROR: Found invalid value: [%s] but expected [%s]\n", (char *)r, keys[i]);
|
||||
}
|
||||
a += rdtsc() - s;
|
||||
ck_epoch_end(&epoch_record, NULL);
|
||||
|
||||
n_state = ck_pr_load_int(&state);
|
||||
if (n_state != state_previous) {
|
||||
ck_spinlock_lock(&mtx);
|
||||
accumulator[state_previous] += a / (j * keys_length);
|
||||
ck_spinlock_unlock(&mtx);
|
||||
|
||||
ck_pr_inc_int(&barrier[state_previous]);
|
||||
while (ck_pr_load_int(&barrier[state_previous]) != n_threads + 1)
|
||||
ck_pr_stall();
|
||||
|
||||
state_previous = n_state;
|
||||
s = j = a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
acc(size_t i)
|
||||
{
|
||||
uint64_t r;
|
||||
|
||||
ck_spinlock_lock(&mtx);
|
||||
r = accumulator[i];
|
||||
ck_spinlock_unlock(&mtx);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
FILE *fp;
|
||||
char buffer[512];
|
||||
size_t i, j, r;
|
||||
unsigned int d = 0;
|
||||
uint64_t s, e, a, repeated;
|
||||
char **t;
|
||||
pthread_t *readers;
|
||||
double p_r, p_d;
|
||||
|
||||
COMMON_ALARM_DECLARE_LOCAL(hs_alarm, alarm_event)
|
||||
|
||||
r = 20;
|
||||
s = 8;
|
||||
p_d = 0.5;
|
||||
p_r = 0.5;
|
||||
n_threads = CORES - 1;
|
||||
|
||||
if (argc < 2) {
|
||||
ck_error("Usage: parallel <dictionary> [<interval length> <initial size> <readers>\n"
|
||||
" <probability of replacement> <probability of deletion> <epoch threshold>]\n");
|
||||
}
|
||||
|
||||
if (argc >= 3)
|
||||
r = atoi(argv[2]);
|
||||
|
||||
if (argc >= 4)
|
||||
s = (uint64_t)atoi(argv[3]);
|
||||
|
||||
if (argc >= 5) {
|
||||
n_threads = atoi(argv[4]);
|
||||
if (n_threads < 1) {
|
||||
ck_error("ERROR: Number of readers must be >= 1.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (argc >= 6) {
|
||||
p_r = atof(argv[5]) / 100.00;
|
||||
if (p_r < 0) {
|
||||
ck_error("ERROR: Probability of replacement must be >= 0 and <= 100.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (argc >= 7) {
|
||||
p_d = atof(argv[6]) / 100.00;
|
||||
if (p_d < 0) {
|
||||
ck_error("ERROR: Probability of deletion must be >= 0 and <= 100.\n");
|
||||
}
|
||||
}
|
||||
|
||||
COMMON_ALARM_INIT(hs_alarm, alarm_event, r)
|
||||
|
||||
affinerator.delta = 1;
|
||||
readers = malloc(sizeof(pthread_t) * n_threads);
|
||||
assert(readers != NULL);
|
||||
|
||||
keys = malloc(sizeof(char *) * keys_capacity);
|
||||
assert(keys != NULL);
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
assert(fp != NULL);
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
buffer[strlen(buffer) - 1] = '\0';
|
||||
keys[keys_length++] = strdup(buffer);
|
||||
assert(keys[keys_length - 1] != NULL);
|
||||
|
||||
if (keys_length == keys_capacity) {
|
||||
t = realloc(keys, sizeof(char *) * (keys_capacity *= 2));
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
}
|
||||
}
|
||||
|
||||
t = realloc(keys, sizeof(char *) * keys_length);
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
|
||||
set_init();
|
||||
|
||||
for (i = 0; i < (size_t)n_threads; i++) {
|
||||
if (pthread_create(&readers[i], NULL, reader, NULL) != 0) {
|
||||
ck_error("ERROR: Failed to create thread %zu.\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += set_insert(keys[i]) == false;
|
||||
|
||||
fprintf(stderr, " [S] %d readers, 1 writer.\n", n_threads);
|
||||
fprintf(stderr, " [S] %zu entries stored and %u duplicates.\n\n",
|
||||
set_count(), d);
|
||||
|
||||
fprintf(stderr, " ,- BASIC TEST\n");
|
||||
fprintf(stderr, " | Executing SMR test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
if (set_reset() == false) {
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
}
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += set_insert(keys[i]) == false;
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
fprintf(stderr, " | Executing replacement test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_replace(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
fprintf(stderr, " | Executing get test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
if (set_get(keys[i]) == NULL) {
|
||||
ck_error("ERROR: Unexpected NULL value.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
a = 0;
|
||||
fprintf(stderr, " | Executing removal test...");
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_remove(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_insert(keys[i]);
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
fprintf(stderr, " | Executing negative look-up test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
set_get("\x50\x03\x04\x05\x06\x10");
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
ck_epoch_record_t epoch_temporary = epoch_wr;
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
|
||||
fprintf(stderr, " '- Summary: %u pending, %u peak, %lu reclamations -> "
|
||||
"%u pending, %u peak, %lu reclamations\n\n",
|
||||
epoch_temporary.n_pending, epoch_temporary.n_peak, epoch_temporary.n_dispatch,
|
||||
epoch_wr.n_pending, epoch_wr.n_peak, epoch_wr.n_dispatch);
|
||||
|
||||
fprintf(stderr, " ,- READER CONCURRENCY\n");
|
||||
fprintf(stderr, " | Executing reader test...");
|
||||
|
||||
ck_pr_store_int(&state, HS_STATE_GET);
|
||||
while (ck_pr_load_int(&barrier[HS_STATE_STOP]) != n_threads)
|
||||
ck_pr_stall();
|
||||
ck_pr_inc_int(&barrier[HS_STATE_STOP]);
|
||||
common_sleep(r);
|
||||
ck_pr_store_int(&state, HS_STATE_STRICT_REPLACEMENT);
|
||||
while (ck_pr_load_int(&barrier[HS_STATE_GET]) != n_threads)
|
||||
ck_pr_stall();
|
||||
|
||||
fprintf(stderr, "done (reader = %" PRIu64 " ticks)\n",
|
||||
acc(HS_STATE_GET) / n_threads);
|
||||
|
||||
fprintf(stderr, " | Executing strict replacement test...");
|
||||
|
||||
a = repeated = 0;
|
||||
common_alarm(alarm_handler, &alarm_event, r);
|
||||
|
||||
ck_pr_inc_int(&barrier[HS_STATE_GET]);
|
||||
for (;;) {
|
||||
repeated++;
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
if (i & 1) {
|
||||
set_replace(keys[i]);
|
||||
} else {
|
||||
set_swap(keys[i]);
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
if (next_stage == true) {
|
||||
next_stage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_store_int(&state, HS_STATE_DELETION);
|
||||
while (ck_pr_load_int(&barrier[HS_STATE_STRICT_REPLACEMENT]) != n_threads)
|
||||
ck_pr_stall();
|
||||
set_reset();
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
fprintf(stderr, "done (writer = %" PRIu64 " ticks, reader = %" PRIu64 " ticks)\n",
|
||||
a / (repeated * keys_length), acc(HS_STATE_STRICT_REPLACEMENT) / n_threads);
|
||||
|
||||
common_alarm(alarm_handler, &alarm_event, r);
|
||||
|
||||
fprintf(stderr, " | Executing deletion test (%.2f)...", p_d * 100);
|
||||
a = repeated = 0;
|
||||
ck_pr_inc_int(&barrier[HS_STATE_STRICT_REPLACEMENT]);
|
||||
for (;;) {
|
||||
double delete;
|
||||
|
||||
repeated++;
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
set_insert(keys[i]);
|
||||
if (p_d != 0.0) {
|
||||
delete = common_drand48();
|
||||
if (delete <= p_d)
|
||||
set_remove(keys[i]);
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
if (next_stage == true) {
|
||||
next_stage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ck_pr_store_int(&state, HS_STATE_REPLACEMENT);
|
||||
while (ck_pr_load_int(&barrier[HS_STATE_DELETION]) != n_threads)
|
||||
ck_pr_stall();
|
||||
|
||||
set_reset();
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
fprintf(stderr, "done (writer = %" PRIu64 " ticks, reader = %" PRIu64 " ticks)\n",
|
||||
a / (repeated * keys_length), acc(HS_STATE_DELETION) / n_threads);
|
||||
|
||||
common_alarm(alarm_handler, &alarm_event, r);
|
||||
|
||||
fprintf(stderr, " | Executing replacement test (%.2f)...", p_r * 100);
|
||||
a = repeated = 0;
|
||||
ck_pr_inc_int(&barrier[HS_STATE_DELETION]);
|
||||
for (;;) {
|
||||
double delete, replace;
|
||||
|
||||
repeated++;
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
set_insert(keys[i]);
|
||||
if (p_d != 0.0) {
|
||||
delete = common_drand48();
|
||||
if (delete <= p_d)
|
||||
set_remove(keys[i]);
|
||||
} else {
|
||||
delete = 0.0;
|
||||
}
|
||||
|
||||
if (p_r != 0.0) {
|
||||
replace = common_drand48();
|
||||
if (replace <= p_r) {
|
||||
if ((i & 1) || (delete <= p_d)) {
|
||||
set_replace(keys[i]);
|
||||
} else {
|
||||
set_swap(keys[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
if (next_stage == true) {
|
||||
next_stage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ck_pr_store_int(&state, HS_STATE_STOP);
|
||||
while (ck_pr_load_int(&barrier[HS_STATE_REPLACEMENT]) != n_threads)
|
||||
ck_pr_stall();
|
||||
set_reset();
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
fprintf(stderr, "done (writer = %" PRIu64 " ticks, reader = %" PRIu64 " ticks)\n",
|
||||
a / (repeated * keys_length), acc(HS_STATE_REPLACEMENT) / n_threads);
|
||||
|
||||
ck_pr_inc_int(&barrier[HS_STATE_REPLACEMENT]);
|
||||
epoch_temporary = epoch_wr;
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
|
||||
fprintf(stderr, " '- Summary: %u pending, %u peak, %lu reclamations -> "
|
||||
"%u pending, %u peak, %lu reclamations\n\n",
|
||||
epoch_temporary.n_pending, epoch_temporary.n_peak, epoch_temporary.n_dispatch,
|
||||
epoch_wr.n_pending, epoch_wr.n_peak, epoch_wr.n_dispatch);
|
||||
return 0;
|
||||
}
|
||||
|
517
regressions/ck_hs/benchmark/serial.c
Normal file
517
regressions/ck_hs/benchmark/serial.c
Normal file
|
@ -0,0 +1,517 @@
|
|||
/*
|
||||
* Copyright 2012 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 copyrighs
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyrighs
|
||||
* 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 <ck_hs.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ck_malloc.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#include "../../../src/ck_ht_hash.h"
|
||||
|
||||
static ck_hs_t hs;
|
||||
static char **keys;
|
||||
static size_t keys_length = 0;
|
||||
static size_t keys_capacity = 128;
|
||||
static unsigned long global_seed;
|
||||
|
||||
static void *
|
||||
hs_malloc(size_t r)
|
||||
{
|
||||
|
||||
return malloc(r);
|
||||
}
|
||||
|
||||
static void
|
||||
hs_free(void *p, size_t b, bool r)
|
||||
{
|
||||
|
||||
(void)b;
|
||||
(void)r;
|
||||
|
||||
free(p);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ck_malloc my_allocator = {
|
||||
.malloc = hs_malloc,
|
||||
.free = hs_free
|
||||
};
|
||||
|
||||
static unsigned long
|
||||
hs_hash(const void *object, unsigned long seed)
|
||||
{
|
||||
const char *c = object;
|
||||
unsigned long h;
|
||||
|
||||
h = (unsigned long)MurmurHash64A(c, strlen(c), seed);
|
||||
return h;
|
||||
}
|
||||
|
||||
static bool
|
||||
hs_compare(const void *previous, const void *compare)
|
||||
{
|
||||
|
||||
return strcmp(previous, compare) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_destroy(void)
|
||||
{
|
||||
|
||||
ck_hs_destroy(&hs);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
set_init(unsigned int size, unsigned int mode)
|
||||
{
|
||||
|
||||
if (ck_hs_init(&hs, CK_HS_MODE_OBJECT | CK_HS_MODE_SPMC | mode, hs_hash, hs_compare,
|
||||
&my_allocator, size, global_seed) == false) {
|
||||
perror("ck_hs_init");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static bool
|
||||
set_remove(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
return ck_hs_remove(&hs, h, value) != NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
set_swap(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
void *previous;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
return ck_hs_fas(&hs, h, value, &previous);
|
||||
}
|
||||
|
||||
static bool
|
||||
set_replace(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
void *previous;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
ck_hs_set(&hs, h, value, &previous);
|
||||
return previous == value;
|
||||
}
|
||||
|
||||
static void *
|
||||
set_get(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
void *v;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
v = ck_hs_get(&hs, h, value);
|
||||
return v;
|
||||
}
|
||||
|
||||
static bool
|
||||
set_insert(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
return ck_hs_put(&hs, h, value);
|
||||
}
|
||||
|
||||
static bool
|
||||
set_insert_unique(const char *value)
|
||||
{
|
||||
unsigned long h;
|
||||
|
||||
h = CK_HS_HASH(&hs, hs_hash, value);
|
||||
return ck_hs_put_unique(&hs, h, value);
|
||||
}
|
||||
|
||||
static size_t
|
||||
set_count(void)
|
||||
{
|
||||
|
||||
return ck_hs_count(&hs);
|
||||
}
|
||||
|
||||
static bool
|
||||
set_reset(void)
|
||||
{
|
||||
|
||||
return ck_hs_reset(&hs);
|
||||
}
|
||||
|
||||
static void
|
||||
set_gc(void)
|
||||
{
|
||||
|
||||
ck_hs_gc(&hs, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
set_rebuild(void)
|
||||
{
|
||||
|
||||
ck_hs_rebuild(&hs);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
keys_shuffle(char **k)
|
||||
{
|
||||
size_t i, j;
|
||||
char *t;
|
||||
|
||||
for (i = keys_length; i > 1; i--) {
|
||||
j = rand() % (i - 1);
|
||||
|
||||
if (j != i - 1) {
|
||||
t = k[i - 1];
|
||||
k[i - 1] = k[j];
|
||||
k[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
run_test(const char *file, size_t r, unsigned int size, unsigned int mode)
|
||||
{
|
||||
FILE *fp;
|
||||
char buffer[512];
|
||||
size_t i, j;
|
||||
unsigned int d = 0;
|
||||
uint64_t s, e, a, ri, si, ai, sr, rg, sg, ag, sd, ng, ss, sts, su, sgc, sb;
|
||||
struct ck_hs_stat st;
|
||||
char **t;
|
||||
|
||||
keys = malloc(sizeof(char *) * keys_capacity);
|
||||
assert(keys != NULL);
|
||||
|
||||
fp = fopen(file, "r");
|
||||
assert(fp != NULL);
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
buffer[strlen(buffer) - 1] = '\0';
|
||||
keys[keys_length++] = strdup(buffer);
|
||||
assert(keys[keys_length - 1] != NULL);
|
||||
|
||||
if (keys_length == keys_capacity) {
|
||||
t = realloc(keys, sizeof(char *) * (keys_capacity *= 2));
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
}
|
||||
}
|
||||
|
||||
t = realloc(keys, sizeof(char *) * keys_length);
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
|
||||
set_init(size, mode);
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += set_insert(keys[i]) == false;
|
||||
ck_hs_stat(&hs, &st);
|
||||
|
||||
fprintf(stderr, "# %zu entries stored, %u duplicates, %u probe.\n",
|
||||
set_count(), d, st.probe_maximum);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
if (set_reset() == false) {
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
}
|
||||
|
||||
s = rdtsc();
|
||||
for (i = keys_length; i > 0; i--)
|
||||
d += set_insert(keys[i - 1]) == false;
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
ri = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
if (set_reset() == false) {
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
}
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += set_insert(keys[i]) == false;
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
si = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
keys_shuffle(keys);
|
||||
|
||||
if (set_reset() == false) {
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
}
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += set_insert(keys[i]) == false;
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
ai = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_swap(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
ss = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_replace(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
sr = a / (r * keys_length);
|
||||
|
||||
set_reset();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_insert(keys[i]);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = keys_length; i > 0; i--) {
|
||||
if (set_get(keys[i - 1]) == NULL) {
|
||||
ck_error("ERROR: Unexpected NULL value.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
rg = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
if (set_get(keys[i]) == NULL) {
|
||||
ck_error("ERROR: Unexpected NULL value.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
sg = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
keys_shuffle(keys);
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
if (set_get(keys[i]) == NULL) {
|
||||
ck_error("ERROR: Unexpected NULL value.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
ag = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_remove(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_insert(keys[i]);
|
||||
}
|
||||
sd = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
set_get("\x50\x03\x04\x05\x06\x10");
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
ng = a / (r * keys_length);
|
||||
|
||||
set_reset();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_insert(keys[i]);
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_remove(keys[i]);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_insert(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_remove(keys[i]);
|
||||
}
|
||||
sts = a / (r * keys_length);
|
||||
|
||||
set_reset();
|
||||
|
||||
/* Prune duplicates. */
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
if (set_insert(keys[i]) == true)
|
||||
continue;
|
||||
|
||||
free(keys[i]);
|
||||
keys[i] = keys[--keys_length];
|
||||
}
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_remove(keys[i]);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_insert_unique(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_remove(keys[i]);
|
||||
}
|
||||
su = a / (r * keys_length);
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
set_insert_unique(keys[i]);
|
||||
|
||||
for (i = 0; i < keys_length / 2; i++)
|
||||
set_remove(keys[i]);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
set_gc();
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
sgc = a / r;
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
set_rebuild();
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
sb = a / r;
|
||||
|
||||
printf("%zu "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 "\n",
|
||||
keys_length, ri, si, ai, ss, sr, rg, sg, ag, sd, ng, sts, su, sgc, sb);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
free(keys[i]);
|
||||
}
|
||||
|
||||
free(keys);
|
||||
keys_length = 0;
|
||||
set_destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int r, size;
|
||||
|
||||
common_srand48((long int)time(NULL));
|
||||
if (argc < 2) {
|
||||
ck_error("Usage: ck_hs <dictionary> [<repetitions> <initial size>]\n");
|
||||
}
|
||||
|
||||
r = 16;
|
||||
if (argc >= 3)
|
||||
r = atoi(argv[2]);
|
||||
|
||||
size = 8;
|
||||
if (argc >= 4)
|
||||
size = atoi(argv[3]);
|
||||
|
||||
global_seed = common_lrand48();
|
||||
run_test(argv[1], r, size, 0);
|
||||
run_test(argv[1], r, size, CK_HS_MODE_DELETE);
|
||||
fprintf(stderr, "# reverse_insertion serial_insertion random_insertion serial_swap "
|
||||
"serial_replace reverse_get serial_get random_get serial_remove negative_get tombstone "
|
||||
"set_unique gc rebuild\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
17
regressions/ck_hs/validate/Makefile
Normal file
17
regressions/ck_hs/validate/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=serial
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
serial: serial.c ../../../include/ck_hs.h ../../../src/ck_hs.c
|
||||
$(CC) $(CFLAGS) -o serial serial.c ../../../src/ck_hs.c
|
||||
|
||||
check: all
|
||||
./serial
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o $(OBJECTS) *.dSYM *.exe
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=-D_GNU_SOURCE
|
315
regressions/ck_hs/validate/serial.c
Normal file
315
regressions/ck_hs/validate/serial.c
Normal file
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* Copyright 2012 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 copyrighs
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyrighs
|
||||
* 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 <ck_hs.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ck_malloc.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static void *
|
||||
hs_malloc(size_t r)
|
||||
{
|
||||
|
||||
return malloc(r);
|
||||
}
|
||||
|
||||
static void
|
||||
hs_free(void *p, size_t b, bool r)
|
||||
{
|
||||
|
||||
(void)b;
|
||||
(void)r;
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ck_malloc my_allocator = {
|
||||
.malloc = hs_malloc,
|
||||
.free = hs_free
|
||||
};
|
||||
|
||||
const char *test[] = { "Samy", "Al", "Bahra", "dances", "in", "the", "wind.", "Once",
|
||||
"upon", "a", "time", "his", "gypsy", "ate", "one", "itsy",
|
||||
"bitsy", "spider.", "What", "goes", "up", "must",
|
||||
"come", "down.", "What", "is", "down", "stays",
|
||||
"down.", "A", "B", "C", "D", "E", "F", "G", "H",
|
||||
"I", "J", "K", "L", "M", "N", "O", "P", "Q" };
|
||||
|
||||
const char *negative = "negative";
|
||||
|
||||
/* Purposefully crappy hash function. */
|
||||
static unsigned long
|
||||
hs_hash(const void *object, unsigned long seed)
|
||||
{
|
||||
const char *c = object;
|
||||
unsigned long h;
|
||||
|
||||
(void)seed;
|
||||
h = c[0];
|
||||
return h;
|
||||
}
|
||||
|
||||
static bool
|
||||
hs_compare(const void *previous, const void *compare)
|
||||
{
|
||||
|
||||
return strcmp(previous, compare) == 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
test_ip(void *key, void *closure)
|
||||
{
|
||||
const char *a = key;
|
||||
const char *b = closure;
|
||||
|
||||
if (strcmp(a, b) != 0)
|
||||
ck_error("Mismatch: %s != %s\n", a, b);
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
static void *
|
||||
test_negative(void *key, void *closure)
|
||||
{
|
||||
|
||||
(void)closure;
|
||||
if (key != NULL)
|
||||
ck_error("ERROR: Apply callback expects NULL argument instead of [%s]\n", key);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
test_unique(void *key, void *closure)
|
||||
{
|
||||
|
||||
if (key != NULL)
|
||||
ck_error("ERROR: Apply callback expects NULL argument instead of [%s]\n", key);
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
static void *
|
||||
test_remove(void *key, void *closure)
|
||||
{
|
||||
|
||||
(void)key;
|
||||
(void)closure;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
run_test(unsigned int is, unsigned int ad)
|
||||
{
|
||||
ck_hs_t hs[16];
|
||||
const size_t size = sizeof(hs) / sizeof(*hs);
|
||||
size_t i, j;
|
||||
const char *blob = "#blobs";
|
||||
unsigned long h;
|
||||
|
||||
if (ck_hs_init(&hs[0], CK_HS_MODE_SPMC | CK_HS_MODE_OBJECT | ad, hs_hash, hs_compare, &my_allocator, is, 6602834) == false)
|
||||
ck_error("ck_hs_init\n");
|
||||
|
||||
for (j = 0; j < size; j++) {
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
h = test[i][0];
|
||||
if (ck_hs_get(&hs[j], h, test[i]) != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i & 1) {
|
||||
if (ck_hs_put_unique(&hs[j], h, test[i]) == false)
|
||||
ck_error("ERROR [%zu]: Failed to insert unique (%s)\n", j, test[i]);
|
||||
} else if (ck_hs_apply(&hs[j], h, test[i], test_unique, (void *)(uintptr_t)test[i]) == false) {
|
||||
ck_error("ERROR: Failed to apply for insertion.\n");
|
||||
}
|
||||
|
||||
if (i & 1) {
|
||||
if (ck_hs_remove(&hs[j], h, test[i]) == false)
|
||||
ck_error("ERROR [%zu]: Failed to remove unique (%s)\n", j, test[i]);
|
||||
} else if (ck_hs_apply(&hs[j], h, test[i], test_remove, NULL) == false) {
|
||||
ck_error("ERROR: Failed to remove apply.\n");
|
||||
}
|
||||
|
||||
if (ck_hs_apply(&hs[j], h, test[i], test_negative, (char *)(uintptr_t)test[i]) == false)
|
||||
ck_error("ERROR: Failed to apply.\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (ck_hs_gc(&hs[j], 0, 0) == false)
|
||||
ck_error("ERROR: Failed to GC empty set.\n");
|
||||
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
h = test[i][0];
|
||||
ck_hs_put(&hs[j], h, test[i]);
|
||||
if (ck_hs_put(&hs[j], h, test[i]) == true) {
|
||||
ck_error("ERROR [%u] [1]: put must fail on collision (%s).\n", is, test[i]);
|
||||
}
|
||||
if (ck_hs_get(&hs[j], h, test[i]) == NULL) {
|
||||
ck_error("ERROR [%u]: get must not fail after put\n", is);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test grow semantics. */
|
||||
ck_hs_grow(&hs[j], 128);
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
h = test[i][0];
|
||||
if (ck_hs_put(&hs[j], h, test[i]) == true) {
|
||||
ck_error("ERROR [%u] [2]: put must fail on collision.\n", is);
|
||||
}
|
||||
|
||||
if (ck_hs_get(&hs[j], h, test[i]) == NULL) {
|
||||
ck_error("ERROR [%u]: get must not fail\n", is);
|
||||
}
|
||||
}
|
||||
|
||||
h = blob[0];
|
||||
if (ck_hs_get(&hs[j], h, blob) == NULL) {
|
||||
if (j > 0)
|
||||
ck_error("ERROR [%u]: Blob must always exist after first.\n", is);
|
||||
|
||||
if (ck_hs_put(&hs[j], h, blob) == false) {
|
||||
ck_error("ERROR [%u]: A unique blob put failed.\n", is);
|
||||
}
|
||||
} else {
|
||||
if (ck_hs_put(&hs[j], h, blob) == true) {
|
||||
ck_error("ERROR [%u]: Duplicate blob put succeeded.\n", is);
|
||||
}
|
||||
}
|
||||
|
||||
/* Grow set and check get semantics. */
|
||||
ck_hs_grow(&hs[j], 512);
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
h = test[i][0];
|
||||
if (ck_hs_get(&hs[j], h, test[i]) == NULL) {
|
||||
ck_error("ERROR [%u]: get must not fail\n", is);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete and check negative membership. */
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
void *r;
|
||||
|
||||
h = test[i][0];
|
||||
if (ck_hs_get(&hs[j], h, test[i]) == NULL)
|
||||
continue;
|
||||
|
||||
if (r = ck_hs_remove(&hs[j], h, test[i]), r == NULL) {
|
||||
ck_error("ERROR [%u]: remove must not fail\n", is);
|
||||
}
|
||||
|
||||
if (strcmp(r, test[i]) != 0) {
|
||||
ck_error("ERROR [%u]: Removed incorrect node (%s != %s)\n", (char *)r, test[i], is);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test replacement semantics. */
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
void *r;
|
||||
bool d;
|
||||
|
||||
h = test[i][0];
|
||||
d = ck_hs_get(&hs[j], h, test[i]) != NULL;
|
||||
if (ck_hs_set(&hs[j], h, test[i], &r) == false) {
|
||||
ck_error("ERROR [%u]: Failed to set\n", is);
|
||||
}
|
||||
|
||||
/* Expected replacement. */
|
||||
if (d == true && (r == NULL || strcmp(r, test[i]) != 0)) {
|
||||
ck_error("ERROR [%u]: Incorrect previous value: %s != %s\n",
|
||||
is, test[i], (char *)r);
|
||||
}
|
||||
|
||||
/* Replacement should succeed. */
|
||||
if (ck_hs_fas(&hs[j], h, test[i], &r) == false)
|
||||
ck_error("ERROR [%u]: ck_hs_fas must succeed.\n", is);
|
||||
|
||||
if (strcmp(r, test[i]) != 0) {
|
||||
ck_error("ERROR [%u]: Incorrect replaced value: %s != %s\n",
|
||||
is, test[i], (char *)r);
|
||||
}
|
||||
|
||||
if (ck_hs_fas(&hs[j], h, negative, &r) == true)
|
||||
ck_error("ERROR [%u]: Replacement of negative should fail.\n", is);
|
||||
|
||||
if (ck_hs_set(&hs[j], h, test[i], &r) == false) {
|
||||
ck_error("ERROR [%u]: Failed to set [1]\n", is);
|
||||
}
|
||||
|
||||
if (strcmp(r, test[i]) != 0) {
|
||||
ck_error("ERROR [%u]: Invalid &hs[j]: %s != %s\n", is, test[i], (char *)r);
|
||||
}
|
||||
|
||||
/* Attempt in-place mutation. */
|
||||
if (ck_hs_apply(&hs[j], h, test[i], test_ip, (void *)(uintptr_t)test[i]) == false)
|
||||
ck_error("ERROR [%u]: Failed to apply: %s != %s\n", is, (char *)r, test[i]);
|
||||
|
||||
d = ck_hs_get(&hs[j], h, test[i]) != NULL;
|
||||
if (d == false)
|
||||
ck_error("ERROR [%u]: Expected [%s] to exist.\n", is, test[i]);
|
||||
}
|
||||
|
||||
if (j == size - 1)
|
||||
break;
|
||||
|
||||
if (ck_hs_move(&hs[j + 1], &hs[j], hs_hash, hs_compare, &my_allocator) == false)
|
||||
ck_error("Failed to move hash table");
|
||||
|
||||
if (j & 1) {
|
||||
ck_hs_gc(&hs[j + 1], 0, 0);
|
||||
} else {
|
||||
ck_hs_gc(&hs[j + 1], 26, 26);
|
||||
}
|
||||
|
||||
if (ck_hs_rebuild(&hs[j + 1]) == false)
|
||||
ck_error("Failed to rebuild");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
unsigned int k;
|
||||
|
||||
for (k = 16; k <= 64; k <<= 1) {
|
||||
run_test(k, 0);
|
||||
run_test(k, CK_HS_MODE_DELETE);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
27
regressions/ck_ht/benchmark/Makefile
Normal file
27
regressions/ck_ht/benchmark/Makefile
Normal file
|
@ -0,0 +1,27 @@
|
|||
.PHONY: clean distribution
|
||||
|
||||
OBJECTS=serial serial.delete parallel_bytestring parallel_bytestring.delete parallel_direct
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
serial: serial.c ../../../include/ck_ht.h ../../../src/ck_ht.c
|
||||
$(CC) $(CFLAGS) -o serial serial.c ../../../src/ck_ht.c
|
||||
|
||||
serial.delete: serial.c ../../../include/ck_ht.h ../../../src/ck_ht.c
|
||||
$(CC) $(CFLAGS) -DHT_DELETE -o serial.delete serial.c ../../../src/ck_ht.c
|
||||
|
||||
parallel_bytestring.delete: parallel_bytestring.c ../../../include/ck_ht.h ../../../src/ck_ht.c ../../../src/ck_epoch.c
|
||||
$(CC) $(PTHREAD_CFLAGS) $(CFLAGS) -DHT_DELETE -o parallel_bytestring.delete parallel_bytestring.c ../../../src/ck_ht.c ../../../src/ck_epoch.c
|
||||
|
||||
parallel_bytestring: parallel_bytestring.c ../../../include/ck_ht.h ../../../src/ck_ht.c ../../../src/ck_epoch.c
|
||||
$(CC) $(PTHREAD_CFLAGS) $(CFLAGS) -o parallel_bytestring parallel_bytestring.c ../../../src/ck_ht.c ../../../src/ck_epoch.c
|
||||
|
||||
parallel_direct: parallel_direct.c ../../../include/ck_ht.h ../../../src/ck_ht.c ../../../src/ck_epoch.c
|
||||
$(CC) $(PTHREAD_CFLAGS) $(CFLAGS) -o parallel_direct parallel_direct.c ../../../src/ck_ht.c ../../../src/ck_epoch.c
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o $(OBJECTS) *.dSYM *.exe
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=-D_GNU_SOURCE
|
||||
|
559
regressions/ck_ht/benchmark/parallel_bytestring.c
Normal file
559
regressions/ck_ht/benchmark/parallel_bytestring.c
Normal file
|
@ -0,0 +1,559 @@
|
|||
/*
|
||||
* Copyright 2012-2015 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 <ck_ht.h>
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <ck_epoch.h>
|
||||
#include <ck_malloc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <ck_spinlock.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static ck_ht_t ht CK_CC_CACHELINE;
|
||||
static char **keys;
|
||||
static size_t keys_length = 0;
|
||||
static size_t keys_capacity = 128;
|
||||
static ck_epoch_t epoch_ht;
|
||||
static ck_epoch_record_t epoch_wr;
|
||||
static int n_threads;
|
||||
static bool next_stage;
|
||||
|
||||
enum state {
|
||||
HT_STATE_STOP = 0,
|
||||
HT_STATE_GET,
|
||||
HT_STATE_STRICT_REPLACEMENT,
|
||||
HT_STATE_DELETION,
|
||||
HT_STATE_REPLACEMENT,
|
||||
HT_STATE_COUNT
|
||||
};
|
||||
|
||||
static struct affinity affinerator = AFFINITY_INITIALIZER;
|
||||
static uint64_t accumulator[HT_STATE_COUNT];
|
||||
static ck_spinlock_t accumulator_mutex = CK_SPINLOCK_INITIALIZER;
|
||||
static int barrier[HT_STATE_COUNT];
|
||||
static int state;
|
||||
|
||||
struct ht_epoch {
|
||||
ck_epoch_entry_t epoch_entry;
|
||||
};
|
||||
|
||||
COMMON_ALARM_DECLARE_GLOBAL(ht_alarm, alarm_event, next_stage)
|
||||
|
||||
static void
|
||||
alarm_handler(int s)
|
||||
{
|
||||
|
||||
(void)s;
|
||||
next_stage = true;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ht_destroy(ck_epoch_entry_t *e)
|
||||
{
|
||||
|
||||
free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
ht_malloc(size_t r)
|
||||
{
|
||||
ck_epoch_entry_t *b;
|
||||
|
||||
b = malloc(sizeof(*b) + r);
|
||||
return b + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ht_free(void *p, size_t b, bool r)
|
||||
{
|
||||
struct ht_epoch *e = p;
|
||||
|
||||
(void)b;
|
||||
|
||||
if (r == true) {
|
||||
/* Destruction requires safe memory reclamation. */
|
||||
ck_epoch_call(&epoch_wr, &(--e)->epoch_entry, ht_destroy);
|
||||
} else {
|
||||
free(--e);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ck_malloc my_allocator = {
|
||||
.malloc = ht_malloc,
|
||||
.free = ht_free
|
||||
};
|
||||
|
||||
static void
|
||||
table_init(void)
|
||||
{
|
||||
unsigned int mode = CK_HT_MODE_BYTESTRING;
|
||||
|
||||
#ifdef HT_DELETE
|
||||
mode |= CK_HT_WORKLOAD_DELETE;
|
||||
#endif
|
||||
|
||||
ck_epoch_init(&epoch_ht);
|
||||
ck_epoch_register(&epoch_ht, &epoch_wr);
|
||||
common_srand48((long int)time(NULL));
|
||||
if (ck_ht_init(&ht, mode, NULL, &my_allocator, 8, common_lrand48()) == false) {
|
||||
perror("ck_ht_init");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static bool
|
||||
table_remove(const char *value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
size_t l = strlen(value);
|
||||
|
||||
ck_ht_hash(&h, &ht, value, l);
|
||||
ck_ht_entry_key_set(&entry, value, l);
|
||||
return ck_ht_remove_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
static bool
|
||||
table_replace(const char *value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
size_t l = strlen(value);
|
||||
|
||||
ck_ht_hash(&h, &ht, value, l);
|
||||
ck_ht_entry_set(&entry, h, value, l, "REPLACED");
|
||||
return ck_ht_set_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
static void *
|
||||
table_get(const char *value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
size_t l = strlen(value);
|
||||
|
||||
ck_ht_hash(&h, &ht, value, l);
|
||||
ck_ht_entry_key_set(&entry, value, l);
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == true)
|
||||
return ck_ht_entry_value(&entry);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
table_insert(const char *value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
size_t l = strlen(value);
|
||||
|
||||
ck_ht_hash(&h, &ht, value, l);
|
||||
ck_ht_entry_set(&entry, h, value, l, value);
|
||||
return ck_ht_put_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
static size_t
|
||||
table_count(void)
|
||||
{
|
||||
|
||||
return ck_ht_count(&ht);
|
||||
}
|
||||
|
||||
static bool
|
||||
table_reset(void)
|
||||
{
|
||||
|
||||
return ck_ht_reset_spmc(&ht);
|
||||
}
|
||||
|
||||
static void *
|
||||
reader(void *unused)
|
||||
{
|
||||
size_t i;
|
||||
ck_epoch_record_t epoch_record;
|
||||
int state_previous = HT_STATE_STOP;
|
||||
int n_state;
|
||||
uint64_t s, j, a;
|
||||
|
||||
(void)unused;
|
||||
if (aff_iterate(&affinerator) != 0)
|
||||
perror("WARNING: Failed to affine thread");
|
||||
|
||||
s = j = a = 0;
|
||||
ck_epoch_register(&epoch_ht, &epoch_record);
|
||||
for (;;) {
|
||||
j++;
|
||||
ck_epoch_begin(&epoch_record, NULL);
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
char *r;
|
||||
|
||||
r = table_get(keys[i]);
|
||||
if (r == NULL)
|
||||
continue;
|
||||
|
||||
if (strcmp(r, "REPLACED") == 0)
|
||||
continue;
|
||||
|
||||
if (strcmp(r, keys[i]) == 0)
|
||||
continue;
|
||||
|
||||
ck_error("ERROR: Found invalid value: [%s] but expected [%s]\n", r, keys[i]);
|
||||
}
|
||||
a += rdtsc() - s;
|
||||
ck_epoch_end(&epoch_record, NULL);
|
||||
|
||||
n_state = ck_pr_load_int(&state);
|
||||
if (n_state != state_previous) {
|
||||
ck_spinlock_lock(&accumulator_mutex);
|
||||
accumulator[state_previous] += a / (j * keys_length);
|
||||
ck_spinlock_unlock(&accumulator_mutex);
|
||||
ck_pr_inc_int(&barrier[state_previous]);
|
||||
while (ck_pr_load_int(&barrier[state_previous]) != n_threads + 1)
|
||||
ck_pr_stall();
|
||||
|
||||
state_previous = n_state;
|
||||
s = j = a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
FILE *fp;
|
||||
char buffer[512];
|
||||
size_t i, j, r;
|
||||
unsigned int d = 0;
|
||||
uint64_t s, e, a, repeated;
|
||||
char **t;
|
||||
pthread_t *readers;
|
||||
double p_r, p_d;
|
||||
|
||||
COMMON_ALARM_DECLARE_LOCAL(ht_alarm, alarm_event)
|
||||
|
||||
r = 20;
|
||||
s = 8;
|
||||
p_d = 0.5;
|
||||
p_r = 0.5;
|
||||
n_threads = CORES - 1;
|
||||
|
||||
if (argc < 2) {
|
||||
ck_error("Usage: parallel <dictionary> [<interval length> <initial size> <readers>\n"
|
||||
" <probability of replacement> <probability of deletion> <epoch threshold>]\n");
|
||||
}
|
||||
|
||||
if (argc >= 3)
|
||||
r = atoi(argv[2]);
|
||||
|
||||
if (argc >= 4)
|
||||
s = (uint64_t)atoi(argv[3]);
|
||||
|
||||
if (argc >= 5) {
|
||||
n_threads = atoi(argv[4]);
|
||||
if (n_threads < 1) {
|
||||
ck_error("ERROR: Number of readers must be >= 1.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (argc >= 6) {
|
||||
p_r = atof(argv[5]) / 100.00;
|
||||
if (p_r < 0) {
|
||||
ck_error("ERROR: Probability of replacement must be >= 0 and <= 100.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (argc >= 7) {
|
||||
p_d = atof(argv[6]) / 100.00;
|
||||
if (p_d < 0) {
|
||||
ck_error("ERROR: Probability of deletion must be >= 0 and <= 100.\n");
|
||||
}
|
||||
}
|
||||
|
||||
COMMON_ALARM_INIT(ht_alarm, alarm_event, r)
|
||||
|
||||
affinerator.delta = 1;
|
||||
readers = malloc(sizeof(pthread_t) * n_threads);
|
||||
assert(readers != NULL);
|
||||
|
||||
keys = malloc(sizeof(char *) * keys_capacity);
|
||||
assert(keys != NULL);
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
assert(fp != NULL);
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
buffer[strlen(buffer) - 1] = '\0';
|
||||
keys[keys_length++] = strdup(buffer);
|
||||
assert(keys[keys_length - 1] != NULL);
|
||||
|
||||
if (keys_length == keys_capacity) {
|
||||
t = realloc(keys, sizeof(char *) * (keys_capacity *= 2));
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
}
|
||||
}
|
||||
|
||||
t = realloc(keys, sizeof(char *) * keys_length);
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
|
||||
table_init();
|
||||
|
||||
for (i = 0; i < (size_t)n_threads; i++) {
|
||||
if (pthread_create(&readers[i], NULL, reader, NULL) != 0) {
|
||||
ck_error("ERROR: Failed to create thread %zu.\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += table_insert(keys[i]) == false;
|
||||
|
||||
fprintf(stderr, " [S] %d readers, 1 writer.\n", n_threads);
|
||||
fprintf(stderr, " [S] %zu entries stored and %u duplicates.\n\n",
|
||||
table_count(), d);
|
||||
|
||||
fprintf(stderr, " ,- BASIC TEST\n");
|
||||
fprintf(stderr, " | Executing SMR test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
if (table_reset() == false) {
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
}
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += table_insert(keys[i]) == false;
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
fprintf(stderr, " | Executing replacement test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_replace(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
fprintf(stderr, " | Executing get test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
if (table_get(keys[i]) == NULL) {
|
||||
ck_error("ERROR: Unexpected NULL value.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
a = 0;
|
||||
fprintf(stderr, " | Executing removal test...");
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_remove(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_insert(keys[i]);
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
fprintf(stderr, " | Executing negative look-up test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
table_get("\x50\x03\x04\x05\x06\x10");
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
ck_epoch_record_t epoch_temporary = epoch_wr;
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
|
||||
fprintf(stderr, " '- Summary: %u pending, %u peak, %lu reclamations -> "
|
||||
"%u pending, %u peak, %lu reclamations\n\n",
|
||||
epoch_temporary.n_pending, epoch_temporary.n_peak, epoch_temporary.n_dispatch,
|
||||
epoch_wr.n_pending, epoch_wr.n_peak, epoch_wr.n_dispatch);
|
||||
|
||||
fprintf(stderr, " ,- READER CONCURRENCY\n");
|
||||
fprintf(stderr, " | Executing reader test...");
|
||||
|
||||
ck_pr_store_int(&state, HT_STATE_GET);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_STOP]) != n_threads)
|
||||
ck_pr_stall();
|
||||
ck_pr_inc_int(&barrier[HT_STATE_STOP]);
|
||||
common_sleep(r);
|
||||
ck_pr_store_int(&state, HT_STATE_STRICT_REPLACEMENT);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_GET]) != n_threads)
|
||||
ck_pr_stall();
|
||||
fprintf(stderr, "done (reader = %" PRIu64 " ticks)\n",
|
||||
accumulator[HT_STATE_GET] / n_threads);
|
||||
|
||||
fprintf(stderr, " | Executing strict replacement test...");
|
||||
|
||||
a = repeated = 0;
|
||||
common_alarm(alarm_handler, &alarm_event, r);
|
||||
|
||||
ck_pr_inc_int(&barrier[HT_STATE_GET]);
|
||||
for (;;) {
|
||||
repeated++;
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_replace(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
if (next_stage == true) {
|
||||
next_stage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_store_int(&state, HT_STATE_DELETION);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_STRICT_REPLACEMENT]) != n_threads)
|
||||
ck_pr_stall();
|
||||
table_reset();
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
fprintf(stderr, "done (writer = %" PRIu64 " ticks, reader = %" PRIu64 " ticks)\n",
|
||||
a / (repeated * keys_length), accumulator[HT_STATE_STRICT_REPLACEMENT] / n_threads);
|
||||
|
||||
common_alarm(alarm_handler, &alarm_event, r);
|
||||
|
||||
fprintf(stderr, " | Executing deletion test (%.2f)...", p_d * 100);
|
||||
a = repeated = 0;
|
||||
ck_pr_inc_int(&barrier[HT_STATE_STRICT_REPLACEMENT]);
|
||||
for (;;) {
|
||||
double delete;
|
||||
|
||||
repeated++;
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
table_insert(keys[i]);
|
||||
if (p_d != 0.0) {
|
||||
delete = common_drand48();
|
||||
if (delete <= p_d)
|
||||
table_remove(keys[i]);
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
if (next_stage == true) {
|
||||
next_stage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ck_pr_store_int(&state, HT_STATE_REPLACEMENT);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_DELETION]) != n_threads)
|
||||
ck_pr_stall();
|
||||
|
||||
table_reset();
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
fprintf(stderr, "done (writer = %" PRIu64 " ticks, reader = %" PRIu64 " ticks)\n",
|
||||
a / (repeated * keys_length), accumulator[HT_STATE_DELETION] / n_threads);
|
||||
|
||||
common_alarm(alarm_handler, &alarm_event, r);
|
||||
|
||||
fprintf(stderr, " | Executing replacement test (%.2f)...", p_r * 100);
|
||||
a = repeated = 0;
|
||||
ck_pr_inc_int(&barrier[HT_STATE_DELETION]);
|
||||
for (;;) {
|
||||
double replace, delete;
|
||||
|
||||
repeated++;
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
table_insert(keys[i]);
|
||||
if (p_d != 0.0) {
|
||||
delete = common_drand48();
|
||||
if (delete <= p_d)
|
||||
table_remove(keys[i]);
|
||||
}
|
||||
if (p_r != 0.0) {
|
||||
replace = common_drand48();
|
||||
if (replace <= p_r)
|
||||
table_replace(keys[i]);
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
if (next_stage == true) {
|
||||
next_stage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ck_pr_store_int(&state, HT_STATE_STOP);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_REPLACEMENT]) != n_threads)
|
||||
ck_pr_stall();
|
||||
table_reset();
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
fprintf(stderr, "done (writer = %" PRIu64 " ticks, reader = %" PRIu64 " ticks)\n",
|
||||
a / (repeated * keys_length), accumulator[HT_STATE_REPLACEMENT] / n_threads);
|
||||
|
||||
ck_pr_inc_int(&barrier[HT_STATE_REPLACEMENT]);
|
||||
epoch_temporary = epoch_wr;
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
|
||||
fprintf(stderr, " '- Summary: %u pending, %u peak, %lu reclamations -> "
|
||||
"%u pending, %u peak, %lu reclamations\n\n",
|
||||
epoch_temporary.n_pending, epoch_temporary.n_peak, epoch_temporary.n_dispatch,
|
||||
epoch_wr.n_pending, epoch_wr.n_peak, epoch_wr.n_dispatch);
|
||||
return 0;
|
||||
}
|
545
regressions/ck_ht/benchmark/parallel_direct.c
Normal file
545
regressions/ck_ht/benchmark/parallel_direct.c
Normal file
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
* Copyright 2012-2015 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 <ck_ht.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ck_epoch.h>
|
||||
#include <ck_malloc.h>
|
||||
#include <ck_pr.h>
|
||||
#include <ck_spinlock.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static ck_ht_t ht CK_CC_CACHELINE;
|
||||
static uintptr_t *keys;
|
||||
static size_t keys_length = 0;
|
||||
static ck_epoch_t epoch_ht;
|
||||
static ck_epoch_record_t epoch_wr;
|
||||
static int n_threads;
|
||||
static bool next_stage;
|
||||
|
||||
enum state {
|
||||
HT_STATE_STOP = 0,
|
||||
HT_STATE_GET,
|
||||
HT_STATE_STRICT_REPLACEMENT,
|
||||
HT_STATE_DELETION,
|
||||
HT_STATE_REPLACEMENT,
|
||||
HT_STATE_COUNT
|
||||
};
|
||||
|
||||
static struct affinity affinerator = AFFINITY_INITIALIZER;
|
||||
static uint64_t accumulator[HT_STATE_COUNT];
|
||||
static ck_spinlock_t accumulator_mutex = CK_SPINLOCK_INITIALIZER;
|
||||
static int barrier[HT_STATE_COUNT];
|
||||
static int state;
|
||||
|
||||
struct ht_epoch {
|
||||
ck_epoch_entry_t epoch_entry;
|
||||
};
|
||||
|
||||
COMMON_ALARM_DECLARE_GLOBAL(ht_alarm, alarm_event, next_stage)
|
||||
|
||||
static void
|
||||
alarm_handler(int s)
|
||||
{
|
||||
|
||||
(void)s;
|
||||
next_stage = true;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ht_destroy(ck_epoch_entry_t *e)
|
||||
{
|
||||
|
||||
free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
ht_malloc(size_t r)
|
||||
{
|
||||
ck_epoch_entry_t *b;
|
||||
|
||||
b = malloc(sizeof(*b) + r);
|
||||
return b + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ht_free(void *p, size_t b, bool r)
|
||||
{
|
||||
struct ht_epoch *e = p;
|
||||
|
||||
(void)b;
|
||||
|
||||
if (r == true) {
|
||||
/* Destruction requires safe memory reclamation. */
|
||||
ck_epoch_call(&epoch_wr, &(--e)->epoch_entry, ht_destroy);
|
||||
} else {
|
||||
free(--e);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ck_malloc my_allocator = {
|
||||
.malloc = ht_malloc,
|
||||
.free = ht_free
|
||||
};
|
||||
|
||||
static void
|
||||
hash_function(ck_ht_hash_t *h, const void *key, size_t key_length, uint64_t seed)
|
||||
{
|
||||
const uintptr_t *value = key;
|
||||
|
||||
(void)key_length;
|
||||
(void)seed;
|
||||
h->value = *value;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
table_init(void)
|
||||
{
|
||||
|
||||
ck_epoch_init(&epoch_ht);
|
||||
ck_epoch_register(&epoch_ht, &epoch_wr);
|
||||
common_srand48((long int)time(NULL));
|
||||
if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, hash_function, &my_allocator, 8, common_lrand48()) == false) {
|
||||
perror("ck_ht_init");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static bool
|
||||
table_remove(uintptr_t value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
|
||||
ck_ht_hash_direct(&h, &ht, value);
|
||||
ck_ht_entry_key_set_direct(&entry, value);
|
||||
return ck_ht_remove_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
static bool
|
||||
table_replace(uintptr_t value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
|
||||
ck_ht_hash_direct(&h, &ht, value);
|
||||
ck_ht_entry_set_direct(&entry, h, value, 6605241);
|
||||
return ck_ht_set_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
static uintptr_t
|
||||
table_get(uintptr_t value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
|
||||
ck_ht_hash_direct(&h, &ht, value);
|
||||
ck_ht_entry_key_set_direct(&entry, value);
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == true)
|
||||
return ck_ht_entry_value_direct(&entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
table_insert(uintptr_t value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
|
||||
ck_ht_hash_direct(&h, &ht, value);
|
||||
ck_ht_entry_set_direct(&entry, h, value, value);
|
||||
return ck_ht_put_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
static size_t
|
||||
table_count(void)
|
||||
{
|
||||
|
||||
return ck_ht_count(&ht);
|
||||
}
|
||||
|
||||
static bool
|
||||
table_reset(void)
|
||||
{
|
||||
|
||||
return ck_ht_reset_spmc(&ht);
|
||||
}
|
||||
|
||||
static void *
|
||||
ht_reader(void *unused)
|
||||
{
|
||||
size_t i;
|
||||
ck_epoch_record_t epoch_record;
|
||||
int state_previous = HT_STATE_STOP;
|
||||
int n_state;
|
||||
uint64_t s, j, a;
|
||||
|
||||
(void)unused;
|
||||
if (aff_iterate(&affinerator) != 0)
|
||||
perror("WARNING: Failed to affine thread");
|
||||
|
||||
s = j = a = 0;
|
||||
ck_epoch_register(&epoch_ht, &epoch_record);
|
||||
for (;;) {
|
||||
j++;
|
||||
ck_epoch_begin(&epoch_record, NULL);
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
uintptr_t r;
|
||||
|
||||
r = table_get(keys[i]);
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
if (r == 6605241)
|
||||
continue;
|
||||
|
||||
if (r == keys[i])
|
||||
continue;
|
||||
|
||||
ck_error("ERROR: Found invalid value: [%ju]\n",
|
||||
(uintmax_t)r);
|
||||
}
|
||||
a += rdtsc() - s;
|
||||
ck_epoch_end(&epoch_record, NULL);
|
||||
|
||||
n_state = ck_pr_load_int(&state);
|
||||
if (n_state != state_previous) {
|
||||
ck_spinlock_lock(&accumulator_mutex);
|
||||
accumulator[state_previous] += a / (j * keys_length);
|
||||
ck_spinlock_unlock(&accumulator_mutex);
|
||||
ck_pr_inc_int(&barrier[state_previous]);
|
||||
while (ck_pr_load_int(&barrier[state_previous]) != n_threads + 1)
|
||||
ck_pr_stall();
|
||||
|
||||
state_previous = n_state;
|
||||
s = j = a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
size_t i, j, r;
|
||||
unsigned int d = 0;
|
||||
uint64_t s, e, a, repeated;
|
||||
pthread_t *readers;
|
||||
double p_r, p_d;
|
||||
|
||||
COMMON_ALARM_DECLARE_LOCAL(ht_alarm, alarm_event)
|
||||
|
||||
r = 20;
|
||||
s = 8;
|
||||
p_d = 0.5;
|
||||
p_r = 0.5;
|
||||
n_threads = CORES - 1;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: parallel <#entries> [<interval length> <initial size> <readers>\n"
|
||||
" <probability of replacement> <probability of deletion> <epoch threshold>]\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (argc >= 3)
|
||||
r = atoi(argv[2]);
|
||||
|
||||
if (argc >= 4)
|
||||
s = (uint64_t)atoi(argv[3]);
|
||||
|
||||
if (argc >= 5) {
|
||||
n_threads = atoi(argv[4]);
|
||||
if (n_threads < 1) {
|
||||
ck_error("ERROR: Number of readers must be >= 1.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (argc >= 6) {
|
||||
p_r = atof(argv[5]) / 100.00;
|
||||
if (p_r < 0) {
|
||||
ck_error("ERROR: Probability of replacement must be >= 0 and <= 100.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (argc >= 7) {
|
||||
p_d = atof(argv[6]) / 100.00;
|
||||
if (p_d < 0) {
|
||||
ck_error("ERROR: Probability of deletion must be >= 0 and <= 100.\n");
|
||||
}
|
||||
}
|
||||
|
||||
COMMON_ALARM_INIT(ht_alarm, alarm_event, r)
|
||||
|
||||
affinerator.delta = 1;
|
||||
readers = malloc(sizeof(pthread_t) * n_threads);
|
||||
assert(readers != NULL);
|
||||
|
||||
keys_length = (size_t)atoi(argv[1]);
|
||||
keys = malloc(sizeof(uintptr_t) * keys_length);
|
||||
assert(keys != NULL);
|
||||
|
||||
table_init();
|
||||
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
keys[i] = (uintptr_t)common_lrand48();
|
||||
while (keys[i] == 2)
|
||||
keys[i] = (uintptr_t)common_lrand48();
|
||||
}
|
||||
|
||||
for (i = 0; i < (size_t)n_threads; i++) {
|
||||
if (pthread_create(&readers[i], NULL, ht_reader, NULL) != 0) {
|
||||
ck_error("ERROR: Failed to create thread %zu.\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += table_insert(keys[i]) == false;
|
||||
|
||||
fprintf(stderr, " [S] %zu entries stored and %u duplicates.\n\n",
|
||||
table_count(), d);
|
||||
|
||||
fprintf(stderr, " ,- BASIC TEST\n");
|
||||
fprintf(stderr, " | Executing SMR test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
if (table_reset() == false) {
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
}
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += table_insert(keys[i]) == false;
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
fprintf(stderr, " | Executing replacement test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_replace(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
fprintf(stderr, " | Executing get test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
if (table_get(keys[i]) == 0) {
|
||||
ck_error("ERROR: Unexpected 0 value.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
a = 0;
|
||||
fprintf(stderr, " | Executing removal test...");
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_remove(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_insert(keys[i]);
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
fprintf(stderr, " | Executing negative look-up test...");
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
table_get(2);
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
fprintf(stderr, "done (%" PRIu64 " ticks)\n", a / (r * keys_length));
|
||||
|
||||
ck_epoch_record_t epoch_temporary = epoch_wr;
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
|
||||
fprintf(stderr, " '- Summary: %u pending, %u peak, %lu reclamations -> "
|
||||
"%u pending, %u peak, %lu reclamations\n\n",
|
||||
epoch_temporary.n_pending, epoch_temporary.n_peak, epoch_temporary.n_dispatch,
|
||||
epoch_wr.n_pending, epoch_wr.n_peak, epoch_wr.n_dispatch);
|
||||
|
||||
fprintf(stderr, " ,- READER CONCURRENCY\n");
|
||||
fprintf(stderr, " | Executing reader test...");
|
||||
|
||||
ck_pr_store_int(&state, HT_STATE_GET);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_STOP]) != n_threads)
|
||||
ck_pr_stall();
|
||||
ck_pr_inc_int(&barrier[HT_STATE_STOP]);
|
||||
common_sleep(r);
|
||||
ck_pr_store_int(&state, HT_STATE_STRICT_REPLACEMENT);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_GET]) != n_threads)
|
||||
ck_pr_stall();
|
||||
fprintf(stderr, "done (reader = %" PRIu64 " ticks)\n",
|
||||
accumulator[HT_STATE_GET] / n_threads);
|
||||
|
||||
fprintf(stderr, " | Executing strict replacement test...");
|
||||
|
||||
a = repeated = 0;
|
||||
common_alarm(alarm_handler, &alarm_event, r);
|
||||
|
||||
ck_pr_inc_int(&barrier[HT_STATE_GET]);
|
||||
for (;;) {
|
||||
repeated++;
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_replace(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
if (next_stage == true) {
|
||||
next_stage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ck_pr_store_int(&state, HT_STATE_DELETION);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_STRICT_REPLACEMENT]) != n_threads)
|
||||
ck_pr_stall();
|
||||
table_reset();
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
fprintf(stderr, "done (writer = %" PRIu64 " ticks, reader = %" PRIu64 " ticks)\n",
|
||||
a / (repeated * keys_length), accumulator[HT_STATE_STRICT_REPLACEMENT] / n_threads);
|
||||
|
||||
common_alarm(alarm_handler, &alarm_event, r);
|
||||
|
||||
fprintf(stderr, " | Executing deletion test (%.2f)...", p_d * 100);
|
||||
a = repeated = 0;
|
||||
ck_pr_inc_int(&barrier[HT_STATE_STRICT_REPLACEMENT]);
|
||||
for (;;) {
|
||||
double delete;
|
||||
|
||||
repeated++;
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
table_insert(keys[i]);
|
||||
if (p_d != 0.0) {
|
||||
delete = common_drand48();
|
||||
if (delete <= p_d)
|
||||
table_remove(keys[i]);
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
if (next_stage == true) {
|
||||
next_stage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ck_pr_store_int(&state, HT_STATE_REPLACEMENT);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_DELETION]) != n_threads)
|
||||
ck_pr_stall();
|
||||
|
||||
table_reset();
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
fprintf(stderr, "done (writer = %" PRIu64 " ticks, reader = %" PRIu64 " ticks)\n",
|
||||
a / (repeated * keys_length), accumulator[HT_STATE_DELETION] / n_threads);
|
||||
|
||||
common_alarm(alarm_handler, &alarm_event, r);
|
||||
|
||||
fprintf(stderr, " | Executing replacement test (%.2f)...", p_r * 100);
|
||||
a = repeated = 0;
|
||||
ck_pr_inc_int(&barrier[HT_STATE_DELETION]);
|
||||
for (;;) {
|
||||
double replace, delete;
|
||||
|
||||
repeated++;
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
table_insert(keys[i]);
|
||||
if (p_d != 0.0) {
|
||||
delete = common_drand48();
|
||||
if (delete <= p_d)
|
||||
table_remove(keys[i]);
|
||||
}
|
||||
if (p_r != 0.0) {
|
||||
replace = common_drand48();
|
||||
if (replace <= p_r)
|
||||
table_replace(keys[i]);
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
if (next_stage == true) {
|
||||
next_stage = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ck_pr_store_int(&state, HT_STATE_STOP);
|
||||
while (ck_pr_load_int(&barrier[HT_STATE_REPLACEMENT]) != n_threads)
|
||||
ck_pr_stall();
|
||||
table_reset();
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
fprintf(stderr, "done (writer = %" PRIu64 " ticks, reader = %" PRIu64 " ticks)\n",
|
||||
a / (repeated * keys_length), accumulator[HT_STATE_REPLACEMENT] / n_threads);
|
||||
|
||||
ck_pr_inc_int(&barrier[HT_STATE_REPLACEMENT]);
|
||||
epoch_temporary = epoch_wr;
|
||||
ck_epoch_synchronize(&epoch_wr);
|
||||
|
||||
fprintf(stderr, " '- Summary: %u pending, %u peak, %lu reclamations -> "
|
||||
"%u pending, %u peak, %lu reclamations\n\n",
|
||||
epoch_temporary.n_pending, epoch_temporary.n_peak, epoch_temporary.n_dispatch,
|
||||
epoch_wr.n_pending, epoch_wr.n_peak, epoch_wr.n_dispatch);
|
||||
return 0;
|
||||
}
|
387
regressions/ck_ht/benchmark/serial.c
Normal file
387
regressions/ck_ht/benchmark/serial.c
Normal file
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* Copyright 2012-2015 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 <ck_ht.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ck_malloc.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
static ck_ht_t ht;
|
||||
static char **keys;
|
||||
static size_t keys_length = 0;
|
||||
static size_t keys_capacity = 128;
|
||||
|
||||
static void *
|
||||
ht_malloc(size_t r)
|
||||
{
|
||||
|
||||
return malloc(r);
|
||||
}
|
||||
|
||||
static void
|
||||
ht_free(void *p, size_t b, bool r)
|
||||
{
|
||||
|
||||
(void)b;
|
||||
(void)r;
|
||||
|
||||
free(p);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ck_malloc my_allocator = {
|
||||
.malloc = ht_malloc,
|
||||
.free = ht_free
|
||||
};
|
||||
|
||||
static void
|
||||
table_init(void)
|
||||
{
|
||||
unsigned int mode = CK_HT_MODE_BYTESTRING;
|
||||
|
||||
#ifdef HT_DELETE
|
||||
mode |= CK_HT_WORKLOAD_DELETE;
|
||||
#endif
|
||||
|
||||
common_srand48((long int)time(NULL));
|
||||
if (ck_ht_init(&ht, mode, NULL, &my_allocator, 8, common_lrand48()) == false) {
|
||||
perror("ck_ht_init");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static bool
|
||||
table_remove(const char *value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
size_t l = strlen(value);
|
||||
|
||||
ck_ht_hash(&h, &ht, value, l);
|
||||
ck_ht_entry_key_set(&entry, value, l);
|
||||
return ck_ht_remove_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
static bool
|
||||
table_replace(const char *value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
size_t l = strlen(value);
|
||||
|
||||
ck_ht_hash(&h, &ht, value, l);
|
||||
ck_ht_entry_set(&entry, h, value, l, "REPLACED");
|
||||
return ck_ht_set_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
static void *
|
||||
table_get(const char *value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
size_t l = strlen(value);
|
||||
void *v = NULL;
|
||||
|
||||
ck_ht_hash(&h, &ht, value, l);
|
||||
ck_ht_entry_key_set(&entry, value, l);
|
||||
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == true) {
|
||||
v = ck_ht_entry_value(&entry);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static bool
|
||||
table_insert(const char *value)
|
||||
{
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
size_t l = strlen(value);
|
||||
|
||||
ck_ht_hash(&h, &ht, value, l);
|
||||
ck_ht_entry_set(&entry, h, value, l, "VALUE");
|
||||
return ck_ht_put_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
static size_t
|
||||
table_count(void)
|
||||
{
|
||||
|
||||
return ck_ht_count(&ht);
|
||||
}
|
||||
|
||||
static bool
|
||||
table_gc(void)
|
||||
{
|
||||
|
||||
return ck_ht_gc(&ht, 0, common_lrand48());
|
||||
}
|
||||
|
||||
static bool
|
||||
table_reset(void)
|
||||
{
|
||||
|
||||
return ck_ht_reset_spmc(&ht);
|
||||
}
|
||||
|
||||
static void
|
||||
keys_shuffle(char **k)
|
||||
{
|
||||
size_t i, j;
|
||||
char *t;
|
||||
|
||||
for (i = keys_length; i > 1; i--) {
|
||||
j = rand() % (i - 1);
|
||||
|
||||
if (j != i - 1) {
|
||||
t = k[i - 1];
|
||||
k[i - 1] = k[j];
|
||||
k[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
FILE *fp;
|
||||
char buffer[512];
|
||||
size_t i, j, r;
|
||||
unsigned int d = 0;
|
||||
uint64_t s, e, a, ri, si, ai, sr, rg, sg, ag, sd, ng, gg;
|
||||
char **t;
|
||||
struct ck_ht_stat st;
|
||||
|
||||
r = 20;
|
||||
s = 8;
|
||||
srand(time(NULL));
|
||||
|
||||
if (argc < 2) {
|
||||
ck_error("Usage: ck_ht <dictionary> [<repetitions> <initial size>]\n");
|
||||
}
|
||||
|
||||
if (argc >= 3)
|
||||
r = atoi(argv[2]);
|
||||
|
||||
if (argc >= 4)
|
||||
s = (uint64_t)atoi(argv[3]);
|
||||
|
||||
keys = malloc(sizeof(char *) * keys_capacity);
|
||||
assert(keys != NULL);
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
assert(fp != NULL);
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
buffer[strlen(buffer) - 1] = '\0';
|
||||
keys[keys_length++] = strdup(buffer);
|
||||
assert(keys[keys_length - 1] != NULL);
|
||||
|
||||
if (keys_length == keys_capacity) {
|
||||
t = realloc(keys, sizeof(char *) * (keys_capacity *= 2));
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
}
|
||||
}
|
||||
|
||||
t = realloc(keys, sizeof(char *) * keys_length);
|
||||
assert(t != NULL);
|
||||
keys = t;
|
||||
|
||||
table_init();
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += table_insert(keys[i]) == false;
|
||||
ck_ht_stat(&ht, &st);
|
||||
|
||||
fprintf(stderr, "# %zu entries stored, %u duplicates, %" PRIu64 " probe.\n",
|
||||
table_count(), d, st.probe_maximum);
|
||||
|
||||
fprintf(stderr, "# reverse_insertion serial_insertion random_insertion serial_replace reverse_get serial_get random_get serial_remove negative_get garbage_collect\n\n");
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
if (table_reset() == false) {
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
}
|
||||
|
||||
s = rdtsc();
|
||||
for (i = keys_length; i > 0; i--)
|
||||
d += table_insert(keys[i - 1]) == false;
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
ri = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
if (table_reset() == false) {
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
}
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += table_insert(keys[i]) == false;
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
si = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
keys_shuffle(keys);
|
||||
|
||||
if (table_reset() == false) {
|
||||
ck_error("ERROR: Failed to reset hash table.\n");
|
||||
}
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
d += table_insert(keys[i]) == false;
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
ai = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_replace(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
sr = a / (r * keys_length);
|
||||
|
||||
table_reset();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_insert(keys[i]);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = keys_length; i > 0; i--) {
|
||||
if (table_get(keys[i - 1]) == NULL) {
|
||||
ck_error("ERROR: Unexpected NULL value.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
rg = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
if (table_get(keys[i]) == NULL) {
|
||||
ck_error("ERROR: Unexpected NULL value.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
sg = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
keys_shuffle(keys);
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
if (table_get(keys[i]) == NULL) {
|
||||
ck_error("ERROR: Unexpected NULL value.\n");
|
||||
}
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
ag = a / (r * keys_length);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_remove(keys[i]);
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
|
||||
for (i = 0; i < keys_length; i++)
|
||||
table_insert(keys[i]);
|
||||
}
|
||||
sd = a / (r * keys_length);
|
||||
|
||||
for (i = 0; i < keys_length / 2; i++)
|
||||
table_remove(keys[i]);
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
table_gc();
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
gg = a / r;
|
||||
|
||||
a = 0;
|
||||
for (j = 0; j < r; j++) {
|
||||
s = rdtsc();
|
||||
for (i = 0; i < keys_length; i++) {
|
||||
table_get("\x50\x03\x04\x05\x06\x10");
|
||||
}
|
||||
e = rdtsc();
|
||||
a += e - s;
|
||||
}
|
||||
ng = a / (r * keys_length);
|
||||
|
||||
printf("%zu "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 " "
|
||||
"%" PRIu64 "\n",
|
||||
keys_length, ri, si, ai, sr, rg, sg, ag, sd, ng, gg);
|
||||
|
||||
return 0;
|
||||
}
|
21
regressions/ck_ht/validate/Makefile
Normal file
21
regressions/ck_ht/validate/Makefile
Normal file
|
@ -0,0 +1,21 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=serial serial.delete
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
serial: serial.c ../../../include/ck_ht.h ../../../src/ck_ht.c
|
||||
$(CC) $(CFLAGS) -o serial serial.c ../../../src/ck_ht.c
|
||||
|
||||
serial.delete: serial.c ../../../include/ck_ht.h ../../../src/ck_ht.c
|
||||
$(CC) $(CFLAGS) -DHT_DELETE -o serial.delete serial.c ../../../src/ck_ht.c
|
||||
|
||||
check: all
|
||||
./serial
|
||||
./serial.delete
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o $(OBJECTS) *.dSYM *.exe
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=-D_GNU_SOURCE
|
309
regressions/ck_ht/validate/serial.c
Normal file
309
regressions/ck_ht/validate/serial.c
Normal file
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* Copyright 2012-2015 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 <ck_ht.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ck_malloc.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../../common.h"
|
||||
#include "../../../src/ck_ht_hash.h"
|
||||
|
||||
static size_t hash_times_called = 0;
|
||||
|
||||
static void *
|
||||
ht_malloc(size_t r)
|
||||
{
|
||||
|
||||
return malloc(r);
|
||||
}
|
||||
|
||||
static void
|
||||
ht_free(void *p, size_t b, bool r)
|
||||
{
|
||||
|
||||
(void)b;
|
||||
(void)r;
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ht_hash_wrapper(struct ck_ht_hash *h,
|
||||
const void *key,
|
||||
size_t length,
|
||||
uint64_t seed)
|
||||
{
|
||||
hash_times_called++;
|
||||
|
||||
h->value = (unsigned long)MurmurHash64A(key, length, seed);
|
||||
return;
|
||||
}
|
||||
|
||||
static struct ck_malloc my_allocator = {
|
||||
.malloc = ht_malloc,
|
||||
.free = ht_free
|
||||
};
|
||||
|
||||
const char *test[] = {"Samy", "Al", "Bahra", "dances", "in", "the", "wind.", "Once",
|
||||
"upon", "a", "time", "his", "gypsy", "ate", "one", "itsy",
|
||||
"bitsy", "spider.", "What", "goes", "up", "must",
|
||||
"come", "down.", "What", "is", "down", "stays",
|
||||
"down.", "A", "B", "C", "D", "E", "F", "G", "H",
|
||||
"I", "J", "K", "L", "M", "N", "O"};
|
||||
|
||||
static uintptr_t direct[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 1, 2, 3, 4, 5, 9 };
|
||||
|
||||
const char *negative = "negative";
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
size_t i, l;
|
||||
ck_ht_t ht;
|
||||
ck_ht_entry_t entry;
|
||||
ck_ht_hash_t h;
|
||||
ck_ht_iterator_t iterator = CK_HT_ITERATOR_INITIALIZER;
|
||||
ck_ht_entry_t *cursor;
|
||||
unsigned int mode = CK_HT_MODE_BYTESTRING;
|
||||
|
||||
#ifdef HT_DELETE
|
||||
mode |= CK_HT_WORKLOAD_DELETE;
|
||||
#endif
|
||||
|
||||
if (ck_ht_init(&ht, mode, ht_hash_wrapper, &my_allocator, 2, 6602834) == false) {
|
||||
perror("ck_ht_init");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
l = strlen(test[i]);
|
||||
ck_ht_hash(&h, &ht, test[i], l);
|
||||
ck_ht_entry_set(&entry, h, test[i], l, test[i]);
|
||||
ck_ht_put_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
l = strlen(test[0]);
|
||||
ck_ht_hash(&h, &ht, test[0], l);
|
||||
ck_ht_entry_set(&entry, h, test[0], l, test[0]);
|
||||
ck_ht_put_spmc(&ht, h, &entry);
|
||||
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
l = strlen(test[i]);
|
||||
ck_ht_hash(&h, &ht, test[i], l);
|
||||
ck_ht_entry_key_set(&entry, test[i], l);
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == false) {
|
||||
ck_error("ERROR (put): Failed to find [%s]\n", test[i]);
|
||||
} else {
|
||||
void *k, *v;
|
||||
|
||||
k = ck_ht_entry_key(&entry);
|
||||
v = ck_ht_entry_value(&entry);
|
||||
|
||||
if (strcmp(k, test[i]) || strcmp(v, test[i])) {
|
||||
ck_error("ERROR: Mismatch: (%s, %s) != (%s, %s)\n",
|
||||
(char *)k, (char *)v, test[i], test[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ck_ht_hash(&h, &ht, negative, strlen(negative));
|
||||
ck_ht_entry_key_set(&entry, negative, strlen(negative));
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == true) {
|
||||
ck_error("ERROR: Found non-existing entry.\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
l = strlen(test[i]);
|
||||
ck_ht_hash(&h, &ht, test[i], l);
|
||||
ck_ht_entry_key_set(&entry, test[i], l);
|
||||
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == false)
|
||||
continue;
|
||||
|
||||
if (ck_ht_remove_spmc(&ht, h, &entry) == false) {
|
||||
ck_error("ERROR: Failed to delete existing entry\n");
|
||||
}
|
||||
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == true)
|
||||
ck_error("ERROR: Able to find [%s] after delete\n", test[i]);
|
||||
|
||||
ck_ht_entry_set(&entry, h, test[i], l, test[i]);
|
||||
if (ck_ht_put_spmc(&ht, h, &entry) == false)
|
||||
ck_error("ERROR: Failed to insert [%s]\n", test[i]);
|
||||
|
||||
if (ck_ht_remove_spmc(&ht, h, &entry) == false) {
|
||||
ck_error("ERROR: Failed to delete existing entry\n");
|
||||
}
|
||||
}
|
||||
|
||||
ck_ht_reset_spmc(&ht);
|
||||
if (ck_ht_count(&ht) != 0) {
|
||||
ck_error("ERROR: Map was not reset.\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
l = strlen(test[i]);
|
||||
ck_ht_hash(&h, &ht, test[i], l);
|
||||
ck_ht_entry_set(&entry, h, test[i], l, test[i]);
|
||||
ck_ht_put_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
for (i = 0; ck_ht_next(&ht, &iterator, &cursor) == true; i++);
|
||||
if (i != 42) {
|
||||
ck_error("ERROR: Incorrect number of entries in table.\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
l = strlen(test[i]);
|
||||
ck_ht_hash(&h, &ht, test[i], l);
|
||||
ck_ht_entry_set(&entry, h, test[i], l, test[i]);
|
||||
ck_ht_set_spmc(&ht, h, &entry);
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
l = strlen(test[i]);
|
||||
ck_ht_hash(&h, &ht, test[i], l);
|
||||
ck_ht_entry_key_set(&entry, test[i], l);
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == false) {
|
||||
ck_error("ERROR (set): Failed to find [%s]\n", test[i]);
|
||||
} else {
|
||||
void *k, *v;
|
||||
|
||||
k = ck_ht_entry_key(&entry);
|
||||
v = ck_ht_entry_value(&entry);
|
||||
|
||||
if (strcmp(k, test[i]) || strcmp(v, test[i])) {
|
||||
ck_error("ERROR: Mismatch: (%s, %s) != (%s, %s)\n",
|
||||
(char *)k, (char *)v, test[i], test[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ck_ht_gc(&ht, 0, 27) == false) {
|
||||
ck_error("ck_ht_gc\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
l = strlen(test[i]);
|
||||
ck_ht_hash(&h, &ht, test[i], l);
|
||||
ck_ht_entry_set(&entry, h, test[i], l, "REPLACED");
|
||||
ck_ht_set_spmc(&ht, h, &entry);
|
||||
|
||||
if (strcmp(test[i], "What") == 0)
|
||||
continue;
|
||||
|
||||
if (strcmp(test[i], "down.") == 0)
|
||||
continue;
|
||||
|
||||
if (strcmp(ck_ht_entry_value(&entry), test[i]) != 0) {
|
||||
ck_error("Mismatch detected: %s, expected %s\n",
|
||||
(char *)ck_ht_entry_value(&entry),
|
||||
test[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ck_ht_iterator_init(&iterator);
|
||||
while (ck_ht_next(&ht, &iterator, &cursor) == true) {
|
||||
if (strcmp(ck_ht_entry_value(cursor), "REPLACED") != 0) {
|
||||
ck_error("Mismatch detected: %s, expected REPLACED\n",
|
||||
(char *)ck_ht_entry_value(cursor));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(test) / sizeof(*test); i++) {
|
||||
l = strlen(test[i]);
|
||||
ck_ht_hash(&h, &ht, test[i], l);
|
||||
ck_ht_entry_key_set(&entry, test[i], l);
|
||||
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == false)
|
||||
continue;
|
||||
|
||||
if (ck_ht_remove_spmc(&ht, h, &entry) == false) {
|
||||
ck_error("ERROR: Failed to delete existing entry\n");
|
||||
}
|
||||
|
||||
if (ck_ht_get_spmc(&ht, h, &entry) == true)
|
||||
ck_error("ERROR: Able to find [%s] after delete\n", test[i]);
|
||||
|
||||
ck_ht_entry_set(&entry, h, test[i], l, test[i]);
|
||||
if (ck_ht_put_spmc(&ht, h, &entry) == false)
|
||||
ck_error("ERROR: Failed to insert [%s]\n", test[i]);
|
||||
|
||||
if (ck_ht_remove_spmc(&ht, h, &entry) == false) {
|
||||
ck_error("ERROR: Failed to delete existing entry\n");
|
||||
}
|
||||
}
|
||||
|
||||
ck_ht_destroy(&ht);
|
||||
|
||||
if (hash_times_called == 0) {
|
||||
ck_error("ERROR: Our hash function was not called!\n");
|
||||
}
|
||||
|
||||
hash_times_called = 0;
|
||||
|
||||
if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, ht_hash_wrapper, &my_allocator, 8, 6602834) == false) {
|
||||
perror("ck_ht_init");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
l = 0;
|
||||
for (i = 0; i < sizeof(direct) / sizeof(*direct); i++) {
|
||||
ck_ht_hash_direct(&h, &ht, direct[i]);
|
||||
ck_ht_entry_set_direct(&entry, h, direct[i], (uintptr_t)test[i]);
|
||||
l += ck_ht_put_spmc(&ht, h, &entry) == false;
|
||||
}
|
||||
|
||||
if (l != 7) {
|
||||
ck_error("ERROR: Got %zu failures rather than 7\n", l);
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(direct) / sizeof(*direct); i++) {
|
||||
ck_ht_hash_direct(&h, &ht, direct[i]);
|
||||
ck_ht_entry_set_direct(&entry, h, direct[i], (uintptr_t)"REPLACED");
|
||||
l += ck_ht_set_spmc(&ht, h, &entry) == false;
|
||||
}
|
||||
|
||||
ck_ht_iterator_init(&iterator);
|
||||
while (ck_ht_next(&ht, &iterator, &cursor) == true) {
|
||||
if (strcmp(ck_ht_entry_value(cursor), "REPLACED") != 0) {
|
||||
ck_error("Mismatch detected: %s, expected REPLACED\n",
|
||||
(char *)ck_ht_entry_value(cursor));
|
||||
}
|
||||
}
|
||||
|
||||
ck_ht_destroy(&ht);
|
||||
|
||||
if (hash_times_called == 0) {
|
||||
ck_error("ERROR: Our hash function was not called!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
17
regressions/ck_pflock/benchmark/Makefile
Normal file
17
regressions/ck_pflock/benchmark/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: clean distribution
|
||||
|
||||
OBJECTS=latency throughput
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
latency: latency.c ../../../include/ck_rwlock.h
|
||||
$(CC) $(CFLAGS) -o latency latency.c
|
||||
|
||||
throughput: throughput.c ../../../include/ck_rwlock.h
|
||||
$(CC) $(CFLAGS) -o throughput throughput.c
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
72
regressions/ck_pflock/benchmark/latency.c
Normal file
72
regressions/ck_pflock/benchmark/latency.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright 2011-2015 Samy Al Bahra.
|
||||
* Copyright 2013 John Wittrock.
|
||||
* 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 OTHEPFISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ck_pflock.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef STEPS
|
||||
#define STEPS 1000000
|
||||
#endif
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
uint64_t s_b, e_b, i;
|
||||
ck_pflock_t pflock = CK_PFLOCK_INITIALIZER;
|
||||
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_pflock_write_lock(&pflock);
|
||||
ck_pflock_write_unlock(&pflock);
|
||||
}
|
||||
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_pflock_write_lock(&pflock);
|
||||
ck_pflock_write_unlock(&pflock);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("WRITE: pflock %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
}
|
||||
|
||||
s_b = rdtsc();
|
||||
for (i = 0; i < STEPS; i++) {
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
}
|
||||
e_b = rdtsc();
|
||||
printf("READ: pflock %15" PRIu64 "\n", (e_b - s_b) / STEPS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
163
regressions/ck_pflock/benchmark/throughput.c
Normal file
163
regressions/ck_pflock/benchmark/throughput.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright 2011-2015 Samy Al Bahra.
|
||||
* Copyright 2013 John Wittrock.
|
||||
* 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 OTHEPFISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ck_pflock.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef STEPS
|
||||
#define STEPS 1000000
|
||||
#endif
|
||||
|
||||
static int barrier;
|
||||
static int threads;
|
||||
static unsigned int flag CK_CC_CACHELINE;
|
||||
static ck_pflock_t pflock = CK_PFLOCK_INITIALIZER;
|
||||
static struct affinity affinity;
|
||||
|
||||
static void *
|
||||
thread_pflock(void *pun)
|
||||
{
|
||||
uint64_t s_b, e_b, a, i;
|
||||
uint64_t *value = pun;
|
||||
|
||||
if (aff_iterate(&affinity) != 0) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ck_pr_inc_int(&barrier);
|
||||
while (ck_pr_load_int(&barrier) != threads)
|
||||
ck_pr_stall();
|
||||
|
||||
for (i = 1, a = 0;; i++) {
|
||||
s_b = rdtsc();
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
ck_pflock_read_lock(&pflock);
|
||||
ck_pflock_read_unlock(&pflock);
|
||||
e_b = rdtsc();
|
||||
|
||||
a += (e_b - s_b) >> 4;
|
||||
|
||||
if (ck_pr_load_uint(&flag) == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
ck_pr_inc_int(&barrier);
|
||||
while (ck_pr_load_int(&barrier) != threads * 2)
|
||||
ck_pr_stall();
|
||||
|
||||
*value = (a / i);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int t;
|
||||
pthread_t *p;
|
||||
uint64_t *latency;
|
||||
|
||||
if (argc != 3) {
|
||||
ck_error("Usage: throughput <delta> <threads>\n");
|
||||
}
|
||||
|
||||
threads = atoi(argv[2]);
|
||||
if (threads <= 0) {
|
||||
ck_error("ERROR: Threads must be a value > 0.\n");
|
||||
}
|
||||
|
||||
p = malloc(sizeof(pthread_t) * threads);
|
||||
if (p == NULL) {
|
||||
ck_error("ERROR: Failed to initialize thread.\n");
|
||||
}
|
||||
|
||||
latency = malloc(sizeof(uint64_t) * threads);
|
||||
if (latency == NULL) {
|
||||
ck_error("ERROR: Failed to create latency buffer.\n");
|
||||
}
|
||||
|
||||
affinity.delta = atoi(argv[1]);
|
||||
affinity.request = 0;
|
||||
|
||||
fprintf(stderr, "Creating threads (pflock)...");
|
||||
for (t = 0; t < threads; t++) {
|
||||
if (pthread_create(&p[t], NULL, thread_pflock, latency + t) != 0) {
|
||||
ck_error("ERROR: Could not create thread %d\n", t);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
common_sleep(10);
|
||||
ck_pr_store_uint(&flag, 1);
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish acquisition regression...");
|
||||
for (t = 0; t < threads; t++)
|
||||
pthread_join(p[t], NULL);
|
||||
fprintf(stderr, "done\n\n");
|
||||
|
||||
for (t = 1; t <= threads; t++)
|
||||
printf("%10u %20" PRIu64 "\n", t, latency[t - 1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
17
regressions/ck_pflock/validate/Makefile
Normal file
17
regressions/ck_pflock/validate/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=validate
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
validate: validate.c ../../../include/ck_pflock.h
|
||||
$(CC) $(CFLAGS) -o validate validate.c
|
||||
|
||||
check: all
|
||||
./validate $(CORES) 1
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM *.exe *~ *.o $(OBJECTS)
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
151
regressions/ck_pflock/validate/validate.c
Normal file
151
regressions/ck_pflock/validate/validate.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright 2011-2015 Samy Al Bahra, John Wittrock.
|
||||
* 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 <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
#include <ck_pflock.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef ITERATE
|
||||
#define ITERATE 1000000
|
||||
#endif
|
||||
|
||||
static struct affinity a;
|
||||
static unsigned int locked;
|
||||
static int nthr;
|
||||
static ck_pflock_t lock = CK_PFLOCK_INITIALIZER;
|
||||
|
||||
static void *
|
||||
thread(void *null CK_CC_UNUSED)
|
||||
{
|
||||
int i = ITERATE;
|
||||
unsigned int l;
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while (i--) {
|
||||
ck_pflock_write_lock(&lock);
|
||||
{
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
ck_pr_inc_uint(&locked);
|
||||
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 8) {
|
||||
ck_error("ERROR [WR:%d]: %u != 2\n", __LINE__, l);
|
||||
}
|
||||
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
ck_pr_dec_uint(&locked);
|
||||
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
}
|
||||
ck_pflock_write_unlock(&lock);
|
||||
|
||||
ck_pflock_read_lock(&lock);
|
||||
{
|
||||
l = ck_pr_load_uint(&locked);
|
||||
if (l != 0) {
|
||||
ck_error("ERROR [RD:%d]: %u != 0\n", __LINE__, l);
|
||||
}
|
||||
}
|
||||
ck_pflock_read_unlock(&lock);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t *threads;
|
||||
int i;
|
||||
|
||||
if (argc != 3) {
|
||||
ck_error("Usage: validate <number of threads> <affinity delta>\n");
|
||||
}
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
|
||||
fprintf(stderr, "Creating threads (mutual exclusion)...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
if (pthread_create(&threads[i], NULL, thread, NULL)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish correctness regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done (passed)\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
31
regressions/ck_pr/benchmark/Makefile
Normal file
31
regressions/ck_pr/benchmark/Makefile
Normal file
|
@ -0,0 +1,31 @@
|
|||
.PHONY: clean
|
||||
|
||||
all: ck_pr_cas_64 ck_pr_fas_64 ck_pr_cas_64_2 ck_pr_add_64 ck_pr_faa_64 ck_pr_neg_64 fp
|
||||
|
||||
fp: fp.c
|
||||
$(CC) $(CFLAGS) -o fp fp.c
|
||||
|
||||
ck_pr_cas_64_2: ck_pr_cas_64_2.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_cas_64_2 ck_pr_cas_64_2.c -lm
|
||||
|
||||
ck_pr_cas_64: ck_pr_cas_64.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_cas_64 ck_pr_cas_64.c -lm
|
||||
|
||||
ck_pr_fas_64: ck_pr_fas_64.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_fas_64 ck_pr_fas_64.c -lm
|
||||
|
||||
ck_pr_add_64: ck_pr_add_64.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_add_64 ck_pr_add_64.c -lm
|
||||
|
||||
ck_pr_faa_64: ck_pr_faa_64.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_faa_64 ck_pr_faa_64.c -lm
|
||||
|
||||
ck_pr_neg_64: ck_pr_neg_64.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_neg_64 ck_pr_neg_64.c -lm
|
||||
|
||||
clean:
|
||||
rm -rf ck_pr_cas_64 ck_pr_fas_64 ck_pr_cas_64_2 ck_pr_add_64 \
|
||||
ck_pr_faa_64 ck_pr_neg_64 *.dSYM *.exe
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=$(PTHREAD_CFLAGS) -D_GNU_SOURCE
|
130
regressions/ck_pr/benchmark/benchmark.h
Normal file
130
regressions/ck_pr/benchmark/benchmark.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
/* 8! = 40320, evenly divide 1 .. 8 processor workload. */
|
||||
#define WORKLOAD (40320 * 2056)
|
||||
|
||||
struct block {
|
||||
unsigned int tid;
|
||||
};
|
||||
|
||||
static struct affinity a;
|
||||
static unsigned int ready;
|
||||
static uint64_t *count;
|
||||
static uint64_t nthr;
|
||||
|
||||
static uint64_t object[2] CK_CC_CACHELINE;
|
||||
|
||||
static void *
|
||||
fairness(void *null)
|
||||
{
|
||||
struct block *context = null;
|
||||
unsigned int i = context->tid;
|
||||
|
||||
if (aff_iterate(&a)) {
|
||||
perror("ERROR: Could not affine thread");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while (ck_pr_load_uint(&ready) == 0);
|
||||
while (ck_pr_load_uint(&ready)) {
|
||||
ATOMIC;
|
||||
ATOMIC;
|
||||
ATOMIC;
|
||||
ATOMIC;
|
||||
ck_pr_store_64(count + i, count[i] + 1);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
uint64_t v, d;
|
||||
unsigned int i;
|
||||
pthread_t *threads;
|
||||
struct block *context;
|
||||
|
||||
if (argc != 3) {
|
||||
ck_error("Usage: " ATOMIC_STRING " <number of threads> <affinity delta>\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
nthr = atoi(argv[1]);
|
||||
if (nthr <= 0) {
|
||||
ck_error("ERROR: Number of threads must be greater than 0\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
threads = malloc(sizeof(pthread_t) * nthr);
|
||||
if (threads == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread structures\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
context = malloc(sizeof(struct block) * nthr);
|
||||
if (context == NULL) {
|
||||
ck_error("ERROR: Could not allocate thread contexts\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
a.delta = atoi(argv[2]);
|
||||
a.request = 0;
|
||||
|
||||
count = malloc(sizeof(uint64_t) * nthr);
|
||||
if (count == NULL) {
|
||||
ck_error("ERROR: Could not create acquisition buffer\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
memset(count, 0, sizeof(uint64_t) * nthr);
|
||||
|
||||
fprintf(stderr, "Creating threads (fairness)...");
|
||||
for (i = 0; i < nthr; i++) {
|
||||
context[i].tid = i;
|
||||
if (pthread_create(&threads[i], NULL, fairness, context + i)) {
|
||||
ck_error("ERROR: Could not create thread %d\n", i);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "done\n");
|
||||
|
||||
ck_pr_store_uint(&ready, 1);
|
||||
common_sleep(10);
|
||||
ck_pr_store_uint(&ready, 0);
|
||||
|
||||
fprintf(stderr, "Waiting for threads to finish acquisition regression...");
|
||||
for (i = 0; i < nthr; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
fprintf(stderr, "done\n\n");
|
||||
|
||||
for (i = 0, v = 0; i < nthr; i++) {
|
||||
printf("%d %15" PRIu64 "\n", i, count[i]);
|
||||
v += count[i];
|
||||
}
|
||||
|
||||
printf("\n# total : %15" PRIu64 "\n", v);
|
||||
printf("# throughput : %15" PRIu64 " a/s\n", (v /= nthr) / 10);
|
||||
|
||||
for (i = 0, d = 0; i < nthr; i++)
|
||||
d += (count[i] - v) * (count[i] - v);
|
||||
|
||||
printf("# average : %15" PRIu64 "\n", v);
|
||||
printf("# deviation : %.2f (%.2f%%)\n\n", sqrt(d / nthr), (sqrt(d / nthr) / v) * 100.00);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
16
regressions/ck_pr/benchmark/ck_pr_add_64.c
Normal file
16
regressions/ck_pr/benchmark/ck_pr_add_64.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <ck_pr.h>
|
||||
|
||||
#ifdef CK_F_PR_ADD_64
|
||||
#define ATOMIC ck_pr_add_64(object, 1)
|
||||
#define ATOMIC_STRING "ck_pr_add_64"
|
||||
#include "benchmark.h"
|
||||
#else
|
||||
#warning Did not find ADD_64 implementation.
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
16
regressions/ck_pr/benchmark/ck_pr_cas_64.c
Normal file
16
regressions/ck_pr/benchmark/ck_pr_cas_64.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <ck_pr.h>
|
||||
|
||||
#ifdef CK_F_PR_CAS_64
|
||||
#define ATOMIC ck_pr_cas_64(object, 1, 1)
|
||||
#define ATOMIC_STRING "ck_pr_cas_64"
|
||||
#include "benchmark.h"
|
||||
#else
|
||||
#warning Did not find CAS_64 implementation.
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
17
regressions/ck_pr/benchmark/ck_pr_cas_64_2.c
Normal file
17
regressions/ck_pr/benchmark/ck_pr_cas_64_2.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <ck_pr.h>
|
||||
|
||||
#ifdef CK_F_PR_CAS_64_2
|
||||
#define ATOMIC { uint64_t z[2] = {1, 2}; ck_pr_cas_64_2(object, z, z); }
|
||||
#define ATOMIC_STRING "ck_pr_cas_64_2"
|
||||
#include "benchmark.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
fprintf(stderr, "Unsupported.\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
16
regressions/ck_pr/benchmark/ck_pr_faa_64.c
Normal file
16
regressions/ck_pr/benchmark/ck_pr_faa_64.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <ck_pr.h>
|
||||
|
||||
#ifdef CK_F_PR_FAA_64
|
||||
#define ATOMIC ck_pr_faa_64(object, 1)
|
||||
#define ATOMIC_STRING "ck_pr_faa_64"
|
||||
#include "benchmark.h"
|
||||
#else
|
||||
#warning Did not find FAA_64 implementation.
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
17
regressions/ck_pr/benchmark/ck_pr_fas_64.c
Normal file
17
regressions/ck_pr/benchmark/ck_pr_fas_64.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <ck_pr.h>
|
||||
|
||||
#ifdef CK_F_PR_FAS_64
|
||||
#define ATOMIC ck_pr_fas_64(object, 1)
|
||||
#define ATOMIC_STRING "ck_pr_fas_64"
|
||||
#include "benchmark.h"
|
||||
#else
|
||||
#warning Did not find FAS_64 implementation.
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
16
regressions/ck_pr/benchmark/ck_pr_neg_64.c
Normal file
16
regressions/ck_pr/benchmark/ck_pr_neg_64.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <ck_pr.h>
|
||||
|
||||
#ifdef CK_F_PR_NEG_64
|
||||
#define ATOMIC ck_pr_neg_64(object)
|
||||
#define ATOMIC_STRING "ck_pr_neg_64"
|
||||
#include "benchmark.h"
|
||||
#else
|
||||
#warning Did not find NEG_64 implementation.
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
66
regressions/ck_pr/benchmark/fp.c
Normal file
66
regressions/ck_pr/benchmark/fp.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#ifndef IR
|
||||
#define IR 3000000
|
||||
#endif /* IR */
|
||||
|
||||
static int a CK_CC_CACHELINE;
|
||||
static int b CK_CC_CACHELINE;
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
uint64_t s, e;
|
||||
unsigned int i;
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < IR; i++) {
|
||||
ck_pr_load_int(&a);
|
||||
ck_pr_fence_strict_load();
|
||||
ck_pr_load_int(&b);
|
||||
}
|
||||
e = rdtsc();
|
||||
printf("[A] fence_load: %" PRIu64 "\n", (e - s) / IR);
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < IR; i++) {
|
||||
if (ck_pr_load_int(&a) == 0)
|
||||
ck_pr_barrier();
|
||||
ck_pr_fence_strict_lock();
|
||||
ck_pr_load_int(&b);
|
||||
}
|
||||
e = rdtsc();
|
||||
printf("[A] fence_lock: %" PRIu64 "\n", (e - s) / IR);
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < IR; i++) {
|
||||
ck_pr_store_int(&a, 0);
|
||||
ck_pr_fence_strict_store();
|
||||
ck_pr_store_int(&b, 0);
|
||||
}
|
||||
e = rdtsc();
|
||||
printf("[B] fence_store: %" PRIu64 "\n", (e - s) / IR);
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < IR; i++) {
|
||||
ck_pr_store_int(&a, 0);
|
||||
ck_pr_fence_strict_memory();
|
||||
ck_pr_load_int(&b);
|
||||
}
|
||||
e = rdtsc();
|
||||
printf("[C] fence_memory: %" PRIu64 "\n", (e - s) / IR);
|
||||
|
||||
s = rdtsc();
|
||||
for (i = 0; i < IR; i++) {
|
||||
ck_pr_store_int(&a, 0);
|
||||
ck_pr_faa_int(&a, 0);
|
||||
ck_pr_load_int(&b);
|
||||
}
|
||||
e = rdtsc();
|
||||
printf("[C] atomic: %" PRIu64 "\n", (e - s) / IR);
|
||||
return 0;
|
||||
}
|
84
regressions/ck_pr/validate/Makefile
Normal file
84
regressions/ck_pr/validate/Makefile
Normal file
|
@ -0,0 +1,84 @@
|
|||
.PHONY: check clean distribution
|
||||
|
||||
OBJECTS=ck_pr_cas ck_pr_faa ck_pr_inc ck_pr_dec ck_pr_bts \
|
||||
ck_pr_btr ck_pr_btc ck_pr_load ck_pr_store \
|
||||
ck_pr_and ck_pr_or ck_pr_xor ck_pr_add ck_pr_sub \
|
||||
ck_pr_fas ck_pr_bin ck_pr_btx ck_pr_fax ck_pr_n \
|
||||
ck_pr_unary
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
check: all
|
||||
for d in $(OBJECTS) ; do \
|
||||
echo $$d; \
|
||||
./$$d || exit 1; \
|
||||
done;
|
||||
|
||||
ck_pr_cas: ck_pr_cas.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_cas ck_pr_cas.c
|
||||
|
||||
ck_pr_inc: ck_pr_inc.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_inc ck_pr_inc.c
|
||||
|
||||
ck_pr_dec: ck_pr_dec.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_dec ck_pr_dec.c
|
||||
|
||||
ck_pr_faa: ck_pr_faa.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_faa ck_pr_faa.c
|
||||
|
||||
ck_pr_btc: ck_pr_btc.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_btc ck_pr_btc.c
|
||||
|
||||
ck_pr_btr: ck_pr_btr.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_btr ck_pr_btr.c
|
||||
|
||||
ck_pr_bts: ck_pr_bts.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_bts ck_pr_bts.c
|
||||
|
||||
ck_pr_load: ck_pr_load.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_load ck_pr_load.c
|
||||
|
||||
ck_pr_store: ck_pr_store.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_store ck_pr_store.c
|
||||
|
||||
ck_pr_and: ck_pr_and.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_and ck_pr_and.c
|
||||
|
||||
ck_pr_or: ck_pr_or.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_or ck_pr_or.c
|
||||
|
||||
ck_pr_xor: ck_pr_xor.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_xor ck_pr_xor.c
|
||||
|
||||
ck_pr_add: ck_pr_add.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_add ck_pr_add.c
|
||||
|
||||
ck_pr_sub: ck_pr_sub.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_sub ck_pr_sub.c
|
||||
|
||||
ck_pr_fas: ck_pr_fas.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_fas ck_pr_fas.c
|
||||
|
||||
ck_tp: ck_tp.c
|
||||
$(CC) $(CFLAGS) -o ck_tp ck_tp.c
|
||||
|
||||
ck_pr_bin: ck_pr_bin.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_bin ck_pr_bin.c
|
||||
|
||||
ck_pr_btx: ck_pr_btx.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_btx ck_pr_btx.c
|
||||
|
||||
ck_pr_fax: ck_pr_fax.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_fax ck_pr_fax.c
|
||||
|
||||
ck_pr_n: ck_pr_n.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_n ck_pr_n.c
|
||||
|
||||
ck_pr_unary: ck_pr_unary.c
|
||||
$(CC) $(CFLAGS) -o ck_pr_unary ck_pr_unary.c
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o $(OBJECTS) *.dSYM *.exe
|
||||
|
||||
include ../../../build/regressions.build
|
||||
CFLAGS+=-D_GNU_SOURCE
|
151
regressions/ck_pr/validate/ck_pr_add.c
Normal file
151
regressions/ck_pr/validate/ck_pr_add.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define CK_PR_ADD_T(w, v, d) \
|
||||
{ \
|
||||
uint##w##_t t = v; \
|
||||
ck_pr_add_##w(&t, d); \
|
||||
if (t != (uint##w##_t)(v + d)) { \
|
||||
printf("FAIL ["); \
|
||||
printf("%" PRIu##w " (%" PRIu##w ") -> %" PRIu##w "]\n",\
|
||||
(uint##w##_t)v, d, t); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_ADD_B(w) \
|
||||
{ \
|
||||
unsigned int __ck_i = 0; \
|
||||
printf("ck_pr_add_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
for (__ck_i = 0; __ck_i < R_REPEAT; __ck_i++) { \
|
||||
uint##w##_t a = common_rand() % ((uint##w##_t)-1 / 2); \
|
||||
uint##w##_t b = common_rand() % ((uint##w##_t)-1 / 2); \
|
||||
CK_PR_ADD_T(w, a, b); \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_ADD_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t t = -1, r = -1 & ~(uint##m##_t)(uint##w##_t)-1; \
|
||||
ck_pr_add_##w((uint##w##_t *)(void *)&t, 1); \
|
||||
if (t != r) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, r);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
t = 0, r = (uint##m##_t)(uint##w##_t)-1; \
|
||||
ck_pr_add_##w((uint##w##_t *)(void *)&t, -1); \
|
||||
if (t != r) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, r);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_ADD_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_ADD_32)
|
||||
CK_PR_ADD_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_ADD_16)
|
||||
CK_PR_ADD_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_ADD_8)
|
||||
CK_PR_ADD_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_ADD_64 */
|
||||
|
||||
#ifdef CK_F_PR_ADD_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_ADD_16)
|
||||
CK_PR_ADD_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_ADD_8)
|
||||
CK_PR_ADD_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_ADD_32 */
|
||||
|
||||
#if defined(CK_F_PR_ADD_16) && defined(CK_PR_ADD_8)
|
||||
if (m == 16) {
|
||||
CK_PR_ADD_W(16, 8);
|
||||
}
|
||||
#endif /* CK_PR_ADD_16 && CK_PR_ADD_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_ADD_64
|
||||
CK_PR_ADD_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_ADD_32
|
||||
CK_PR_ADD_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_ADD_16
|
||||
CK_PR_ADD_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_ADD_8
|
||||
CK_PR_ADD_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
147
regressions/ck_pr/validate/ck_pr_and.c
Normal file
147
regressions/ck_pr/validate/ck_pr_and.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define BM(m, w) ((uint##m##_t)-1 << (w))
|
||||
|
||||
#define CK_PR_AND_T(w, v, d) \
|
||||
{ \
|
||||
uint##w##_t t = v; \
|
||||
ck_pr_and_##w(&t, d); \
|
||||
if (t != (uint##w##_t)(v & d)) { \
|
||||
printf("FAIL ["); \
|
||||
printf("%" PRIu##w " (%" PRIu##w ") -> %" PRIu##w "]\n",\
|
||||
(uint##w##_t)v, d, t); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_AND_B(w) \
|
||||
{ \
|
||||
unsigned int __ck_i = 0; \
|
||||
printf("ck_pr_and_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
for (__ck_i = 0; __ck_i < R_REPEAT; __ck_i++) { \
|
||||
uint##w##_t a = (uint##w##_t)common_rand(); \
|
||||
uint##w##_t b = (uint##w##_t)common_rand(); \
|
||||
CK_PR_AND_T(w, a, b); \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_AND_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t t = -1; \
|
||||
ck_pr_and_##w((uint##w##_t *)(void *)&t, 0); \
|
||||
if (t != BM(m, w)) { \
|
||||
printf(" FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, BM(m, w)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_AND_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_AND_32)
|
||||
CK_PR_AND_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_AND_16)
|
||||
CK_PR_AND_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_AND_8)
|
||||
CK_PR_AND_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_AND_64 */
|
||||
|
||||
#ifdef CK_F_PR_AND_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_AND_16)
|
||||
CK_PR_AND_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_AND_8)
|
||||
CK_PR_AND_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_AND_32 */
|
||||
|
||||
#if defined(CK_F_PR_AND_16) && defined(CK_PR_AND_8)
|
||||
if (m == 16) {
|
||||
CK_PR_AND_W(16, 8);
|
||||
}
|
||||
#endif /* CK_PR_AND_16 && CK_PR_AND_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_AND_64
|
||||
CK_PR_AND_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_AND_32
|
||||
CK_PR_AND_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_AND_16
|
||||
CK_PR_AND_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_AND_8
|
||||
CK_PR_AND_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
94
regressions/ck_pr/validate/ck_pr_bin.c
Normal file
94
regressions/ck_pr/validate/ck_pr_bin.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <ck_pr.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#define REPEAT 2000000
|
||||
|
||||
#define TEST_BINARY(K, S, T, P, D) \
|
||||
static void \
|
||||
run_test_##K##_##S(void) \
|
||||
{ \
|
||||
int i, r; \
|
||||
T serial_result = 65535; \
|
||||
T ck_result = 65535; \
|
||||
\
|
||||
puts("***TESTING ck_pr_" #K "_" #S "***"); \
|
||||
common_srand((unsigned int)getpid()); \
|
||||
for (i = 0; i < REPEAT; ++i) { \
|
||||
r = common_rand(); \
|
||||
serial_result = serial_result P r; \
|
||||
ck_pr_##K##_##S(&ck_result, r); \
|
||||
} \
|
||||
\
|
||||
printf("Value of operation " #K " on 2000000 " \
|
||||
"random numbers\n\tusing " #P ": %" #D ",\n" \
|
||||
"\tusing ck_pr_"#K"_"#S": %" #D "\n", \
|
||||
serial_result, ck_result); \
|
||||
(serial_result == ck_result) ? puts("SUCCESS.") \
|
||||
: puts("FAILURE."); \
|
||||
\
|
||||
return; \
|
||||
} \
|
||||
|
||||
#define GENERATE_TEST(K, P) \
|
||||
TEST_BINARY(K, int, int, P, d) \
|
||||
TEST_BINARY(K, uint, unsigned int, P, u) \
|
||||
static void \
|
||||
run_test_##K(void) \
|
||||
{ \
|
||||
run_test_##K##_int(); \
|
||||
run_test_##K##_uint(); \
|
||||
\
|
||||
return; \
|
||||
}
|
||||
|
||||
GENERATE_TEST(add, +)
|
||||
GENERATE_TEST(sub, -)
|
||||
GENERATE_TEST(and, &)
|
||||
GENERATE_TEST(or, |)
|
||||
GENERATE_TEST(xor, ^)
|
||||
|
||||
#undef GENERATE_TEST
|
||||
#undef TEST_BINARY
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
run_test_add();
|
||||
run_test_sub();
|
||||
run_test_and();
|
||||
run_test_or();
|
||||
run_test_xor();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
96
regressions/ck_pr/validate/ck_pr_btc.c
Normal file
96
regressions/ck_pr/validate/ck_pr_btc.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Bit selector.
|
||||
*/
|
||||
#define BM(v, b) (((v) >> (b)) & 1)
|
||||
|
||||
#define CK_PR_BTC_T(w, v) \
|
||||
{ \
|
||||
unsigned int j; \
|
||||
uint##w##_t r = v; \
|
||||
bool t; \
|
||||
for (j = 0; j < (w); j++) { \
|
||||
t = ck_pr_btc_##w(&r, j); \
|
||||
if ((t && !BM(v, j)) || ((BM(v, j) + BM(r, j)) != 1)) { \
|
||||
printf("FAIL [%" PRIx##w ":%u]\n", r, j); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_BTC_B(w) \
|
||||
{ \
|
||||
uint##w##_t o; \
|
||||
unsigned int i; \
|
||||
printf("ck_pr_btc_" #w ": "); \
|
||||
for (i = 0; i < R_REPEAT; i++) { \
|
||||
o = (uint##w##_t)common_rand(); \
|
||||
CK_PR_BTC_T(w, o); \
|
||||
} \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_BTC_64
|
||||
CK_PR_BTC_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_BTC_32
|
||||
CK_PR_BTC_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_BTC_16
|
||||
CK_PR_BTC_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_BTC_8
|
||||
CK_PR_BTC_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
97
regressions/ck_pr/validate/ck_pr_btr.c
Normal file
97
regressions/ck_pr/validate/ck_pr_btr.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Bit selector.
|
||||
*/
|
||||
#define BM(v, b) (((v) >> (b)) & 1)
|
||||
|
||||
#define CK_PR_BTR_T(w, v) \
|
||||
{ \
|
||||
unsigned int j; \
|
||||
uint##w##_t r = v, c = v; \
|
||||
bool t; \
|
||||
for (j = 0; j < (w); j++) { \
|
||||
c &= (uint##w##_t)-1 ^ (1 << j); \
|
||||
t = ck_pr_btr_##w(&r, j); \
|
||||
if ((t && !BM(v, j)) || (r != c)) { \
|
||||
printf("FAIL [%" PRIx##w ":%u != %" PRIx##w ":%u]\n", r, j, c, j); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_BTR_B(w) \
|
||||
{ \
|
||||
uint##w##_t o; \
|
||||
unsigned int i; \
|
||||
printf("ck_pr_btr_" #w ": "); \
|
||||
for (i = 0; i < R_REPEAT; i++) { \
|
||||
o = (uint##w##_t)common_rand(); \
|
||||
CK_PR_BTR_T(w, o); \
|
||||
} \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_BTR_64
|
||||
CK_PR_BTR_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_BTR_32
|
||||
CK_PR_BTR_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_BTR_16
|
||||
CK_PR_BTR_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_BTR_8
|
||||
CK_PR_BTR_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
97
regressions/ck_pr/validate/ck_pr_bts.c
Normal file
97
regressions/ck_pr/validate/ck_pr_bts.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Bit selector.
|
||||
*/
|
||||
#define BM(v, b) (((v) >> (b)) & 1)
|
||||
|
||||
#define CK_PR_BTS_T(w, v) \
|
||||
{ \
|
||||
unsigned int j; \
|
||||
uint##w##_t r = v, c = v; \
|
||||
bool t; \
|
||||
for (j = 0; j < (w); j++) { \
|
||||
c |= (uint##w##_t)1 << j; \
|
||||
t = ck_pr_bts_##w(&r, j); \
|
||||
if ((t && !BM(v, j)) || (r != c)) { \
|
||||
printf("FAIL [%" PRIx##w ":%u != %" PRIx##w ":%u]\n", r, j, c, j); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_BTS_B(w) \
|
||||
{ \
|
||||
uint##w##_t o; \
|
||||
unsigned int i; \
|
||||
printf("ck_pr_bts_" #w ": "); \
|
||||
for (i = 0; i < R_REPEAT; i++) { \
|
||||
o = (uint##w##_t)common_rand(); \
|
||||
CK_PR_BTS_T(w, o); \
|
||||
} \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_BTS_64
|
||||
CK_PR_BTS_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_BTS_32
|
||||
CK_PR_BTS_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_BTS_16
|
||||
CK_PR_BTS_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_BTS_8
|
||||
CK_PR_BTS_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
112
regressions/ck_pr/validate/ck_pr_btx.c
Normal file
112
regressions/ck_pr/validate/ck_pr_btx.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#define REPEAT 2000000
|
||||
|
||||
#define TEST_BTX(K, S, M, T, L, P, D, R) \
|
||||
static bool \
|
||||
test_##K##_##S(M *target, int offset) \
|
||||
{ \
|
||||
T previous; \
|
||||
const L change = R (0x01 << offset); \
|
||||
\
|
||||
previous = (T)*target; \
|
||||
*target = previous P change; \
|
||||
return ((previous >> offset) & 0x01); \
|
||||
} \
|
||||
static void \
|
||||
run_test_##K##_##S(void) \
|
||||
{ \
|
||||
int i, offset, m; \
|
||||
bool serial_t, ck_pr_t; \
|
||||
T x = 65535, y = 65535; \
|
||||
\
|
||||
common_srand((unsigned int)getpid()); \
|
||||
m = sizeof(T) * 8; \
|
||||
\
|
||||
puts("***TESTING ck_pr_"#K"_"#S"***"); \
|
||||
for (i = 0; i < REPEAT; ++i) { \
|
||||
offset = common_rand() % m; \
|
||||
serial_t = test_##K##_##S(&x, offset); \
|
||||
ck_pr_t = ck_pr_##K##_##S(&y, offset); \
|
||||
\
|
||||
if (serial_t != ck_pr_t || x != y ) { \
|
||||
printf("Serial(%"#D") and ck_pr(%"#D")" \
|
||||
#K"_"#S " do not match.\n" \
|
||||
"FAILURE.\n", \
|
||||
serial_t, ck_pr_t); \
|
||||
\
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
printf("\tserial_"#K"_"#S": %"#D"\n" \
|
||||
"\tck_pr_"#K"_"#S": %"#D"\n" \
|
||||
"SUCCESS.\n", \
|
||||
x, y); \
|
||||
\
|
||||
return; \
|
||||
}
|
||||
|
||||
#define TEST_BTX_S(K, S, T, P, D, R) TEST_BTX(K, S, T, T, T, P, D, R)
|
||||
|
||||
#define GENERATE_TEST(K, P, R) \
|
||||
TEST_BTX_S(K, int, int, P, d, R) \
|
||||
TEST_BTX_S(K, uint, unsigned int, P, u, R) \
|
||||
static void \
|
||||
run_test_##K(void) \
|
||||
{ \
|
||||
run_test_##K##_int(); \
|
||||
run_test_##K##_uint(); \
|
||||
\
|
||||
return; \
|
||||
}
|
||||
|
||||
GENERATE_TEST(btc, ^, 0+)
|
||||
GENERATE_TEST(btr, &, ~)
|
||||
GENERATE_TEST(bts, |, 0+)
|
||||
|
||||
#undef GENERATE_TEST
|
||||
#undef TEST_BTX_S
|
||||
#undef TEST_BTX
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
run_test_btc();
|
||||
run_test_btr();
|
||||
run_test_bts();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
158
regressions/ck_pr/validate/ck_pr_cas.c
Normal file
158
regressions/ck_pr/validate/ck_pr_cas.c
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define W(w, x) (uint##w##_t)((x) & (uint##w##_t)~0)
|
||||
|
||||
#define CK_PR_CAS_T(w, v, c, s) \
|
||||
{ \
|
||||
uint##w##_t t = v; \
|
||||
bool r; \
|
||||
r = ck_pr_cas_##w(&t, c, s); \
|
||||
if (((c == v) && (r == false)) || ((c != v) && (r == true)) || \
|
||||
((r == true) && (W(w, s) != t))) { \
|
||||
printf("FAIL ["); \
|
||||
printf("%" PRIu##w " (%" PRIu##w " -> %" PRIu##w ")" \
|
||||
" -> %" PRIu##w "]\n", \
|
||||
(uint##w##_t)(v), (uint##w##_t)(c), W(w, s), (uint##w##_t)(t)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_CAS_B(w) \
|
||||
{ \
|
||||
unsigned int __ck_i; \
|
||||
printf("ck_pr_cas_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
for (__ck_i = 0; __ck_i < R_REPEAT; __ck_i++) { \
|
||||
uint##w##_t a = common_rand() % (uint##w##_t)-1; \
|
||||
CK_PR_CAS_T(w, a, a + 1, (a - 1)); \
|
||||
CK_PR_CAS_T(w, a, a, (a - 1)); \
|
||||
CK_PR_CAS_T(w, a, a + 1, a); \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_CAS_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t t = -1, r = -1 & ~(uint##m##_t)(uint##w##_t)-1; \
|
||||
ck_pr_cas_##w((uint##w##_t *)(void *)&t, (uint##w##_t)t, 0); \
|
||||
if (t != r) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", \
|
||||
(uint##m##_t)t, (uint##m##_t)r); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_CAS_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_CAS_32)
|
||||
CK_PR_CAS_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_CAS_16)
|
||||
CK_PR_CAS_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_CAS_8)
|
||||
CK_PR_CAS_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_CAS_64 */
|
||||
|
||||
#ifdef CK_F_PR_CAS_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_CAS_16)
|
||||
CK_PR_CAS_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_CAS_8)
|
||||
CK_PR_CAS_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_CAS_32 */
|
||||
|
||||
#if defined(CK_F_PR_CAS_16) && defined(CK_PR_CAS_8)
|
||||
if (m == 16) {
|
||||
CK_PR_CAS_W(16, 8);
|
||||
}
|
||||
#endif /* CK_PR_CAS_16 && CK_PR_CAS_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_CAS_64
|
||||
CK_PR_CAS_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_CAS_32
|
||||
CK_PR_CAS_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_CAS_16
|
||||
CK_PR_CAS_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_CAS_8
|
||||
CK_PR_CAS_B(8);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_CAS_64_VALUE
|
||||
uint64_t a = 0xffffffffaaaaaaaa, b = 0x8888888800000000;
|
||||
|
||||
printf("%" PRIx64 " (%" PRIx64 ") -> ", b, a);
|
||||
ck_pr_cas_64_value(&a, a, b, &b);
|
||||
printf("%" PRIx64 " (%" PRIx64 ")\n", b, a);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
143
regressions/ck_pr/validate/ck_pr_dec.c
Normal file
143
regressions/ck_pr/validate/ck_pr_dec.c
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define CK_PR_DEC_T(w, v) \
|
||||
{ \
|
||||
uint##w##_t t = v; \
|
||||
ck_pr_dec_##w(&t); \
|
||||
if ((t != (uint##w##_t)(v - 1))) { \
|
||||
printf("FAIL ["); \
|
||||
printf("%" PRIu##w " -> %" PRIu##w "]\n", (uint##w##_t)v, t); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_DEC_B(w) \
|
||||
{ \
|
||||
unsigned int __ck_i = 0; \
|
||||
printf("ck_pr_dec_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
for (__ck_i = 0; __ck_i < R_REPEAT; __ck_i++) { \
|
||||
uint##w##_t a = common_rand() % ((uint##w##_t)-1); \
|
||||
CK_PR_DEC_T(w, a); \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_DEC_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t t = 0, r = (uint##w##_t)-1; \
|
||||
ck_pr_dec_##w((uint##w##_t *)(void *)&t); \
|
||||
if (t != r) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, r);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_DEC_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_DEC_32)
|
||||
CK_PR_DEC_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_DEC_16)
|
||||
CK_PR_DEC_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_DEC_8)
|
||||
CK_PR_DEC_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_DEC_64 */
|
||||
|
||||
#ifdef CK_F_PR_DEC_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_DEC_16)
|
||||
CK_PR_DEC_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_DEC_8)
|
||||
CK_PR_DEC_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_DEC_32 */
|
||||
|
||||
#if defined(CK_F_PR_DEC_16) && defined(CK_PR_DEC_8)
|
||||
if (m == 16) {
|
||||
CK_PR_DEC_W(16, 8);
|
||||
}
|
||||
#endif /* CK_PR_DEC_16 && CK_PR_DEC_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_DEC_64
|
||||
CK_PR_DEC_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_DEC_32
|
||||
CK_PR_DEC_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_DEC_16
|
||||
CK_PR_DEC_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_DEC_8
|
||||
CK_PR_DEC_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
152
regressions/ck_pr/validate/ck_pr_faa.c
Normal file
152
regressions/ck_pr/validate/ck_pr_faa.c
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define CK_PR_FAA_T(w, v, d) \
|
||||
{ \
|
||||
uint##w##_t r, t = v; \
|
||||
r = ck_pr_faa_##w(&t, d); \
|
||||
if ((t != (uint##w##_t)(v + d)) || (r != v)) { \
|
||||
printf("FAIL ["); \
|
||||
printf("%" PRIu##w " (%" PRIu##w ") -> %" PRIu##w \
|
||||
" (%" PRIu##w ")]\n", \
|
||||
(uint##w##_t)v, d, t, r); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_FAA_B(w) \
|
||||
{ \
|
||||
unsigned int __ck_i = 0; \
|
||||
printf("ck_pr_faa_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
for (__ck_i = 0; __ck_i < R_REPEAT; __ck_i++) { \
|
||||
uint##w##_t a = common_rand() % ((uint##w##_t)-1 / 2); \
|
||||
uint##w##_t b = common_rand() % ((uint##w##_t)-1 / 2); \
|
||||
CK_PR_FAA_T(w, a, b); \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_FAA_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t t = -1, r = -1 & ~(uint##m##_t)(uint##w##_t)-1; \
|
||||
ck_pr_faa_##w((uint##w##_t *)(void *)&t, 1); \
|
||||
if (t != r) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, r);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
t = 0, r = (uint##m##_t)(uint##w##_t)-1; \
|
||||
ck_pr_faa_##w((uint##w##_t *)(void *)&t, -1); \
|
||||
if (t != r) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, r);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_FAA_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_FAA_32)
|
||||
CK_PR_FAA_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_FAA_16)
|
||||
CK_PR_FAA_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_FAA_8)
|
||||
CK_PR_FAA_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_FAA_64 */
|
||||
|
||||
#ifdef CK_F_PR_FAA_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_FAA_16)
|
||||
CK_PR_FAA_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_FAA_8)
|
||||
CK_PR_FAA_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_FAA_32 */
|
||||
|
||||
#if defined(CK_F_PR_FAA_16) && defined(CK_PR_FAA_8)
|
||||
if (m == 16) {
|
||||
CK_PR_FAA_W(16, 8);
|
||||
}
|
||||
#endif /* CK_PR_FAA_16 && CK_PR_FAA_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_FAA_64
|
||||
CK_PR_FAA_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_FAA_32
|
||||
CK_PR_FAA_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_FAA_16
|
||||
CK_PR_FAA_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_FAA_8
|
||||
CK_PR_FAA_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
148
regressions/ck_pr/validate/ck_pr_fas.c
Normal file
148
regressions/ck_pr/validate/ck_pr_fas.c
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define BM(m, w) ((uint##m##_t)(uint##w##_t)(-1))
|
||||
|
||||
#define CK_PR_FAS_T(w, v, d) \
|
||||
{ \
|
||||
uint##w##_t r, t = v; \
|
||||
r = ck_pr_fas_##w(&t, d); \
|
||||
if ((t != d) || (r != v)) { \
|
||||
printf("FAIL ["); \
|
||||
printf("%" PRIu##w " (%" PRIu##w ") -> %" PRIu##w \
|
||||
" (%" PRIu##w ")]\n", \
|
||||
(uint##w##_t)v, d, t, r); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_FAS_B(w) \
|
||||
{ \
|
||||
unsigned int __ck_i = 0; \
|
||||
printf("ck_pr_fas_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
for (__ck_i = 0; __ck_i < R_REPEAT; __ck_i++) { \
|
||||
uint##w##_t a = common_rand(); \
|
||||
uint##w##_t b = common_rand(); \
|
||||
CK_PR_FAS_T(w, a, b); \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_FAS_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t t = 0; \
|
||||
ck_pr_fas_##w((uint##w##_t *)(void *)&t, -1); \
|
||||
if (t != BM(m, w)) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, BM(m, w)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_FAS_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_FAS_32)
|
||||
CK_PR_FAS_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_FAS_16)
|
||||
CK_PR_FAS_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_FAS_8)
|
||||
CK_PR_FAS_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_FAS_64 */
|
||||
|
||||
#ifdef CK_F_PR_FAS_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_FAS_16)
|
||||
CK_PR_FAS_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_FAS_8)
|
||||
CK_PR_FAS_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_FAS_32 */
|
||||
|
||||
#if defined(CK_F_PR_FAS_16) && defined(CK_PR_FAS_8)
|
||||
if (m == 16) {
|
||||
CK_PR_FAS_W(16, 8);
|
||||
}
|
||||
#endif /* CK_PR_FAS_16 && CK_PR_FAS_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_FAS_64
|
||||
CK_PR_FAS_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_FAS_32
|
||||
CK_PR_FAS_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_FAS_16
|
||||
CK_PR_FAS_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_FAS_8
|
||||
CK_PR_FAS_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
121
regressions/ck_pr/validate/ck_pr_fax.c
Normal file
121
regressions/ck_pr/validate/ck_pr_fax.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#define REPEAT 2000000
|
||||
|
||||
#define TEST_FAX_FN(S, T, M) \
|
||||
static T \
|
||||
test_faa_##S(M *target, T delta) \
|
||||
{ \
|
||||
T previous = (T)*target; \
|
||||
*target = (T)*target + delta; \
|
||||
\
|
||||
return (previous); \
|
||||
} \
|
||||
static T \
|
||||
test_fas_##S(M *target, T update) \
|
||||
{ \
|
||||
T previous = *target; \
|
||||
*target = update; \
|
||||
\
|
||||
return (previous); \
|
||||
}
|
||||
|
||||
#define TEST_FAX_FN_S(S, T) TEST_FAX_FN(S, T, T)
|
||||
|
||||
TEST_FAX_FN_S(int, int)
|
||||
TEST_FAX_FN_S(uint, unsigned int)
|
||||
|
||||
#undef TEST_FAX_FN_S
|
||||
#undef TEST_FAX_FN
|
||||
|
||||
#define TEST_FAX(K, S, T, D) \
|
||||
static void \
|
||||
run_test_##K##_##S(void) \
|
||||
{ \
|
||||
int i, r; \
|
||||
T x = 0, y = 0, x_b, y_b; \
|
||||
\
|
||||
puts("***TESTING ck_pr_"#K"_"#S"***"); \
|
||||
common_srand((unsigned int)getpid()); \
|
||||
for (i = 0; i < REPEAT; ++i) { \
|
||||
r = common_rand(); \
|
||||
x_b = test_##K##_##S(&x, r); \
|
||||
y_b = ck_pr_##K##_##S(&y, r); \
|
||||
\
|
||||
if (x_b != y_b) { \
|
||||
printf("Serial fetch does not match ck_pr fetch.\n" \
|
||||
"\tSerial: %"#D"\n" \
|
||||
"\tck_pr: %"#D"\n", \
|
||||
x_b, y_b); \
|
||||
\
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
printf("Final result:\n" \
|
||||
"\tSerial: %"#D"\n" \
|
||||
"\tck_pr: %"#D"\n", \
|
||||
x, y); \
|
||||
(x == y) ? puts("SUCCESS.") \
|
||||
: puts("FAILURE."); \
|
||||
\
|
||||
return; \
|
||||
} \
|
||||
|
||||
|
||||
#define GENERATE_TEST(K) \
|
||||
TEST_FAX(K, int, int, d) \
|
||||
TEST_FAX(K, uint, unsigned int, u) \
|
||||
static void \
|
||||
run_test_##K(void) \
|
||||
{ \
|
||||
run_test_##K##_int(); \
|
||||
run_test_##K##_uint(); \
|
||||
}
|
||||
|
||||
GENERATE_TEST(faa)
|
||||
GENERATE_TEST(fas)
|
||||
|
||||
#undef GENERATE_TEST
|
||||
#undef TEST_FAX
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
run_test_faa();
|
||||
run_test_fas();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
143
regressions/ck_pr/validate/ck_pr_inc.c
Normal file
143
regressions/ck_pr/validate/ck_pr_inc.c
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define CK_PR_INC_T(w, v) \
|
||||
{ \
|
||||
uint##w##_t t = v; \
|
||||
ck_pr_inc_##w(&t); \
|
||||
if ((t != (uint##w##_t)(v + 1))) { \
|
||||
printf("FAIL [%" PRIu##w " -> %" PRIu##w "]\n", \
|
||||
(uint##w##_t)v, t); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_INC_B(w) \
|
||||
{ \
|
||||
unsigned int __ck_i = 0; \
|
||||
printf("ck_pr_inc_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
for (__ck_i = 0; __ck_i < R_REPEAT; __ck_i++) { \
|
||||
uint##w##_t a = common_rand() % ((uint##w##_t)-1); \
|
||||
CK_PR_INC_T(w, a); \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_INC_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t t = -1, r = -1 & ~(uint##m##_t)(uint##w##_t)-1; \
|
||||
ck_pr_inc_##w((uint##w##_t *)(void *)&t); \
|
||||
if (t != r) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, r);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_INC_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_INC_32)
|
||||
CK_PR_INC_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_INC_16)
|
||||
CK_PR_INC_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_INC_8)
|
||||
CK_PR_INC_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_INC_64 */
|
||||
|
||||
#ifdef CK_F_PR_INC_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_INC_16)
|
||||
CK_PR_INC_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_INC_8)
|
||||
CK_PR_INC_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_INC_32 */
|
||||
|
||||
#if defined(CK_F_PR_INC_16) && defined(CK_PR_INC_8)
|
||||
if (m == 16) {
|
||||
CK_PR_INC_W(16, 8);
|
||||
}
|
||||
#endif /* CK_PR_INC_16 && CK_PR_INC_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_INC_64
|
||||
CK_PR_INC_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_INC_32
|
||||
CK_PR_INC_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_INC_16
|
||||
CK_PR_INC_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_INC_8
|
||||
CK_PR_INC_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
149
regressions/ck_pr/validate/ck_pr_load.c
Normal file
149
regressions/ck_pr/validate/ck_pr_load.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define CK_PR_LOAD_B(w) \
|
||||
{ \
|
||||
uint##w##_t t = (uint##w##_t)-1, a = 0; \
|
||||
unsigned int i; \
|
||||
printf("ck_pr_load_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
a = ck_pr_load_##w(&t); \
|
||||
if (a != t) { \
|
||||
printf("FAIL [%#" PRIx##w " != %#" PRIx##w "]\n", a, t); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
for (i = 0; i < R_REPEAT; i++) { \
|
||||
t = (uint##w##_t)common_rand(); \
|
||||
a = ck_pr_load_##w(&t); \
|
||||
if (a != t) { \
|
||||
printf("FAIL [%#" PRIx##w " != %#" PRIx##w "]\n", a, t);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_LOAD_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t f = 0; \
|
||||
uint##w##_t j = (uint##w##_t)-1; \
|
||||
f = ck_pr_load_##w(&j); \
|
||||
if (f != j) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##w "]\n", f, j);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_LOAD_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_LOAD_32)
|
||||
CK_PR_LOAD_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_LOAD_16)
|
||||
CK_PR_LOAD_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_LOAD_8)
|
||||
CK_PR_LOAD_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_LOAD_64 */
|
||||
|
||||
#ifdef CK_F_PR_LOAD_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_LOAD_16)
|
||||
CK_PR_LOAD_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_LOAD_8)
|
||||
CK_PR_LOAD_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_LOAD_32 */
|
||||
|
||||
#if defined(CK_F_PR_LOAD_16) && defined(CK_PR_LOAD_8)
|
||||
if (m == 16)
|
||||
CK_PR_LOAD_W(16, 8);
|
||||
#endif /* CK_PR_LOAD_16 && CK_PR_LOAD_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_LOAD_64
|
||||
CK_PR_LOAD_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_LOAD_32
|
||||
CK_PR_LOAD_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_LOAD_16
|
||||
CK_PR_LOAD_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_LOAD_8
|
||||
CK_PR_LOAD_B(8);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
uint64_t a[2] = {0, 0}, b[2] = {0x1111111144444444, 0x2222222266666666};
|
||||
printf("%" PRIx64 ":%" PRIx64 " -> ", a[0], a[1]);
|
||||
ck_pr_load_64_2(&b, &a);
|
||||
printf("%" PRIx64 ":%" PRIx64 "\n", a[0], a[1]);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
90
regressions/ck_pr/validate/ck_pr_n.c
Normal file
90
regressions/ck_pr/validate/ck_pr_n.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2011 David Joseph.
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#define REPEAT 2000000
|
||||
|
||||
#define TEST_N(K, S, T, P, D) \
|
||||
static void \
|
||||
run_test_##K##_##S(void) \
|
||||
{ \
|
||||
int i, r; \
|
||||
T x = 0, y = 0; \
|
||||
\
|
||||
puts("***TESTING ck_pr_"#K"_"#S"***"); \
|
||||
common_srand((unsigned int)getpid()); \
|
||||
for (i = 0; i < REPEAT; ++i) { \
|
||||
r = common_rand(); \
|
||||
x += r; \
|
||||
x = P x; \
|
||||
y += r; \
|
||||
ck_pr_##K##_##S(&y); \
|
||||
} \
|
||||
\
|
||||
printf("Value of operation "#K" on 2000000 " \
|
||||
"random numbers\n" \
|
||||
"\tusing "#P": %"#D",\n" \
|
||||
"\tusing ck_pr_"#K"_"#S": %"#D",\n", \
|
||||
x, y); \
|
||||
(x == y) ? puts("SUCCESS.") \
|
||||
: puts("FAILURE."); \
|
||||
\
|
||||
return; \
|
||||
}
|
||||
|
||||
#define GENERATE_TEST(K, P) \
|
||||
TEST_N(K, int, int, P, d) \
|
||||
TEST_N(K, uint, unsigned int, P, u) \
|
||||
static void \
|
||||
run_test_##K(void) \
|
||||
{ \
|
||||
run_test_##K##_int(); \
|
||||
run_test_##K##_uint(); \
|
||||
\
|
||||
return; \
|
||||
}
|
||||
|
||||
GENERATE_TEST(not, ~)
|
||||
GENERATE_TEST(neg, -)
|
||||
|
||||
#undef GENERATE_TEST
|
||||
#undef TEST_N
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
run_test_not();
|
||||
run_test_neg();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
149
regressions/ck_pr/validate/ck_pr_or.c
Normal file
149
regressions/ck_pr/validate/ck_pr_or.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define BM(m, w) (uint##m##_t)(uint##w##_t)-1
|
||||
|
||||
#define CK_PR_OR_T(w, v, d) \
|
||||
{ \
|
||||
uint##w##_t t; \
|
||||
ck_pr_or_##w(&t, 1ULL << (w - 1)); \
|
||||
t = v; \
|
||||
ck_pr_or_##w(&t, d); \
|
||||
if (t != (uint##w##_t)(v | d)) { \
|
||||
printf("FAIL ["); \
|
||||
printf("%" PRIu##w " (%" PRIu##w ") -> %" PRIu##w "]\n",\
|
||||
(uint##w##_t)v, d, t); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_OR_B(w) \
|
||||
{ \
|
||||
unsigned int __ck_i = 0; \
|
||||
printf("ck_pr_or_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
for (__ck_i = 0; __ck_i < R_REPEAT; __ck_i++) { \
|
||||
uint##w##_t a = (uint##w##_t)common_rand(); \
|
||||
uint##w##_t b = (uint##w##_t)common_rand(); \
|
||||
CK_PR_OR_T(w, a, b); \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_OR_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t t = 0; \
|
||||
ck_pr_or_##w((uint##w##_t *)(void *)&t, -1); \
|
||||
if (t != BM(m, w)) { \
|
||||
printf(" FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, BM(m, w)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_OR_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_OR_32)
|
||||
CK_PR_OR_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_OR_16)
|
||||
CK_PR_OR_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_OR_8)
|
||||
CK_PR_OR_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_OR_64 */
|
||||
|
||||
#ifdef CK_F_PR_OR_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_OR_16)
|
||||
CK_PR_OR_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_OR_8)
|
||||
CK_PR_OR_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_OR_32 */
|
||||
|
||||
#if defined(CK_F_PR_OR_16) && defined(CK_PR_OR_8)
|
||||
if (m == 16) {
|
||||
CK_PR_OR_W(16, 8);
|
||||
}
|
||||
#endif /* CK_PR_OR_16 && CK_PR_OR_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_OR_64
|
||||
CK_PR_OR_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_OR_32
|
||||
CK_PR_OR_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_OR_16
|
||||
CK_PR_OR_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_OR_8
|
||||
CK_PR_OR_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
150
regressions/ck_pr/validate/ck_pr_store.c
Normal file
150
regressions/ck_pr/validate/ck_pr_store.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright 2009 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 "../../common.h"
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define CK_PR_STORE_B(w) \
|
||||
{ \
|
||||
uint##w##_t t = (uint##w##_t)-1, a = 0, b; \
|
||||
ck_pr_store_##w(&b, 1ULL << (w - 1)); \
|
||||
unsigned int i; \
|
||||
printf("ck_pr_store_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
ck_pr_store_##w(&a, t); \
|
||||
if (a != t) { \
|
||||
printf("FAIL [%#" PRIx##w " != %#" PRIx##w "]\n", a, t); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
for (i = 0; i < R_REPEAT; i++) { \
|
||||
t = (uint##w##_t)common_rand(); \
|
||||
ck_pr_store_##w(&a, t); \
|
||||
if (a != t) { \
|
||||
printf("FAIL [%#" PRIx##w " != %#" PRIx##w "]\n", a, t);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf("SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_STORE_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t f = 0; \
|
||||
uint##w##_t j = (uint##w##_t)-1; \
|
||||
ck_pr_store_##w((uint##w##_t *)(void *)&f, j); \
|
||||
if (f != j) { \
|
||||
printf("FAIL [%#" PRIx##m " != %#" PRIx##w "]\n", f, j);\
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_STORE_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_STORE_32)
|
||||
CK_PR_STORE_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_STORE_16)
|
||||
CK_PR_STORE_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_STORE_8)
|
||||
CK_PR_STORE_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_STORE_64 */
|
||||
|
||||
#ifdef CK_F_PR_STORE_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_STORE_16)
|
||||
CK_PR_STORE_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_STORE_8)
|
||||
CK_PR_STORE_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_STORE_32 */
|
||||
|
||||
#if defined(CK_F_PR_STORE_16) && defined(CK_PR_STORE_8)
|
||||
if (m == 16)
|
||||
CK_PR_STORE_W(16, 8);
|
||||
#endif /* CK_PR_STORE_16 && CK_PR_STORE_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
#if defined(CK_F_PR_STORE_DOUBLE) && defined(CK_F_PR_LOAD_DOUBLE)
|
||||
double d;
|
||||
|
||||
ck_pr_store_double(&d, 0.0);
|
||||
if (ck_pr_load_double(&d) != 0.0) {
|
||||
ck_error("Stored 0 in double, did not find 0.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_STORE_64
|
||||
CK_PR_STORE_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_STORE_32
|
||||
CK_PR_STORE_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_STORE_16
|
||||
CK_PR_STORE_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_STORE_8
|
||||
CK_PR_STORE_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
151
regressions/ck_pr/validate/ck_pr_sub.c
Normal file
151
regressions/ck_pr/validate/ck_pr_sub.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright 2009 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 <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ck_pr.h>
|
||||
|
||||
#include "../../common.h"
|
||||
#ifndef R_REPEAT
|
||||
#define R_REPEAT 200000
|
||||
#endif
|
||||
|
||||
#define CK_PR_SUB_T(w, v, d) \
|
||||
{ \
|
||||
uint##w##_t t = v; \
|
||||
ck_pr_sub_##w(&t, d); \
|
||||
if (t != (uint##w##_t)(v - d)) { \
|
||||
printf("FAIL ["); \
|
||||
printf("%" PRIu##w " (%" PRIu##w ") -> %" PRIu##w "]\n", \
|
||||
(uint##w##_t)v, d, t); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CK_PR_SUB_B(w) \
|
||||
{ \
|
||||
unsigned int __ck_i = 0; \
|
||||
printf("ck_pr_sub_" #w ": "); \
|
||||
if (w < 10) \
|
||||
printf(" "); \
|
||||
for (__ck_i = 0; __ck_i < R_REPEAT; __ck_i++) { \
|
||||
uint##w##_t a = common_rand() % ((uint##w##_t)-1 / 2); \
|
||||
uint##w##_t b = common_rand() % ((uint##w##_t)-1 / 2); \
|
||||
CK_PR_SUB_T(w, a, b); \
|
||||
} \
|
||||
rg_width(w); \
|
||||
printf(" SUCCESS\n"); \
|
||||
}
|
||||
|
||||
#define CK_PR_SUB_W(m, w) \
|
||||
{ \
|
||||
uint##m##_t t = 0, r = (uint##m##_t)(uint##w##_t)-1; \
|
||||
ck_pr_sub_##w((uint##w##_t *)(void *)&t, 1); \
|
||||
if (t != r) { \
|
||||
printf(" FAIL [%#" PRIx##m " != %#" PRIx##m "]\n", t, r); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
t = 0; \
|
||||
ck_pr_sub_##w((uint##w##_t *)(void *)&t, -1); \
|
||||
if (t != 1) { \
|
||||
printf(" FAIL [%#" PRIx##m " != 1]\n", t); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
static void
|
||||
rg_width(int m)
|
||||
{
|
||||
|
||||
/* Other architectures are bi-endian. */
|
||||
#if !defined(__x86__) && !defined(__x86_64__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_SUB_64
|
||||
if (m == 64) {
|
||||
#if defined(CK_F_PR_SUB_32)
|
||||
CK_PR_SUB_W(64, 32);
|
||||
#endif
|
||||
#if defined(CK_PR_SUB_16)
|
||||
CK_PR_SUB_W(64, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_SUB_8)
|
||||
CK_PR_SUB_W(64, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_SUB_64 */
|
||||
|
||||
#ifdef CK_F_PR_SUB_32
|
||||
if (m == 32) {
|
||||
#if defined(CK_F_PR_SUB_16)
|
||||
CK_PR_SUB_W(32, 16);
|
||||
#endif
|
||||
#if defined(CK_PR_SUB_8)
|
||||
CK_PR_SUB_W(32, 8);
|
||||
#endif
|
||||
}
|
||||
#endif /* CK_PR_SUB_32 */
|
||||
|
||||
#if defined(CK_F_PR_SUB_16) && defined(CK_PR_SUB_8)
|
||||
if (m == 16) {
|
||||
CK_PR_SUB_W(16, 8);
|
||||
}
|
||||
#endif /* CK_PR_SUB_16 && CK_PR_SUB_8 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
||||
common_srand((unsigned int)getpid());
|
||||
|
||||
#ifdef CK_F_PR_SUB_64
|
||||
CK_PR_SUB_B(64);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_SUB_32
|
||||
CK_PR_SUB_B(32);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_SUB_16
|
||||
CK_PR_SUB_B(16);
|
||||
#endif
|
||||
|
||||
#ifdef CK_F_PR_SUB_8
|
||||
CK_PR_SUB_B(8);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue