/*  DO NOT EDIT THIS FILE.

    It has been auto-edited by fixincludes from:

	"/usr/include/sys/spinlock.h"

    This had to be done to correct non-standard usages in the
    original, manufacturer supplied header file.  */

/*
 * @(#) spinlock.h $Date: 1998/12/15 09:18:22 $Revision: r11ros/cup_ros_ep1_pb/2 PATCH_11.00 (PHKL_17205)
 * $Locker:  $
 */

#ifndef	_SPINLOCK_INCLUDED
#define	_SPINLOCK_INCLUDED

#ifdef	SEMAPHORE_DEBUG
#define	SPINLOCK_DEBUG
#endif	/* SEMAPHORE_DEBUG */


#ifdef _KERNEL_BUILD
#include "../h/types.h"
#include "../h/kern_svcs.h"
#else  /* ! _KERNEL_BUILD */
#include <sys/types.h>
#include <sys/kern_svcs.h>
#endif /* _KERNEL_BUILD */

/*
 * minimum and maximum for pools of hashed spinlocks,
 * see init_hashed_spinlocks in spinlock.c
 * These must be a power of two for the hashing
 * to work correctly.
 */

#define MINIMUM_HASH_POOL_LOCKS		64
#define MAXIMUM_HASH_POOL_LOCKS		4096
#define IS_POWER_OF_TWO(x)		(!((x - 1) & x))

#ifndef	LOCORE

/*
 *  Lock.  Simple protection mechanism for protecting critical sections.  
 *  Building block for semaphores.
 *
 *  If either of these macros (LOCK_FIELDS or DEBUG_FIELDS) changes be
 *  sure to change the padding (sl_spares[]) in the struct lock if
 *  necessary to maintain cache line size.
 */

	/* 
	 * sl_indirect  0 = sl_name_ptr is a ptr to name
	 *		1 = sl_name_ptr is a ptr to auxillary
	 *		    data structure
	 * sl_name_ptr	((ptr to name)>>2)
	 *	or	((ptr to aux data_structure)>>2)
	 *		NOTE; if the ptr won't fit in the 23 bits,
	 *		then zero is placed in sl_name_ptr.
	 */
#define LOCK_FIELDS /* 8 words */					\
	volatile u_int   sl_lock;					\
 	volatile u_int	sl_owner;	/* MP id of owning processor	*/\
	volatile u_int   sl_flag;	/* arbitration */		\
	volatile u_int   sl_next_cpu;	/* arbitration */		\
	volatile u_int	sl_indirect:1;	/* what does sl_name_ptr mean? */\
	volatile u_int	sl_name_ptr:23; /* 23 bit pointer */		\
	u_int	sl_pad[3];	/* padding to 32 bytes */		\

#define DEBUG_FIELDS /* 8 words */					      \
	struct	{							      \
		unsigned short maj;					      \
		unsigned short min;					      \
	} sl_order;	        	/* (DEBUG) lock order		*/    \
	char *	sl_name;		/* (DEBUG) lock name            */    \
	struct lock	*sl_g_link;	/* (DEBUG) list of all locks	*/    \
	struct lock	*sl_link;	/* (DEBUG) link of owned locks	*/    \
	u_int	sl_lock_caller;	 	/* (DEBUG) last locker's rp 	*/    \
	u_int	sl_unlock_caller;	/* (DEBUG) last unlocker's rp	*/    \
	u_int	sl_start_lock;		/* (DEBUG) cr16 when lock taken */    \
	u_int	sl_start_stu;		/* (DEBUG) mpinfo->spintime_stu */

#ifndef _LOCK_T
#define _LOCK_T
typedef struct lock lock_t;
#endif /* _LOCK_T */

struct lock
{
	LOCK_FIELDS
#ifdef SEMAPHORE_DEBUG
	DEBUG_FIELDS
#endif /* SEMAPHORE_DEBUG */
};

