umtx.h revision 139427
1163712Simp/* 2163712Simp * Copyright (c) 2002, Jeffrey Roberson <jeff@freebsd.org> 3163712Simp * All rights reserved. 4163712Simp * 5163712Simp * Redistribution and use in source and binary forms, with or without 6163712Simp * modification, are permitted provided that the following conditions 7163712Simp * are met: 8163712Simp * 1. Redistributions of source code must retain the above copyright 9163712Simp * notice unmodified, this list of conditions, and the following 10163712Simp * disclaimer. 11163712Simp * 2. Redistributions in binary form must reproduce the above copyright 12163712Simp * notice, this list of conditions and the following disclaimer in the 13163712Simp * documentation and/or other materials provided with the distribution. 14163712Simp * 15163712Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16163712Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17163712Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18163712Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19163712Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20163712Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21163712Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22163712Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23163712Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24163712Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25163712Simp * 26163712Simp * $FreeBSD: head/sys/sys/umtx.h 139427 2004-12-30 02:56:17Z davidxu $ 27163712Simp * 28163712Simp */ 29163712Simp 30163712Simp#ifndef _SYS_UMTX_H_ 31163712Simp#define _SYS_UMTX_H_ 32163712Simp 33163712Simp#include <sys/limits.h> 34163712Simp 35163712Simp/* 36163712Simp * See pthread_* 37163712Simp */ 38163712Simp 39163712Simp#define UMTX_UNOWNED 0x0 40163712Simp#define UMTX_CONTESTED LONG_MIN 41163712Simp 42163712Simpstruct umtx { 43163712Simp void *u_owner; /* Owner of the mutex. */ 44163712Simp}; 45163712Simp 46163712Simp/* op code for _umtx_op */ 47163712Simp#define UMTX_OP_LOCK 0 48163712Simp#define UMTX_OP_UNLOCK 1 49163712Simp#define UMTX_OP_WAIT 2 50163712Simp#define UMTX_OP_WAKE 3 51163712Simp 52163712Simp#ifndef _KERNEL 53163712Simp 54163712Simp/* 55185996Ssbruno * System calls for acquiring and releasing contested mutexes. 56163712Simp */ 57163712Simp/* deprecated becaues it can only use thread id */ 58185996Ssbrunoint _umtx_lock(struct umtx *mtx); 59185996Ssbruno/* deprecated becaues it can only use thread id */ 60185996Ssbrunoint _umtx_unlock(struct umtx *mtx); 61185996Ssbrunoint _umtx_op(struct umtx *umtx, int op, long id, void *uaddr, void *uaddr2); 62185996Ssbruno 63185996Ssbruno/* 64163712Simp * Standard api. Try uncontested acquire/release and asks the 65185996Ssbruno * kernel to resolve failures. 66163712Simp */ 67163712Simpstatic __inline void 68163712Simpumtx_init(struct umtx *umtx) 69163712Simp{ 70163712Simp umtx->u_owner = UMTX_UNOWNED; 71163712Simp} 72163712Simp 73163712Simpstatic __inline long 74163712Simpumtx_owner(struct umtx *umtx) 75163712Simp{ 76163712Simp return ((long)umtx->u_owner & ~LONG_MIN); 77163712Simp} 78163712Simp 79163712Simpstatic __inline int 80163712Simpumtx_lock(struct umtx *umtx, long id) 81163712Simp{ 82163712Simp if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED, 83163712Simp (void *)id) == 0) 84163712Simp if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0, 0) == -1) 85163712Simp return (errno); 86163712Simp return (0); 87163712Simp} 88163712Simp 89163712Simpstatic __inline int 90163712Simpumtx_trylock(struct umtx *umtx, long id) 91163712Simp{ 92163712Simp if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED, 93163712Simp (void *)id) == 0) 94163712Simp return (EBUSY); 95163712Simp return (0); 96163712Simp} 97228990Suqs 98163712Simpstatic __inline int 99163712Simpumtx_timedlock(struct umtx *umtx, long id, const struct timespec *abstime) 100163712Simp{ 101163712Simp if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED, 102163712Simp (void *)id) == 0) 103163712Simp if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0, (void *)abstime) == -1) 104163712Simp return (errno); 105163712Simp return (0); 106163712Simp} 107163712Simp 108163712Simpstatic __inline int 109163712Simpumtx_unlock(struct umtx *umtx, long id) 110163712Simp{ 111163712Simp if (atomic_cmpset_rel_ptr(&umtx->u_owner, (void *)id, 112163712Simp (void *)UMTX_UNOWNED) == 0) 113163712Simp if (_umtx_op(umtx, UMTX_OP_UNLOCK, id, 0, 0) == -1) 114163712Simp return (errno); 115163712Simp return (0); 116163712Simp} 117163712Simp 118163712Simp/* Unlock umtx and wait on a user address. */ 119163712Simp 120163712Simpstatic __inline int 121163712Simpumtx_wait(struct umtx *umtx, long id) 122293290Sbdrewery{ 123163712Simp if (_umtx_op(umtx, UMTX_OP_WAIT, id, 0, 0) == -1) 124163712Simp return (errno); 125163712Simp return (0); 126163712Simp} 127163712Simp 128163712Simpstatic __inline int 129163712Simpumtx_timedwait(struct umtx *umtx, long id, const struct timespec *abstime) 130163712Simp{ 131163712Simp if (_umtx_op(umtx, UMTX_OP_WAIT, id, 0, (void *)abstime) == -1) 132163712Simp return (errno); 133163712Simp return (0); 134163712Simp} 135163712Simp 136163712Simp/* Wake threads waiting on a user address. */ 137163712Simpstatic __inline int 138163712Simpumtx_wake(struct umtx *umtx, int nr_wakeup) 139163712Simp{ 140163712Simp /* return how many threads were woke up, -1 if error */ 141163712Simp return _umtx_op(umtx, UMTX_OP_WAKE, nr_wakeup, 0, 0); 142163712Simp} 143163712Simp 144163712Simp#endif /* !_KERNEL */ 145163712Simp#endif /* !_SYS_UMTX_H_ */ 146163712Simp