From owner-svn-src-user@FreeBSD.ORG Wed Nov 10 03:18:14 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C49E41065697; Wed, 10 Nov 2010 03:18:14 +0000 (UTC) (envelope-from davidxu@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B25488FC1B; Wed, 10 Nov 2010 03:18:14 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oAA3IE1g076788; Wed, 10 Nov 2010 03:18:14 GMT (envelope-from davidxu@svn.freebsd.org) Received: (from davidxu@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oAA3IEkT076782; Wed, 10 Nov 2010 03:18:14 GMT (envelope-from davidxu@svn.freebsd.org) Message-Id: <201011100318.oAA3IEkT076782@svn.freebsd.org> From: David Xu Date: Wed, 10 Nov 2010 03:18:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r215074 - in user/davidxu/libthr: include lib/libthr lib/libthr/thread sys/sys X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Nov 2010 03:18:14 -0000 Author: davidxu Date: Wed Nov 10 03:18:14 2010 New Revision: 215074 URL: http://svn.freebsd.org/changeset/base/215074 Log: Convert pthread_rwlock_t from pointer to structure, this allows us to use process-shared rwlock. Modified: user/davidxu/libthr/include/pthread.h user/davidxu/libthr/lib/libthr/pthread.map user/davidxu/libthr/lib/libthr/thread/thr_private.h user/davidxu/libthr/lib/libthr/thread/thr_rwlock.c user/davidxu/libthr/sys/sys/_pthreadtypes.h Modified: user/davidxu/libthr/include/pthread.h ============================================================================== --- user/davidxu/libthr/include/pthread.h Wed Nov 10 01:52:10 2010 (r215073) +++ user/davidxu/libthr/include/pthread.h Wed Nov 10 03:18:14 2010 (r215074) @@ -105,7 +105,7 @@ #define PTHREAD_COND_INITIALIZER \ {0, 0, 0, 0, 0, 0, 0, 0, 0, CLOCK_REALTIME} -#define PTHREAD_RWLOCK_INITIALIZER NULL +#define PTHREAD_RWLOCK_INITIALIZER { .__owner.__ownertd = 0, 0, 0, 0, 0} /* * Default attribute arguments (draft 4, deprecated). @@ -183,6 +183,18 @@ struct pthread_cond { __uint32_t __clock_id; }; +struct pthread_rwlock { + union { + __uint32_t __ownertid; + struct pthread *__ownertd; + char __pad[8]; + } __owner; + __uint32_t __state; + __uint32_t __flags; + __uint32_t __blocked_readers; + __uint32_t __blocked_writers; +}; + /* * Thread function prototype definitions: */ Modified: user/davidxu/libthr/lib/libthr/pthread.map ============================================================================== --- user/davidxu/libthr/lib/libthr/pthread.map Wed Nov 10 01:52:10 2010 (r215073) +++ user/davidxu/libthr/lib/libthr/pthread.map Wed Nov 10 03:18:14 2010 (r215074) @@ -90,15 +90,6 @@ FBSD_1.0 { pthread_once; pthread_resume_all_np; pthread_resume_np; - pthread_rwlock_destroy; - pthread_rwlock_init; - pthread_rwlock_rdlock; - pthread_rwlock_timedrdlock; - pthread_rwlock_timedwrlock; - pthread_rwlock_tryrdlock; - pthread_rwlock_trywrlock; - pthread_rwlock_unlock; - pthread_rwlock_wrlock; pthread_rwlockattr_destroy; pthread_rwlockattr_getpshared; pthread_rwlockattr_init; @@ -407,6 +398,15 @@ FBSD_1.2 { pthread_mutex_timedlock; pthread_mutex_trylock; pthread_mutex_unlock; + pthread_rwlock_destroy; + pthread_rwlock_init; + pthread_rwlock_rdlock; + pthread_rwlock_timedrdlock; + pthread_rwlock_timedwrlock; + pthread_rwlock_tryrdlock; + pthread_rwlock_trywrlock; + pthread_rwlock_unlock; + pthread_rwlock_wrlock; setcontext; swapcontext; }; Modified: user/davidxu/libthr/lib/libthr/thread/thr_private.h ============================================================================== --- user/davidxu/libthr/lib/libthr/thread/thr_private.h Wed Nov 10 01:52:10 2010 (r215073) +++ user/davidxu/libthr/lib/libthr/thread/thr_private.h Wed Nov 10 03:18:14 2010 (r215074) @@ -278,11 +278,6 @@ struct pthread_rwlockattr { int pshared; }; -struct pthread_rwlock { - struct urwlock lock; - struct pthread *owner; -}; - /* * Thread states. */ Modified: user/davidxu/libthr/lib/libthr/thread/thr_rwlock.c ============================================================================== --- user/davidxu/libthr/lib/libthr/thread/thr_rwlock.c Wed Nov 10 01:52:10 2010 (r215073) +++ user/davidxu/libthr/lib/libthr/thread/thr_rwlock.c Wed Nov 10 03:18:14 2010 (r215074) @@ -29,6 +29,7 @@ #include #include #include +#include #include "namespace.h" #include @@ -45,89 +46,66 @@ __weak_reference(_pthread_rwlock_unlock, __weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock); __weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); -#define CHECK_AND_INIT_RWLOCK \ - if (__predict_false((prwlock = (*rwlock)) <= THR_RWLOCK_DESTROYED)) { \ - if (prwlock == THR_RWLOCK_INITIALIZER) { \ - int ret; \ - ret = init_static(_get_curthread(), rwlock); \ - if (ret) \ - return (ret); \ - } else if (prwlock == THR_RWLOCK_DESTROYED) { \ - return (EINVAL); \ - } \ - prwlock = *rwlock; \ - } +typedef struct pthread_rwlock *pthread_rwlock_old_t; + +int _pthread_rwlock_destroy_1_0(pthread_rwlock_old_t *); +int _pthread_rwlock_init_1_0(pthread_rwlock_old_t *, + const pthread_rwlockattr_t *); +int _pthread_rwlock_timedrdlock_1_0(pthread_rwlock_old_t *, + const struct timespec *); +int _pthread_rwlock_tryrdlock_1_0(pthread_rwlock_old_t *); +int _pthread_rwlock_trywrlock_1_0(pthread_rwlock_old_t *); +int _pthread_rwlock_rdlock_1_0(pthread_rwlock_old_t *, const struct timespec *); +int _pthread_rwlock_unlock_1_0(pthread_rwlock_old_t *); + +#define RWL_PSHARED(rwp) ((rwp->__flags & USYNC_PROCESS_SHARED) != 0) /* * Prototypes */ static int -rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr __unused) -{ - pthread_rwlock_t prwlock; - - prwlock = (pthread_rwlock_t)calloc(1, sizeof(struct pthread_rwlock)); - if (prwlock == NULL) - return (ENOMEM); - *rwlock = prwlock; - return (0); -} - -int -_pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +rwlock_init(struct pthread_rwlock *rwp, const pthread_rwlockattr_t *attr) { - pthread_rwlock_t prwlock; - int ret; - prwlock = *rwlock; - if (prwlock == THR_RWLOCK_INITIALIZER) - ret = 0; - else if (prwlock == THR_RWLOCK_DESTROYED) - ret = EINVAL; + memset(rwp, 0, sizeof(*rwp)); + if (attr == NULL || *attr == NULL) + return (0); else { - *rwlock = THR_RWLOCK_DESTROYED; - - free(prwlock); - ret = 0; + if ((*attr)->pshared) + rwp->__flags |= USYNC_PROCESS_SHARED; } - return (ret); + + return (0); } static int -init_static(struct pthread *thread, pthread_rwlock_t *rwlock) +rwlock_destroy_common(struct pthread_rwlock *rwp) { - int ret; - - THR_LOCK_ACQUIRE(thread, &_rwlock_static_lock); - - if (*rwlock == THR_RWLOCK_INITIALIZER) - ret = rwlock_init(rwlock, NULL); - else - ret = 0; - - THR_LOCK_RELEASE(thread, &_rwlock_static_lock); + if (rwp->__state != 0) + return (EBUSY); + return (0); +} - return (ret); +int +_pthread_rwlock_destroy (pthread_rwlock_t *rwp) +{ + return rwlock_destroy_common(rwp); } int -_pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) +_pthread_rwlock_init(pthread_rwlock_t *rwp, const pthread_rwlockattr_t *attr) { - *rwlock = NULL; - return (rwlock_init(rwlock, attr)); + return (rwlock_init(rwp, attr)); } static int -rwlock_rdlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime) +rwlock_rdlock_common(struct pthread_rwlock *rwlp, const struct timespec *abstime) { struct pthread *curthread = _get_curthread(); - pthread_rwlock_t prwlock; struct timespec ts, ts2, *tsp; int flags; - int ret; - - CHECK_AND_INIT_RWLOCK + int error; if (curthread->rdlock_count) { /* @@ -148,13 +126,13 @@ rwlock_rdlock_common(pthread_rwlock_t *r } /* - * POSIX said the validity of the abstimeout parameter need + * POSIX said the validity of the abstime parameter need * not be checked if the lock can be immediately acquired. */ - ret = _thr_rwlock_tryrdlock(&prwlock->lock, flags); - if (ret == 0) { + error = _thr_rwlock_tryrdlock((struct urwlock *)&rwlp->__state, flags); + if (error == 0) { curthread->rdlock_count++; - return (ret); + return (error); } if (__predict_false(abstime && @@ -173,43 +151,40 @@ rwlock_rdlock_common(pthread_rwlock_t *r tsp = NULL; /* goto kernel and lock it */ - ret = __thr_rwlock_rdlock(&prwlock->lock, flags, tsp); - if (ret != EINTR) + error = __thr_rwlock_rdlock((struct urwlock *)&rwlp->__state, flags, tsp); + if (error != EINTR) break; /* if interrupted, try to lock it in userland again. */ - if (_thr_rwlock_tryrdlock(&prwlock->lock, flags) == 0) { - ret = 0; + if (_thr_rwlock_tryrdlock((struct urwlock *)&rwlp->__state, flags) == 0) { + error = 0; break; } } - if (ret == 0) + if (error == 0) curthread->rdlock_count++; - return (ret); + return (error); } int -_pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) +_pthread_rwlock_rdlock (pthread_rwlock_t *rwlp) { - return (rwlock_rdlock_common(rwlock, NULL)); + return (rwlock_rdlock_common(rwlp, NULL)); } int -_pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, - const struct timespec *abstime) +_pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlp, + const struct timespec *abstime) { - return (rwlock_rdlock_common(rwlock, abstime)); + return (rwlock_rdlock_common(rwlp, abstime)); } int -_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) +_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlp) { struct pthread *curthread = _get_curthread(); - pthread_rwlock_t prwlock; int flags; - int ret; - - CHECK_AND_INIT_RWLOCK + int error; if (curthread->rdlock_count) { /* @@ -229,45 +204,48 @@ _pthread_rwlock_tryrdlock (pthread_rwloc flags = 0; } - ret = _thr_rwlock_tryrdlock(&prwlock->lock, flags); - if (ret == 0) + error = _thr_rwlock_tryrdlock((struct urwlock *)&rwlp->__state, flags); + if (error == 0) curthread->rdlock_count++; - return (ret); + return (error); +} + +static void +rwlock_setowner(struct pthread_rwlock *rwlp, struct pthread *td) +{ + if (!RWL_PSHARED(rwlp)) + rwlp->__owner.__ownertd = td; + else + rwlp->__owner.__ownertid = TID(td); } int -_pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) +_pthread_rwlock_trywrlock (pthread_rwlock_t *rwlp) { struct pthread *curthread = _get_curthread(); - pthread_rwlock_t prwlock; - int ret; + int error; - CHECK_AND_INIT_RWLOCK - - ret = _thr_rwlock_trywrlock(&prwlock->lock); - if (ret == 0) - prwlock->owner = curthread; - return (ret); + error = _thr_rwlock_trywrlock((struct urwlock *)&rwlp->__state); + if (error == 0) + rwlock_setowner(rwlp, curthread); + return (error); } static int -rwlock_wrlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) +rwlock_wrlock_common(pthread_rwlock_t *rwlp, const struct timespec *abstime) { struct pthread *curthread = _get_curthread(); - pthread_rwlock_t prwlock; struct timespec ts, ts2, *tsp; - int ret; - - CHECK_AND_INIT_RWLOCK + int error; /* - * POSIX said the validity of the abstimeout parameter need + * POSIX said the validity of the abstime parameter need * not be checked if the lock can be immediately acquired. */ - ret = _thr_rwlock_trywrlock(&prwlock->lock); - if (ret == 0) { - prwlock->owner = curthread; - return (ret); + error = _thr_rwlock_trywrlock((struct urwlock *)&rwlp->__state); + if (error == 0) { + rwlock_setowner(rwlp, curthread); + return (error); } if (__predict_false(abstime && @@ -286,61 +264,196 @@ rwlock_wrlock_common (pthread_rwlock_t * tsp = NULL; /* goto kernel and lock it */ - ret = __thr_rwlock_wrlock(&prwlock->lock, tsp); - if (ret == 0) { - prwlock->owner = curthread; + error = __thr_rwlock_wrlock((struct urwlock *)&rwlp->__state, tsp); + if (error == 0) { + rwlock_setowner(rwlp, curthread); break; } - if (ret != EINTR) + if (error != EINTR) break; /* if interrupted, try to lock it in userland again. */ - if (_thr_rwlock_trywrlock(&prwlock->lock) == 0) { - ret = 0; - prwlock->owner = curthread; + if (_thr_rwlock_trywrlock((struct urwlock *)&rwlp->__state) == 0) { + error = 0; + rwlock_setowner(rwlp, curthread); break; } } - return (ret); + return (error); } int -_pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) +_pthread_rwlock_wrlock (pthread_rwlock_t *rwlp) { - return (rwlock_wrlock_common (rwlock, NULL)); + return (rwlock_wrlock_common(rwlp, NULL)); } int -_pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, - const struct timespec *abstime) +_pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlp, + const struct timespec *abstime) { - return (rwlock_wrlock_common (rwlock, abstime)); + return (rwlock_wrlock_common(rwlp, abstime)); } int -_pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +_pthread_rwlock_unlock(pthread_rwlock_t *rwlp) { struct pthread *curthread = _get_curthread(); - pthread_rwlock_t prwlock; - int ret; - int32_t state; - - prwlock = *rwlock; - - if (__predict_false(prwlock <= THR_RWLOCK_DESTROYED)) - return (EINVAL); + int error; + uint32_t state; - state = prwlock->lock.rw_state; + state = rwlp->__state; if (state & URWLOCK_WRITE_OWNER) { - if (__predict_false(prwlock->owner != curthread)) + if (RWL_PSHARED(rwlp) && + rwlp->__owner.__ownertid == TID(curthread)) { + rwlp->__owner.__ownertid = 0; + } else if (!RWL_PSHARED(rwlp) && + rwlp->__owner.__ownertd == curthread) { + rwlp->__owner.__ownertd = NULL; + } else return (EPERM); - prwlock->owner = NULL; } - - ret = _thr_rwlock_unlock(&prwlock->lock); - if (ret == 0 && (state & URWLOCK_WRITE_OWNER) == 0) + error = _thr_rwlock_unlock((struct urwlock *)&rwlp->__state); + if (error == 0 && (state & URWLOCK_WRITE_OWNER) == 0) curthread->rdlock_count--; + return (error); +} + +#define CHECK_AND_INIT_RWLOCK \ + if (__predict_false((rwlp = (*rwlpp)) <= THR_RWLOCK_DESTROYED)) { \ + if (rwlp == THR_RWLOCK_INITIALIZER) { \ + int error; \ + error = init_static(_get_curthread(), rwlpp); \ + if (error) \ + return (error); \ + } else if (rwlp == THR_RWLOCK_DESTROYED) { \ + return (EINVAL); \ + } \ + *rwlpp = rwlp; \ + } + +static int +rwlock_init_old(pthread_rwlock_old_t *rwlpp, const pthread_rwlockattr_t *attr) +{ + struct pthread_rwlock *rwlp; + int error; + + rwlp = (struct pthread_rwlock *)malloc(sizeof(struct pthread_rwlock)); + if (rwlp == NULL) + return (ENOMEM); + error = rwlock_init(rwlp, attr); + if (error) { + free(rwlp); + return (error); + } + *rwlpp = rwlp; + return (0); +} + +static int +init_static(struct pthread *thread, pthread_rwlock_old_t *rwlpp) +{ + int error; + + THR_LOCK_ACQUIRE(thread, &_rwlock_static_lock); + + if (*rwlpp == THR_RWLOCK_INITIALIZER) + error = rwlock_init_old(rwlpp, NULL); + else + error = 0; + + THR_LOCK_RELEASE(thread, &_rwlock_static_lock); + + return (error); +} - return (ret); +int +_pthread_rwlock_destroy_1_0(pthread_rwlock_old_t *rwlpp) +{ + struct pthread_rwlock *rwlp; + int error; + + rwlp = *rwlpp; + if (rwlp == THR_RWLOCK_INITIALIZER) + error = 0; + else if (rwlp == THR_RWLOCK_DESTROYED) + error = EINVAL; + else { + error = rwlock_destroy_common(rwlp); + if (error) + return (error); + *rwlpp = THR_RWLOCK_DESTROYED; + free(rwlp); + } + return (error); +} + +int +_pthread_rwlock_init_1_0(pthread_rwlock_old_t *rwlpp, const pthread_rwlockattr_t *attr) +{ + *rwlpp = NULL; + return (rwlock_init_old(rwlpp, attr)); } + +int +_pthread_rwlock_timedrdlock_1_0(pthread_rwlock_old_t *rwlpp, + const struct timespec *abstime) +{ + struct pthread_rwlock *rwlp; + + CHECK_AND_INIT_RWLOCK + + return (rwlock_rdlock_common(rwlp, abstime)); +} + +int +_pthread_rwlock_tryrdlock_1_0(pthread_rwlock_old_t *rwlpp) +{ + struct pthread_rwlock *rwlp; + + CHECK_AND_INIT_RWLOCK + + return _pthread_rwlock_tryrdlock(rwlp); +} + +int +_pthread_rwlock_trywrlock_1_0(pthread_rwlock_old_t *rwlpp) +{ + struct pthread_rwlock *rwlp; + + CHECK_AND_INIT_RWLOCK + + return _pthread_rwlock_trywrlock(rwlp); +} + +int +_pthread_rwlock_rdlock_1_0(pthread_rwlock_old_t *rwlpp, const struct timespec *abstime) +{ + struct pthread_rwlock *rwlp; + + CHECK_AND_INIT_RWLOCK + + return rwlock_rdlock_common(rwlp, abstime); +} + +int +_pthread_rwlock_unlock_1_0(pthread_rwlock_old_t *rwlpp) +{ + struct pthread_rwlock *rwlp; + + rwlp = *rwlpp; + if (__predict_false(rwlp <= THR_RWLOCK_DESTROYED)) + return (EINVAL); + return _pthread_rwlock_unlock(rwlp); +} + +FB10_COMPAT(_pthread_rwlock_destroy_1_0, pthread_rwlock_destroy); +FB10_COMPAT(_pthread_rwlock_init_1_0, pthread_rwlock_init); +FB10_COMPAT(_pthread_rwlock_rdlock_1_0, pthread_rwlock_rdlock); +FB10_COMPAT(_pthread_rwlock_timedrdlock_1_0, pthread_rwlock_timedrdlock); +FB10_COMPAT(_pthread_rwlock_tryrdlock_1_0, pthread_rwlock_tryrdlock); +FB10_COMPAT(_pthread_rwlock_trywrlock_1_0, pthread_rwlock_trywrlock); +FB10_COMPAT(_pthread_rwlock_unlock_1_0, pthread_rwlock_unlock); +FB10_COMPAT(_pthread_rwlock_wrlock_1_0, pthread_rwlock_wrlock); +FB10_COMPAT(_pthread_rwlock_timedwrlock_1_0, pthread_rwlock_timedwrlock); Modified: user/davidxu/libthr/sys/sys/_pthreadtypes.h ============================================================================== --- user/davidxu/libthr/sys/sys/_pthreadtypes.h Wed Nov 10 01:52:10 2010 (r215073) +++ user/davidxu/libthr/sys/sys/_pthreadtypes.h Wed Nov 10 03:18:14 2010 (r215074) @@ -66,13 +66,13 @@ typedef struct pthread *pthread_t; #define _PTHREAD_T_DECLARED #endif typedef struct pthread_attr *pthread_attr_t; -typedef struct pthread_mutex *pthread_mutex_t; +typedef struct pthread_mutex pthread_mutex_t; typedef struct pthread_mutex_attr *pthread_mutexattr_t; -typedef struct pthread_cond *pthread_cond_t; +typedef struct pthread_cond pthread_cond_t; typedef struct pthread_cond_attr *pthread_condattr_t; typedef int pthread_key_t; typedef struct pthread_once pthread_once_t; -typedef struct pthread_rwlock *pthread_rwlock_t; +typedef struct pthread_rwlock pthread_rwlock_t; typedef struct pthread_rwlockattr *pthread_rwlockattr_t; typedef struct pthread_barrier *pthread_barrier_t; typedef struct pthread_barrierattr *pthread_barrierattr_t; @@ -92,7 +92,6 @@ typedef void *(*pthread_startroutine_t)( */ struct pthread_once { int state; - pthread_mutex_t mutex; }; #endif /* ! _SYS__PTHREADTYPES_H_ */