mutex.h revision 331756
1167465Smp/*-
259243Sobrien * Copyright (c) 2010 Isilon Systems, Inc.
359243Sobrien * Copyright (c) 2010 iX Systems, Inc.
459243Sobrien * Copyright (c) 2010 Panasas, Inc.
559243Sobrien * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
659243Sobrien * All rights reserved.
759243Sobrien *
859243Sobrien * Redistribution and use in source and binary forms, with or without
959243Sobrien * modification, are permitted provided that the following conditions
1059243Sobrien * are met:
1159243Sobrien * 1. Redistributions of source code must retain the above copyright
1259243Sobrien *    notice unmodified, this list of conditions, and the following
1359243Sobrien *    disclaimer.
1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1559243Sobrien *    notice, this list of conditions and the following disclaimer in the
1659243Sobrien *    documentation and/or other materials provided with the distribution.
17100616Smp *
1859243Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1959243Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2059243Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2159243Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2259243Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2359243Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2459243Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2559243Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2659243Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2759243Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2859243Sobrien *
2959243Sobrien * $FreeBSD: stable/11/sys/compat/linuxkpi/common/include/linux/mutex.h 331756 2018-03-30 02:04:46Z emaste $
3059243Sobrien */
3159243Sobrien#ifndef	_LINUX_MUTEX_H_
3259243Sobrien#define	_LINUX_MUTEX_H_
3359243Sobrien
3459243Sobrien#include <sys/param.h>
35167465Smp#include <sys/proc.h>
3659243Sobrien#include <sys/lock.h>
3759243Sobrien#include <sys/sx.h>
3859243Sobrien
3959243Sobrien#include <linux/spinlock.h>
4059243Sobrien
4159243Sobrientypedef struct mutex {
4259243Sobrien	struct sx sx;
4359243Sobrien} mutex_t;
4459243Sobrien
4559243Sobrien/*
4659243Sobrien * By defining CONFIG_NO_MUTEX_SKIP LinuxKPI mutexes and asserts will
4759243Sobrien * not be skipped during panic().
4859243Sobrien */
49184072Sru#ifdef CONFIG_NO_MUTEX_SKIP
5059243Sobrien#define	MUTEX_SKIP(void) 0
5159243Sobrien#else
5259243Sobrien#define	MUTEX_SKIP(void) unlikely(SCHEDULER_STOPPED() || kdb_active)
5359243Sobrien#endif
5459243Sobrien
5559243Sobrien#define	mutex_lock(_m) do {			\
5659243Sobrien	if (MUTEX_SKIP())			\
5759243Sobrien		break;				\
5859243Sobrien	sx_xlock(&(_m)->sx);			\
5959243Sobrien} while (0)
6059243Sobrien
6159243Sobrien#define	mutex_lock_nested(_m, _s)	mutex_lock(_m)
6259243Sobrien#define	mutex_lock_nest_lock(_m, _s)	mutex_lock(_m)
6359243Sobrien
6459243Sobrien#define	mutex_lock_interruptible(_m) ({		\
6559243Sobrien	MUTEX_SKIP() ? 0 :			\
6659243Sobrien	linux_mutex_lock_interruptible(_m);	\
6759243Sobrien})
6859243Sobrien
6959243Sobrien#define	mutex_unlock(_m) do {			\
7059243Sobrien	if (MUTEX_SKIP())			\
7159243Sobrien		break;				\
7259243Sobrien	sx_xunlock(&(_m)->sx);			\
7359243Sobrien} while (0)
7459243Sobrien
7559243Sobrien#define	mutex_trylock(_m) ({			\
7659243Sobrien	MUTEX_SKIP() ? 1 :			\
7759243Sobrien	!!sx_try_xlock(&(_m)->sx);		\
7859243Sobrien})
7959243Sobrien
8059243Sobrienenum mutex_trylock_recursive_enum {
8159243Sobrien	MUTEX_TRYLOCK_FAILED = 0,
8259243Sobrien	MUTEX_TRYLOCK_SUCCESS = 1,
8359243Sobrien	MUTEX_TRYLOCK_RECURSIVE = 2,
8459243Sobrien};
8559243Sobrien
8659243Sobrienstatic inline __must_check enum mutex_trylock_recursive_enum
87145479Smpmutex_trylock_recursive(struct mutex *lock)
88145479Smp{
8959243Sobrien	if (unlikely(sx_xholder(&lock->sx) == curthread))
9059243Sobrien		return (MUTEX_TRYLOCK_RECURSIVE);
9159243Sobrien
9259243Sobrien	return (mutex_trylock(lock));
9359243Sobrien}
9459243Sobrien
9559243Sobrien#define	mutex_init(_m) \
9659243Sobrien	linux_mutex_init(_m, mutex_name(#_m), SX_NOWITNESS)
9759243Sobrien
9859243Sobrien#define	mutex_init_witness(_m) \
9959243Sobrien	linux_mutex_init(_m, mutex_name(#_m), SX_DUPOK)
10059243Sobrien
10159243Sobrien#define	mutex_destroy(_m) \
10259243Sobrien	linux_mutex_destroy(_m)
10359243Sobrien
10459243Sobrienstatic inline bool
10559243Sobrienmutex_is_locked(mutex_t *m)
10659243Sobrien{
10759243Sobrien	return ((struct thread *)SX_OWNER(m->sx.sx_lock) != NULL);
10859243Sobrien}
10959243Sobrien
11059243Sobrienstatic inline bool
11159243Sobrienmutex_is_owned(mutex_t *m)
11259243Sobrien{
11359243Sobrien	return (sx_xlocked(&m->sx));
11459243Sobrien}
11559243Sobrien
11669408Sache#ifdef WITNESS_ALL
11769408Sache/* NOTE: the maximum WITNESS name is 64 chars */
118100616Smp#define	__mutex_name(name, file, line)		\
11969408Sache	(((const char *){file ":" #line "-" name}) +	\
12059243Sobrien	(sizeof(file) > 16 ? sizeof(file) - 16 : 0))
12159243Sobrien#else
12259243Sobrien#define	__mutex_name(name, file, line)	name
12359243Sobrien#endif
124131962Smp#define	_mutex_name(...)	__mutex_name(__VA_ARGS__)
125131962Smp#define	mutex_name(name)	_mutex_name(name, __FILE__, __LINE__)
126131962Smp
12759243Sobrien#define	DEFINE_MUTEX(lock)						\
128131962Smp	mutex_t lock;							\
129145479Smp	SX_SYSINIT_FLAGS(lock, &(lock).sx, mutex_name(#lock), SX_DUPOK)
130145479Smp
131145479Smpstatic inline void
132145479Smplinux_mutex_init(mutex_t *m, const char *name, int flags)
133145479Smp{
134145479Smp	memset(m, 0, sizeof(*m));
13559243Sobrien	sx_init_flags(&m->sx, name, flags);
13659243Sobrien}
13759243Sobrien
13859243Sobrienstatic inline void
13959243Sobrienlinux_mutex_destroy(mutex_t *m)
140131962Smp{
14159415Sobrien	if (mutex_is_owned(m))
14290446Smp		mutex_unlock(m);
14359243Sobrien	sx_destroy(&m->sx);
144131962Smp}
14559415Sobrien
14659415Sobrienextern int linux_mutex_lock_interruptible(mutex_t *m);
14759243Sobrien
14859415Sobrien#endif					/* _LINUX_MUTEX_H_ */
14959415Sobrien