#ifdef _KERNEL
typedef struct lock_nopad
{
	LOCK_FIELDS
#ifdef SEMAPHORE_DEBUG
	DEBUG_FIELDS
#endif /* SEMAPHORE_DEBUG */
} lock_nopad_t;
#endif /*_KERNEL */


#undef LOCK_FIELDS
#undef DEBUG_FIELDS

typedef	lock_t		*vm_lock_t;

#ifdef _KERNEL
typedef	struct sv_lock {
	lock_t *saved;
} sv_lock_t;

extern u_int	vnode_hash_locks;
extern u_int	vnode_cd_hash_locks;
extern u_int	bufcache_hash_locks;
extern u_int	sysv_hash_locks;
extern u_int	region_hash_locks;
extern u_int	io_ports_hash_locks;
extern u_int	ftable_hash_locks;
extern u_int	chanq_hash_locks;
extern u_int	pfdat_hash_locks;
extern u_int	dnlc_hash_locks;
extern	lock_t *sched_lock;
extern	lock_t *rpregs_lock;
extern	lock_t *activeproc_lock;
extern  lock_t *activethread_lock;
extern	lock_t	lock_init_lock;
extern	lock_t *semaphore_log_lock;
extern	lock_t *crash_monarch_lock;
extern	lock_t *callout_lock;
extern	lock_t *eraccsr_lock;
extern	lock_t *cred_lock;
extern	lock_t *vmsys_lock;
extern  lock_t *file_table_lock;
extern	lock_t *devvp_lock;
extern	lock_t *biodone_lock;
extern	lock_t *bbusy_lock;
extern	lock_t *ioserv_lock;
extern	lock_t *UP_pseudo_lock;
extern	lock_t *UP_msgq_lock;
extern	lock_t *io_tree_lock;
extern	lock_t *io_alias_lock;
extern	lock_t *dma_lock;
extern	lock_t *v_count_lock;
extern	lock_t *unrm_table_lock;
extern	lock_t *inode_lock;
extern  lock_t *inode_move_lock;
extern  lock_t *rootvfs_lock;
extern	lock_t *lpmc_log_lock;
extern	lock_t *itmr_sync_lock;
extern	lock_t *itmr_state_lock;
extern	lock_t *pdce_proc_lock;
extern	lock_t *pfail_cntr_lock;
extern	lock_t *dnlc_alloc_lock;
extern	lock_t *audit_spinlock;
extern	lock_t *time_lock;
extern	lock_t *space_id_lock;
extern  lock_t *lofs_lo_lock;
extern  lock_t *lofs_lfs_lock;
extern  lock_t *lofs_li_lock;
extern	lock_t *ksi_lock;
extern  lock_t *ll_hash_spinlock;
extern  lock_t *lgpg_io_lock;

/* networking spinlocks */
extern	lock_t *netisr_lock;
extern	lock_t *ntimo_lock;
extern	lock_t *bsdskts_lock;
extern	lock_t *mbuf_lock;
extern	lock_t *nm_lock;

/* NFS spinlocks */
extern	lock_t *nfs_exi_lock;
extern  lock_t *lm_lock_list_lock;

/* Network Trace/Log spinlocks */
extern	lock_t *log_mask_lock;
extern	lock_t *log_que_lock;
extern	lock_t *trace_mask_lock;
extern	lock_t *trace_que_lock;

/* sysV_sem locks */
extern	lock_t *sysVsema_list_lock;
extern	lock_t *sysVsema_undo_lock;
 
/* sysV_msg locks */
extern	lock_t *sysV_msghdr_lock;
extern	lock_t *sysV_msgque_lock;
extern	lock_t *sysV_msgmap_lock;

/* reboot lock */
extern	lock_t *reboot_lock;

/* watchdog alive lock  */
extern lock_t live_proc_lock;

/* kernel malloc lock */
extern lock_t *kmemlock;

/* pfdat locks - pfdat.h */
extern lock_t *pfdat_hash;
extern lock_t *pfdat_lock;

/* resource map lock */
extern lock_t *rmap_lock;

