/* * 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 #include #include #include #include #include #include #ifdef HAVE_DIRSRV_SLAPI_PLUGIN_H #include #include #include #else #include #endif #ifdef USE_PTHREADS #include #endif #include #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 }