184 lines
5.4 KiB
C
184 lines
5.4 KiB
C
/* @(#)lockf.h 1.1 94/10/31 SMI */
|
|
|
|
#ifndef _ufs_lockf_h
|
|
#define _ufs_lockf_h
|
|
|
|
/* constants and structures for the locking code ... */
|
|
|
|
/*
|
|
* Sized to be MAXPROCESSes which actually gives us some spare slots
|
|
* because as many processes (system types) won't ask for file locks
|
|
*/
|
|
|
|
#ifdef KERNEL
|
|
#ifndef MAXPROCESS
|
|
#define MAXPROCESS 135
|
|
#endif
|
|
#else
|
|
#define MAXPROCESS 135
|
|
#endif
|
|
|
|
int can_lock();
|
|
int merge_lock();
|
|
void add_lock();
|
|
void rem_lock();
|
|
int lock_region();
|
|
int unlock_region();
|
|
int lock();
|
|
int unlock();
|
|
|
|
#ifndef NULL
|
|
#define NULL 0
|
|
#endif
|
|
struct lock_ref {
|
|
struct lock_ref *Next, /* Link list pointers */
|
|
*Prev;
|
|
struct data_lock *ThisLock, /* Lock this reference refers too */
|
|
*Conflict; /* Lock in conflict with this one */
|
|
int Type; /* BLOCKING, BLOCKED, or FREE */
|
|
};
|
|
|
|
struct data_lock {
|
|
struct data_lock *Next, /* Next lock in the list */
|
|
*Prev, /* Previous Lock in the list */
|
|
*NextProc; /* Link list of process' locks */
|
|
struct process_locks *MyProc; /* Points to process lock list */
|
|
struct lock_ref *Is_Blocking, /* Is Blocking list */
|
|
*Blocked_By; /* Blocked by list NULL == ACTIVE */
|
|
struct vnode *vp; /* A back pointer to the vnode */
|
|
int base, /* Region description. */
|
|
length, /* Length of lock */
|
|
type, /* EXCLUSIVE or SHARED */
|
|
granted, /* The granted flag */
|
|
color, /* Used during deadlock search */
|
|
LockID, /* ID of this lock */
|
|
system, /* System process 'pid' is on.. */
|
|
pid, /* "Owner" of lock. */
|
|
class; /* Class of lock (FILE, IO, NET) */
|
|
long rsys, /* System process 'rpid' is on.. */
|
|
rpid; /* Remote process identifier */
|
|
};
|
|
|
|
/* process lock structure holds locks owned by a given process */
|
|
struct process_locks {
|
|
long pid;
|
|
struct process_locks *next;
|
|
struct data_lock *lox;
|
|
};
|
|
|
|
|
|
/* pointed to by the vnode */
|
|
struct lock_list {
|
|
struct data_lock *exclusive, /* The exclusive list */
|
|
*shared, /* The shared list */
|
|
*pending; /* Those that want to get on */
|
|
};
|
|
|
|
/*
|
|
* Special values for eld.l_xxx.
|
|
*
|
|
* GRANT_LOCK_FLAG The kernel uses this value to notify the lock
|
|
* manager that it needs to check for granted locks.
|
|
* The lock manager uses this value to notify the
|
|
* kernel that it is checking for granted locks.
|
|
*
|
|
* LOCKD_LAST_REF The kernel uses this value to notify the lock
|
|
* manager that it has no more locks on the given
|
|
* file (so the lock manager can close it).
|
|
*/
|
|
|
|
#define GRANT_LOCK_FLAG 0xf
|
|
#define LOCKD_LAST_REF 0x10
|
|
|
|
#ifdef KERNEL
|
|
#define MAX_GRANT_LOCKS 52
|
|
|
|
/* structure that contains list of locks to be granted */
|
|
|
|
struct grant_lock {
|
|
struct data_lock *grant_lock_list[MAX_GRANT_LOCKS];
|
|
struct grant_lock *next;
|
|
};
|
|
#endif /* KERNEL */
|
|
|
|
/* Reference 'types' also BLOCKING below is used */
|
|
#define FREE 0
|
|
#define BLOCKED 1
|
|
|
|
#define EXCLUSIVE 1 /* Lock is an Exclusive lock */
|
|
#define BLOCKING 2 /* Block process for this lock. */
|
|
|
|
/* Lock classes, determines how they are treated when they are unlocked. */
|
|
#define FILE_LOCK 0 /* Generic class no special treatment */
|
|
#define IO_LOCK 1 /* Indicates I/O waiting to complete */
|
|
#define LOCKMGR 2 /* Indicates lock manager lock */
|
|
|
|
/* These defines are used with lock structures to determine various things */
|
|
#define LOCK_TO_EOF -1
|
|
#define END(l) ((l)->length == LOCK_TO_EOF ? \
|
|
LOCK_TO_EOF : (l)->base + (l)->length - 1)
|
|
#define ACTIVE(l) ((l)->Blocked_By == NULL)
|
|
|
|
/*
|
|
* Determine if locks intersect. Lock intersection is computed
|
|
* by determining:
|
|
*
|
|
* If Then they intersect if
|
|
* -- ----------------------
|
|
* Both not to-EOF locks bases and ends are mutually out of range
|
|
* One only is EOF lock If the EOF-lock base is within end of
|
|
* non-EOF lock
|
|
* Both are EOF locks Always
|
|
*/
|
|
#define TOUCHING(a, b) \
|
|
((END(a) >= 0 && END(b) >= 0 && \
|
|
(!((END(a) < (b)->base) || ((a)->base > END(b))))) || \
|
|
(END(a) < 0 && END(b) >= 0 && END(b) >= (a)->base) || \
|
|
(END(a) >= 0 && END(b) < 0 && END(a) >= (b)->base) || \
|
|
(END(a) < 0 && END(b) < 0))
|
|
|
|
/* Is TRUE if A and B are adjacent */
|
|
#define ADJACENT(a, b) ((END(a)+1 == (b)->base) || ((a)->base == END(b)+1))
|
|
|
|
/* Is TRUE if a is completely contained within b */
|
|
#define WITHIN(a, b) \
|
|
(((a)->base >= (b)->base) && \
|
|
((END(a) >= 0 && END(b) >= 0 && END(a) <= END(b)) || (END(b) < 0) || \
|
|
((b)->length == 0x7fffffff)))
|
|
|
|
/* Is TRUE if a and b are owned by the same process... (even remotely) */
|
|
#ifdef KERNEL
|
|
#define SAMEOWNER(a, b) (((a)->pid == (b)->pid) && \
|
|
((a)->rpid == (b)->rpid) && \
|
|
((a)->rsys == (b)->rsys))
|
|
#else
|
|
#define SAMEOWNER(a, b) (((a)->pid == (b)->pid) && \
|
|
((a)->rpid == (b)->rpid))
|
|
#endif
|
|
|
|
#ifdef KERNEL
|
|
#define SAMELOCK(a, b) (((a)->base == (b)->base) && \
|
|
((a)->length == (b)->length) && \
|
|
((a)->type == (b)->type) && \
|
|
((a)->class == (b)->class))
|
|
#endif
|
|
|
|
#ifdef KERNEL
|
|
#define LOCKS(v) ((struct lock_list *)((v)->v_filocks))
|
|
#define Exclusive ((LOCKS(vp)) ? LOCKS(vp)->exclusive : NULL)
|
|
#define Shared ((LOCKS(vp)) ? LOCKS(vp)->shared : NULL)
|
|
#define Pending ((LOCKS(vp)) ? LOCKS(vp)->pending : NULL)
|
|
|
|
#endif
|
|
|
|
#ifndef KERNEL
|
|
struct data_lock *free_locks;
|
|
|
|
#define GETLOCK(l) (l) = get_lock()
|
|
#define FREELOCK(l) { (l)->pid = 0; \
|
|
(l)->Next = free_locks; \
|
|
free_locks = (l); }
|
|
#endif
|
|
|
|
#endif /*!_ufs_lockf_h*/
|