/* swap reserve lock - swap.h */
extern lock_t *rswap_lock;

/* vm textcache lock */
extern lock_t *text_hash;

/* pde freelist lock */
extern lock_t *pd_fl_lock;
extern lock_t *pd_locks_ptr[];

/* pa_cdio mapping lock */
extern lock_t *pa_map_lock;

/* per processor spinlocks for syswait structure */
extern lock_t *iowait_lock[];


/*
 * Locking operations.  
 */
#ifdef _KERNEL_BUILD
#include <machine/inline.h>
#include <machine/psl.h>
#else /* _KERNEL_BUILD */
#include <machine/inline.h>
#include <machine/psl.h>
#endif /* _KERNEL_BUILD */


#ifdef	WEAKLY_ORDERED
	Error:  The implementation of the software mutual exclusion
	algorithms for spinlock primitives depends on strongly ordered
	accesses to the sl_count field in the lock_t structure.
	Appropriate ordering hints need to be added to these algorithms.
#endif	/* WEAKLY_ORDERED */


#define	DISABLE_INT(VAR)	_RSM(PSW_I, VAR)
#define	ENABLE_INT(VAR)		((PSW_I & VAR) ? (_SSM(PSW_I, 0),0) : 0 )
#define	INTS_ENABLED(VAR)	(_RSM(0L, VAR), (VAR & PSW_I))
#define	INTS_DISABLED(VAR)	(_RSM(0L, VAR), !(VAR & PSW_I))

#define spinlocks_held()	(getproc_info()->spinlock_depth)

#ifdef SEMAPHORE_DEBUG
#define TERMLOCK(x)     	termlock(x)
#else
#define TERMLOCK(x)
#endif /* SEMAPHORE_DEBUG */

/* Sizes of prototypes for inline spinlocks */
extern u_int mp_proto_sl_size;
extern u_int mp_proto_su_size;
extern u_int mp_proto_sl_usav_size;
extern u_int mp_proto_su_usav_size;

#ifdef __LP64__

#define I_SPINLOCK_SIZE 16
#define I_SPINLOCK_PLACEHOLDERS \
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0);
#define I_SPINUNLOCK_SIZE 13
#define I_SPINUNLOCK_PLACEHOLDERS \
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);
#define I_SPINLOCK_USAV_SIZE 10
#define I_SPINLOCK_USAV_PLACEHOLDERS \
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);
#define I_SPINUNLOCK_USAV_SIZE 8
#define I_SPINUNLOCK_USAV_PLACEHOLDERS \
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0);

#else

#define I_SPINLOCK_SIZE 16
#define I_SPINLOCK_PLACEHOLDERS \
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);     \
	_RSM(0, 0);
#define I_SPINUNLOCK_SIZE 13
#define I_SPINUNLOCK_PLACEHOLDERS \
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);
#define I_SPINLOCK_USAV_SIZE 10
#define I_SPINLOCK_USAV_PLACEHOLDERS \
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);
#define I_SPINUNLOCK_USAV_SIZE 8
#define I_SPINUNLOCK_USAV_PLACEHOLDERS \
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0); _RSM(0, 0);	_RSM(0, 0);	\
	_RSM(0, 0); _RSM(0, 0); _RSM(0, 0);

#endif

/*
      Lower overhead spinlocks.
*/
#ifndef SEMAPHORE_DEBUG

#define SPINLOCK_USAV(lock, context)	context = spinlock_usav(lock)
#define SPINUNLOCK_USAV(lock, context)	spinunlock_usav(lock, context)
#define CONVERT_USAV(context)  ((void)convert_usav(context))

#ifdef GPROF
#define I_SPINLOCK(lock)	spinlock(lock)
#define I_SPINUNLOCK(lock)	spinunlock(lock)
#define I_SPINLOCK_USAV(lock, context) context = spinlock_usav(lock)
#define I_SPINUNLOCK_USAV(lock, context) spinunlock_usav(lock, context)
#else /* GPROF */

