/* @(#)38 1.7.9.4 src/bos/kernel/sys/stream.h, sysxpse, bos72F, f2017_09B2 2/8/17 03:28: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. */ /** Copyright (c) 2000-2005 by Innovative Security Systems, Inc. **/ #ifndef _SYS_STREAM_H #define _SYS_STREAM_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include #ifdef _KERNEL #include #include #include #include /* * Resolution of name conflicts... * * The method is to redefine names with "pse_"+"name". * We can neither change the AT&T STREAMS spec, nor do we want to * change the OS environment. So we have to intercept those occurrences * using the C preprocessor. Because of this, it is imperative that * STREAMS header files be included LAST in files that care. * See function name resolution at end of this file. */ #undef queue #define queue pse_queue #undef queue_t #define queue_t pse_queue_t #endif /* _KERNEL */ /* defines module or driver */ struct streamtab { struct qinit * st_rdinit; /* defines read QUEUE */ struct qinit * st_wrinit; /* defines write QUEUE */ struct qinit * st_muxrinit; /* for multiplexing drivers only */ struct qinit * st_muxwinit; /* ditto */ }; #ifndef MSG_KERNEL_FIELDS #define MSG_KERNEL_FIELDS #endif /* message block */ struct msgb { struct msgb * b_next; /* next message on queue */ struct msgb * b_prev; /* previous message on queue */ struct msgb * b_cont; /* next message block of message */ unsigned char * b_rptr; /* first unread data byte in buffer */ unsigned char * b_wptr; /* first unwritten data byte */ struct datab * b_datap; /* data block */ unsigned char b_band; /* message priority */ unsigned char b_pad1; /* emulation type and 7318 data */ /* 7318 uses the low bit */ /* UW7 compat uses the top bit */ unsigned short b_flag; /* message flags */ long b_pad2; MSG_KERNEL_FIELDS }; typedef struct msgb mblk_t; #define b_emul b_pad1 /* Setup b_emul for UW7 compat */ /* mblk flags */ #define MSGMARK 0x01 /* last byte of message is tagged */ #define MSGNOLOOP 0x02 /* don't pass message to write-side of stream */ #define MSGDELIM 0x04 /* message is delimited */ #define MSGCOMPRESS 0x0100 /* compress like messages as space allows */ #define MSGNOTIFY 0x0200 /* notify when message consumed */ #define MSGPKT 0x0400 /* hack for ptys */ #define MSG64BIT 0x0800 /* 64-bit message flag */ #define MSGIA32BIN 0x1000 /* process is an IA-32 binary */ #define MSGATTR 0x8000 /* message contains security info */ /* data descriptor */ struct datab { union { struct datab * freep; struct free_rtn * frtnp; } db_f; unsigned char * db_base; /* first byte of buffer */ unsigned char * db_lim; /* last byte+1 of buffer */ unsigned char db_ref; /* count of messages pointing to block*/ unsigned char db_type; /* message type */ unsigned char db_iswhat; /* message status */ unsigned int db_size; /* used internally */ caddr_t db_msgaddr; /* used internally */ long db_filler; struct net_secattr *db_secinfop; /* MLS credential */ }; #define db_freep db_f.freep #define db_frtnp db_f.frtnp typedef struct datab dblk_t; #define b_secinfop b_datap->db_secinfop #define MSGB_EYE_SIZE 8 #define MSGB_EYE_CATCHER "pse_msgb" /* message block for checkpoint/restart */ struct cr_msgb { char cr_b_eye_catcher[MSGB_EYE_SIZE]; unsigned int cr_b_totlen; /* total message len not including this header */ unsigned int cr_b_totblk; /* total blocks as in b_cont */ unsigned int cr_db_size; /* size for allocb on restart */ unsigned short cr_b_flag; /* message flags */ unsigned char cr_b_band; /* message priority */ unsigned char cr_db_type; /* message type */ }; typedef struct cr_msgb cr_mblk_t; /* message block header for checkpoint/restart */ struct cr_msgb_hdr { unsigned int cr_h_totlen; /* total len not including this header */ unsigned int cr_h_totmsg; /* total messages as in b_next */ unsigned int cr_h_totblk; /* total blocks as in b_cont */ }; typedef struct cr_msgb_hdr cr_mblk_hdr_t; /* Free return structure for esballoc */ typedef struct free_rtn { void (*free_func)(char *, char *); /* Routine to free buffer */ char * free_arg; /* Parameter to free_func */ } frtn_t; #ifndef QUEUE_KERNEL_FIELDS #define QUEUE_KERNEL_FIELDS #endif struct queue { struct qinit * q_qinfo; /* procedures and limits for queue */ struct msgb * q_first; /* head of message queue */ struct msgb * q_last; /* tail of message queue */ struct queue * q_next; /* next QUEUE in Stream */ struct queue * q_link; /* link to scheduling queue */ caddr_t q_ptr; /* to private data structure */ ulong q_count; /* weighted count of characters on q */ ulong q_flag; /* QUEUE state */ long q_minpsz; /* min packet size accepted */ long q_maxpsz; /* max packet size accepted */ ulong q_hiwat; /* high water mark, for flow control */ ulong q_lowat; /* low water mark */ struct qband * q_bandp; /* band information */ unsigned char q_nband; /* number of bands */ unsigned char q_pad1[3]; /* reserved */ struct queue * q_other; /* pointer to other Q in queue pair */ QUEUE_KERNEL_FIELDS }; typedef struct queue queue_t; /* queue_t flag defines */ #define QREADR 0x1 /* This queue is a read queue */ #define QNOENB 0x2 /* Don't enable in putq */ #define QFULL 0x4 /* The queue is full */ #define QWANTR 0x8 /* The queue should be scheduled in the next putq */ #define QWANTW 0x10 /* The stream should be back enabled when this queue drains */ #define QUSE 0x20 /* The queue is allocated and ready for use */ #define QENAB 0x40 /* The queue is scheduled (on the run queue) */ #define QBACK 0x80 /* The queue has been back enabled */ #define QOLD 0x100 /* Module supports old style opens and closes */ #define QHLIST 0x200 /* The Stream head is doing something with queue (not used by OSF/1) */ #define QFUN 0x400 /* The queue is funneled */ #define QSAFE 0x02000 /* Flag for "safe" callbacks needed */ #define QWELDED 0x04000 /* Flag for welded queues */ #define QNOTTOSPEC 0x08000 /* Service routines not coded to spec. Must be scheduled to run. */ #define QCLOSING 0x10000 /* queue is closing */ #define QINSCHEDULE 0x20000 /* queue is running in scheduler */ #define QMSGSIZE 0x40000 /* message is large than socket buffer hiwat */ struct qband { struct qband * qb_next; /* next band for this queue */ ulong qb_count; /* weighted character count in band */ struct msgb * qb_first; /* head of message queue */ struct msgb * qb_last; /* tail of message queue */ ulong qb_hiwat; /* high water mark */ ulong qb_lowat; /* low water mark */ ulong qb_flag; /* state */ long qb_pad1; /* reserved */ }; typedef struct qband qband_t; #define NODEV (dev_t)(-1) /* qband_t flag defines */ #define QB_FULL 0x1 /* The band is full */ #define QB_WANTW 0x2 /* Back enable when this queue/band drains */ #define QB_BACK 0x4 /* The queue has been back enabled */ /* Cast to these typedefs when qi_qopen|qi_qclose called. */ typedef int (*stropen_V3)(queue_t *, dev_t, int, int); typedef int (*strclose_V3)(queue_t *); typedef int (*stropen_V4)(queue_t *, dev_t *, int, int, cred_t *); typedef int (*strclose_V4)(queue_t *, int, cred_t *); struct qinit { int (*qi_putp)(queue_t *, mblk_t *); int (*qi_srvp)(queue_t *); int (*qi_qopen)(); int (*qi_qclose)(); int (*qi_qadmin)(void); struct module_info * qi_minfo; struct module_stat * qi_mstat; }; struct module_info { unsigned short mi_idnum; /* module ID number */ char * mi_idname; /* module name */ long mi_minpsz; /* min packet size, for developer use */ long mi_maxpsz; /* max packet size, for developer use */ ulong mi_hiwat; /* hi-water mark, for flow control */ ulong mi_lowat; /* lo-water mark, for flow control */ }; /* Used in M_IOCTL mblks to muxes (ioc_cmd I_LINK) */ struct linkblk { queue_t * l_qtop; /* lowest level write queue of upper stream */ queue_t * l_qbot; /* highest level write queue of lower stream */ int l_index; /* system-unique index for lower stream */ long l_pad[5]; }; /* * Structure of M_IOCTL, M_COPYIN, M_COPYOUT and M_IOCDATA messages * * Note that these structures must be interchangeable! * That means: sizes must be identical, and the first fields, * as well as the final private pointer must match. */ typedef union { long l; ulong ul; caddr_t cp; mblk_t * mp; } ioc_pad; struct iocblk { int ioc_cmd; /* ioctl command type */ cred_t * ioc_cr; /* pointer to full credentials */ uint ioc_id; /* ioctl id */ ioc_pad ioc_cnt; /* count of bytes in data field */ int ioc_error; /* error code */ int32long64_t ioc_rval; /* return value */ mblk_t * ioc_private; /* module's private state info */ long ioc_filler[4]; }; #define ioc_count ioc_cnt.ul #define ioc_uid ioc_cr->cr_uid #define ioc_gid ioc_cr->cr_gid struct copyreq { int cq_cmd; /* command type == ioc_cmd */ cred_t * cq_cr; /* pointer to full credentials */ uint cq_id; /* ioctl id == ioc_id */ ioc_pad cq_ad; /* address to copy data to/from */ uint cq_size; /* number of bytes to copy */ int32long64_t cq_flag; /* reserved */ mblk_t * cq_private; /* module's private state info */ long cq_filler[4]; }; #define cq_addr cq_ad.cp #define cq_uid cq_cr->cr_uid #define cq_gid cq_cr->cr_gid #ifdef _KERNEL struct copyreq64 { int cq_cmd; /* command type == ioc_cmd */ cred_t * cq_cr; /* pointer to full credentials */ uint cq_id; /* ioctl id == ioc_id */ ioc_pad cq_ad; /* address to copy data to/from */ uint cq_size; /* number of bytes to copy */ int32long64_t cq_flag; /* reserved */ mblk_t * cq_private; /* module's private state info */ ptr64 cq_addr64; /* 64-bit address to copy data */ long cq_filler[2]; }; #endif /* _KERNEL */ /* structure contained in M_IOCDATA message block */ struct copyresp { int cp_cmd; /* command type == ioc_cmd */ cred_t * cp_cr; /* pointer to full credentials */ uint cp_id; /* ioctl id == ioc_id */ ioc_pad cp_rv; /* 0 = success */ uint cp_pad1; /* reserved */ int32long64_t cp_pad2; /* reserved */ mblk_t * cp_private; /* module's private state info */ long cp_filler[4]; }; #define cp_rval cp_rv.l #define cp_uid cp_cr->cr_uid #define cp_gid cp_cr->cr_gid #define TRANSPARENT (-32768) /* special value for ioc_count! */ /* Message types */ #define QNORM 0 #define M_DATA 0x00 /* Ordinary data */ #define M_PROTO 0x01 /* Internal control info and data */ #define M_BREAK 0x08 /* Request a driver to send a break */ #define M_PASSFP 0x09 /* Used to pass a file pointer */ #define M_SIG 0x0b /* Requests a signal to be sent */ #define M_DELAY 0x0c /* Request a real-time delay */ #define M_CTL 0x0d /* For inter-module communication */ #define M_IOCTL 0x0e /* Used internally for I_STR requests */ #define M_SETOPTS 0x10 /* Alters characteristics of Stream head */ #define M_RSE 0x11 /* Reserved for internal use */ #define M_TTY 0x12 /* Reserved for tty internal use */ /* Priority messages types */ #define QPCTL 0x80 #define M_IOCACK 0x81 /* Positive ack of previous M_IOCTL */ #define M_IOCNAK 0x82 /* Previous M_IOCTL failed */ #define M_PCPROTO 0x83 /* Same as M_PROTO except for priority*/ #define M_PCSIG 0x84 /* Priority signal */ #define M_READ 0x85 /* Reports client read at stream head */ #define M_FLUSH 0x86 /* Requests modules to flush queues */ #define M_STOP 0x87 /* Request drivers to stop output */ #define M_START 0x88 /* Request drivers to start output */ #define M_HANGUP 0x89 /* Driver can no longer produce data */ #define M_ERROR 0x8a /* Reports downstream error condition */ #define M_COPYIN 0x8b /* Module's request to perform copyin */ #define M_COPYOUT 0x8c /* Module's request to perform copyout */ #define M_IOCDATA 0x8d /* Response to M_COPYIN, M_COPYOUT */ #define M_PCRSE 0x8e /* Reserved for internal use */ #define M_STOPI 0x8f /* Request drivers to stop input */ #define M_STARTI 0x90 /* Request drivers to start input */ #define M_HPDATA 0x93 /* OSF-private: high priority data */ /* AIX SPECIFIC follow */ #define M_NOTIFY 0x94 /* Reports result of read at stream head */ #define M_LETSPLAY 0x95 /* Sent up by driver */ #define M_DONTPLAY 0x96 /* Sent down by stream head */ #define M_BACKWASH 0x97 /* Sent down by stream head and modules */ #define M_BACKDONE 0x98 /* End of M_BACKWASH messages */ #define M_PCTTY 0x99 /* Reserved for tty internal use */ #define M_COPYIN64 0x9a /* Module's request to perform 64-bit copyin */ #define M_COPYOUT64 0x9b /* Module's request to perform 64-bit copyout */ #define M_XTIORDREL 0x9c /* Internal msg: wake osrq for T_ORDREL_REQ */ #define M_CKPT 0x9d /* Stream being checkpointed */ #define M_RESTART 0x9e /* Stream being restarted */ #define M_CR_ACK 0x9f /* checkpoint/restart return */ #define FLUSHALL 0x0001 #define FLUSHDATA 0x0000 #define NOERROR (uchar)-1 /* used in M_ERROR messages */ /* structure contained in an M_SETOPTS message block */ struct stroptions { __ulong32_t so_flags; /* options to set */ short so_readopt; /* read option */ ushort so_wroff; /* write offset */ int32long64_t so_minpsz; /* minimum read packet size */ int32long64_t so_maxpsz; /* maximum read packet size */ int32long64_t so_hiwat; /* read queue high-water mark */ int32long64_t so_lowat; /* read queue low-water mark */ unsigned char so_band; /* band for water marks */ }; /* definitions for so_flags field */ #define SO_ALL (~0) /* Update all options */ #define SO_READOPT 0x00000001 /* Set the read mode */ #define SO_WROFF 0x00000002 /* Insert an offset in write M_DATA mblks */ #define SO_MINPSZ 0x00000004 /* Change the min packet size on sth rq */ #define SO_MAXPSZ 0x00000008 /* Change the max packet size on sth rq */ #define SO_HIWAT 0x00000010 /* Change the high water mark on sth rq */ #define SO_LOWAT 0x00000020 /* Change the low water mark */ #define SO_MREADON 0x00000040 /* Request M_READ messages */ #define SO_MREADOFF 0x00000080 /* Don't gen M_READ messages */ #define SO_ISTTY 0x00000100 /* Act as controlling tty */ #define SO_ISNTTY 0x00000200 /* Don't act as controlling tty */ #define SO_NDELON 0x00000400 /* Apply TTY semantics on ONDELAY */ #define SO_NDELOFF 0x00000800 /* Apply STREAMS semantics on ONDELAY */ #define SO_TOSTOP 0x00001000 /* Stop on background writes */ #define SO_TONSTOP 0x00002000 /* Don't stop on background writes */ #define SO_BAND 0x00004000 /* Water marks are for a band */ #define SO_MSGATTR 0x00008000 /* ask sth wq to provide security info */ #define SO_PTY 0x00010000 /* VSU PTY HANGUP mod */ /* Buffer Allocation Priority */ #define BPRI_LO 1 #define BPRI_MED 2 #define BPRI_HI 3 #define BPRI_WAITOK 255 /** Test whether message is a data message */ #define datamsg(type) ((type) == M_DATA || (type) == M_PROTO || \ (type) == M_PCPROTO || (type) == M_DELAY) /** Get pointer to the mate queue */ #define OTHERQ(q) ((q)->q_other) /** Get pointer to the read queue, assumes 'q' is a write queue ptr */ #define RD(q) OTHERQ(q) /** Get pointer to the write queue, assumes 'q' is a read queue ptr */ #define WR(q) OTHERQ(q) #define OPENFAIL (-1) #define CLONEOPEN 0x2 #define MODOPEN 0x1 #define STRMSGSZ 0 #define STRCTLSZ 1024 /* Unused - compat for V.4/V3.2 spec */ #define STRLOFRAC 80 #define STRMEDFRAC 90 #define STRTHRESH 0 /* Used for Streams tunable parameters */ #define NSTREVENT 20 #define STRTURNCNT 15 #define PSETHRESH 85 #define STRLOWTHRESH 90 #define STRMEDTHRESH 95 /* "Infinity" for messages */ #define INFPSZ (-1L) /* Maximum length of module name. */ #define FMNAMESZ 8 /* Enumeration values for strqget and strqset */ typedef enum qfields { QHIWAT = 0, QLOWAT = 1, QMAXPSZ = 2, QMINPSZ = 3, QCOUNT = 4, QFIRST = 5, QLAST = 6, QFLAG = 7, QBAD = 8 } qfields_t; struct wantiosw { int (*w_read)(queue_t *, struct uio *, int); int (*w_write)(queue_t *, struct uio *, int); int (*w_select)(queue_t *, ushort, ushort *, void *); int (*w_reserved1)(); /* Future use. */ int (*w_reserved2)(); /* Future use. */ int (*w_reserved3)(); /* Future use. */ }; struct wantio { Simple_lock w_lock; int w_flags; struct wantiosw *wantiosw; }; /* w_flags bits */ #define W_SIGIO 0x0001 #define W_LOCKME 0x0002 /* Not implemented yet. Wantio modules responsible * for serialization. */ /* M_TTY and M_PCTTY sub-opcodes and stuff */ #define MTTY_VERSION 0x01 #define S_READGONE 0x01 #define S_IOCTLGONE 0x02 #define S_LETSPLAY 0x03 #define S_DONTPLAY 0x04 #define S_BACKWASH 0x05 #define S_BACKDONE 0x06 #define S_DRAINO 0x07 #define S_DRAIN_ACK 0x08 struct ttyblk { ushort tty_ver; /* version number */ ushort tty_len; /* length of valid data */ uint tty_op; /* sub-opcode, listed above */ }; struct drain_blk { ushort mod_id; /* module id of issuing module */ ushort count; /* id of this drain request */ }; /* The V.4 Programmer's guide says these are available... */ #ifndef max #define max(x1,x2) ((x1) >= (x2) ? (x1) : (x2)) #endif #ifndef min #define min(x1,x2) ((x1) <= (x2) ? (x1) : (x2)) #endif #ifdef _KERNEL /* svr4 compatible macros */ #define getmajor major_num #define getminor minor_num #define getemajor major_num #define geteminor minor_num #define makedevice makedevno /* * Name resolution continued from above. */ /* The V.4 guide has a non-portable and wrong prototype for bufcall. */ #undef bufcall typedef void * bufcall_arg_t; typedef void (*bufcall_fcn_t)(bufcall_arg_t); extern int pse_bufcall(uint, int, bufcall_fcn_t,bufcall_arg_t); #define bufcall(a,b,c,d) \ pse_bufcall((a), (b), (bufcall_fcn_t)(c), (bufcall_arg_t)(d)) #undef timeout typedef caddr_t timeout_arg_t; typedef void (*timeout_fcn_t)(timeout_arg_t); extern int32long64_t pse_timeout(timeout_fcn_t, timeout_arg_t, int); #define timeout(a,b,c) pse_timeout((timeout_fcn_t)(a),(timeout_arg_t)(b),c) #undef untimeout extern void pse_untimeout(int32long64_t); #define untimeout pse_untimeout #undef timeoutcf extern int pse_timeout_cf(long); #define timeoutcf pse_timeout_cf #undef sleepx #define sleepx(a, b, c) pse_sleepx((a),(b),(c)) #undef e_sleep #define e_sleep(a, b) pse_sleep((a),(b)) #undef e_sleepl #define e_sleepl(a, b, c) pse_sleepl((a),(b),(c)) #undef e_sleep_thread #define e_sleep_thread(a, b, c) pse_sleep_thread((a),(b),(c)) #undef e_block_thread #define e_block_thread() pse_block_thread() /* MLS macros */ #define SECINFO_DUP( to , from ) \ if (__MLS_KERNEL() && (to) && (from)) { \ if ((from)->b_secinfop) \ ncred_ref((from)->b_secinfop); \ if ((to)->b_secinfop) \ ncred_free((to)->b_secinfop); \ (to)->b_secinfop = (from)->b_secinfop; \ } #define LABELMBLK( blk , ncredp ) \ if (__MLS_KERNEL() && (ncredp) && (blk)) { \ ncred_ref(ncredp); \ if ((blk)->b_secinfop) \ ncred_free((blk)->b_secinfop); \ (blk)->b_secinfop = ncredp; \ } #define MBUF_TO_MBLK_SECINFO( to , from ) \ if (MBUFLABELED(from)) { \ if ((to)->b_secinfop) \ ncred_free((to)->b_secinfop); \ ncred_ref(MBUFSEC(from)); \ (to)->b_secinfop = MBUFSEC(from); \ } #define MBLK_TO_MBUF_SECINFO( to , from ) \ if ((from)->b_secinfop) { \ ncred_ref((from)->b_secinfop); \ if (MBUFLABELED(to)) \ ncred_free(MBUFSEC(to)); \ LABELMBUF((to), (from)->b_secinfop); \ } #ifdef __64BIT_KERNEL /* returns 64-bit queue_t pointer for I_FDINSERT ioctl */ #define fdinsert_q64p(mp, offset) *(queue_t **)(mp->b_rptr + offset) #endif extern int pse_sleep(tid_t *, int32long64_t); extern int pse_sleepl(lock_t *, tid_t *, int32long64_t); extern int pse_sleepx(int32long64_t, int, int32long64_t); extern int pse_sleep_thread(tid_t *, void *, int32long64_t); extern int pse_block_thread(); /* * Other Streams utilities. */ extern int adjmsg(mblk_t *, int); extern mblk_t * allocb(int, uint); extern mblk_t * allocbi(int, int, void (*)(char *, char *), char *, uchar *); extern queue_t * backq(queue_t *); extern int bcanput(queue_t *, unsigned char); extern int canenable(queue_t *); extern int canput(queue_t *); extern mblk_t * copyb(mblk_t *); extern mblk_t * copymsg(mblk_t *); extern mblk_t * dupb(mblk_t *); extern mblk_t * dupmsg(mblk_t *); extern void enableok(queue_t *); extern mblk_t * esballoc(unsigned char *, int, int, frtn_t *); extern void flushband(queue_t *, unsigned char, int); extern void flushq(queue_t *, int); extern void freeb(mblk_t *); extern void freemsg(mblk_t *); extern int (*getadmin(ushort))(void); extern ushort getmid(char *); extern mblk_t * getq(queue_t *); extern int insq(queue_t *, mblk_t *, mblk_t *); extern void linkb(mblk_t *, mblk_t *); extern void mpsprintf(mblk_t *, char *, ...); extern int msgdsize(mblk_t *); extern int msgsize_blks(mblk_t *, struct cr_msgb *); extern int crset_blks(mblk_t *, struct cr_msgb *); extern void msgsize_msgs_blks(mblk_t *, struct cr_msgb_hdr *); extern void noenable(queue_t *); extern int pullupmsg(mblk_t *, int); extern int putbq(queue_t *, mblk_t *); extern int putctl(queue_t *, int); extern int putctl1(queue_t *, int, int); extern int putctl2(queue_t *, int, int, int); extern void puthere(queue_t *, mblk_t *); extern void putnext(queue_t *, mblk_t *); extern int putq(queue_t *, mblk_t *); extern int qenable(queue_t *); extern void qreply(queue_t *, mblk_t *); extern int qsize(queue_t *); extern mblk_t * rmvb(mblk_t *, mblk_t *); extern void rmvq(queue_t *, mblk_t *); extern int strlog(short, short, char, unsigned short, char *, ...); extern int strqget(queue_t *, qfields_t, unsigned char, long *); extern int strqset(queue_t *, qfields_t, unsigned char, long); extern int testb(int, uint); extern void unbufcall(int); extern mblk_t * unlinkb(mblk_t *); extern int wantio(queue_t *q, struct wantio *w); typedef void * weld_arg_t; typedef void (*weld_fcn_t)(weld_arg_t); extern int weldq(queue_t *, queue_t *, queue_t *, queue_t *, weld_fcn_t, weld_arg_t, queue_t *); extern int unweldq(queue_t *, queue_t *, queue_t *, queue_t *, weld_fcn_t, weld_arg_t, queue_t *); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_STREAM_H */