/*
 * Copyright (c) 1998 The Santa Cruz Operation, Inc.. All Rights Reserved.
 *
 *        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF THE
 *                   SANTA CRUZ OPERATION INC.
 *
 *   The copyright notice above does not evidence any actual or intended
 *   publication of such source code.
 */

#ifndef _FS_FIFOFS_FIFONODE_H	/* wrapper symbol for kernel use */
#define _FS_FIFOFS_FIFONODE_H	/* subject to change without notice */

#ident	"@(#)kern:fs/fifofs/fifonode.h	1.14"
#ident	"$Header: $"

#if defined(__cplusplus)
extern "C" {
#endif

#ifdef _KERNEL_HEADERS

#include <util/types.h>		/* REQUIRED */
#include <util/ksynch.h>	/* REQUIRED */
#include <fs/vnode.h>		/* REQUIRED */

#elif defined(_KERNEL) || defined(_KMEMUSER)

#include <sys/types.h>		/* REQUIRED */
#include <sys/ksynch.h>	/* REQUIRED */
#include <sys/vnode.h>		/* REQUIRED */

#endif /* _KERNEL_HEADERS */

#if defined(_KERNEL) || defined(_KMEMUSER)

struct nodelock {
	lock_t	n_lock;
	int	n_count;
};

/*
 * Each FIFOFS object is identified by a struct fifonode/vnode pair.
 */
struct fifonode {
	struct vnode	fn_vnode;	/* represents the fifo/pipe */
	struct vnode	*fn_mate;	/* the other end of a pipe */
	struct vnode	*fn_realvp;	/* node being shadowed by fifo */
	sleep_t		fn_iolock;	/* fifonode iolock */
	sv_t		fn_rwait;	/* wait for first reader */
	sv_t		fn_wwait;	/* wait for first writer */
	sv_t		fn_fdwait;	/* to synchronize fd passing */
	sv_t		fn_openwait;	/* to serialize fifo_open */
	ino_t		fn_ino;		/* node id for pipes */
	short		fn_wcnt;	/* number of writers */
	short		fn_rcnt;	/* number of readers */
	short		fn_open;	/* open count of node*/
	ushort		fn_flag;	/* flags as defined below */
	struct vnode	*fn_unique;	/* new vnode created by CONNLD */
	time_t		fn_atime;	/* creation times for pipe */
	time_t		fn_mtime;
	time_t		fn_ctime;
	struct fifonode	*fn_nextp;	/* next link in the linked list */
	struct fifonode	*fn_backp;	/* back link in linked list */
	struct nodelock *fn_nodelp;	/* lock shared by both ends of a pipe */
};

#endif /* _KERNEL || _KMEMUSER */

#ifdef _KERNEL

/*
 * Valid flags for fifonodes.
 */
#define ISPIPE		01	/* fifonode is that of a pipe */
#define FIFOWOPEN	02	/* open in progress */
#define FIFOWCLOSE      04	/* close in progress */
#define FIFOSEND       010	/* file descriptor at stream head of pipe */
#define FIFOPASS       020	/* CONNLD passed a new vnode in fn_unique */
#define	FIFOMACPRIV    040	/* bypass MAC checks for privilege process */
#define CONNLDPUSHED  0100	/* CONNLD is pushed */
#define FIFOMODTIME   0200	/* access/modification/change time modified */

#define FIFOBSIZE       1024    /* FIFOFS block size */

/* #ifdef MERGE */
extern int fifo_rdchk(vnode_t *);
/* #endif MERGE */

/*
 * Macros to convert a vnode to a fifonode, and vice versa.
 */
#define VTOF(vp) ((struct fifonode *)((vp)->v_data))
#define FTOV(fp) (&(fp)->fn_vnode)

/*
 * Functions used in multiple places.
 */
extern int fifo_rdchk(vnode_t *);
extern int fifo_mkpipe(vnode_t **, vnode_t **, cred_t *);
extern void fifo_rmpipe(vnode_t *, vnode_t *, cred_t *);

/*
 * Macros for manipulating locks and synchronization variables
 */

/*
 * Macros called by fifovp() and fifo_inactive()
 * to avoid a race on the vnode.
 */
#define FIFO_LOCK(fp, lockp) \
	SLEEP_LOCK_RELLOCK(&(fp)->fn_iolock, PRIPIPE, lockp)
#define FIFO_TRYLOCK(fp) SLEEP_TRYLOCK(&(fp)->fn_iolock)
#define FIFO_LOCKBLKD(fp) SLEEP_LOCKBLKD(&(fp)->fn_iolock)
#define FIFO_UNLOCK(fp) SLEEP_UNLOCK(&(fp)->fn_iolock)

/*
 * Macro to manipulate fn_nodelp->n_lock.
 */
#define PIPE_LOCK(fp) LOCK(&(fp)->fn_nodelp->n_lock, PLFIFO)
#define PIPE_UNLOCK(fp, pl) UNLOCK(&(fp)->fn_nodelp->n_lock, pl)

/*
 * Macro to manipulate fn_fdwait.
 * While waiting on fn_fdwait, fn_nodelp->n_lock is dropped.
 */
#define FIFO_FDWAIT(fp) \
	SV_WAIT_SIG(&(fp)->fn_fdwait, PRIPIPE, &(fp)->fn_nodelp->n_lock)
#define FIFO_FDWAKEUP(fp) SV_SIGNAL(&(fp)->fn_fdwait, 0)

/*
 * Macro to obtain and release the stream head mutex, sd_mutex
 */
#define	STREAM_LOCK(stp) LOCK((stp)->sd_mutex, PLSTR);
#define	STREAM_UNLOCK(stp, pl) UNLOCK((stp)->sd_mutex, pl);

#endif	/* _KERNEL */

#if defined(__cplusplus)
	}
#endif

#endif	/* _FS_FIFOFS_FIFONODE_H */