#define  I_SPINLOCK(lock)  					\
{								\
	di_spinlock(lock);					\
	I_SPINLOCK_PLACEHOLDERS                                 \
}

#define  I_SPINUNLOCK(lock)  					\
{								\
	di_spinunlock(lock);					\
	I_SPINUNLOCK_PLACEHOLDERS                               \
} 

#define I_SPINLOCK_USAV(lock, context)				\
{								\
        register u_long  temp;					\
        _MFCTL(CR_EIEM, temp);					\
        (context) = temp;					\
	di_spinlock_usav(lock);					\
	I_SPINLOCK_USAV_PLACEHOLDERS                            \
}
	
#define I_SPINUNLOCK_USAV(lock, context)			\
{								\
	di_spinunlock_usav(lock, context);			\
	I_SPINUNLOCK_USAV_PLACEHOLDERS                          \
} 

#endif /* GPROF */

#else /* ! SEMAPHORE_DEBUG */

#define  I_SPINLOCK(lock)  					\
{								\
        u_int start_stu, prev_pc = -1;				\
        sl_pre_check(lock, &start_stu);				\
	di_spinlock(lock);					\
	I_SPINLOCK_PLACEHOLDERS                                 \
        sl_post_check(lock, start_stu, prev_pc);		\
} 

#define  I_SPINUNLOCK(lock)  					\
{								\
	u_int	prev_pc = -1;					\
	su_pre_check(lock, prev_pc);				\
	di_spinunlock(lock);					\
	I_SPINUNLOCK_PLACEHOLDERS                               \
} 

#define I_SPINLOCK_USAV(lock, context) I_SPINLOCK(lock)
#define I_SPINUNLOCK_USAV(lock, context) I_SPINUNLOCK(lock)
#define SPINLOCK_USAV(lock, context)	spinlock(lock)
#define SPINUNLOCK_USAV(lock, context)	spinunlock(lock)
#define CONVERT_USAV(context)

#endif /* ! SEMAPHORE_DEBUG */

extern int uniprocessor;

#define MP_SPINLOCK_USAV(lock, context)		\
		if (!uniprocessor) SPINLOCK_USAV(lock,context)
#define MP_SPINUNLOCK_USAV(lock, context)	\
		if (!uniprocessor) SPINUNLOCK_USAV(lock, context)



/*
 *  The sleep/wakeup race is protected with spinlocks.
 *
 *  get_sleep_lock()/MP_GET_SLEEP_LOCK() will acquire the appropriate sleep lock
 *  for going to sleep in one indivisible step, without a "lost wakeup"
 *  occuring in between. They return the spinlock acquired. The caller
 *  can then release the spinlock, if desired, through a call to 
 *  MP_SPINUNLOCK()/spinunlock().
 *
 *  sleep_spinunlock()/MP_SLEEP_SPINUNLOCK() will release a specified spinlock
 *  after acquiring the sleep lock and before going to sleep.
 *  
 */
/*
 * MP_GET_SLEEP_LOCK() returns the lock address which may then be unlocked
 * using MP_SPINLOCK().
 */
#define MP_GET_SLEEP_LOCK(WCHAN)	(uniprocessor ?0:get_sleep_lock(WCHAN))


#define MP_SPINLOCK(lock)	if(!uniprocessor) {spinlock(lock);}
#define MP_SPINUNLOCK(lock)	if(!uniprocessor) {spinunlock(lock);}
#define I_MP_SPINLOCK(lock)     if(!uniprocessor) I_SPINLOCK(lock)
#define I_MP_SPINUNLOCK(lock)   if(!uniprocessor) I_SPINUNLOCK(lock)

#define MP_SLEEP_SPINUNLOCK(wchan,disp,lock) \
		sleep_spinunlock(wchan,disp,((uniprocessor)?(lock_t *)-1:lock))


#define	MP_SPINLOCKX(lock,ss)	if(!uniprocessor) {spinlockx(lock,ss);}
#define	MP_SPINUNLOCKX(lock,ss)	if(!uniprocessor) {spinunlockx(lock,ss);}

