Deleted Added
sdiff udiff text old ( 216463 ) new ( 216641 )
full compact
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 $");
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/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;
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);
2361 umtxq_lock(&uq->uq_key);
2362 umtxq_busy(&uq->uq_key);
2363 umtxq_insert(uq);
2364 umtxq_unlock(&uq->uq_key);
2365
2366 /*
2367 * The magic thing is we should set c_has_waiters to 1 before
2368 * releasing user mutex.
2369 */
2370 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) {
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) {
2385 error = umtxq_sleep(uq, "ucond", 0);
2386 } else {
2387 getnanouptime(&ets);
2388 timespecadd(&ets, timeout);
2389 TIMESPEC_TO_TIMEVAL(&tv, timeout);
2390 for (;;) {
2391 error = umtxq_sleep(uq, "ucond", tvtohz(&tv));
2392 if (error != ETIMEDOUT)
2393 break;
2394 getnanouptime(&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 {
2409 umtxq_remove(uq);
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
3032static 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 */
3248 __umtx_op_sem_wake /* UMTX_OP_SEM_WAKE */
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
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 */
3511 __umtx_op_sem_wake /* UMTX_OP_SEM_WAKE */
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 ---