From a6b9b59e0486667a43fda2ab77a7a053c820c2d9 Mon Sep 17 00:00:00 2001 From: David Xu Date: Mon, 18 Oct 2010 05:09:22 +0000 Subject: [PATCH] Add pthread_rwlockattr_setkind_np and pthread_rwlockattr_getkind_np, the functions set or get pthread_rwlock type, current supported types are: PTHREAD_RWLOCK_PREFER_READER_NP, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_RWLOCK_PREFER_WRITER_NP, default is PTHREAD_RWLOCK_PREFER_WRITER_NONCECURSIVE_NP, this maintains binary compatible with old code. --- include/pthread.h | 16 ++++++++++++++-- lib/libthr/pthread.map | 4 ++++ lib/libthr/thread/thr_private.h | 3 +++ lib/libthr/thread/thr_rwlock.c | 25 +++++++++++++++++++++++-- lib/libthr/thread/thr_rwlockattr.c | 20 ++++++++++++++++++++ 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/include/pthread.h b/include/pthread.h index 56f6ef4de4e..9a8e2ae1f04 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -135,6 +135,15 @@ enum pthread_mutextype { #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_ERRORCHECK +enum pthread_rwlocktype_np +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_DEFAULT_NP = + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP +}; + struct _pthread_cleanup_info { __uintptr_t pthread_cleanup_pad[8]; }; @@ -233,11 +242,14 @@ int pthread_rwlock_tryrdlock(pthread_rwlock_t *); int pthread_rwlock_trywrlock(pthread_rwlock_t *); int pthread_rwlock_unlock(pthread_rwlock_t *); int pthread_rwlock_wrlock(pthread_rwlock_t *); -int pthread_rwlockattr_init(pthread_rwlockattr_t *); +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); +int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *, + int *); int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *); +int pthread_rwlockattr_init(pthread_rwlockattr_t *); +int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int); int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int); -int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); pthread_t pthread_self(void); int pthread_setspecific(pthread_key_t, const void *); diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index 5e36239e8e2..2d7624ead3e 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -318,7 +318,9 @@ FBSDprivate_1.0 { _pthread_rwlock_wrlock; _pthread_rwlockattr_destroy; _pthread_rwlockattr_getpshared; + _pthread_rwlockattr_getkind_np; _pthread_rwlockattr_init; + _pthread_rwlockattr_setkind_np; _pthread_rwlockattr_setpshared; _pthread_self; _pthread_set_name_np; @@ -403,4 +405,6 @@ FBSD_1.2 { openat; setcontext; swapcontext; + pthread_rwlockattr_getkind_np; + pthread_rwlockattr_setkind_np; }; diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index aa9feefcf7d..5d0c301cd04 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -285,11 +285,14 @@ struct pthread_prio { struct pthread_rwlockattr { int pshared; + int kind; }; struct pthread_rwlock { struct urwlock lock; struct pthread *owner; + int recurse; + int kind; }; /* diff --git a/lib/libthr/thread/thr_rwlock.c b/lib/libthr/thread/thr_rwlock.c index ebdeae7e611..20b9b79e31c 100644 --- a/lib/libthr/thread/thr_rwlock.c +++ b/lib/libthr/thread/thr_rwlock.c @@ -63,13 +63,19 @@ __weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); */ static int -rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr __unused) +rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { pthread_rwlock_t prwlock; prwlock = (pthread_rwlock_t)calloc(1, sizeof(struct pthread_rwlock)); if (prwlock == NULL) return (ENOMEM); + if (attr != NULL) + prwlock->kind = (*attr)->kind; + else + prwlock->kind = PTHREAD_RWLOCK_DEFAULT_NP; + if (prwlock->kind == PTHREAD_RWLOCK_PREFER_READER_NP) + prwlock->lock.rw_flags |= URWLOCK_PREFER_READER; *rwlock = prwlock; return (0); } @@ -112,7 +118,7 @@ init_static(struct pthread *thread, pthread_rwlock_t *rwlock) } int -_pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) +_pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { *rwlock = NULL; return (rwlock_init(rwlock, attr)); @@ -260,6 +266,14 @@ rwlock_wrlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) CHECK_AND_INIT_RWLOCK + if (__predict_false(prwlock->owner == curthread)) { + if (__predict_false( + prwlock->kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)) { + prwlock->recurse++; + return (0); + } + } + /* * POSIX said the validity of the abstimeout parameter need * not be checked if the lock can be immediately acquired. @@ -335,6 +349,13 @@ _pthread_rwlock_unlock (pthread_rwlock_t *rwlock) if (state & URWLOCK_WRITE_OWNER) { if (__predict_false(prwlock->owner != curthread)) return (EPERM); + if (__predict_false( + prwlock->kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)) { + if (prwlock->recurse > 0) { + prwlock->recurse--; + return (0); + } + } prwlock->owner = NULL; } diff --git a/lib/libthr/thread/thr_rwlockattr.c b/lib/libthr/thread/thr_rwlockattr.c index b47d16700d7..edc87d25a40 100644 --- a/lib/libthr/thread/thr_rwlockattr.c +++ b/lib/libthr/thread/thr_rwlockattr.c @@ -36,8 +36,10 @@ __weak_reference(_pthread_rwlockattr_destroy, pthread_rwlockattr_destroy); __weak_reference(_pthread_rwlockattr_getpshared, pthread_rwlockattr_getpshared); +__weak_reference(_pthread_rwlockattr_getkind_np, pthread_rwlockattr_getkind_np); __weak_reference(_pthread_rwlockattr_init, pthread_rwlockattr_init); __weak_reference(_pthread_rwlockattr_setpshared, pthread_rwlockattr_setpshared); +__weak_reference(_pthread_rwlockattr_setkind_np, pthread_rwlockattr_setkind_np); int _pthread_rwlockattr_destroy(pthread_rwlockattr_t *rwlockattr) @@ -98,3 +100,21 @@ _pthread_rwlockattr_setpshared(pthread_rwlockattr_t *rwlockattr, int pshared) return(0); } +int +_pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int kind) +{ + if (kind != PTHREAD_RWLOCK_PREFER_READER_NP || + kind != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP || + kind != PTHREAD_RWLOCK_PREFER_WRITER_NP) { + return (EINVAL); + } + (*attr)->kind = kind; + return (0); +} + +int +_pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *kind) +{ + *kind = (*attr)->kind; + return (0); +}