/* hashed spinlocks */
/*
 * Description:
 *
 * Hashed spinlocks are used typically when each instance of a 
 * particular data structure is to be protected by a spinlock and there
 * are several such instances. 
 * 
 * For eg: The vnode data structure. There are several instances of this 
 * in the system. The manipulation of the count field of any instance is 
 * to be protected by a spinlock. Using a single spinlock leads to a lot of 
 * contention. Using one spinlock per vnode is an overkill. A pool of hashed 
 * spinlocks can be used. 
 * 
 * The spinlock corresponding to an instance would then be chosen by hashing
 * on the address or some unique attribute of the instance.
 *
 * A pool of hashed spinlocks must be allocated using alloc_h_spinlock_pool()
 * with the appropriate spinlock order. Typically, this is done in the 
 * routine init_hashed_spinlocks(), called during system boot.
 * The pool id returned is one of the
 * parameters to be used for all the locking primitives. The locking 
 * primitives come in two flavors: the short version and the long version
 * (ends in _L). The long version gives the user some flexibility to 
 * choose his/her own hash macro. The short version uses the default hash
 * macro defined below. 
 *
 * All the locking primitives return a pointer to the hash lock acquired.
 * This is to be used as the parameter to MP_SPINUNLOCK in order to unlock 
 * the hash lock.
 */

typedef struct hash_sl_pool {
		unsigned int hash_sl_mask;
		int 	n_hash_spinlocks;
		int     padding[5];
		lock_t  **hash_sl_table;
	} pool_id_t;

/* declarations for pools currently in use */
extern pool_id_t *vn_h_sl_pool;
extern pool_id_t *sysv_h_sl_pool;
extern pool_id_t *reg_h_sl_pool;
extern pool_id_t *ft_h_sl_pool;
extern pool_id_t *chanq_h_sl_pool;
extern pool_id_t *pfd_h_sl_pool;
extern pool_id_t *dnlc_h_sl_pool;
  /* note: the dnlc pool cannot be accessed with the standard macros
   * because of the special nature of the hash function used.
   */

/* hash macro definitions. Add as necessary. */
#define DEFAULT_HASH_TYPE 	0
#define SINGLE_L_HASH_TYPE 	1
#define IO_HASH_TYPE  		2
#define SYSV_SEM_HASH_TYPE  	3
#define CHANQ_USER_HASH_TYPE  	4
#define CHANQ_KERNEL_HASH_TYPE  5

/* hash macros */
#define DEFAULT_HASH_MACRO(pool_id,addr) \
	((((uintptr_t)addr>>15) ^ ((uintptr_t)addr>>5) ) & \
		pool_id->hash_sl_mask)
#define SINGLE_L_HASH_MACRO(pool_id,addr) 0
#define IO_HASH_MACRO(pool_id,addr)     \
	(((uintptr_t)addr) & pool_id->hash_sl_mask)
#define SYSV_SEM_HASH_MACRO(pool_id,addr) \
	(((uintptr_t)addr) & pool_id->hash_sl_mask)
#define CHANQ_KERNEL_HASH_MACRO(pool_id,addr) \
	(((((uintptr_t)addr >> 15) ^ ((uintptr_t)addr>>5)) & \
		pool_id->hash_sl_mask))
#define CHANQ_USER_HASH_MACRO(pool_id,addr) \
	((((uintptr_t)addr) ^ ((uintptr_t)addr>>12)) & \
		pool_id->hash_sl_mask)

