umtx.h revision 216641
1124350Sschweikh/*- 299026Sjulian * Copyright (c) 2002, Jeffrey Roberson <jeff@freebsd.org> 399026Sjulian * All rights reserved. 499026Sjulian * 599026Sjulian * Redistribution and use in source and binary forms, with or without 699026Sjulian * modification, are permitted provided that the following conditions 799026Sjulian * are met: 899026Sjulian * 1. Redistributions of source code must retain the above copyright 999026Sjulian * notice unmodified, this list of conditions, and the following 10124350Sschweikh * disclaimer. 1199026Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1299026Sjulian * notice, this list of conditions and the following disclaimer in the 1399026Sjulian * documentation and/or other materials provided with the distribution. 1499026Sjulian * 1599026Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1699026Sjulian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1799026Sjulian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1899026Sjulian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1999026Sjulian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2099026Sjulian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2199026Sjulian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2299026Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2399026Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2499026Sjulian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2599026Sjulian * 2699026Sjulian * $FreeBSD: head/sys/sys/umtx.h 216641 2010-12-22 05:01:52Z davidxu $ 2799026Sjulian * 2899026Sjulian */ 29116182Sobrien 30116182Sobrien#ifndef _SYS_UMTX_H_ 31116182Sobrien#define _SYS_UMTX_H_ 3299026Sjulian 3399026Sjulian#include <sys/_umtx.h> 3499026Sjulian#include <sys/limits.h> 3599026Sjulian 3699026Sjulian#define UMTX_UNOWNED 0x0 3799026Sjulian#define UMTX_CONTESTED LONG_MIN 38130355Sjulian 3999026Sjulian#define USYNC_PROCESS_SHARED 0x0001 /* Process shared sync objs */ 40107126Sjeff 41126326Sjhb#define UMUTEX_UNOWNED 0x0 42122514Sjhb#define UMUTEX_CONTESTED 0x80000000U 4399026Sjulian 4499026Sjulian#define UMUTEX_ERROR_CHECK 0x0002 /* Error-checking mutex */ 4599026Sjulian#define UMUTEX_PRIO_INHERIT 0x0004 /* Priority inherited mutex */ 46116355Salc#define UMUTEX_PRIO_PROTECT 0x0008 /* Priority protect mutex */ 4799026Sjulian 4899026Sjulian/* urwlock flags */ 4999026Sjulian#define URWLOCK_PREFER_READER 0x0002 50103367Sjulian 5199026Sjulian#define URWLOCK_WRITE_OWNER 0x80000000U 52103367Sjulian#define URWLOCK_WRITE_WAITERS 0x40000000U 53103367Sjulian#define URWLOCK_READ_WAITERS 0x20000000U 5499026Sjulian#define URWLOCK_MAX_READERS 0x1fffffffU 5599026Sjulian#define URWLOCK_READER_COUNT(c) ((c) & URWLOCK_MAX_READERS) 56103367Sjulian 5799026Sjulian/* _usem flags */ 58107719Sjulian#define SEM_NAMED 0x0002 59107719Sjulian 60107719Sjulian/* op code for _umtx_op */ 6199026Sjulian#define UMTX_OP_LOCK 0 62130199Sjulian#define UMTX_OP_UNLOCK 1 63107006Sdavidxu#define UMTX_OP_WAIT 2 64103367Sjulian#define UMTX_OP_WAKE 3 65103367Sjulian#define UMTX_OP_MUTEX_TRYLOCK 4 66130199Sjulian#define UMTX_OP_MUTEX_LOCK 5 67107006Sdavidxu#define UMTX_OP_MUTEX_UNLOCK 6 68107006Sdavidxu#define UMTX_OP_SET_CEILING 7 69107006Sdavidxu#define UMTX_OP_CV_WAIT 8 70130199Sjulian#define UMTX_OP_CV_SIGNAL 9 71111115Sdavidxu#define UMTX_OP_CV_BROADCAST 10 72111115Sdavidxu#define UMTX_OP_WAIT_UINT 11 73111115Sdavidxu#define UMTX_OP_RW_RDLOCK 12 74130355Sjulian#define UMTX_OP_RW_WRLOCK 13 75111028Sjeff#define UMTX_OP_RW_UNLOCK 14 76130355Sjulian#define UMTX_OP_WAIT_UINT_PRIVATE 15 77130355Sjulian#define UMTX_OP_WAKE_PRIVATE 16 78111028Sjeff#define UMTX_OP_MUTEX_WAIT 17 79105854Sjulian#define UMTX_OP_MUTEX_WAKE 18 80105854Sjulian#define UMTX_OP_SEM_WAIT 19 81111028Sjeff#define UMTX_OP_SEM_WAKE 20 82111028Sjeff#define UMTX_OP_NWAKE_PRIVATE 21 8399026Sjulian#define UMTX_OP_MAX 22 84130199Sjulian 85130199Sjulian/* Flags for UMTX_OP_CV_WAIT */ 86105854Sjulian#define CVWAIT_CHECK_UNPARKING 0x01 87130199Sjulian#define CVWAIT_ABSTIME 0x02 88130199Sjulian#define CVWAIT_CLOCKID 0x04 89130199Sjulian 90111028Sjeff#define UMTX_CHECK_UNPARKING CVWAIT_CHECK_UNPARKING 91111028Sjeff 92130355Sjulian#ifndef _KERNEL 93130355Sjulian 94130355Sjulianint _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2); 95130355Sjulian 96130355Sjulian/* 97111028Sjeff * Old (deprecated) userland mutex system calls. 98130355Sjulian */ 99130355Sjulianint _umtx_lock(struct umtx *mtx); 100130355Sjulianint _umtx_unlock(struct umtx *mtx); 101130355Sjulian 102130355Sjulian/* 103130355Sjulian * Standard api. Try uncontested acquire/release and asks the 104133713Sjulian * kernel to resolve failures. 105130355Sjulian */ 106130355Sjulianstatic __inline void 107130355Sjulianumtx_init(struct umtx *umtx) 108130355Sjulian{ 109130355Sjulian umtx->u_owner = UMTX_UNOWNED; 110130355Sjulian} 111130355Sjulian 112130355Sjulianstatic __inline u_long 113130355Sjulianumtx_owner(struct umtx *umtx) 114130355Sjulian{ 115130355Sjulian return (umtx->u_owner & ~LONG_MIN); 116130355Sjulian} 11799026Sjulian 118127794Smarcelstatic __inline int 119127794Smarcelumtx_lock(struct umtx *umtx, u_long id) 120127794Smarcel{ 121127794Smarcel if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0) 122127794Smarcel if (_umtx_lock(umtx) == -1) 123127794Smarcel return (errno); 124127794Smarcel return (0); 125127794Smarcel} 126127794Smarcel 127127794Smarcelstatic __inline int 128127794Smarcelumtx_trylock(struct umtx *umtx, u_long id) 129127794Smarcel{ 130127794Smarcel if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0) 131127794Smarcel return (EBUSY); 132130735Smarcel return (0); 133127794Smarcel} 134127794Smarcel 135127794Smarcelstatic __inline int 136127794Smarcelumtx_timedlock(struct umtx *umtx, u_long id, const struct timespec *timeout) 137127794Smarcel{ 138127794Smarcel if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0) 139127794Smarcel if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0, 140127794Smarcel __DECONST(void *, timeout)) == -1) 141127794Smarcel return (errno); 142127794Smarcel return (0); 143127794Smarcel} 144107719Sjulian 14599026Sjulianstatic __inline int 146132987Sgreenumtx_unlock(struct umtx *umtx, u_long id) 147132987Sgreen{ 14899026Sjulian if (atomic_cmpset_rel_long(&umtx->u_owner, id, UMTX_UNOWNED) == 0) 14999026Sjulian if (_umtx_unlock(umtx) == -1) 15099026Sjulian return (errno); 15199026Sjulian return (0); 152103216Sjulian} 153113339Sjulian 154130269Sjmallettstatic __inline int 155130269Sjmallettumtx_wait(u_long *p, long val, const struct timespec *timeout) 156130269Sjmallett{ 157130269Sjmallett if (_umtx_op(p, UMTX_OP_WAIT, val, 0, 158130269Sjmallett __DECONST(void *, timeout)) == -1) 159130269Sjmallett return (errno); 160130269Sjmallett return (0); 161130269Sjmallett} 162130269Sjmallett 163130269Sjmallett/* Wake threads waiting on a user address. */ 164130269Sjmallettstatic __inline int 165130269Sjmallettumtx_wake(u_long *p, int nr_wakeup) 166130269Sjmallett{ 167118442Sjhb if (_umtx_op(p, UMTX_OP_WAKE, nr_wakeup, 0, 0) == -1) 168132987Sgreen return (errno); 16999026Sjulian return (0); 17099026Sjulian} 17199026Sjulian 17299026Sjulian#else 17399026Sjulian 17499026Sjulianstruct thread; 17599026Sjulian 17699026Sjulianstruct umtx_q *umtxq_alloc(void); 177127794Smarcelvoid umtxq_free(struct umtx_q *); 17899026Sjulianint kern_umtx_wake(struct thread *, void *, int, int); 17999026Sjulianvoid umtx_pi_adjust(struct thread *, u_char); 18099026Sjulianvoid umtx_thread_init(struct thread *); 18199026Sjulianvoid umtx_thread_fini(struct thread *); 18299026Sjulianvoid umtx_thread_alloc(struct thread *); 18399026Sjulianvoid umtx_thread_exit(struct thread *); 184103216Sjulian#endif /* !_KERNEL */ 185103216Sjulian#endif /* !_SYS_UMTX_H_ */ 186103216Sjulian