710 lines
19 KiB
C
710 lines
19 KiB
C
/* @(#)04 1.37 src/bos/kernel/include/pse/str_stream.h, sysxpse, bos41J, 9521B_all 5/25/95 15:33:02 */
|
|
/*
|
|
* COMPONENT_NAME: SYSXPSE - Streams Framework
|
|
*
|
|
* ORIGINS: 63, 71, 83
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* LEVEL 1, 5 Years Bull Confidential Information
|
|
*/
|
|
|
|
/*
|
|
* (c) Copyright 1990, 1991, 1992 OPEN SOFTWARE FOUNDATION, INC.
|
|
* ALL RIGHTS RESERVED
|
|
*/
|
|
/*
|
|
* OSF/1 1.1
|
|
*/
|
|
/** Copyright (c) 1988-1991 Mentat Inc. */
|
|
|
|
#ifndef _STR_STREAM_H
|
|
#define _STR_STREAM_H
|
|
|
|
#include <pse/str_system.h>
|
|
#include <sys/sleep.h>
|
|
|
|
#include <sys/uio.h>
|
|
#include <sys/encap.h>
|
|
#include <pse/str_lock.h>
|
|
#include <sys/lock_alloc.h>
|
|
#ifdef SQH_LOCK_COUNT
|
|
short sqh_lock_count = 0;
|
|
#else
|
|
extern short sqh_lock_count;
|
|
#endif
|
|
|
|
#include <net/net_malloc.h>
|
|
|
|
/*
|
|
* Note: <sys/stream.h> is included later, since we need to complete
|
|
* the configuration first.
|
|
*/
|
|
|
|
#include <pse/str_debug.h>
|
|
|
|
#if STREAMS_DEBUG
|
|
#define staticf
|
|
#else
|
|
#define staticf static
|
|
#endif
|
|
|
|
#define INTR_STACK 0x3000
|
|
#define INITDONE 0x8000
|
|
#define cdevsw devsw
|
|
|
|
#define nilp(t) ((t *)0)
|
|
#define nil(t) ((t)0)
|
|
#define reg register
|
|
#define LONG_SIGN_BIT ((long) ~((~((unsigned long)0)) >> 1))
|
|
#define MS_TO_TICKS(ms) (((ms)*hz)/1000)
|
|
#define TICKS_TO_MS(ticks) (((ticks)*1000)/hz)
|
|
|
|
/*
|
|
* The Synch Queues arbitrate all access to Streams queues.
|
|
* A synch queue is a synch queue head if the SQ_IS_HEAD bit
|
|
* is set in sqh_flags, else it's a sync queue element. The
|
|
* first three elements of the SQH and the SQ must be identical.
|
|
*/
|
|
|
|
struct sqh_s {
|
|
struct sqe_s * sqh_next;
|
|
struct sqe_s * sqh_prev;
|
|
long sqh_flags;
|
|
struct sqh_s * sqh_parent;
|
|
struct sqe_s * sqh_owner;
|
|
int sqh_refcnt;
|
|
decl_simple_lock_data(EMPTY_FIELD, sqh_lock)
|
|
};
|
|
typedef struct sqh_s SQH;
|
|
typedef struct sqh_s * SQHP;
|
|
|
|
typedef void (*sq_entry_t)(void *, void *);
|
|
|
|
struct sqe_s {
|
|
struct sqe_s * sq_next;
|
|
struct sqe_s * sq_prev;
|
|
long sq_flags;
|
|
struct sqh_s * sq_target;
|
|
struct pse_queue * sq_queue;
|
|
sq_entry_t sq_entry;
|
|
void * sq_arg0;
|
|
void * sq_arg1;
|
|
int sq_sleeper;
|
|
int sq_count;
|
|
};
|
|
typedef struct sqe_s SQ;
|
|
typedef struct sqe_s * SQP;
|
|
|
|
/* Special SQH used when synchronizing multiple SQH's. */
|
|
extern SQH mult_sqh;
|
|
/* Global SQH used by globally synchronized modules */
|
|
extern SQH sq_sqh;
|
|
|
|
/* SQ flags */
|
|
#define SQ_IS_HEAD 0x00000001
|
|
#define SQ_INUSE 0x00000002
|
|
#define SQ_HOLD 0x00000004
|
|
#define SQ_QUEUED 0x00000008
|
|
#define SQ_IS_TIMEOUT 0x00000010
|
|
#define SQ_IS_FUNNEL 0x00000400
|
|
|
|
typedef struct t_list {
|
|
struct t_list * next;
|
|
tid_t t_id;
|
|
} tidlist;
|
|
|
|
/*
|
|
* A generic doubly-linked list (queue).
|
|
*/
|
|
|
|
struct queue_entry {
|
|
struct queue_entry *next; /* next element */
|
|
struct queue_entry *prev; /* previous element */
|
|
};
|
|
|
|
/*
|
|
* The following macros define some additional parts of certain data
|
|
* structures, which are needed by the stream head in order to provide
|
|
* synchronization.
|
|
*
|
|
* Note that these macros are undefined for normal modules and drivers.
|
|
* This gives them a wrong impression about the size of those structures.
|
|
* But that should not matter, since - according to the STREAMS spec -
|
|
* they should not make such assumptions anyway. The idea is that
|
|
* module code also becomes independent of the configuration, and binary
|
|
* compatibility is guaranteed.
|
|
*
|
|
* Note: even modules which include this file for debugging purposes, should
|
|
* not refer to these fields, since they do not necessarily form a standard
|
|
* to which OSF/1 will adhere in the future.
|
|
*/
|
|
|
|
/*
|
|
* Extra fields for queue structure:
|
|
* struct queue * q_ffcp; Forward flow control pointer
|
|
* struct queue * q_bfcp; Backward flow control pointer
|
|
* SQH q_sqh; Sync queue head for laterals
|
|
* SQP q_runq_sq; Sync queue element for runq
|
|
* simple_lock_data_t q_qlock; short term lock for (de)queueing
|
|
*
|
|
* struct queue_entry q_act; ... currently active queues
|
|
* tidlist q_tids; and thread identifier,
|
|
* for identification
|
|
*
|
|
* These present only if SEC_BASE defined
|
|
* struct msgb * b_attr; pointer to security attributes
|
|
*
|
|
* Extra fields for message structure:
|
|
* SQ b_sq; Sync queue element for lateral
|
|
*
|
|
* The q_runq_sq is a pointer to permit sizeof (queue_t) to be <128 bytes
|
|
* in the production configuration. Increase with care.
|
|
*/
|
|
|
|
#if SEC_BASE
|
|
|
|
#define MSG_KERNEL_SEC_FIELDS \
|
|
struct msgb * b_attr;
|
|
|
|
#else
|
|
|
|
#define MSG_KERNEL_SEC_FIELDS
|
|
|
|
#endif
|
|
|
|
#define QUEUE_KERNEL_FIELDS \
|
|
struct pse_queue * q_ffcp; \
|
|
struct pse_queue * q_bfcp; \
|
|
SQH q_sqh; \
|
|
SQP q_runq_sq; \
|
|
struct queue_entry q_act; \
|
|
tidlist q_tids; \
|
|
int (*q_is_interesting) (mblk_t *); \
|
|
int q_int_count; \
|
|
decl_simple_lock_data(EMPTY_FIELD, q_qlock) \
|
|
struct wantio * q_wantio;
|
|
|
|
#define MSG_KERNEL_FIELDS \
|
|
SQ b_sq; \
|
|
MSG_KERNEL_SEC_FIELDS
|
|
|
|
/*
|
|
* OK, we can include <sys/stream.h> *now*, after having defined those
|
|
* extra pieces.
|
|
*/
|
|
|
|
#include <sys/strconf.h>
|
|
#include <sys/stream.h>
|
|
#include <sys/sad.h>
|
|
|
|
#undef tsleep
|
|
#undef e_sleep
|
|
#undef e_sleepl
|
|
#undef e_mpsleep
|
|
#undef e_block_thread
|
|
#undef sleep
|
|
#undef sleepx
|
|
#define tsleep(a,b,c,d) sleepx((a),(b),0)
|
|
|
|
/*
|
|
* Streams framework does not want to undef the followings, so it can use
|
|
* these symbols as defined in stream.h. The framework will define STR_DEFINES
|
|
* and so for others who includes this file, the undef's will be done.
|
|
*/
|
|
|
|
#ifndef STR_DEFINES
|
|
#undef timeout
|
|
#undef untimeout
|
|
#endif
|
|
|
|
typedef struct msgb * MBLKP;
|
|
typedef struct msgb ** MBLKPP;
|
|
|
|
#define MSGEXT 0x08 /* external association. Define should be in stream.h */
|
|
|
|
/* Extra PSE mblk type */
|
|
#define M_MI 64
|
|
/* Subfields for M_MI messages */
|
|
#define M_MI_READ_RESET 1
|
|
#define M_MI_READ_SEEK 2
|
|
#define M_MI_READ_END 4
|
|
|
|
/* Extra for FLUSHALL, FLUSHDATA */
|
|
#define FLUSH_CAN_CLOSE 0x8000
|
|
#define FLUSH_NOTIFYONLY 0x4000
|
|
|
|
#define DEF_CLOSE_WAIT 15 /* seconds to wait per non-empty module
|
|
* or driver during close. */
|
|
#define STH_HASH_TBL_SIZE 32 /* Now defined only here. */
|
|
|
|
#include <sys/stropts.h> /* for struct bandinfo, etc. */
|
|
|
|
typedef struct ioctl_osr_s {
|
|
struct iovec ioc_oia[3];
|
|
mblk_t *ioc_data;
|
|
/* Ioctl data buffer - large enough for largest copyin/out */
|
|
union streams_ioctl_buffer {
|
|
char c[FMNAMESZ+1];
|
|
int i;
|
|
long l;
|
|
caddr_t p;
|
|
struct stat sb;
|
|
struct bandinfo b;
|
|
struct str_list s1;
|
|
struct strfdinsert s2;
|
|
#ifdef SEC_BASE
|
|
struct strfdinsert_attr s2a;
|
|
#endif
|
|
struct strioctl s3;
|
|
#ifdef SEC_BASE
|
|
struct strioctl_attr s3a;
|
|
#endif
|
|
struct strpmsg s4;
|
|
#ifdef SEC_BASE
|
|
struct strpmsg_attr s4a;
|
|
#endif
|
|
struct strpeek s5;
|
|
#ifdef SEC_BASE
|
|
struct strpeek_attr s5a;
|
|
#endif
|
|
struct strrecvfd s6;
|
|
#ifdef SEC_BASE
|
|
struct strrecvfd_attr s6a;
|
|
/* there is no struct strsendfd */
|
|
struct strsendfd_attr s7a;
|
|
#endif
|
|
} ioc_buf;
|
|
} IOCTL_OSR;
|
|
|
|
#define osr_ioctl_arg0 osr_osru.ioctl_osr.ioc_oia[0].iov_len
|
|
#define osr_ioctl_arg0p osr_osru.ioctl_osr.ioc_oia[0].iov_base
|
|
#define osr_ioctl_arg0_len osr_osru.ioctl_osr.ioc_oia[0].iov_len
|
|
#define osr_ioctl_arg1 osr_osru.ioctl_osr.ioc_oia[1].iov_len
|
|
#define osr_ioctl_arg1p osr_osru.ioctl_osr.ioc_oia[1].iov_base
|
|
#define osr_ioctl_arg1_len osr_osru.ioctl_osr.ioc_oia[1].iov_len
|
|
#define osr_ioctl_arg2 osr_osru.ioctl_osr.ioc_oia[2].iov_len
|
|
#define osr_ioctl_arg2p osr_osru.ioctl_osr.ioc_oia[2].iov_base
|
|
#define osr_ioctl_arg2_len osr_osru.ioctl_osr.ioc_oia[2].iov_len
|
|
#define osr_ioctl_data osr_osru.ioctl_osr.ioc_data
|
|
|
|
typedef struct open_osr_s {
|
|
dev_t open_dev;
|
|
int open_dindex;
|
|
int open_fflag;
|
|
} OPEN_OSR;
|
|
|
|
#define osr_open_dev osr_osru.open_osr.open_dev
|
|
#define osr_open_dindex osr_osru.open_osr.open_dindex
|
|
#define osr_open_fflag osr_osru.open_osr.open_fflag
|
|
|
|
typedef struct rw_osr_s {
|
|
struct uio *rw_uio;
|
|
int rw_total;
|
|
int rw_count;
|
|
int rw_offset;
|
|
enum uio_rw uio_rw;
|
|
} RD_OSR;
|
|
|
|
#define osr_rw_uio osr_osru.rw_osr.rw_uio
|
|
#define osr_rw_total osr_osru.rw_osr.rw_total
|
|
#define osr_rw_count osr_osru.rw_osr.rw_count
|
|
#define osr_rw_offset osr_osru.rw_osr.rw_offset
|
|
#define osr_rw_rw osr_osru.rw_osr.uio_rw
|
|
|
|
struct osrq_s {
|
|
struct osr_s * osrq_first;
|
|
struct osr_s * osrq_last; /* (Undefined when osrq_first is nil!) */
|
|
decl_simple_lock_data(EMPTY_FIELD, osrq_lock)
|
|
int osrq_sleeper;
|
|
};
|
|
|
|
typedef struct osrq_s OSRQ;
|
|
typedef struct osrq_s * OSRQP;
|
|
|
|
struct osr_s {
|
|
SQ osr_sq; /* this OSR's synch queue element */
|
|
struct osrq_s * osr_osrq; /* pointer to OSRQ where this OSR is queued */
|
|
struct osr_s * osr_next; /* next OSR in the same OSRQ */
|
|
struct sth_s * osr_sth;
|
|
int osr_ret_val;
|
|
int (*osr_handler)(struct osr_s *);
|
|
ulong osr_closeout;
|
|
ulong osr_flags;
|
|
int osr_bufcall_id;
|
|
int osr_awakened;
|
|
cred_t *osr_creds;
|
|
union {
|
|
IOCTL_OSR ioctl_osr;
|
|
OPEN_OSR open_osr;
|
|
RD_OSR rw_osr;
|
|
} osr_osru;
|
|
int osr_sleeper;
|
|
};
|
|
|
|
typedef struct osr_s OSR;
|
|
typedef struct osr_s * OSRP;
|
|
typedef struct osr_s ** OSRPP;
|
|
|
|
/*
|
|
* Values for osr_flags
|
|
*
|
|
* F_OSR_NEED_MULT_SQH - the OSR must allocate mult_sqh first
|
|
* F_OSR_HAVE_MULT_SQH - this OSR is holding the mult_sqh
|
|
* F_OSR_NDELAY - this OSR wants non-delay mode
|
|
* F_OSR_NONBLOCK - this OSR wants non-block mode
|
|
* F_OSR_RTTY_CHECK - OSR needs read-style bg check if tty
|
|
* F_OSR_WTTY_CHECK - OSR needs write-style bg check if tty
|
|
* F_OSR_ITTY_CHECK - OSR needs ioctl-style bg check if tty
|
|
* F_OSR_BLOCK_TTY - BG proc. attempting access to ctl. tty: block it
|
|
* F_OSR_AUDIT_READ - SEC_BASE ioctl: generate read audit record
|
|
* F_OSR_AUDIT_WRITE - SEC_BASE ioctl: generate write audit record
|
|
*/
|
|
|
|
#define F_OSR_NEED_MULT_SQH 0x00000001
|
|
#define F_OSR_HAVE_MULT_SQH 0x00000002
|
|
#define F_OSR_NDELAY 0x00000004
|
|
#define F_OSR_NONBLOCK 0x00000008
|
|
#define F_OSR_NBIO (F_OSR_NDELAY|F_OSR_NONBLOCK)
|
|
#define F_OSR_RTTY_CHECK 0x00000010
|
|
#define F_OSR_WTTY_CHECK 0x00000020
|
|
#define F_OSR_ITTY_CHECK 0x00000040
|
|
#define F_OSR_TTYBITS (F_OSR_RTTY_CHECK|F_OSR_WTTY_CHECK|F_OSR_ITTY_CHECK)
|
|
#define F_OSR_BLOCK_TTY 0x00000080
|
|
#define F_OSR_AUDIT_READ 0x00000100
|
|
#define F_OSR_AUDIT_WRITE 0x00000200
|
|
#define F_OSR_KCOPY 0x00010000
|
|
#define F_OSR_TTY_IOCTL 0x00020000
|
|
|
|
struct sthq_s {
|
|
struct sthq_s *next, *prev;
|
|
};
|
|
|
|
struct poll_s {
|
|
struct sthq_s ps_link;
|
|
struct sth_s * ps_sth;
|
|
ushort ps_events;
|
|
chan_t ps_chan;
|
|
};
|
|
|
|
typedef struct poll_s POLLS;
|
|
typedef struct poll_s * POLLSP;
|
|
typedef struct sthq_s POLLQ;
|
|
typedef struct sthq_s * POLLQP;
|
|
#define sth_poll_active(sth) \
|
|
((sth)->sth_pollq.next != &(sth)->sth_pollq)
|
|
|
|
struct sigs_s {
|
|
struct sthq_s ss_q;
|
|
struct sthq_s ss_pq;
|
|
struct sth_s * ss_sth;
|
|
pid_t ss_pid;
|
|
ulong ss_mask;
|
|
ulong ss_async;
|
|
};
|
|
|
|
typedef struct sigs_s SIGS;
|
|
typedef struct sigs_s * SIGSP;
|
|
typedef struct sthq_s SIGSQ;
|
|
#define sth_sigs_active(sth) \
|
|
((sth)->sth_sigsq.next != &(sth)->sth_sigsq)
|
|
#define ss_link ss_q.next
|
|
#define ss_proclink ss_pq.next
|
|
|
|
/*
|
|
* Stream head tty control structure.
|
|
* Allocated at stream head tty open.
|
|
*/
|
|
typedef struct shtty_s {
|
|
pid_t shtty_pgrp; /* process grou identificator */
|
|
pid_t shtty_sid; /* session identificator */
|
|
pid_t shtty_tsm; /* terminal state manager id */
|
|
ulong shtty_flags; /* general streamhead tty flags */
|
|
/* for the erminal state. */
|
|
};
|
|
|
|
/*
|
|
* Stream head tty definitions for shtty_flags.
|
|
*/
|
|
#define F_SHTTY_TRUST 0x0001 /* terminal trusted or not */
|
|
#define F_SHTTY_SAK 0x0002 /* sak sequence enabled or not */
|
|
#define F_SHTTY_KEP 0x0004 /* keyboard emulation program */
|
|
/* emulated or not */
|
|
#define F_SHTTY_CONS 0x0008 /* console redirected or not */
|
|
|
|
/* Stream head control structure */
|
|
/* Warning - production configuration almost 256 bytes - increase with care. */
|
|
struct sth_s {
|
|
queue_t * sth_rq; /* Stream head read queue */
|
|
queue_t * sth_wq; /* Stream head write queue */
|
|
dev_t sth_dev; /* Device number of stream */
|
|
ulong sth_read_mode; /* RNORM, etc. */
|
|
ulong sth_write_mode; /* SNDZERO if 0 byte messages are ok */
|
|
int sth_close_wait_timeout; /* ms to wait during close */
|
|
uchar sth_read_error;
|
|
uchar sth_write_error;
|
|
uchar sth_prev_band; /* last band written to sth */
|
|
uchar sth_pad;
|
|
ulong sth_flags;
|
|
int sth_ioc_id; /* id of outstanding M_IOCTL */
|
|
mblk_t * sth_ioc_mp; /* M_IOCACK or M_IOCNAK reply */
|
|
OSRQ sth_ioctl_osrq; /* Ioctl request queue */
|
|
OSRQ sth_read_osrq; /* Read request queue */
|
|
OSRQ sth_write_osrq; /* Write request queue */
|
|
ulong sth_wroff; /* Write offset to prepend to M_DATA */
|
|
int sth_muxid; /* linked id of lower mux */
|
|
struct sth_s * sth_mux_link; /* link to next muxed lower stream */
|
|
struct sth_s * sth_mux_top; /* controlling mux list */
|
|
struct sth_s * sth_pmux_top; /* mux list for persistent links */
|
|
struct shtty_s * shttyp; /* pointer to tty informations */
|
|
struct sth_s * sth_next; /* Link on sth_open_streams list */
|
|
POLLQ sth_pollq; /* list of active polls/selects */
|
|
SIGSQ sth_sigsq; /* list of I_SETSIGs */
|
|
int sth_push_cnt; /* Number of modules pushed */
|
|
POLLS sth_polls; /* Poll per sth */
|
|
OSR sth_osr; /* Osr per sth */
|
|
ulong sth_ext_flags; /* Flags looked at by threads
|
|
* that don't own the Stream head. */
|
|
int sth_open_count; /* number of simultaneous open */
|
|
int sth_open_ev; /* open event */
|
|
};
|
|
|
|
typedef struct sth_s STH;
|
|
typedef struct sth_s * STHP;
|
|
typedef struct sth_s ** STHPP;
|
|
|
|
/*
|
|
* Values for sth_read_mode: see stropts.h
|
|
* {RNORM, RFILL, RMSGD, RMSGN, ...}
|
|
*/
|
|
|
|
/*
|
|
* Values for sth_flags
|
|
*
|
|
* F_STH_READ_ERROR - M_ERROR with read error received, fail all read calls
|
|
* F_STH_WRITE_ERROR - M_ERROR with write error received, fail all writes
|
|
* F_STH_HANGUP - M_HANGUP received, no more data
|
|
* F_STH_NDELON - do TTY semantics for ONDELAY handling
|
|
* F_STH_ISATTY - this stream acts a terminal
|
|
* F_STH_MREADON - generate M_READ messages
|
|
* F_STH_TOSTOP - disallow background writes (for job control)
|
|
* F_STH_PIPE - stream is one end of a pipe or fifo
|
|
* F_STH_WPIPE - stream is the "write" side of a pipe
|
|
* F_STH_FIFO - stream is a fifo
|
|
* F_STH_LINKED - stream has one or more lower streams linked
|
|
*
|
|
* F_STH_CLOSED - stream has been closed, and should be freed
|
|
* F_STH_CLOSING - actively on the way down
|
|
* F_STH_MSDRAIN - ask to send a M_PCRSE to ptydd when data drained
|
|
*
|
|
* RWHL_ERROR_FLAGS - error flags which prevent input and output ops
|
|
* RWL_ERROR_FLAGS - combination of flags which prevent output ops
|
|
* RL_ERROR_FLAGS - combination of flags which prevent input ops
|
|
* WHL_ERROR_FLAGS - combination of flags which prevent output ops
|
|
*/
|
|
#define F_STH_READ_ERROR 0x0001
|
|
#define F_STH_WRITE_ERROR 0x0002
|
|
#define F_STH_HANGUP 0x0004
|
|
#define F_STH_NDELON 0x0008
|
|
#define F_STH_ISATTY 0x0010
|
|
#define F_STH_MREADON 0x0020
|
|
#define F_STH_TOSTOP 0x0040
|
|
#define F_STH_PIPE 0x0080
|
|
#define F_STH_WPIPE 0x0100
|
|
#define F_STH_FIFO 0x0200
|
|
#define F_STH_LINKED 0x0400
|
|
#define F_STH_CTTY 0x0800
|
|
|
|
#define F_STH_CLOSED 0x4000
|
|
#define F_STH_CLOSING 0x8000
|
|
#define F_STH_MSDRAIN 0x10000
|
|
|
|
#define MSDRAIN 0x0800 /* another hack for ptys */
|
|
|
|
#define RWHL_ERROR_FLAGS (F_STH_READ_ERROR | F_STH_WRITE_ERROR \
|
|
| F_STH_HANGUP | F_STH_LINKED | F_STH_CLOSED)
|
|
#define RWL_ERROR_FLAGS (F_STH_READ_ERROR | F_STH_WRITE_ERROR \
|
|
| F_STH_LINKED | F_STH_CLOSED)
|
|
#define RL_ERROR_FLAGS (F_STH_READ_ERROR | F_STH_LINKED | F_STH_CLOSED)
|
|
#define WHL_ERROR_FLAGS (F_STH_WRITE_ERROR | F_STH_HANGUP \
|
|
| F_STH_LINKED | F_STH_CLOSED)
|
|
/*
|
|
* Values for sth_ext_flags. These are flags which must sometimes be
|
|
* inspected in a context where the Stream head has not been acquired.
|
|
* Atomic primitives must be used to manipulate these flags.
|
|
*
|
|
* F_STH_OSR_INUSE - per stream OSR is in use
|
|
*
|
|
*/
|
|
#define F_STH_OSR_INUSE 0x0001
|
|
#define F_STH_POLL_INUSE 0x0002
|
|
#define F_STH_PUSHING 0x0004
|
|
#define F_STH_PUSHED 0x0008
|
|
|
|
#define sth_id(sth) (((ulong)(sth)) & ~LONG_SIGN_BIT)
|
|
|
|
#define STREAM_END(q) (!(q)->q_next \
|
|
|| ((q)->q_next->q_flag & QREADR))
|
|
|
|
/* Stream head qinfo structure */
|
|
extern struct streamtab sthinfo;
|
|
|
|
/* Maximum number of qbands any queue can have */
|
|
#define MAX_QBAND 255
|
|
|
|
/* Minimum number of seconds close can wait for a stream to drain */
|
|
#define MIN_CLOSE_WAIT_TIMEOUT 0
|
|
|
|
/* Minimum number of bytes allocated for a M_PROTO block */
|
|
#define MIN_CTL_BUF 64
|
|
|
|
#define READ_MODE_MASK (RNORM | RMSGD | RMSGN | RFILL)
|
|
#define READ_PROTO_MASK (RPROTNORM | RPROTDAT | RPROTDIS | RPROTCOMPRESS)
|
|
#define READ_OPTIONS_MASK (READ_MODE_MASK | READ_PROTO_MASK)
|
|
|
|
/*
|
|
* module and device switches
|
|
*
|
|
* d_sqh pointer to synchronization queue for module-wide
|
|
* synchronization. Also, in the case of external
|
|
* synchronization, this element points to it.
|
|
* d_str pointer to streamtab
|
|
* d_funnel_str pointer to true streamtab, when d_str point to funnelized one
|
|
* d_sq_level synchronization level
|
|
* d_name name
|
|
* d_flags flags derived from configuration parameters
|
|
* d_refcnt non-0 if opened and/or pushed
|
|
* d_major major number of this device if device
|
|
*/
|
|
|
|
struct modsw {
|
|
struct modsw * d_next;
|
|
struct modsw * d_prev;
|
|
char d_name[FMNAMESZ+1];
|
|
char d_flags;
|
|
SQHP d_sqh;
|
|
struct streamtab * d_str;
|
|
struct streamtab * d_funnel_str;
|
|
int d_sq_level;
|
|
int d_refcnt;
|
|
int d_major;
|
|
};
|
|
|
|
/* Supports old-style (V.3) open/close parameters */
|
|
#define F_MODSW_OLD_OPEN 0x1
|
|
/* Module requires safe timeout/bufcall callbacks - XXX */
|
|
#define F_MODSW_QSAFETY 0x2
|
|
/* non MP Safe drivers need funneling */
|
|
#define F_MODSW_MPSAFE 0x4
|
|
/* non safe service routines need scheduling */
|
|
#define F_MODSW_NOTTOSPEC 0x8
|
|
|
|
struct file_cookie {
|
|
int fc_magic;
|
|
struct file * fc_fp;
|
|
int fc_flags;
|
|
};
|
|
|
|
#define FILE_COOKIE_MAGIC 0x6e616773
|
|
|
|
struct mh_s {
|
|
mblk_t mh_mblk;
|
|
dblk_t mh_dblk;
|
|
frtn_t mh_frtn;
|
|
};
|
|
|
|
typedef struct mh_s MH;
|
|
typedef struct mh_s * MHP;
|
|
|
|
struct open_args {
|
|
int (*a_func)(); /* casted to V3/V4 signature */
|
|
queue_t * a_queue;
|
|
dev_t * a_devp;
|
|
int a_fflag;
|
|
int a_sflag;
|
|
cred_t * a_creds;
|
|
};
|
|
|
|
/*
|
|
* Inlined synch operations.
|
|
*/
|
|
|
|
#define sqh_init(sqh) do { \
|
|
(sqh)->sqh_next = (sqh)->sqh_prev = (SQP)(sqh); \
|
|
(sqh)->sqh_flags = SQ_IS_HEAD; \
|
|
lock_alloc((&(sqh)->sqh_lock), LOCK_ALLOC_PIN, PSE_SQH_LOCK, sqh_lock_count++);\
|
|
simple_lock_init(&(sqh)->sqh_lock); \
|
|
(sqh)->sqh_parent = (sqh); \
|
|
(sqh)->sqh_owner = nilp(SQ); \
|
|
(sqh)->sqh_refcnt = 0; \
|
|
} while (0)
|
|
|
|
#define sqh_term(sqh) lock_free(&(sqh)->sqh_lock)
|
|
|
|
#define sq_init(sq) do { \
|
|
bzero((sq), sizeof *(sq)); \
|
|
/* new field to satisfy sleep routines interface */ \
|
|
(sq)->sq_sleeper = EVENT_NULL; \
|
|
/* Other fields set later */ \
|
|
} while (0)
|
|
|
|
#define csq_acquire(sqh, sq) do { \
|
|
SQHP _psqh = (sqh)->sqh_parent; \
|
|
DISABLE_LOCK_DECL \
|
|
LOCK_QUEUE(_psqh); \
|
|
if (!(_psqh->sqh_flags & SQ_INUSE)) { \
|
|
_psqh->sqh_flags |= SQ_INUSE; \
|
|
_psqh->sqh_owner = (sq); \
|
|
_psqh->sqh_refcnt = 1; \
|
|
UNLOCK_QUEUE(_psqh); \
|
|
} else { \
|
|
UNLOCK_QUEUE(_psqh); \
|
|
if (_psqh->sqh_owner == (sq)) \
|
|
_psqh->sqh_refcnt++; \
|
|
else \
|
|
_csq_acquire((sqh), (sq)); \
|
|
} \
|
|
} while (0)
|
|
|
|
#if MACH_ASSERT
|
|
|
|
extern const char csqrel1[], csqrel2[];
|
|
|
|
#define csq_release(sqh) do { \
|
|
if (--(sqh)->sqh_parent->sqh_refcnt <= 0) { \
|
|
SQHP _psqh = (sqh)->sqh_parent; \
|
|
DISABLE_LOCK_DECL \
|
|
if (_psqh->sqh_refcnt < 0) \
|
|
panic(csqrel1); \
|
|
LOCK_QUEUE(_psqh); \
|
|
if (_psqh->sqh_owner == 0 \
|
|
|| !(_psqh->sqh_flags & SQ_INUSE)) \
|
|
panic(csqrel2); \
|
|
_psqh->sqh_flags &= ~SQ_INUSE; \
|
|
_psqh->sqh_owner = 0; \
|
|
UNLOCK_QUEUE(_psqh); \
|
|
if (_psqh->sqh_next != (SQP)_psqh) \
|
|
csq_turnover(_psqh); \
|
|
} \
|
|
} while (0)
|
|
|
|
#else
|
|
|
|
#define csq_release(sqh) do { \
|
|
if (--(sqh)->sqh_parent->sqh_refcnt <= 0) { \
|
|
SQHP _psqh = (sqh)->sqh_parent; \
|
|
DISABLE_LOCK_DECL \
|
|
LOCK_QUEUE(_psqh); \
|
|
_psqh->sqh_flags &= ~SQ_INUSE; \
|
|
_psqh->sqh_owner = 0; \
|
|
UNLOCK_QUEUE(_psqh); \
|
|
if (_psqh->sqh_next != (SQP)_psqh) \
|
|
csq_turnover(_psqh); \
|
|
} \
|
|
} while (0)
|
|
|
|
#endif
|
|
|
|
#endif /* _STR_STREAM_H */
|