/* extend this as necessary. NB: This expression is expanded at compile time */
#define MY_HASH_M(pool_id,addr,type) 			\
	((type == DEFAULT_HASH_TYPE) 			\
		? (DEFAULT_HASH_MACRO(pool_id,addr)) 	\
	: (type == SINGLE_L_HASH_TYPE)			\
		? (SINGLE_L_HASH_MACRO(pool_id,addr))	\
	: (type == IO_HASH_TYPE)                        \
		? (IO_HASH_MACRO(pool_id,addr))         \
	: (type == SYSV_SEM_HASH_TYPE)                  \
		? (SYSV_SEM_HASH_MACRO(pool_id,addr))   \
	: (type == CHANQ_USER_HASH_TYPE)		\
		? (CHANQ_USER_HASH_MACRO(pool_id,addr)) \
	: (type == CHANQ_KERNEL_HASH_TYPE)		\
		? (CHANQ_KERNEL_HASH_MACRO(pool_id,addr)) \
	: (panic("Invalid hash type"), 1))

/* hashlock primitives: short version */
#define MP_H_SPINLOCK(pool_id,addr,lockpp) \
		MP_H_SPINLOCK_L(pool_id,addr,lockpp,DEFAULT_HASH_TYPE)
#define MP_H_SPINLOCKX(pool_id,addr,lockpp,ssp) \
		MP_H_SPINLOCKX_L(pool_id,addr,lockpp,ssp,DEFAULT_HASH_TYPE)
#define MP_H_SPINLOCK_USAV(pool_id,addr,lockpp,contextp) \
	MP_H_SPINLOCK_USAV_L(pool_id,addr,lockpp,contextp,DEFAULT_HASH_TYPE)

#define h_spinlock(pool_id,addr,lockpp)	\
		h_spinlock_l(pool_id,addr,lockpp,DEFAULT_HASH_TYPE)
#define i_h_spinlock(pool_id,addr,lockpp)	\
		i_h_spinlock_l(pool_id,addr,lockpp,DEFAULT_HASH_TYPE)
#define h_spinlockx(pool_id,addr,lockpp,ssp) \
		h_spinlockx_l(pool_id,addr,lockpp,ssp,DEFAULT_HASH_TYPE)
#define h_spinlock_usav(pool_id,addr,lockpp,contextp) \
		h_spinlock_usav_l(pool_id,addr,lockpp,contextp,DEFAULT_HASH_TYPE)	

/* NB: H_OWNS_SPINLOCK() and H_CSPINLOCK() "return" a value */
#define H_OWNS_SPINLOCK(pool_id,addr) \
		H_OWNS_SPINLOCK_L(pool_id,addr,DEFAULT_HASH_TYPE)
#define H_CSPINLOCK(pool_id,addr,lockpp) \
		H_CSPINLOCK_L(pool_id,addr,lockpp,DEFAULT_HASH_TYPE)
		

/* hashlock primitives: long version */
#define MP_H_SPINLOCK_L(pool_id,addr,lockpp,type) { 	\
		if (!uniprocessor) {			\
			*(lockpp) = 			\
				pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))];\
			spinlock(*(lockpp));		\
		}					\
	}

#define MP_H_SPINLOCKX_L(pool_id,addr,lockpp,ssp,type) {\
		if (!uniprocessor) {			\
			*(lockpp) =			\
				pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))];\
			spinlockx(*(lockpp),ssp);	\
		}					\
	}
#define h_spinlock_l(pool_id,addr,lockpp,type) { 	\
		*(lockpp) = 			     	\
			pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))];\
		spinlock(*(lockpp));		     	\
	}
#define i_h_spinlock_l(pool_id,addr,lockpp,type) { 	\
		*(lockpp) = 			     	\
			pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))];\
		I_SPINLOCK(*(lockpp));		     	\
	}
#define h_spinlockx_l(pool_id,addr,lockpp,ssp,type)	{\
		*(lockpp) =				\
			pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))];\
		spinlockx(*(lockpp),ssp);		\
	}

#if !defined(SEMAPHORE_DEBUG)
#define MP_H_SPINLOCK_USAV_L(pool_id,addr,lockpp,contextp,type) { \
		if (!uniprocessor) {				\
			*(lockpp) = 				\
				pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))];\
			*(contextp)=spinlock_usav(*(lockpp));	\
		}						\
	}
