diff options
-rw-r--r-- | src/wrap.c | 235 | ||||
-rw-r--r-- | src/wrap.h | 40 |
2 files changed, 275 insertions, 0 deletions
diff --git a/src/wrap.c b/src/wrap.c new file mode 100644 index 0000000..a2ac5ba --- /dev/null +++ b/src/wrap.c @@ -0,0 +1,235 @@ +/* + * Copyright 2008 Red Hat, Inc. + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This Program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; if not, write to the + * + * Free Software Foundation, Inc. + * 59 Temple Place, Suite 330 + * Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include <sys/types.h> +#include <pthread.h> +#include <search.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#ifdef HAVE_DIRSRV_SLAPI_PLUGIN_H +#include <nspr.h> +#include <nss.h> +#include <dirsrv/slapi-plugin.h> +#else +#include <slapi-plugin.h> +#endif + +#ifdef USE_PTHREADS +#include <pthread.h> +#endif + +#include <rpc/xdr.h> + +#include "wrap.h" + +struct wrapped_thread { +#if defined(USE_PTHREADS) + pthread_t tid; + void *arg; +#elif defined(USE_NSPR_THREADS) + PRThread *tid; + struct wrapped_pthread_args { + void * (*fn)(struct wrapped_thread *); + void *arg, *result; + } args; +#else +#error "Unknown threading model!" +#endif + int stopfd[2]; +}; + +struct wrapped_rwlock { +#if defined(USE_PTHREADS) + pthread_rwlock_t rwlock; +#elif defined(USE_NSPR_THREADS) + PRRWLock *rwlock; +#else +#error "Unknown threading model!" +#endif +}; + +#ifdef USE_NSPR_THREADS +static void +wrap_pthread_starter(void *p) +{ + struct wrapped_thread *t = p; + t->args.result = t->args.fn(t); +} +#endif + +void * +wrap_thread_arg(struct wrapped_thread *t) +{ +#ifdef USE_PTHREADS + return t->arg; +#endif +#ifdef USE_NSPR_THREADS + return t->args.arg; +#endif +} + +struct wrapped_thread * +wrap_start_thread(void * (*fn)(struct wrapped_thread *), void *arg) +{ + struct wrapped_thread *t; + void *returned; + t = malloc(sizeof(*t)); + if (t == NULL) { + return NULL; + } + memset(t, 0, sizeof(*t)); + if (pipe(t->stopfd) == -1) { + free(t); + return NULL; + } +#ifdef USE_PTHREADS + t->arg = arg; + if (pthread_create(&t->tid, NULL, fn, t) != 0) { + free(t); + return NULL; + } +#endif +#ifdef USE_NSPR_THREADS + t->args.fn = fn; + t->args.arg = arg; + t->args.result = NULL; + t->tid = PR_CreateThread(PR_SYSTEM_THREAD, + wrap_pthread_starter, t, + PR_PRIORITY_NORMAL, + PR_GLOBAL_THREAD, + PR_JOINABLE_THREAD, + 0); + if (t->tid == NULL) { + free(t); + return NULL; + } +#endif + return t; +} + +void * +wrap_stop_thread(struct wrapped_thread *t) +{ + void *returned = NULL; +#ifdef USE_PTHREADS + write(t->stopfd[1], "", 1); + close(t->stopfd[1]); + pthread_join(t->tid, &returned); +#endif +#ifdef USE_NSPR_THREADS + write(t->stopfd[1], "", 1); + close(t->stopfd[1]); + PR_JoinThread(t->tid); + returned = t->args.result; +#endif + free(t); + return returned; +} + +int +wrap_thread_stopfd(struct wrapped_thread *t) +{ + int ret; +#ifdef USE_PTHREADS + ret = t->stopfd[0]; +#endif +#ifdef USE_NSPR_THREADS + ret = t->stopfd[0]; +#endif + return ret; +} + +struct wrapped_rwlock * +wrap_new_rwlock(void) +{ + struct wrapped_rwlock *rwlock; + rwlock = malloc(sizeof(*rwlock)); + if (rwlock == NULL) { + return NULL; + } +#ifdef USE_PTHREADS + if (pthread_rwlock_init(&rwlock->rwlock, NULL) != 0) { + free(rwlock); + return NULL; + } +#endif +#ifdef USE_NSPR_THREADS + rwlock->rwlock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, + PACKAGE_NAME "-rw-lock"); + if (rwlock->rwlock == NULL) { + free(rwlock); + return NULL; + } +#endif + return rwlock; +} + +void +wrap_free_rwlock(struct wrapped_rwlock *rwlock) +{ +#ifdef USE_PTHREADS + pthread_rwlock_destroy(&rwlock->rwlock); +#endif +#ifdef USE_NSPR_THREADS + PR_DestroyRWLock(rwlock->rwlock); +#endif + free(rwlock); +} + +void +wrap_rwlock_rdlock(struct wrapped_rwlock *rwlock) +{ +#ifdef USE_PTHREADS + pthread_rwlock_rdlock(&rwlock->rwlock); +#endif +#ifdef USE_NSPR_THREADS + PR_RWLock_Rlock(rwlock->rwlock); +#endif +} + +void +wrap_rwlock_wrlock(struct wrapped_rwlock *rwlock) +{ +#ifdef USE_PTHREADS + pthread_rwlock_wrlock(&rwlock->rwlock); +#endif +#ifdef USE_NSPR_THREADS + PR_RWLock_Wlock(rwlock->rwlock); +#endif +} + +void +wrap_rwlock_unlock(struct wrapped_rwlock *rwlock) +{ +#ifdef USE_PTHREADS + pthread_rwlock_unlock(&rwlock->rwlock); +#endif +#ifdef USE_NSPR_THREADS + PR_RWLock_Unlock(rwlock->rwlock); +#endif +} diff --git a/src/wrap.h b/src/wrap.h new file mode 100644 index 0000000..d5cc434 --- /dev/null +++ b/src/wrap.h @@ -0,0 +1,40 @@ +/* + * Copyright 2008 Red Hat, Inc. + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This Program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; if not, write to the + * + * Free Software Foundation, Inc. + * 59 Temple Place, Suite 330 + * Boston, MA 02111-1307 USA + * + */ + +#ifndef wrap_h +#define wrap_h + +struct wrapped_thread; +struct wrapped_rwlock; + +struct wrapped_thread * wrap_start_thread(void * (*fn)(struct wrapped_thread *), + void *arg); +void *wrap_stop_thread(struct wrapped_thread *t); +void *wrap_thread_arg(struct wrapped_thread *t); +int wrap_thread_stopfd(struct wrapped_thread *t); + +struct wrapped_rwlock *wrap_new_rwlock(void); +void wrap_free_rwlock(struct wrapped_rwlock *rwlock); +void wrap_rwlock_rdlock(struct wrapped_rwlock *rwlock); +void wrap_rwlock_wrlock(struct wrapped_rwlock *rwlock); +void wrap_rwlock_unlock(struct wrapped_rwlock *rwlock); + +#endif |