thr_rwlock.c (195403) | thr_rwlock.c (213241) |
---|---|
1/*- 2 * Copyright (c) 1998 Alex Nash 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 1998 Alex Nash 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/lib/libthr/thread/thr_rwlock.c 195403 2009-07-06 09:31:04Z attilio $ | 26 * $FreeBSD: head/lib/libthr/thread/thr_rwlock.c 213241 2010-09-28 04:57:56Z davidxu $ |
27 */ 28 29#include <errno.h> 30#include <limits.h> 31#include <stdlib.h> 32 33#include "namespace.h" 34#include <pthread.h> --- 5 unchanged lines hidden (view full) --- 40__weak_reference(_pthread_rwlock_rdlock, pthread_rwlock_rdlock); 41__weak_reference(_pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock); 42__weak_reference(_pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); 43__weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); 44__weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock); 45__weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock); 46__weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); 47 | 27 */ 28 29#include <errno.h> 30#include <limits.h> 31#include <stdlib.h> 32 33#include "namespace.h" 34#include <pthread.h> --- 5 unchanged lines hidden (view full) --- 40__weak_reference(_pthread_rwlock_rdlock, pthread_rwlock_rdlock); 41__weak_reference(_pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock); 42__weak_reference(_pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); 43__weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); 44__weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock); 45__weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock); 46__weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); 47 |
48#define CHECK_AND_INIT_RWLOCK \ 49 if (__predict_false((prwlock = (*rwlock)) <= THR_RWLOCK_DESTROYED)) { \ 50 if (prwlock == THR_RWLOCK_INITIALIZER) { \ 51 int ret; \ 52 ret = init_static(_get_curthread(), rwlock); \ 53 if (ret) \ 54 return (ret); \ 55 } else if (prwlock == THR_RWLOCK_DESTROYED) { \ 56 return (EINVAL); \ 57 } \ 58 prwlock = *rwlock; \ 59 } 60 |
|
48/* 49 * Prototypes 50 */ 51 52static int 53rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr __unused) 54{ 55 pthread_rwlock_t prwlock; 56 57 prwlock = (pthread_rwlock_t)calloc(1, sizeof(struct pthread_rwlock)); 58 if (prwlock == NULL) 59 return (ENOMEM); 60 *rwlock = prwlock; 61 return (0); 62} 63 64int 65_pthread_rwlock_destroy (pthread_rwlock_t *rwlock) 66{ | 61/* 62 * Prototypes 63 */ 64 65static int 66rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr __unused) 67{ 68 pthread_rwlock_t prwlock; 69 70 prwlock = (pthread_rwlock_t)calloc(1, sizeof(struct pthread_rwlock)); 71 if (prwlock == NULL) 72 return (ENOMEM); 73 *rwlock = prwlock; 74 return (0); 75} 76 77int 78_pthread_rwlock_destroy (pthread_rwlock_t *rwlock) 79{ |
80 pthread_rwlock_t prwlock; |
|
67 int ret; 68 | 81 int ret; 82 |
69 if (rwlock == NULL) | 83 prwlock = *rwlock; 84 if (prwlock == THR_RWLOCK_INITIALIZER) 85 ret = 0; 86 else if (prwlock == THR_RWLOCK_DESTROYED) |
70 ret = EINVAL; 71 else { | 87 ret = EINVAL; 88 else { |
72 pthread_rwlock_t prwlock; | 89 *rwlock = THR_RWLOCK_DESTROYED; |
73 | 90 |
74 prwlock = *rwlock; 75 *rwlock = NULL; 76 | |
77 free(prwlock); 78 ret = 0; 79 } 80 return (ret); 81} 82 83static int 84init_static(struct pthread *thread, pthread_rwlock_t *rwlock) 85{ 86 int ret; 87 88 THR_LOCK_ACQUIRE(thread, &_rwlock_static_lock); 89 | 91 free(prwlock); 92 ret = 0; 93 } 94 return (ret); 95} 96 97static int 98init_static(struct pthread *thread, pthread_rwlock_t *rwlock) 99{ 100 int ret; 101 102 THR_LOCK_ACQUIRE(thread, &_rwlock_static_lock); 103 |
90 if (*rwlock == NULL) | 104 if (*rwlock == THR_RWLOCK_INITIALIZER) |
91 ret = rwlock_init(rwlock, NULL); 92 else 93 ret = 0; 94 95 THR_LOCK_RELEASE(thread, &_rwlock_static_lock); 96 97 return (ret); 98} --- 9 unchanged lines hidden (view full) --- 108rwlock_rdlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime) 109{ 110 struct pthread *curthread = _get_curthread(); 111 pthread_rwlock_t prwlock; 112 struct timespec ts, ts2, *tsp; 113 int flags; 114 int ret; 115 | 105 ret = rwlock_init(rwlock, NULL); 106 else 107 ret = 0; 108 109 THR_LOCK_RELEASE(thread, &_rwlock_static_lock); 110 111 return (ret); 112} --- 9 unchanged lines hidden (view full) --- 122rwlock_rdlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime) 123{ 124 struct pthread *curthread = _get_curthread(); 125 pthread_rwlock_t prwlock; 126 struct timespec ts, ts2, *tsp; 127 int flags; 128 int ret; 129 |
116 if (__predict_false(rwlock == NULL)) 117 return (EINVAL); | 130 CHECK_AND_INIT_RWLOCK |
118 | 131 |
119 prwlock = *rwlock; 120 121 /* check for static initialization */ 122 if (__predict_false(prwlock == NULL)) { 123 if ((ret = init_static(curthread, rwlock)) != 0) 124 return (ret); 125 126 prwlock = *rwlock; 127 } 128 | |
129 if (curthread->rdlock_count) { 130 /* 131 * To avoid having to track all the rdlocks held by 132 * a thread or all of the threads that hold a rdlock, 133 * we keep a simple count of all the rdlocks held by 134 * a thread. If a thread holds any rdlocks it is 135 * possible that it is attempting to take a recursive 136 * rdlock. If there are blocked writers and precedence --- 64 unchanged lines hidden (view full) --- 201int 202_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) 203{ 204 struct pthread *curthread = _get_curthread(); 205 pthread_rwlock_t prwlock; 206 int flags; 207 int ret; 208 | 132 if (curthread->rdlock_count) { 133 /* 134 * To avoid having to track all the rdlocks held by 135 * a thread or all of the threads that hold a rdlock, 136 * we keep a simple count of all the rdlocks held by 137 * a thread. If a thread holds any rdlocks it is 138 * possible that it is attempting to take a recursive 139 * rdlock. If there are blocked writers and precedence --- 64 unchanged lines hidden (view full) --- 204int 205_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) 206{ 207 struct pthread *curthread = _get_curthread(); 208 pthread_rwlock_t prwlock; 209 int flags; 210 int ret; 211 |
209 if (__predict_false(rwlock == NULL)) 210 return (EINVAL); | 212 CHECK_AND_INIT_RWLOCK |
211 | 213 |
212 prwlock = *rwlock; 213 214 /* check for static initialization */ 215 if (__predict_false(prwlock == NULL)) { 216 if ((ret = init_static(curthread, rwlock)) != 0) 217 return (ret); 218 219 prwlock = *rwlock; 220 } 221 | |
222 if (curthread->rdlock_count) { 223 /* 224 * To avoid having to track all the rdlocks held by 225 * a thread or all of the threads that hold a rdlock, 226 * we keep a simple count of all the rdlocks held by 227 * a thread. If a thread holds any rdlocks it is 228 * possible that it is attempting to take a recursive 229 * rdlock. If there are blocked writers and precedence --- 15 unchanged lines hidden (view full) --- 245 246int 247_pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) 248{ 249 struct pthread *curthread = _get_curthread(); 250 pthread_rwlock_t prwlock; 251 int ret; 252 | 214 if (curthread->rdlock_count) { 215 /* 216 * To avoid having to track all the rdlocks held by 217 * a thread or all of the threads that hold a rdlock, 218 * we keep a simple count of all the rdlocks held by 219 * a thread. If a thread holds any rdlocks it is 220 * possible that it is attempting to take a recursive 221 * rdlock. If there are blocked writers and precedence --- 15 unchanged lines hidden (view full) --- 237 238int 239_pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) 240{ 241 struct pthread *curthread = _get_curthread(); 242 pthread_rwlock_t prwlock; 243 int ret; 244 |
253 if (__predict_false(rwlock == NULL)) 254 return (EINVAL); | 245 CHECK_AND_INIT_RWLOCK |
255 | 246 |
256 prwlock = *rwlock; 257 258 /* check for static initialization */ 259 if (__predict_false(prwlock == NULL)) { 260 if ((ret = init_static(curthread, rwlock)) != 0) 261 return (ret); 262 263 prwlock = *rwlock; 264 } 265 | |
266 ret = _thr_rwlock_trywrlock(&prwlock->lock); 267 if (ret == 0) 268 prwlock->owner = curthread; 269 return (ret); 270} 271 272static int 273rwlock_wrlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) 274{ 275 struct pthread *curthread = _get_curthread(); 276 pthread_rwlock_t prwlock; 277 struct timespec ts, ts2, *tsp; 278 int ret; 279 | 247 ret = _thr_rwlock_trywrlock(&prwlock->lock); 248 if (ret == 0) 249 prwlock->owner = curthread; 250 return (ret); 251} 252 253static int 254rwlock_wrlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) 255{ 256 struct pthread *curthread = _get_curthread(); 257 pthread_rwlock_t prwlock; 258 struct timespec ts, ts2, *tsp; 259 int ret; 260 |
280 if (__predict_false(rwlock == NULL)) 281 return (EINVAL); | 261 CHECK_AND_INIT_RWLOCK |
282 | 262 |
283 prwlock = *rwlock; 284 285 /* check for static initialization */ 286 if (__predict_false(prwlock == NULL)) { 287 if ((ret = init_static(curthread, rwlock)) != 0) 288 return (ret); 289 290 prwlock = *rwlock; 291 } 292 | |
293 /* 294 * POSIX said the validity of the abstimeout parameter need 295 * not be checked if the lock can be immediately acquired. 296 */ 297 ret = _thr_rwlock_trywrlock(&prwlock->lock); 298 if (ret == 0) { 299 prwlock->owner = curthread; 300 return (ret); --- 50 unchanged lines hidden (view full) --- 351int 352_pthread_rwlock_unlock (pthread_rwlock_t *rwlock) 353{ 354 struct pthread *curthread = _get_curthread(); 355 pthread_rwlock_t prwlock; 356 int ret; 357 int32_t state; 358 | 263 /* 264 * POSIX said the validity of the abstimeout parameter need 265 * not be checked if the lock can be immediately acquired. 266 */ 267 ret = _thr_rwlock_trywrlock(&prwlock->lock); 268 if (ret == 0) { 269 prwlock->owner = curthread; 270 return (ret); --- 50 unchanged lines hidden (view full) --- 321int 322_pthread_rwlock_unlock (pthread_rwlock_t *rwlock) 323{ 324 struct pthread *curthread = _get_curthread(); 325 pthread_rwlock_t prwlock; 326 int ret; 327 int32_t state; 328 |
359 if (__predict_false(rwlock == NULL)) 360 return (EINVAL); 361 | |
362 prwlock = *rwlock; 363 | 329 prwlock = *rwlock; 330 |
364 if (__predict_false(prwlock == NULL)) | 331 if (__predict_false(prwlock <= THR_RWLOCK_DESTROYED)) |
365 return (EINVAL); 366 367 state = prwlock->lock.rw_state; 368 if (state & URWLOCK_WRITE_OWNER) { 369 if (__predict_false(prwlock->owner != curthread)) 370 return (EPERM); 371 prwlock->owner = NULL; 372 } 373 374 ret = _thr_rwlock_unlock(&prwlock->lock); 375 if (ret == 0 && (state & URWLOCK_WRITE_OWNER) == 0) 376 curthread->rdlock_count--; 377 378 return (ret); 379} | 332 return (EINVAL); 333 334 state = prwlock->lock.rw_state; 335 if (state & URWLOCK_WRITE_OWNER) { 336 if (__predict_false(prwlock->owner != curthread)) 337 return (EPERM); 338 prwlock->owner = NULL; 339 } 340 341 ret = _thr_rwlock_unlock(&prwlock->lock); 342 if (ret == 0 && (state & URWLOCK_WRITE_OWNER) == 0) 343 curthread->rdlock_count--; 344 345 return (ret); 346} |