#define	h_spinlock_usav_l(pool_id,addr,lockpp,contextp,type)	{\
		*(lockpp) = 					\
			pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))];\
		*(contextp)=spinlock_usav(*(lockpp));		\
	}
#else /* !SEMAPHORE_DEBUG */
#define MP_H_SPINLOCK_USAV_L(pool_id,addr,lockpp,contextp,type) { \
		if (!uniprocessor) {				\
			*(lockpp) = 				\
				pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))];\
			spinlock(*(lockpp));			\
		}						\
	}
#define h_spinlock_usav_l(pool_id,addr,lockpp,contextp,type) 	{\
		*(lockpp) = 					\
			pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))];\
		spinlock(*(lockpp));				\
	}
#endif  /* !SEMAPHORE_DEBUG */

#define H_OWNS_SPINLOCK_L(pool_id,addr,type) 		\
    owns_spinlock(pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))])
#define H_CSPINLOCK_L(pool_id,addr,lockpp,type) 		\
    cspinlock((*(lockpp)=pool_id->hash_sl_table[(MY_HASH_M(pool_id,addr,type))]))



/* 
 * These are obsolete, all instances should be MP_<name> 
 * We should go through the code and remove these, but no time now.
 */

/* BEGIN OBSOLETE */

#define SPINLOCK(lock)		MP_SPINLOCK(lock)	/* OBSOLETE */
#define SPINUNLOCK(lock)	MP_SPINUNLOCK(lock)	/* OBSOLETE */

#define	SPINLOCKX(lock,ss)	MP_SPINLOCKX(lock,ss)	/* OBSOLETE */
#define	SPINUNLOCKX(lock,ss)	MP_SPINUNLOCKX(lock,ss)	/* OBSOLETE */
/* END OBSOLETE */


#define SPL_REPLACEMENT(lock,func,var)	if (uniprocessor) var=func(); \
					else spinlock(lock)
#define SPLX_REPLACEMENT(lock,var)	if (uniprocessor) splx(var); \
					else spinunlock(lock)
#define	UP_SPL7()		(uniprocessor ? spl7() : 0)
#define	UP_SPL6()		(uniprocessor ? spl6() : 0)
#define	UP_SPL5()		(uniprocessor ? spl5() : 0)
#define	UP_SPL2()		(uniprocessor ? spl2() : 0)
#define	UP_SPLX(var)		(uniprocessor ? splx(var) : 0)

#ifdef  SPINLOCK_DEBUG
#define PFAIL_DISABLE(X)        (X = pfail_disable())
#define PFAIL_ENABLE(X)         pfail_enable(X)
#else   /* ! SPINLOCK_DEBUG */
#define PFAIL_DISABLE(X)        (DISABLE_INT(X), X)
#define PFAIL_ENABLE(X)         ENABLE_INT(X)
#endif  /* ! SPINLOCK_DEBUG */

#define T_SPINLOCK(lock)	MP_ASSERT(owns_spinlock(lock),	\
	"Should own spinlock!")
#define TBAR_SPINLOCK(lock)	MP_ASSERT(!owns_spinlock(lock),	\
	"Can't own spinlock!")
#define DOT_SPINLOCK(lock)	DO_ASSERT(owns_spinlock(lock),	\
	"Should own spinlock!")
#define DOTBAR_SPINLOCK(lock)	DO_ASSERT(!owns_spinlock(lock),	\
	"Can't own spinlock!")

#define	T_SPL(SPL_LVL)						\
	DO_ASSERT(spl_bitcheck(SPL_LVL), "Spl not high enough")
#define	T_UPSPL(SPL_LVL)					\
	UP_ASSERT(spl_bitcheck(SPL_LVL), "Spl not high enough")

/*
 *  These spinlocks are only meaningful on an MP system
 */
#define vmemp_slock()		MP_SPINLOCK(vmsys_lock)
#define vmemp_sunlock()		MP_SPINUNLOCK(vmsys_lock)
#define vmemp_slockx()		MP_SPINLOCKX(vmsys_lock, &sema_state.lock)
#define vmemp_sunlockx()	MP_SPINUNLOCKX(vmsys_lock, &sema_state.lock)

