umtx.h revision 139427
175406Sache/* 226497Sache * Copyright (c) 2002, Jeffrey Roberson <jeff@freebsd.org> 3136644Sache * All rights reserved. 4136644Sache * 5136644Sache * Redistribution and use in source and binary forms, with or without 6136644Sache * modification, are permitted provided that the following conditions 735486Sache * are met: 835486Sache * 1. Redistributions of source code must retain the above copyright 935486Sache * notice unmodified, this list of conditions, and the following 1026497Sache * disclaimer. 1126497Sache * 2. Redistributions in binary form must reproduce the above copyright 1226497Sache * notice, this list of conditions and the following disclaimer in the 13136644Sache * documentation and/or other materials provided with the distribution. 14136644Sache * 15119610Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16119610Sache * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17119610Sache * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18119610Sache * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19119610Sache * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20119610Sache * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21119610Sache * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22119610Sache * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23119610Sache * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24119610Sache * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25119610Sache * 2626497Sache * $FreeBSD: head/sys/sys/umtx.h 139427 2004-12-30 02:56:17Z davidxu $ 2726497Sache * 2826497Sache */ 29119610Sache 30119610Sache#ifndef _SYS_UMTX_H_ 31119610Sache#define _SYS_UMTX_H_ 32119610Sache 33119610Sache#include <sys/limits.h> 34119610Sache 3526497Sache/* 3626497Sache * See pthread_* 3726497Sache */ 38136644Sache 39136644Sache#define UMTX_UNOWNED 0x0 40136644Sache#define UMTX_CONTESTED LONG_MIN 41136644Sache 42136644Sachestruct umtx { 43136644Sache void *u_owner; /* Owner of the mutex. */ 44119610Sache}; 45119610Sache 46119610Sache/* op code for _umtx_op */ 4758310Sache#define UMTX_OP_LOCK 0 4858310Sache#define UMTX_OP_UNLOCK 1 4958310Sache#define UMTX_OP_WAIT 2 5026497Sache#define UMTX_OP_WAKE 3 5126497Sache 5226497Sache#ifndef _KERNEL 5326497Sache 5426497Sache/* 5526497Sache * System calls for acquiring and releasing contested mutexes. 5626497Sache */ 5726497Sache/* deprecated becaues it can only use thread id */ 5826497Sacheint _umtx_lock(struct umtx *mtx); 5926497Sache/* deprecated becaues it can only use thread id */ 6026497Sacheint _umtx_unlock(struct umtx *mtx); 6126497Sacheint _umtx_op(struct umtx *umtx, int op, long id, void *uaddr, void *uaddr2); 62119610Sache 63119610Sache/* 6426497Sache * Standard api. Try uncontested acquire/release and asks the 6526497Sache * kernel to resolve failures. 6626497Sache */ 6726497Sachestatic __inline void 6826497Sacheumtx_init(struct umtx *umtx) 6926497Sache{ 70119610Sache umtx->u_owner = UMTX_UNOWNED; 71119610Sache} 72119610Sache 73119610Sachestatic __inline long 74119610Sacheumtx_owner(struct umtx *umtx) 75119610Sache{ 76119610Sache return ((long)umtx->u_owner & ~LONG_MIN); 77119610Sache} 78119610Sache 79136644Sachestatic __inline int 80136644Sacheumtx_lock(struct umtx *umtx, long id) 81136644Sache{ 82119610Sache if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED, 83119610Sache (void *)id) == 0) 84119610Sache if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0, 0) == -1) 85136644Sache return (errno); 86136644Sache return (0); 8726497Sache} 8826497Sache 8926497Sachestatic __inline int 90119610Sacheumtx_trylock(struct umtx *umtx, long id) 91119610Sache{ 92119610Sache if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED, 93119610Sache (void *)id) == 0) 94119610Sache return (EBUSY); 95119610Sache return (0); 96119610Sache} 97119610Sache 98119610Sachestatic __inline int 99119610Sacheumtx_timedlock(struct umtx *umtx, long id, const struct timespec *abstime) 100119610Sache{ 101119610Sache if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED, 10226497Sache (void *)id) == 0) 10326497Sache if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0, (void *)abstime) == -1) 10426497Sache return (errno); 105119610Sache return (0); 106119610Sache} 107119610Sache 10826497Sachestatic __inline int 10926497Sacheumtx_unlock(struct umtx *umtx, long id) 11026497Sache{ 11126497Sache if (atomic_cmpset_rel_ptr(&umtx->u_owner, (void *)id, 11226497Sache (void *)UMTX_UNOWNED) == 0) 11326497Sache if (_umtx_op(umtx, UMTX_OP_UNLOCK, id, 0, 0) == -1) 114119610Sache return (errno); 115119610Sache return (0); 116119610Sache} 11726497Sache 11826497Sache/* Unlock umtx and wait on a user address. */ 11926497Sache 12026497Sachestatic __inline int 12126497Sacheumtx_wait(struct umtx *umtx, long id) 12226497Sache{ 12326497Sache if (_umtx_op(umtx, UMTX_OP_WAIT, id, 0, 0) == -1) 12426497Sache return (errno); 12526497Sache return (0); 12626497Sache} 12726497Sache 12826497Sachestatic __inline int 12926497Sacheumtx_timedwait(struct umtx *umtx, long id, const struct timespec *abstime) 13026497Sache{ 13126497Sache if (_umtx_op(umtx, UMTX_OP_WAIT, id, 0, (void *)abstime) == -1) 13226497Sache return (errno); 13326497Sache return (0); 13426497Sache} 13526497Sache 13626497Sache/* Wake threads waiting on a user address. */ 13726497Sachestatic __inline int 13826497Sacheumtx_wake(struct umtx *umtx, int nr_wakeup) 13926497Sache{ 14026497Sache /* return how many threads were woke up, -1 if error */ 14126497Sache return _umtx_op(umtx, UMTX_OP_WAKE, nr_wakeup, 0, 0); 14226497Sache} 14326497Sache 14426497Sache#endif /* !_KERNEL */ 14526497Sache#endif /* !_SYS_UMTX_H_ */ 14626497Sache