'\"!  pic | mmdoc
'\"macro stdmacro
.if n .pH ddi_dki.dupb @(#)dupb	40.8 of 12/19/89
.\" Copyright 1989 AT&T
.de IX
.ie '\\n(.z'' .tm .Index: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9	\\n%
.el \\!.IX \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
..
.nr X
.if \nX=0 .ds x} dupb D3DK "STREAMS" "DDI/DKI" "\&"
.if \nX=1 .ds x} dupb D3DK "STREAMS" "DDI/DKI"
.if \nX=2 .ds x} dupb D3DK "" "\&"
.if \nX=3 .ds x} dupb "" "" "\&"
.TH \*(x}
.IX "\f4dupb\fP(D3DK)"
.IX "STREAMS message blocks"
.IX "message block descriptor"
.SH NAME
\f4dupb\f1 \- duplicate a message block descriptor
.SH SYNOPSIS 
.nf
.na
\f4#include <sys/stream.h>
.sp 0.5
mblk_t *dupb(mblk_t *\f2bp\f4);\f1
.ad
.fi
.SH ARGUMENTS
.RS 0n 10
.IP "\f2*bp\f1" 10n
Pointer to the message block to be duplicated.
\f4mblk_t\f1 is an instance of the \f4msgb\f1(D4DK) structure.
.RE
.SH DESCRIPTION
\f4dupb\f1 creates a new \f4mblk_t\f1 structure to reference the message
block pointed to by \f2bp\f1.  Unlike \f4copyb\f1(D3DK), \f4dupb\f1
does not copy
the information in the data block, but creates a new structure to point to it.
.P
.IX "\f4msgb\fP(D4DK)"
The following figure shows how the \f4db_ref\f1 field of the \f4dblk_t\f1 structure
has been changed from \f41\f1 to \f42\f1, 
reflecting the increase in the number of
references to the data block.  The new \f4mblk_t\f1 contains the same
information as the first.
Note that \f4b_rptr\f1 and \f4b_wptr\f1 are copied from \f2bp\f1, and
that \f4db_ref\f1 is incremented.
.IX "\f4datab\fP(D4DK)"
.nf
.PS
scale=100
define m0 |
[ box invis ht 24 wid 1 with .sw at 0,0
line -> from 0,0 to 0,24 
] |

define m1 |
[ box invis ht 62 wid 56 with .sw at 0,0
line  from 0,42 to 56,42 dotted
line  from 0,22 to 56,22 dotted
box ht 62 wid 56 with .nw at 0,62 
] |

define m2 |
[ box invis ht 62 wid 86 with .sw at 0,0
box ht 62 wid 86 with .nw at 0,62 
] |

define m3 |
[ box invis ht 62 wid 64 with .sw at 0,0
box ht 62 wid 64 with .nw at 0,62 
"\f4\s8\&b_datap\f1\s0" at 28,47
"\f1\s8\&\f1\s0" at 8,43 ljust
"\f1\s8\&\f1\s0" at 8,33 ljust
"\f4\s8\&b_rptr\f1\s0" at 26,21
"\f4\s8\&b_wptr\f1\s0" at 26,9
] |