/*
 *  These are the macro names used in the VM system
 *  Some day we can just rename everything to be clean.  For now...
 */
#define	vm_spinlock(SMP)	spinlock(SMP)
#define	vm_spinunlock(SMP)	spinunlock(SMP)
#define	I_VM_SPINLOCK(SMP)	I_SPINLOCK(SMP)
#define	I_VM_SPINUNLOCK(SMP)	I_SPINUNLOCK(SMP)
#define	vm_valulock(LOCK)		( owns_spinlock(LOCK) ? 0 : 1 )
#define vm_initlock(LOCK, ORDER, NAME)	{ LOCK = alloc_spinlock(ORDER, NAME); }

extern void initlock __((lock_t *lock, unsigned int major_order, 
                         unsigned int minor_order, char *name));

extern lock_t *alloc_spinlock __((unsigned int, char *));
extern lock_t *get_sleep_lock __((caddr_t));
extern pool_id_t *alloc_h_spinlock_pool __((int, int));
extern void convert_usav __((ulong_t));
extern int sleep_spinunlock __((caddr_t, int, lock_t *));
extern int owns_spinlock __((lock_t *));
extern ulong_t spinlock_usav __((lock_t *));
extern void spinunlock_usav __((lock_t *, ulong_t));
extern void spinlock __((lock_t *));
extern void spinunlock __((lock_t *));
extern void spinlockx __((lock_t *, sv_lock_t *));
extern void spinunlockx __((lock_t *, sv_lock_t *));
extern int spl_bitcheck __((ulong_t));
extern void pfail_enable __((u_int));
extern u_int pfail_disable __((void));

extern void su_pre_check __((lock_t *, u_int));
extern void sl_post_check __((lock_t *, u_int, u_int));
extern void sl_pre_check __((lock_t *, u_int *));

extern void di_spinlock __((lock_t *));
extern void di_spinunlock __((lock_t *));
extern void di_spinlock_usav __((lock_t *));
extern void di_spinunlock_usav __((lock_t *, ulong_t));

extern ubit8 lock_and_lor_ubit8 __((lock_t *, ubit8 *, ubit8));
extern ubit16 lock_and_lor_ubit16 __((lock_t *, ubit16 *, ubit16));
extern ubit32 lock_and_lor_ubit32 __((lock_t *, ubit32 *, ubit32));
#ifdef __LP64__
extern ulong_t lock_and_lor_ubit64 __((lock_t *, ulong_t *, ulong_t));
#else
extern unsigned long long lock_and_lor_ubit64 __((lock_t *, 
    unsigned long long *, unsigned long long));
#endif /* __LP64__ */
extern ubit8 lock_and_land_ubit8 __((lock_t *, ubit8 *, ubit8));
extern ubit16 lock_and_land_ubit16 __((lock_t *, ubit16 *, ubit16));
extern ubit32 lock_and_land_ubit32 __((lock_t *, ubit32 *, ubit32));
#ifdef __LP64__
extern ulong_t lock_and_land_ubit64 __((lock_t *, ulong_t *, ulong_t));
#else
extern unsigned long long lock_and_land_ubit64 __((lock_t *, 
    unsigned long long *, unsigned long long));
#endif /* __LP64__ */
extern int8_t lock_and_incr_int8 __((lock_t *, int8_t *, int8_t));
extern int16_t lock_and_incr_int16 __((lock_t *, int16_t *, int16_t));
extern int32_t lock_and_incr_int32 __((lock_t *, int32_t *, int32_t));
#ifdef __LP64__
extern long lock_and_incr_int64 __((lock_t *, long *, long));
#else
extern long long lock_and_incr_int64 __((lock_t *, long long *, long long));
#endif /* __LP64__ */

#endif	/* _KERNEL */
#endif	/* ! LOCORE */
#endif	/* ! _SPINLOCK_INCLUDED */
