/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos72V src/bos/kernel/sys/lock_def.h 1.5.6.12                          */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 1993,2020              */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/* @(#)94       1.5.6.12  src/bos/kernel/sys/lock_def.h, sysproc, bos72V, v2020_10B7 3/4/20 14:10:17 */
/*
 *   COMPONENT_NAME: SYSPROC
 *
 *   FUNCTIONS: none
 *
 *   ORIGINS: 27, 83
 *
 */

/*
 * LEVEL 1,  5 Years Bull Confidential Information
 */

#ifndef _H_LOCK_DEFINE
#define _H_LOCK_DEFINE

#include <sys/types.h>

#ifdef __cplusplus
extern "C" {
#endif

/* 
 * Simple_lock control structure is:
 *
 *      +---------------------------------------------------------------+
 *      |    krlock bits     | reserved | I W X X S | owner_id          |
 *      +---------------------------------------------------------------+
 *       ^                  ^ ^        ^  ^       ^  ^                 ^ 
 *       0                 23 24      31  32     36  37               63
 *
 * If instrumentation is enabled, the above structure is interpretted as a
 * pointer to a secondary lock structure that is allocated above the 4GB
 * line.  
 *
 *	I		Interlock bit
 *	W		Waiting bit
 *      S               Secondary structure allocated
 *			(DON'T CHANGE THIS BIT POSITION - instrumentation
 *			 address dependent.  Lock tables are at fixed address)
 *	owner_id	owner's thread id
 */
typedef	int32long64_t 	simple_lock_data;

/*
 * Complex_lock control structure is:
 *
 *      +-------------------------------------------------------------------+
 *      |             |  owner_id       |           | recursion |           |
 *      | I W WW RD S |-----------------| flags     |   depth   | reserved  |
 *      |             |  read count     | (16 bits) | (16 bits) | (32 bits) |
 *      +-------------------------------------------------------------------+
 *        ^         ^  ^               ^ ^         ^ ^         ^ ^         ^
 *        0         4  5              63 64       79 80       95 96      127
 *
 *       I               Interlock bit
 *       W               Waiting bit
 *       WW              Want write bit
 *       RD              Read mode bit
 *       S               Secondary structure allocated
 *			(DON'T CHANGE THIS BIT POSITION - instrumentation
 *			 address dependent)
 *       owner_id	 owner's thread id
 *       read count      readers count
 *       flags           hold recursive bit
 *       recursion depth counter of recursive acquisitions
 *
 * Instrumentation is treated in a similar fashion to that for Simple_locks.
 *
 */
typedef int32long64_t  complex_lock_status;

struct complex_lock_data {
                complex_lock_status   status;
                short   	      flags;
                short   	      recursion_depth;
		uint_t 		      reserved;
};

struct drw_lock_data {
		complex_lock_status	status;
};

/* 
 * Type definition for lock secondary structure.  Holds the lock control 
 * structure and the instrumentation fields.  Allocated by lock_alloc and
 * freed by lock_free.
 */
struct lock_data_instrumented {
		union {
			simple_lock_data		s_lock;
			struct complex_lock_data 	c_lock;
			struct drw_lock_data 		drw_lock;
			struct lock_data_instrumented	*lock_next;
		} lock_control_word;

#define SELECTIVE_TRACE 1
#define LOCK_ALLOCATED  2
		unsigned int    li_flags;       /* lock instrumentation flags*/

                int     reserved[1];            
		union	{			/* lock identifier */
			long	name;
			struct  {
				unsigned int _id;
				unsigned int occurrence;
			} _lock_id;
		} _lockname;
#ifdef DEBUG
		int32long64_t	lock_lr;	/* link register of lock */
		int32long64_t	unlock_lr;	/* link register of unlock */
		tid_t 	        lock_caller; 	/* caller of lock */
		tid_t 	        unlock_caller;  /* caller of unlock */
		int 		lock_cpuid;	/* cpu id of lock */
		int		dbg_zero;	/* this word must be zero */
		int 		unlock_cpuid;	/* cpu id of unlock */
		int		dbg_flags;	/* debug flags */
#define LOCK_IS_ALLOCATED 0x80000000    /* this entry is allocated */
#endif /* DEBUG */
	};

/*
*                                       Instrumentation Structure
*
*                                       |                        |
*        LOCK STRUCTURE                 |                        |
*        ---------------------          |------------------------|
*        |                   |--------->| CONTROL STRUCTURE      |
*        ---------------------          |         .              |
*                                       |         .              |
*                                       | Instrumentation word 1 |
*                                       | Instrumentation word n |
*                                       |------------------------|
*                                       |                        |
*                                       |                        |
*
*        LOCK_STRUCTURE 
*        --------------------- 
*        | CONTROL STRUCTURE |
*        --------------------- 
*/

/* type definition for simple_lock */
union _simple_lock{
	simple_lock_data		_slock;
	struct lock_data_instrumented	*_slockp;
};	

/* type definition for complex_lock */
union _complex_lock{
	struct complex_lock_data	_clock;
	struct lock_data_instrumented	*_clockp;
};	

/* type definition for drw_lock (disabled complex lock) */
union _drw_lock{
	complex_lock_status		_drwlock;
	struct lock_data_instrumented	*_drwlockp;
};	


typedef	union _simple_lock	Simple_lock;
typedef union _complex_lock	Complex_lock;
typedef union _drw_lock		DRW_lock;

/* type definition for lock pointers */
typedef  Simple_lock	*simple_lock_t;
typedef  Complex_lock	*complex_lock_t;
typedef  DRW_lock	*drw_lock_t;

typedef struct complex_upgraded_reader_data { 
		complex_lock_status	read_status;
		char			fill[120];
} complex_upgraded_reader_data_t;

#define CL_BUCKETS 4
#define CL_NOTRANSITION 9999

struct complex_upgraded_reader {
	complex_upgraded_reader_data_t  rdata[CL_BUCKETS];
};

typedef struct complex_upgraded_reader Reader_lock;

/* v3 lockl definition */
typedef int32long64_t	lock_t;

/* Initial available definitions */
#define SIMPLE_LOCK_AVAIL		((simple_lock_data)0)
#define COMPLEX_LOCK_AVAIL		SIMPLE_LOCK_AVAIL 
#define LOCK_AVAIL  			((lock_t) -1)    /* lockl locks */

/* This macro is no longer compatible with AIXv3 */
#define LOCKL_OWNER_MASK	0x3fffffff 	
#ifdef _KERNSYS
#define IS_LOCKED(x)    ((tid_t)(*(x) & LOCKL_OWNER_MASK) == curthread->t_tid)
#else
#define IS_LOCKED(x)    \
  ((*(x) != LOCK_AVAIL) && ((tid_t)(*(x) & LOCKL_OWNER_MASK) == thread_self()))
#endif /* _KERNSYS */

/* lockl flags values: */
#define LOCK_SHORT      (0)             /* short wait, inhibit signals */
#define LOCK_NDELAY     (1)             /* do not wait, if unavailable */
#define LOCK_SIGWAKE    (2)             /* wake on signal */
#define LOCK_SIGRET     (4)             /* return on signal */

/* lockl return codes: */
#define LOCK_SUCC       (0)             /* success */
#define LOCK_NEST       (1)             /* already locked by this process */
#define LOCK_FAIL       (-1)            /* lock not available */
#define LOCK_SIG        (-2)            /* process signalled */

#ifdef _NO_PROTO

/* simple lock routines */
void simple_lock();
void simple_lock_hot();
void simple_unlock();
void simple_unlock_hot();
void simple_unlock_mem();
boolean_t simple_lock_try();
boolean_t simple_dlock_timeout();

/* synchronization for interrupt/interrupt and
 * thread/interrupt critical section
 */
int disable_lock();
void unlock_enable();
void unlock_enable_mem();

/* complex lock basic routines */
void lock_init();
void lock_write();
void lock_read();
void lock_done();
void lock_done_mem();

/* complex lock upgrade/downgrade routines */
boolean_t lock_read_to_write();
void lock_write_to_read();

/* complex lock non blocking routines */
boolean_t lock_try_write();
boolean_t lock_try_read();
boolean_t lock_try_read_to_write();

/* complex lock routines for recursion management */
void lock_set_recursive();
void lock_clear_recursive();
int lock_islocked();

/* lockl routines */
/* - lockl_mine is not exported */
int lockl();
void unlockl();                 
boolean_t lockl_mine();	

#else /* _NO_PROTO */

/* simple lock routines */
void simple_lock(simple_lock_t);
void simple_lock_hot(simple_lock_t);
void simple_unlock(simple_lock_t);
void simple_unlock_mem(simple_lock_t);
void simple_unlock_hot(simple_lock_t);
boolean_t simple_lock_try(simple_lock_t);
boolean_t simple_dlock_timeout(simple_lock_t,long);

/* synchronization for interrupt/interrupt and thread/interrupt critical section
 */
int disable_lock(int,simple_lock_t);
void unlock_enable(int,simple_lock_t);
void unlock_enable_mem(int,simple_lock_t);

/* complex lock basic routines */
void lock_init(complex_lock_t , boolean_t);
void lock_write(complex_lock_t);
void lock_read(complex_lock_t);
void lock_done(complex_lock_t);
void lock_done_mem(complex_lock_t);

/* complex lock read to write upgrade/downgrade routines */
boolean_t lock_read_to_write(complex_lock_t);
void lock_write_to_read(complex_lock_t);
boolean_t lock_try_read_to_write(complex_lock_t);

/* complex lock non blocking routines */
boolean_t lock_try_write(complex_lock_t);
boolean_t lock_try_read(complex_lock_t);

/* complex lock routines for recursion management */
void lock_set_recursive(complex_lock_t);
void lock_clear_recursive(complex_lock_t);
int lock_islocked(complex_lock_t);

/* Disabled complex lock routines */
void drw_lock_init(drw_lock_t);
void drw_lock_free(drw_lock_t);
void drw_lock_read(drw_lock_t);
void drw_lock_write(drw_lock_t);
void drw_lock_done(drw_lock_t);
void drw_lock_write_to_read(drw_lock_t);
boolean_t drw_lock_read_to_write(drw_lock_t);
boolean_t drw_lock_try_read_to_write(drw_lock_t);
boolean_t drw_lock_try_write(drw_lock_t);
boolean_t drw_lock_islocked(drw_lock_t);


/* lockl routines */
/* - lockl_mine is not exported */
int lockl(lock_t *,int);
void unlockl(lock_t *);                
boolean_t lockl_mine(lock_t *);	

#endif /* _NO_PROTO */

#if defined(_POWER_MP) || !defined(_KERNSYS)

#ifdef _NO_PROTO
void simple_lock_init();
#else /* _NO_PROTO */
void simple_lock_init(simple_lock_t);
#endif /* _NO_PROTO */
#else /* _POWER_MP || !_KERNSYS */

/* if the function simple_lock_init changes, so must this MACRO */
#define simple_lock_init(l) *((simple_lock_data *)l) = SIMPLE_LOCK_AVAIL

#endif /* _POWER_MP || !_KERNSYS */

/* simple or complex lock owner test */
boolean_t lock_mine(void *);

#ifdef _INSTRUMENTATION
#define	lo_next		lock_control_word.lock_next
#define lockname	_lockname.name
#define lock_id		_lockname._lock_id._id
#define _occurrence	_lockname._lock_id.occurrence
#endif /* _INSTRUMENTATION */

#ifdef _KERNSYS

/* Sub-definitions of complex_lock */
#define	_status			_clock.status
#define _flags			_clock.flags
#define _recursion_depth	_clock.recursion_depth
#define _rdata_addr		_clock.rdata_addr

extern unsigned int maxspin;
#define MAXSPIN_MP			0x4000
#define MAXSPIN_UP			0x1

/* bit field defines */
#define	KRLOCK_IDX_MASK		0xff00000000000000UL	/* Index of krlock. */
#define KRLOCK_IDX_SHIFT	56			/* KRLOCK_IDX_MASK */
							/*  shift count. */
#define KRLOCK_NUM_SPINNERS	0x00fff00000000000UL	/* Number of CPUs */
							/*  spinning on */
							/*  krlock structure */
#define KRLOCK_NUM_SPINNERS_SHIFT  44			/* shift count */
#define KRLOCK_NUM_SPINNERS_INC	0x0000100000000000UL	/* Increment value */
							/*  for # spinners. */
#define OWNER_MASK			0x07ffffffL 	/* mask all status bit*/
#define	UPGRADED		       0x100000000L	/* Upgraded c_lock */
#define	EXPANDED		       0x200000000L	/* Expanded c_lock*/
#define EXPANDABLE		       0x400000000L	/* Expandable lock */
#define	INTERLOCK			0x80000000L	/* INTERLOCK BIT */
#define	WAITING				0x40000000L	/* WAITING BIT */
#define	WANT_WRITE			0x20000000L	/* WANT_WRITE BIT */
#define	LOCKBIT				0x20000000L	/* LOCK BIT */
#define	SLDISABLED			0x20000000L	/* Disabled simple LOCK BIT */
#define RECURSION 			0x10000000L	/* vmm RECURSION BIT */
#define	READ_MODE			0x10000000L	/* READ_MODE BIT */
#define	INSTR_ON			0x08000000L	/* Instrumented BIT */
#define READ_COUNT_MASK			OWNER_MASK	/* extract READ COUNT */
#define ONE_READER			0x10000001L	/* set one reader */
#define THREAD_BIT			0x00000001L /* set if owner is a thread */

/* Upgraded Locks */

#define	RLE_DOWNGRADED	       0x100000000L/* downgraded reader lock element */

#define CLK_IDX_MASK	 0x7FFFFFF800000000L 	/* IDX of all Reader locks */
#define CLK_IDX_SHIFT	 35ULL 			/* Bits to get to index */


/* Mask for Disabled Reader locks */
#define CLK_IDX_MASK_DIS ((SYSTEM_DISABLED_READER_LOCKS-1) << CLK_IDX_SHIFT)

#define GET_COMPLEX_LOCK_READER(lockword,_enabled) \
	((_enabled) == TRUE ? \
(Reader_lock *)(Reader_locks+((lockword&CLK_IDX_MASK)>> CLK_IDX_SHIFT)):\
(Reader_lock *)(Reader_locks+((lockword&CLK_IDX_MASK_DIS)>>CLK_IDX_SHIFT)))

#define RLOCKS_PER_PAGE PAGE_64K/(sizeof(Reader_lock))
/* Locks reserved for DRW lock use */
#define SYSTEM_DISABLED_READER_LOCKS 0x200L
#define SYSTEM_READER_LOCK_SIZE    	(SEGSIZE<<1ULL)
#define SYSTEM_TOTAL_READER_LOCKS    	SYSTEM_READER_LOCK_SIZE / (sizeof(Reader_lock))

/* recursive flag define */
#define	RECURSIVE	    1	

/* trace sub-hooks */
#define hkwd_LOCK_TAKEN     1
#define hkwd_LOCK_MISS      2
#define hkwd_LOCK_RECURSIVE 3
#define hkwd_LOCK_BUSY      4
#define hkwd_LOCK_DISABLED  8

/* krlock global state transitions */
#define hkwd_KRLOCK		0x10
#define hkwd_KRLOCK_ALLOC	0x11
#define hkwd_KRLOCK_FREE	0x12
#define hkwd_KRLOCK_ACQUIRE	0x13
#define hkwd_KRLOCK_RELEASE	0x14
#define hkwd_KRLOCK_HANDOFF	0x15
#define hkwd_KRLOCK_CONFER	0x16
#define hkwd_KRLOCK_PROD	0x17
#define hkwd_KRLOCK_SPIN	0x18

/* hooks for krlock state changes in simple lock */
/* These use KRLOCK_TRACE macro */
#define hkwd_KRLOCK_INSTALL  	0x19
#define hkwd_KRLOCK_INC_SPIN  	0x1A
#define hkwd_KRLOCK_DEC_SPIN  	0x1B
#define hkwd_KRLOCK_MISS  	0x1C

/* spin count hook */
#define hkwd_SLOCK_LOCKHANG  	0x21
#define hkwd_SLOCK_CONFER1      0x22
#define hkwd_SLOCK_CONFER2      0x23

/* krlock state transitions in group structures */
/* These use KRLOCK_LLTRACE macro */
#define hkwd_KRLOCK_GROUP  		0x30
#define hkwd_KRLOCK_SETCPU_NOCONTEND  	0x31
#define hkwd_KRLOCK_ACQUIRE_NOCONTEND  	0x33
#define hkwd_KRLOCK_unused1  		0x34
#define hkwd_KRLOCK_unused2	  	0x35
#define hkwd_KRLOCK_unused3  		0x36
#define hkwd_KRLOCK_UNLOCKTRY  		0x37
#define hkwd_KRLOCK_SETOWNER  		0x38
#define hkwd_KRLOCK_SETRELEASE_RELEASE  0x3A
#define hkwd_KRLOCK_CLEARCPU_RRUPT  	0x3B
#define hkwd_KRLOCK_CLEARRELEASE_RRUPT  0x3C
#define hkwd_KRLOCK_SETLOCK  		0x3E
#define hkwd_KRLOCK_CLEARLOCK  		0x3F
#define hkwd_KRLOCK_GROUP2  		0x40
#define hkwd_KRLOCK_FREE_GROUP  	0x41
#define hkwd_KRLOCK_FREE_GLOBAL  	0x42
#define hkwd_KRLOCK_AUX2MAIN  		0x43
#define hkwd_KRLOCK_MAIN2AUX  		0x44
#define hkwd_KRLOCK_CLEARRELEASE_UNLOCK 0x45
#define hkwd_KRLOCK_CLEARRELEASE_RELEASE 0x46
#define hkwd_KRLOCK_FREE_LOCAL  	0x47

#define hkwd_SETRECURSIVE   1
#define hkwd_CLEARRECURSIVE 2

/* other defines: lock operation for traces */
#define LOCK_SWRITE_TRACE		1
#define LOCK_CWRITE_TRACE		2
#define LOCK_READ_TRACE			3
#define LOCK_UPGRADE_TRACE		4
#define LOCK_DOWNGRADE_TRACE		5

/* L_INSTR(lockword_value) 
 * Determines whether this lock (complex or simple)
 * is instrumented or not. For POWER, the lock
 * addresses always have the INSTR_ON bit set (it's just
 * where they are)
 */
#define L_INSTR(lw)          ((lw) & INSTR_ON)

#endif	/* _KERNSYS */

#ifdef __cplusplus
}
#endif

#endif /* _H_LOCK_DEFINE */