box invis ht 242 wid 442 with .sw at 0,0
line  from 64,154 to 120,154 
line -> from 120,154 to 120,178 
line -> from 136,204 to 136,122 
line  from 64,116 to 68,116 
line  from 68,116 to 68,82 
line -> from 68,82 to 94,82 
line  from 64,126 to 80,126 
line  from 80,126 to 80,102 
line -> from 80,102 to 94,102 
m1 with .nw at 296,98
m1 with .nw at 94,122
m0 with .nw at 306,178
line -> from 326,206 to 326,98 
line  from 292,154 to 306,154 
"\f4\s9\&nbp=dupb(bp);\f1\s0" at 150,-7 ljust
line  from 180,242 to 180,16 
line  from 180,16 to 440,16 
line  from 180,16 to 0,16 
"\fH\s8\&Before\f1\s0" at 78,23
"\fH\s8\&After\f1\s0" at 326,23
"\f4\s8\&db_base\f1\s0" at 312,211
"\f4\s8\&db_ref (2)\f1\s0" at 320,227
m2 with .nw at 280,240
box ht 62 wid 86 with .nw at 82,240 
"\f4\s8\&db_base\f1\s0" at 114,211
"\f4\s8\&db_ref (1)\f1\s0" at 122,227
"\f4\s8\&bp\f1\s0" at 228,181 ljust
"\f1\s8\&\f1\s0" at 236,137 ljust
"\f1\s8\&\f1\s0" at 236,147 ljust
m3 with .nw at 364,168
m3 with .nw at 228,168
m3 with .nw at 0,168
line -> from 208,58 to 296,58 
line  from 208,126 to 208,58 
"\f4\s8\&nbp\f1\s0" at 416,181
line  from 228,126 to 208,126 
line -> from 216,78 to 296,78 
line  from 216,118 to 216,78 
line  from 228,118 to 216,118 
line  from 428,118 to 434,118 
line -> from 442,58 to 354,58 
line  from 442,126 to 442,58 
line  from 428,126 to 442,126 
line -> from 434,78 to 354,78 
line  from 434,118 to 434,78 
"\f1\s8\&\f1\s0" at 374,137 ljust
"\f1\s8\&\f1\s0" at 374,147 ljust
line -> from 346,154 to 346,178 
line  from 364,154 to 346,154 
"\f4\s8\&bp\f1\s0" at 0,181 ljust
.PE
.fi
.SH "RETURN VALUE" 
If successful, \f4dupb\f1 returns a pointer to the new message block.
Otherwise, it returns a \f4NULL\f1 pointer.
.SH LEVEL
Base or Interrupt
.SH "SEE ALSO"
.na
\f4copyb\f1(D3DK)
.ad
.SH EXAMPLE 
.IX "\f4canput\fP(D3DK), example"
.IX "\f4dupb\fP(D3DK), example"
.IX "\f4putnext\fP(D3DK), example"
.IX "\f4getq\fP(D3DK), example"
.IX "\f4putbq\fP(D3DK), example"
.IX "\f4dupb\fP(D3DK), example"
.IX "\f4timeout\fP(D3DK), example"
.IX "\f4qenable\fP(D3DK), example"
.IX "\f4linkb\fP(D3DK), example"
.IX "\f4queue\fP(D4DK), example"
.P
This \f4srv\f1(D3DK) (service) routine adds a header to 
all \f4M_DATA\f1 messages
before passing them along.  The message block for the header
was allocated elsewhere.  For each message on the queue,
if it is a priority message, pass it along immediately (lines 9\-10).
Otherwise, if it is anything other than an \f4M_DATA\f1 message (line 11),
and if it can be sent along (line 12), then do so (line 13).
Otherwise, put
the message back on the queue and return (lines 15\-16).
For all \f4M_DATA\f1
messages, first check to see if the stream is flow-controlled (line 19).
If it is, put the message back on the queue and return (line 22); 
if it is not, the header block is duplicated (line 20).
If \f4dupb\f1
fails, the service routine is rescheduled in one tenth of a
second (\f4HZ/10\f1) with \f4timeout\f1 and then we return (lines 23\-24).
.ig
Paul, In previous sentence, return what????
..
If \f4dupb\f1
succeeds, link the \f4M_DATA\f1 message to it (line 26) 
and pass it along (line 27).
\f4dupb\f1 can be used here instead of \f4copyb\f1(D3DK)
because the contents of the header block are not changed.
.P
.ne 4
.P
.nf
.ft 4
.ps 7
 1  xxxsrv(q)
 2      queue_t *q;
 3  {
 4	mblk_t *mp;
 5 	mblk_t *bp;
 6	extern mblk_t *hdr;
 7
 8	while ((mp = getq(q)) != NULL) {
 9		if (mp->b_datap->db_type >= QPCTL) {
10			putnext(q, mp);
11		} else if (mp->b_datap->db_type != M_DATA) {
12			if (canput(q->q_next))
13				putnext(q, mp);
14			else {
15				putbq(q, mp);
16				return;
17			}
18		} else {	/* M_DATA */
19			if (canput(q->q_next)) {
20				bp = dupb(hdr);
21				if (bp == NULL) {
22					putbq(q, mp);
23					timeout(qenable, (long)q, HZ/10);
24					return;
25				}
26				linkb(bp, mp);
27				putnext(q, bp);
28			} else {
29				putbq(q, mp);
30				return;
31			}
32		}
33	}
34  }
.ps
.ft 1
.fi
.IX "message (STREAMS), block"
