Deleted Added
full compact
kern_umtx.c (216463) kern_umtx.c (216641)
1/*-
2 * Copyright (c) 2004, David Xu <davidxu@freebsd.org>
3 * Copyright (c) 2002, Jeffrey Roberson <jeff@freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 12 unchanged lines hidden (view full) ---

21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2004, David Xu <davidxu@freebsd.org>
3 * Copyright (c) 2002, Jeffrey Roberson <jeff@freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 12 unchanged lines hidden (view full) ---

21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/kern/kern_umtx.c 216463 2010-12-15 19:30:44Z mdf $");
29__FBSDID("$FreeBSD: head/sys/kern/kern_umtx.c 216641 2010-12-22 05:01:52Z davidxu $");
30
31#include "opt_compat.h"
32#include <sys/param.h>
33#include <sys/kernel.h>
34#include <sys/limits.h>
35#include <sys/lock.h>
36#include <sys/malloc.h>
37#include <sys/mutex.h>
38#include <sys/priv.h>
39#include <sys/proc.h>
40#include <sys/sched.h>
41#include <sys/smp.h>
42#include <sys/sysctl.h>
43#include <sys/sysent.h>
44#include <sys/systm.h>
45#include <sys/sysproto.h>
30
31#include "opt_compat.h"
32#include <sys/param.h>
33#include <sys/kernel.h>
34#include <sys/limits.h>
35#include <sys/lock.h>
36#include <sys/malloc.h>
37#include <sys/mutex.h>
38#include <sys/priv.h>
39#include <sys/proc.h>
40#include <sys/sched.h>
41#include <sys/smp.h>
42#include <sys/sysctl.h>
43#include <sys/sysent.h>
44#include <sys/systm.h>
45#include <sys/sysproto.h>
46#include <sys/syscallsubr.h>
46#include <sys/eventhandler.h>
47#include <sys/umtx.h>
48
49#include <vm/vm.h>
50#include <vm/vm_param.h>
51#include <vm/pmap.h>
52#include <vm/vm_map.h>
53#include <vm/vm_object.h>

--- 2292 unchanged lines hidden (view full) ---

2346static int
2347do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
2348 struct timespec *timeout, u_long wflags)
2349{
2350 struct umtx_q *uq;
2351 struct timeval tv;
2352 struct timespec cts, ets, tts;
2353 uint32_t flags;
47#include <sys/eventhandler.h>
48#include <sys/umtx.h>
49
50#include <vm/vm.h>
51#include <vm/vm_param.h>
52#include <vm/pmap.h>
53#include <vm/vm_map.h>
54#include <vm/vm_object.h>

--- 2292 unchanged lines hidden (view full) ---

2347static int
2348do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
2349 struct timespec *timeout, u_long wflags)
2350{
2351 struct umtx_q *uq;
2352 struct timeval tv;
2353 struct timespec cts, ets, tts;
2354 uint32_t flags;
2355 uint32_t clockid;
2354 int error;
2355
2356 uq = td->td_umtxq;
2357 flags = fuword32(&cv->c_flags);
2358 error = umtx_key_get(cv, TYPE_CV, GET_SHARE(flags), &uq->uq_key);
2359 if (error != 0)
2360 return (error);
2356 int error;
2357
2358 uq = td->td_umtxq;
2359 flags = fuword32(&cv->c_flags);
2360 error = umtx_key_get(cv, TYPE_CV, GET_SHARE(flags), &uq->uq_key);
2361 if (error != 0)
2362 return (error);
2363
2364 if ((wflags & CVWAIT_CLOCKID) != 0) {
2365 clockid = fuword32(&cv->c_clockid);
2366 if (clockid < CLOCK_REALTIME ||
2367 clockid >= CLOCK_THREAD_CPUTIME_ID) {
2368 /* hmm, only HW clock id will work. */
2369 return (EINVAL);
2370 }
2371 } else {
2372 clockid = CLOCK_REALTIME;
2373 }
2374
2361 umtxq_lock(&uq->uq_key);
2362 umtxq_busy(&uq->uq_key);
2363 umtxq_insert(uq);
2364 umtxq_unlock(&uq->uq_key);
2365
2366 /*
2375 umtxq_lock(&uq->uq_key);
2376 umtxq_busy(&uq->uq_key);
2377 umtxq_insert(uq);
2378 umtxq_unlock(&uq->uq_key);
2379
2380 /*
2367 * The magic thing is we should set c_has_waiters to 1 before
2368 * releasing user mutex.
2381 * Set c_has_waiters to 1 before releasing user mutex, also
2382 * don't modify cache line when unnecessary.
2369 */
2383 */
2370 suword32(__DEVOLATILE(uint32_t *, &cv->c_has_waiters), 1);
2384 if (fuword32(__DEVOLATILE(uint32_t *, &cv->c_has_waiters)) == 0)
2385 suword32(__DEVOLATILE(uint32_t *, &cv->c_has_waiters), 1);
2371
2372 umtxq_lock(&uq->uq_key);
2373 umtxq_unbusy(&uq->uq_key);
2374 umtxq_unlock(&uq->uq_key);
2375
2376 error = do_unlock_umutex(td, m);
2377
2378 umtxq_lock(&uq->uq_key);
2379 if (error == 0) {
2386
2387 umtxq_lock(&uq->uq_key);
2388 umtxq_unbusy(&uq->uq_key);
2389 umtxq_unlock(&uq->uq_key);
2390
2391 error = do_unlock_umutex(td, m);
2392
2393 umtxq_lock(&uq->uq_key);
2394 if (error == 0) {
2380 if ((wflags & UMTX_CHECK_UNPARKING) &&
2381 (td->td_pflags & TDP_WAKEUP)) {
2382 td->td_pflags &= ~TDP_WAKEUP;
2383 error = EINTR;
2384 } else if (timeout == NULL) {
2395 if (timeout == NULL) {
2385 error = umtxq_sleep(uq, "ucond", 0);
2386 } else {
2396 error = umtxq_sleep(uq, "ucond", 0);
2397 } else {
2387 getnanouptime(&ets);
2388 timespecadd(&ets, timeout);
2389 TIMESPEC_TO_TIMEVAL(&tv, timeout);
2398 if ((wflags & CVWAIT_ABSTIME) == 0) {
2399 kern_clock_gettime(td, clockid, &ets);
2400 timespecadd(&ets, timeout);
2401 tts = *timeout;
2402 } else { /* absolute time */
2403 ets = *timeout;
2404 tts = *timeout;
2405 kern_clock_gettime(td, clockid, &cts);
2406 timespecsub(&tts, &cts);
2407 }
2408 TIMESPEC_TO_TIMEVAL(&tv, &tts);
2390 for (;;) {
2391 error = umtxq_sleep(uq, "ucond", tvtohz(&tv));
2392 if (error != ETIMEDOUT)
2393 break;
2409 for (;;) {
2410 error = umtxq_sleep(uq, "ucond", tvtohz(&tv));
2411 if (error != ETIMEDOUT)
2412 break;
2394 getnanouptime(&cts);
2413 kern_clock_gettime(td, clockid, &cts);
2395 if (timespeccmp(&cts, &ets, >=)) {
2396 error = ETIMEDOUT;
2397 break;
2398 }
2399 tts = ets;
2400 timespecsub(&tts, &cts);
2401 TIMESPEC_TO_TIMEVAL(&tv, &tts);
2402 }
2403 }
2404 }
2405
2406 if ((uq->uq_flags & UQF_UMTXQ) == 0)
2407 error = 0;
2408 else {
2414 if (timespeccmp(&cts, &ets, >=)) {
2415 error = ETIMEDOUT;
2416 break;
2417 }
2418 tts = ets;
2419 timespecsub(&tts, &cts);
2420 TIMESPEC_TO_TIMEVAL(&tv, &tts);
2421 }
2422 }
2423 }
2424
2425 if ((uq->uq_flags & UQF_UMTXQ) == 0)
2426 error = 0;
2427 else {
2409 umtxq_remove(uq);
2428 /*
2429 * This must be timeout,interrupted by signal or
2430 * surprious wakeup, clear c_has_waiter flag when
2431 * necessary.
2432 */
2433 umtxq_busy(&uq->uq_key);
2434 if ((uq->uq_flags & UQF_UMTXQ) != 0) {
2435 int oldlen = uq->uq_cur_queue->length;
2436 umtxq_remove(uq);
2437 if (oldlen == 1) {
2438 umtxq_unlock(&uq->uq_key);
2439 suword32(
2440 __DEVOLATILE(uint32_t *,
2441 &cv->c_has_waiters), 0);
2442 umtxq_lock(&uq->uq_key);
2443 }
2444 }
2445 umtxq_unbusy(&uq->uq_key);
2410 if (error == ERESTART)
2411 error = EINTR;
2412 }
2413
2414 umtxq_unlock(&uq->uq_key);
2415 umtx_key_release(&uq->uq_key);
2416 return (error);
2417}

