diff options
Diffstat (limited to 'dependencies/uthash/tests/threads')
-rw-r--r-- | dependencies/uthash/tests/threads/Makefile | 31 | ||||
-rw-r--r-- | dependencies/uthash/tests/threads/README | 2 | ||||
-rwxr-xr-x | dependencies/uthash/tests/threads/do_tests | 22 | ||||
-rw-r--r-- | dependencies/uthash/tests/threads/test1.c | 116 | ||||
-rw-r--r-- | dependencies/uthash/tests/threads/test2.c | 75 |
5 files changed, 246 insertions, 0 deletions
diff --git a/dependencies/uthash/tests/threads/Makefile b/dependencies/uthash/tests/threads/Makefile new file mode 100644 index 000000000..01060060a --- /dev/null +++ b/dependencies/uthash/tests/threads/Makefile @@ -0,0 +1,31 @@ +HASHDIR = ../../src +PROGS = test1 test2 + +# Thread support requires compiler-specific options +# ---------------------------------------------------------------------------- +# GNU +CFLAGS += -I$(HASHDIR) -g -pthread +# Solaris (Studio 11) +#CFLAGS = -I$(HASHDIR) -g -mt +# ---------------------------------------------------------------------------- + +ifeq ($(HASH_DEBUG),1) +CFLAGS += -DHASH_DEBUG=1 +endif + +all: $(PROGS) run_tests + +$(PROGS) : $(HASHDIR)/uthash.h + $(CC) $(CPPLFAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(@).c + +debug: + $(MAKE) all HASH_DEBUG=1 + +run_tests: $(PROGS) + perl ../do_tests + +.PHONY: clean + +clean: + rm -f $(PROGS) test*.out + rm -rf test*.dSYM diff --git a/dependencies/uthash/tests/threads/README b/dependencies/uthash/tests/threads/README new file mode 100644 index 000000000..e49a62eed --- /dev/null +++ b/dependencies/uthash/tests/threads/README @@ -0,0 +1,2 @@ +test1: exercise a two-reader, one-writer, rwlock-protected hash. +test2: a template for a nthread, nloop kind of program diff --git a/dependencies/uthash/tests/threads/do_tests b/dependencies/uthash/tests/threads/do_tests new file mode 100755 index 000000000..e6809a157 --- /dev/null +++ b/dependencies/uthash/tests/threads/do_tests @@ -0,0 +1,22 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my @tests; +for (glob "test*[0-9]") { + push @tests, $_ if -e "$_.ans"; +} + +my $num_failed=0; + +for my $test (@tests) { + `./$test > $test.out 2> $test.err`; + `diff $test.out $test.ans`; + print "$test failed\n" if $?; + $num_failed++ if $?; + unlink "$test.err" if -z "$test.err"; +} + +print scalar @tests . " tests conducted, $num_failed failed.\n"; +exit $num_failed; diff --git a/dependencies/uthash/tests/threads/test1.c b/dependencies/uthash/tests/threads/test1.c new file mode 100644 index 000000000..8d6cb6747 --- /dev/null +++ b/dependencies/uthash/tests/threads/test1.c @@ -0,0 +1,116 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <pthread.h> +#include "uthash.h" + +#undef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) fprintf(stderr,"warning: bucket expansion inhibited\n") + +#define LOOPS 100000 + +typedef struct { + int i; + UT_hash_handle hh; +} elt; + +elt *elts=NULL; /* this is our hash table which two threads will use */ +pthread_rwlock_t lock; + +void *thread_routine_r( void *arg ) { + int i; + long num_found=0; + elt *e; + + for(i=0;i<LOOPS;i++) { + if (pthread_rwlock_rdlock(&lock) != 0) { + fprintf(stderr,"can't acquire read lock\n"); + exit(-1); + } + HASH_FIND_INT(elts, &i, e); + if (e) num_found++; + pthread_rwlock_unlock(&lock); + } + return (void*)num_found; +} +void *thread_routine_w( void *arg ) { + int i; + long num_deld=0; + elt *e; + + for(i=0;i<LOOPS;i++) { + if (pthread_rwlock_wrlock(&lock) != 0) { + fprintf(stderr,"can't acquire write lock\n"); + exit(-1); + } + HASH_FIND_INT(elts, &i, e); + if (e) { + /* HASH_DEL(elts, e); */ + /* num_deld++; */ + } else { + e = malloc(sizeof(elt)); + if (!e) exit(-1); + e->i = i; + HASH_ADD_INT(elts, i, e); + } + pthread_rwlock_unlock(&lock); + } + return (void*)num_deld; +} + +int main() { + unsigned i; + long num_added=0; + int status; + pthread_t thread_r1,thread_r2,thread_w1,thread_w2; + void *thread_result; + elt tmp, *e; + + if (pthread_rwlock_init(&lock,NULL) != 0) { + fprintf(stderr,"lock init failed\n"); + exit(-1); + } + + if (( status = pthread_create( &thread_r1, NULL, thread_routine_r, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + if (( status = pthread_create( &thread_r2, NULL, thread_routine_r, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + if (( status = pthread_create( &thread_w1, NULL, thread_routine_w, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + if (( status = pthread_create( &thread_w2, NULL, thread_routine_w, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + + status = pthread_join( thread_r1, &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + + status = pthread_join( thread_r2, &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + + status = pthread_join( thread_w1, &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + + status = pthread_join( thread_w2, &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + + i = HASH_COUNT(elts); + printf("final count of items in hash: %u\n", i); + + if (pthread_rwlock_destroy(&lock) != 0) { + fprintf(stderr,"lock destroy failed\n"); + exit(-1); + } +} diff --git a/dependencies/uthash/tests/threads/test2.c b/dependencies/uthash/tests/threads/test2.c new file mode 100644 index 000000000..316b7e699 --- /dev/null +++ b/dependencies/uthash/tests/threads/test2.c @@ -0,0 +1,75 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <pthread.h> +#include "uthash.h" + +#undef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) fprintf(stderr,"warning: bucket expansion inhibited\n"); + +#define LOOPS 100000 +#define NTHREADS 2 + +typedef struct { + int i; + int v; + UT_hash_handle hh; +} elt; + +elt *elts=NULL; /* this is our hash table which two threads will use */ +pthread_rwlock_t lock; + +void *thread_routine( void *arg ) { + int keepgoing=0; + /* TODO write me */ + return NULL; +} + +int main() { + unsigned i; + long num_added=0; + int status; + pthread_t thread[NTHREADS]; + void *thread_result; + elt tmp, *e; + + if (pthread_rwlock_init(&lock,NULL) != 0) { + fprintf(stderr,"lock init failed\n"); + exit(-1); + } + + /* populate it to start */ + for(i=0; i<LOOPS; i++) { + e = malloc(sizeof(elt)); + if (!e) exit(-1); + e->i = i; + e->v = 0; + HASH_ADD_INT(elts, i, e); + } + + for(i=0; i<NTHREADS; i++) { + if (( status = pthread_create( &thread[i], NULL, thread_routine, NULL) )) { + printf("failure: status %d\n", status); + exit(-1); + } + } + + for(i=0; i<NTHREADS; i++) { + status = pthread_join( thread[i], &thread_result ); + printf("thread result: %d %ld\n", status, (long)thread_result); + } + + i = HASH_COUNT(elts); + printf("final count of items in hash: %u\n", i); + + if (pthread_rwlock_destroy(&lock) != 0) { + fprintf(stderr,"lock destroy failed\n"); + exit(-1); + } +} |