diff --git a/test/core/support/stack_lockfree_test.c b/test/core/support/stack_lockfree_test.c index 4b6cf3f89b9..ebee04d5b89 100644 --- a/test/core/support/stack_lockfree_test.c +++ b/test/core/support/stack_lockfree_test.c @@ -33,20 +33,23 @@ #include "src/core/support/stack_lockfree.h" -#include <stddef.h> #include <stdlib.h> -#include <string.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/useful.h> +#include <grpc/support/sync.h> +#include <grpc/support/thd.h> #include "test/core/util/test_config.h" -void test_serial() { - gpr_stack_lockfree *stack = gpr_stack_lockfree_create(128); +/* max stack size supported */ +#define MAX_STACK_SIZE 65534 + +#define MAX_THREADS 32 + +static void test_serial_sized(int size) { + gpr_stack_lockfree *stack = gpr_stack_lockfree_create(size); int i; - + /* First try popping empty */ GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1); @@ -54,22 +57,98 @@ void test_serial() { gpr_stack_lockfree_push(stack, 3); GPR_ASSERT(gpr_stack_lockfree_pop(stack) == 3); GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1); - + /* Now add repeatedly more items and check them */ - for (i=0; i<128; i++) { + for (i=1; i<size; i*=2) { int j; for (j=0; j<=i; j++) { gpr_stack_lockfree_push(stack, j); } for (j=0; j<=i; j++) { - GPR_ASSERT(gpr_stack_lockfree_pop(stack) == i-j); + GPR_ASSERT(gpr_stack_lockfree_pop(stack) == i-j); } GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1); } + + gpr_stack_lockfree_destroy(stack); +} + +static void test_serial() { + int i; + for (i=128; i<MAX_STACK_SIZE; i*=2) { + test_serial_sized(i); + } + test_serial_sized(MAX_STACK_SIZE); +} + +struct test_arg { + gpr_stack_lockfree *stack; + int stack_size; + int nthreads; + int rank; + int sum; +}; + +static void test_mt_body(void *v) { + struct test_arg *arg = (struct test_arg *)v; + int lo, hi; + int i; + int res; + lo = arg->rank*arg->stack_size/arg->nthreads; + hi = (arg->rank+1)*arg->stack_size/arg->nthreads; + for (i=lo; i<hi; i++) { + gpr_stack_lockfree_push(arg->stack, i); + if ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) { + arg->sum += res; + } + } + while ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) { + arg->sum += res; + } +} + +static void test_mt_sized(int size, int nth) { + gpr_stack_lockfree *stack; + struct test_arg args[MAX_THREADS]; + gpr_thd_id thds[MAX_THREADS]; + int sum; + int i; + gpr_thd_options options = gpr_thd_options_default(); + + stack = gpr_stack_lockfree_create(size); + for (i=0; i<nth; i++) { + args[i].stack = stack; + args[i].stack_size = size; + args[i].nthreads = nth; + args[i].rank = i; + args[i].sum = 0; + } + gpr_thd_options_set_joinable(&options); + for (i = 0; i < nth; i++) { + GPR_ASSERT(gpr_thd_new(&thds[i], test_mt_body, &args[i], &options)); + } + sum = 0; + for (i = 0; i < nth; i++) { + gpr_thd_join(thds[i]); + sum = sum + args[i].sum; + } + GPR_ASSERT((unsigned)sum == ((unsigned)size*(size-1))/2); + gpr_stack_lockfree_destroy(stack); +} + +static void test_mt() { + int size, nth; + for (nth=1; nth < MAX_THREADS; nth++) { + for (size=128; size < MAX_STACK_SIZE; size*=2) { + test_mt_sized(size,nth); + } + test_mt_sized(MAX_STACK_SIZE,nth); + } } int main(int argc, char **argv) { grpc_test_init(argc, argv); test_serial(); + test_mt(); return 0; }