DUPB(9F)                Kernel Functions for Drivers                DUPB(9F)
NAME
       dupb - duplicate a message block descriptor
SYNOPSIS
       #include <sys/stream.h>       
mblk_t *dupb(
mblk_t *bp);
INTERFACE LEVEL
       Architecture independent level 1 (DDI/DKI).
DESCRIPTION
       dupb() creates a new 
mblk_t structure (see 
msgb(9S)) to reference the
       message block pointed to by 
bp.
       Unlike 
copyb(9F), 
dupb() does not copy the information in the 
dblk_t       structure (see 
datab(9S)), but creates a new 
mblk_t structure to
       point to it. The reference count in the 
dblk_t structure (
db_ref) is
       incremented.  The new 
mblk_t structure contains the same information
       as the original.  Note that 
b_rptr and 
b_wptr are copied from the 
bp.
       Printed copy or docs.sun.com shows a figure that shows a new mblk_t
       structure created, with the original and new bp both pointing to the
       dblk_t structure, and db_ref incremented by one
PARAMETERS
       bp              Pointer to the message block to be duplicated. 
mblk_t is an
              instance of the 
msgb(9S) structure.
RETURN VALUES
       If successful, 
dupb() returns a pointer to the new message block. A       
NULL pointer is returned if 
dupb() cannot allocate a new message
       block descriptor or if the 
db_ref field of the data block structure
       (see 
datab(9S)) has reached a maximum value (
255).
CONTEXT
       dupb() can be called from user, kernel, or interrupt context.
EXAMPLES
       Example 1: Using dupb()
       This 
srv(9E) (service) routine adds a header to all 
M_DATA messages
       before passing them along.  
dupb is used instead of 
copyb(9F) because
       the contents of the header block are not changed.
       For each message on the queue, if it is a priority message, pass it
       along immediately (lines 10-11). Otherwise, if it is anything other
       than an 
M_DATA message (line 12), and if it can be sent along (line
       13), then do so (line 14). Otherwise, put the message back on the
       queue and return (lines 16-17). For all 
M_DATA messages, first check
       to see if the stream is flow-controlled (line 20). If it is, put the
       message back on the queue and return (lines 37-38).  If it is not,
       the header block is duplicated (line 21).       
dupb() can fail either due to lack of resources or because the
       message block has already been duplicated 255 times.  In order to
       handle the latter case, the example calls 
copyb(9F) (line 22).  If       
copyb(9F) fails, it is due to buffer allocation failure.  In this
       case, 
qbufcall(9F) is used to initiate a callback (lines 30-31) if
       one is not already pending (lines 26-27).
       The callback function, 
xxxcallback(), clears the recorded       
qbufcall(9F) callback id and schedules the service procedure (lines
       49-50).  Note that the close routine, 
xxxclose(), must cancel any
       outstanding 
qbufcall(9F) callback requests (lines 58-59).
       If 
dupb() or 
copyb(9F) succeed, link the 
M_DATA message to the new
       message block (line 34) and pass it along (line 35).
                1  xxxsrv(q)
               2      queue_t *q;
               3  {
               4   struct xx *xx = (struct xx *)q->q_ptr;
               5   mblk_t *mp;
               6   mblk_t *bp;
               7   extern mblk_t *hdr;
               8
               9   while ((mp = getq(q)) != NULL) {
              10        if (mp->b_datap->db_type >= QPCTL) {
              11             putnext(q, mp);
              12        } else if (mp->b_datap->db_type != M_DATA) {
              13             if (canputnext(q))
              14                  putnext(q, mp);
              15             else {
              16                  putbq(q, mp);
              17                  return;
              18             }
              19        } else {  /* M_DATA */
              20             if (canputnext(q)) {
              21                  if ((bp = dupb(hdr)) == NULL)
              22                       bp = copyb(hdr);
              23                  if (bp == NULL) {
              24                       size_t size = msgdsize(mp);
              25                       putbq(q, mp);
              26                       if (xx->xx_qbufcall_id) {
              27                            /* qbufcall pending */
              28                            return;
              29                       }
              30                       xx->xx_qbufcall_id = qbufcall(q, size,
              31                            BPRI_MED, xxxcallback, (intptr_t)q);
              32                       return;
              33                  }
              34                  linkb(bp, mp);
              35                  putnext(q, bp);
              36             } else {
              37                  putbq(q, mp);
              38                  return;
              39             }
              40        }
              41   }
              42  }
              43   void
              44   xxxcallback(q)
              45        queue_t *q;
              46   {
              47        struct xx *xx = (struct xx *)q->q_ptr;
              48
              49        xx->xx_qbufcall_id = 0;
              50        qenable(q);
              51   }
              52   xxxclose(q, cflag, crp)
              53        queue_t *q;
              54        int  cflag;
              55        cred_t *crp;
              56   {
              57        struct xx *xx = (struct xx *)q->q_ptr;
                        ...
              58        if (xx->xx_qbufcall_id)
              59             qunbufcall(q, xx->xx_qbufcall_id);
                        ...
              60   }
SEE ALSO
       srv(9E), 
copyb(9F), 
qbufcall(9F), 
datab(9S), 
msgb(9S)       Writing Device Drivers STREAMS Programming Guide                                June 20, 2021                       DUPB(9F)