--- 606 unchanged lines hidden (view full) ---

3024}
3025
3026static int
3027__umtx_op_wake(struct thread *td, struct _umtx_op_args *uap)
3028{
3029 return (kern_umtx_wake(td, uap->obj, uap->val, 0));
3030}
3031
2446 if (error == ERESTART)
2447 error = EINTR;
2448 }
2449
2450 umtxq_unlock(&uq->uq_key);
2451 umtx_key_release(&uq->uq_key);
2452 return (error);
2453}

--- 606 unchanged lines hidden (view full) ---

3060}
3061
3062static int
3063__umtx_op_wake(struct thread *td, struct _umtx_op_args *uap)
3064{
3065 return (kern_umtx_wake(td, uap->obj, uap->val, 0));
3066}
3067
3068#define BATCH_SIZE 128
3032static int
3069static int
3070__umtx_op_nwake_private(struct thread *td, struct _umtx_op_args *uap)
3071{
3072 int count = uap->val;
3073 void *uaddrs[BATCH_SIZE];
3074 char **upp = (char **)uap->obj;
3075 int tocopy;
3076 int error = 0;
3077 int i, pos = 0;
3078
3079 while (count > 0) {
3080 tocopy = count;
3081 if (tocopy > BATCH_SIZE)
3082 tocopy = BATCH_SIZE;
3083 error = copyin(upp+pos, uaddrs, tocopy * sizeof(char *));
3084 if (error != 0)
3085 break;
3086 for (i = 0; i < tocopy; ++i)
3087 kern_umtx_wake(td, uaddrs[i], INT_MAX, 1);
3088 count -= tocopy;
3089 pos += tocopy;
3090 }
3091 return (error);
3092}
3093
3094static int
3033__umtx_op_wake_private(struct thread *td, struct _umtx_op_args *uap)
3034{
3035 return (kern_umtx_wake(td, uap->obj, uap->val, 1));
3036}
3037
3038static int
3039__umtx_op_lock_umutex(struct thread *td, struct _umtx_op_args *uap)
3040{

--- 199 unchanged lines hidden (view full) ---

3240 __umtx_op_rw_rdlock, /* UMTX_OP_RW_RDLOCK */
3241 __umtx_op_rw_wrlock, /* UMTX_OP_RW_WRLOCK */
3242 __umtx_op_rw_unlock, /* UMTX_OP_RW_UNLOCK */
3243 __umtx_op_wait_uint_private, /* UMTX_OP_WAIT_UINT_PRIVATE */
3244 __umtx_op_wake_private, /* UMTX_OP_WAKE_PRIVATE */
3245 __umtx_op_wait_umutex, /* UMTX_OP_UMUTEX_WAIT */
3246 __umtx_op_wake_umutex, /* UMTX_OP_UMUTEX_WAKE */
3247 __umtx_op_sem_wait, /* UMTX_OP_SEM_WAIT */
3095__umtx_op_wake_private(struct thread *td, struct _umtx_op_args *uap)
3096{
3097 return (kern_umtx_wake(td, uap->obj, uap->val, 1));
3098}
3099
3100static int
3101__umtx_op_lock_umutex(struct thread *td, struct _umtx_op_args *uap)
3102{

--- 199 unchanged lines hidden (view full) ---

3302 __umtx_op_rw_rdlock, /* UMTX_OP_RW_RDLOCK */
3303 __umtx_op_rw_wrlock, /* UMTX_OP_RW_WRLOCK */
3304 __umtx_op_rw_unlock, /* UMTX_OP_RW_UNLOCK */
3305 __umtx_op_wait_uint_private, /* UMTX_OP_WAIT_UINT_PRIVATE */
3306 __umtx_op_wake_private, /* UMTX_OP_WAKE_PRIVATE */
3307 __umtx_op_wait_umutex, /* UMTX_OP_UMUTEX_WAIT */
3308 __umtx_op_wake_umutex, /* UMTX_OP_UMUTEX_WAKE */
3309 __umtx_op_sem_wait, /* UMTX_OP_SEM_WAIT */
3248 __umtx_op_sem_wake /* UMTX_OP_SEM_WAKE */
3310 __umtx_op_sem_wake, /* UMTX_OP_SEM_WAKE */
3311 __umtx_op_nwake_private /* UMTX_OP_NWAKE_PRIVATE */
3249};
3250
3251int
3252_umtx_op(struct thread *td, struct _umtx_op_args *uap)
3253{
3254 if ((unsigned)uap->op < UMTX_OP_MAX)
3255 return (*op_table[uap->op])(td, uap);
3256 return (EINVAL);

--- 225 unchanged lines hidden (view full) ---

3482 if (timeout.tv_nsec >= 1000000000 ||
3483 timeout.tv_nsec < 0)
3484 return (EINVAL);
3485 ts = &timeout;
3486 }
3487 return (do_sem_wait(td, uap->obj, ts));
3488}
3489
3312};
3313
3314int
3315_umtx_op(struct thread *td, struct _umtx_op_args *uap)
3316{
3317 if ((unsigned)uap->op < UMTX_OP_MAX)
3318 return (*op_table[uap->op])(td, uap);
3319 return (EINVAL);

--- 225 unchanged lines hidden (view full) ---

3545 if (timeout.tv_nsec >= 1000000000 ||
3546 timeout.tv_nsec < 0)
3547 return (EINVAL);
3548 ts = &timeout;
3549 }
3550 return (do_sem_wait(td, uap->obj, ts));
3551}
3552
3553static int
3554__umtx_op_nwake_private32(struct thread *td, struct _umtx_op_args *uap)
3555{
3556 int count = uap->val;
3557 uint32_t uaddrs[BATCH_SIZE];
3558 uint32_t **upp = (uint32_t **)uap->obj;
3559 int tocopy;
3560 int error = 0;
3561 int i, pos = 0;
3562
3563 while (count > 0) {
3564 tocopy = count;
3565 if (tocopy > BATCH_SIZE)
3566 tocopy = BATCH_SIZE;
3567 error = copyin(upp+pos, uaddrs, tocopy * sizeof(uint32_t));
3568 if (error != 0)
3569 break;
3570 for (i = 0; i < tocopy; ++i)
3571 kern_umtx_wake(td, (void *)(intptr_t)uaddrs[i],
3572 INT_MAX, 1);
3573 count -= tocopy;
3574 pos += tocopy;
3575 }
3576 return (error);
3577}
3578
3490static _umtx_op_func op_table_compat32[] = {
3491 __umtx_op_lock_umtx_compat32, /* UMTX_OP_LOCK */
3492 __umtx_op_unlock_umtx_compat32, /* UMTX_OP_UNLOCK */
3493 __umtx_op_wait_compat32, /* UMTX_OP_WAIT */
3494 __umtx_op_wake, /* UMTX_OP_WAKE */
3495 __umtx_op_trylock_umutex, /* UMTX_OP_MUTEX_LOCK */
3496 __umtx_op_lock_umutex_compat32, /* UMTX_OP_MUTEX_TRYLOCK */
3497 __umtx_op_unlock_umutex, /* UMTX_OP_MUTEX_UNLOCK */

--- 5 unchanged lines hidden (view full) ---

3503 __umtx_op_rw_rdlock_compat32, /* UMTX_OP_RW_RDLOCK */
3504 __umtx_op_rw_wrlock_compat32, /* UMTX_OP_RW_WRLOCK */
3505 __umtx_op_rw_unlock, /* UMTX_OP_RW_UNLOCK */
3506 __umtx_op_wait_uint_private_compat32, /* UMTX_OP_WAIT_UINT_PRIVATE */
3507 __umtx_op_wake_private, /* UMTX_OP_WAKE_PRIVATE */
3508 __umtx_op_wait_umutex_compat32, /* UMTX_OP_UMUTEX_WAIT */
3509 __umtx_op_wake_umutex, /* UMTX_OP_UMUTEX_WAKE */
3510 __umtx_op_sem_wait_compat32, /* UMTX_OP_SEM_WAIT */
3579static _umtx_op_func op_table_compat32[] = {
3580 __umtx_op_lock_umtx_compat32, /* UMTX_OP_LOCK */
3581 __umtx_op_unlock_umtx_compat32, /* UMTX_OP_UNLOCK */
3582 __umtx_op_wait_compat32, /* UMTX_OP_WAIT */
3583 __umtx_op_wake, /* UMTX_OP_WAKE */
3584 __umtx_op_trylock_umutex, /* UMTX_OP_MUTEX_LOCK */
3585 __umtx_op_lock_umutex_compat32, /* UMTX_OP_MUTEX_TRYLOCK */
3586 __umtx_op_unlock_umutex, /* UMTX_OP_MUTEX_UNLOCK */

--- 5 unchanged lines hidden (view full) ---

3592 __umtx_op_rw_rdlock_compat32, /* UMTX_OP_RW_RDLOCK */
3593 __umtx_op_rw_wrlock_compat32, /* UMTX_OP_RW_WRLOCK */
3594 __umtx_op_rw_unlock, /* UMTX_OP_RW_UNLOCK */
3595 __umtx_op_wait_uint_private_compat32, /* UMTX_OP_WAIT_UINT_PRIVATE */
3596 __umtx_op_wake_private, /* UMTX_OP_WAKE_PRIVATE */
3597 __umtx_op_wait_umutex_compat32, /* UMTX_OP_UMUTEX_WAIT */
3598 __umtx_op_wake_umutex, /* UMTX_OP_UMUTEX_WAKE */
3599 __umtx_op_sem_wait_compat32, /* UMTX_OP_SEM_WAIT */
3511 __umtx_op_sem_wake /* UMTX_OP_SEM_WAKE */
3600 __umtx_op_sem_wake, /* UMTX_OP_SEM_WAKE */
3601 __umtx_op_nwake_private32 /* UMTX_OP_NWAKE_PRIVATE */
3512};
3513
3514int
3515freebsd32_umtx_op(struct thread *td, struct freebsd32_umtx_op_args *uap)
3516{
3517 if ((unsigned)uap->op < UMTX_OP_MAX)
3518 return (*op_table_compat32[uap->op])(td,
3519 (struct _umtx_op_args *)uap);

--- 76 unchanged lines hidden ---
3602};
3603
3604int
3605freebsd32_umtx_op(struct thread *td, struct freebsd32_umtx_op_args *uap)
3606{
3607 if ((unsigned)uap->op < UMTX_OP_MAX)
3608 return (*op_table_compat32[uap->op])(td,
3609 (struct _umtx_op_args *)uap);

--- 76 unchanged lines hidden ---