Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ copyb(D3) — UnixWare 2.01

Media Vault

Software Library

Restoration Projects

Artifacts Sought






       copyb(D3)                                                  copyb(D3)


       NAME
             copyb - copy a message block

       SYNOPSIS
             #include <sys/stream.h>
             #include <sys/ddi.h>
             mblk_t *copyb(mblk_t *bp);

          Arguments
             bp        Pointer to the message block from which data are
                       copied.

       DESCRIPTION
             copyb allocates a new message block, and copies into it the
             data from the block pointed to by bp.  The new block will be
             at least as large as the block being copied.  The b_rptr and
             b_wptr members of the message block pointed to by bp are used
             to determine how many bytes to copy.

          Return Values
             On success, copyb returns a pointer to the newly allocated
             message block containing the copied data.  On failure, it
             returns a NULL pointer.

       USAGE
          Warnings
             Drivers should not assume that the memory allocated for the
             data buffer is usable for DMA operations, nor should drivers
             assume that the memory has any specific physical properties
             such as starting address alignment, physical address range, or
             physical contiguity.  Beginning with ddi version 6, memory
             with specific physical properties can be obtained by using
             msgphysreq(D3) after the copy or using allocb_physreq(D3) and
             copy manually.

          Level
             Base or Interrupt.

          Synchronization Constraints
             Does not sleep.

             Driver-defined basic locks, read/write locks, and sleep locks
             may be held across calls to this function.





                           Copyright 1994 Novell, Inc.               Page 1













      copyb(D3)                                                  copyb(D3)


         Singlethreaded Example
            This example illustrates how copyb can be used during message
            retransmission.  If there are no messages to retransmit, we
            return (line 18).  For each retransmission record in the list,
            we test to see if the downstream queue is full with the
            canput(D3) function (line 21).  If it is full, we skip the
            current retransmission record and continue searching the list.
            If it is not full, we use copyb(D3) to copy a header message
            block (line 25), and dupmsg(D3) to duplicate the data to be
            retransmitted (line 28).  If either operation fails, we clean
            up and break out of the loop.

            Otherwise, we update the new header block with the correct
            destination address (line 34), link the message to be
            retransmitted to it (line 35), and send it downstream (line
            36).  At the end of the list, we reschedule a timeout at the
            next valid interval (line 39) and return.

             1  struct retrns {
             2    mblk_t         *r_mp;       /* message to retransmit */
             3    long            r_address;  /* destination address */
             4    queue_t        *r_outq;     /* output queue */
             5    struct retrns  *r_next;     /* next retransmission */
             6  };
             7  struct protoheader {
             8    long            h_address;  /* destination address */
                  ...
             9  };
            10  mblk_t *header;
            11  struct retrns *rlist;
                ...
            12  retransmit()
            13  {
            14    mblk_t *bp, *mp;
            15    struct retrns *rp;
            16    struct protoheader *php;
            17    if (!rlist)
            18          return;
            19    rp = rlist;
            20    while (rp) {
            21          if (!canput(rp->r_outq->q_next)) {
            22                rp = rp->r_next;
            23                continue;
            24          }
            25          bp = copyb(header);
            26          if (bp == NULL)


                          Copyright 1994 Novell, Inc.               Page 2













       copyb(D3)                                                  copyb(D3)


             27                break;
             28          mp = dupmsg(rp->r_mp);
             29          if (mp == NULL) {
             30                freeb(bp);
             31                break;
             32          }
             33          php = (struct protoheader *)bp->b_rptr;
             34          php->h_address = rp->r_address;
             35          bp->bp_cont = mp;
             36          putnext(rp->r_outq, bp);
             37          rp = rp->r_next;
             38    }
             39    (void) timeout(retransmit, 0, RETRNS_TIME);
             40  }

          Multithreaded Example
             This example illustrates how copyb can be used during message
             retransmission.  If there are no messages to retransmit, we
             return (line 21).  Otherwise, we lock the retransmission list
             (line 23).  For each retransmission record in the list, we
             test to see if either the message has already been
             retransmitted, or if the downstream queue is full (by calling
             canputnext(D3) on line 26).  If either is true, we skip the
             current retransmission record and continue searching the list.
             Otherwise, we use copyb(D3) to copy a header message block
             (line 30), and dupmsg(D3) to duplicate the data to be
             retransmitted (line 32).

             If either operation fails, we clean up and break out of the
             loop.  Otherwise, we update the new header block with the
             correct destination address (line 37), link the message to be
             retransmitted to it (line 38), mark the retransmission record
             as having sent the message (line 39), unlock the
             retransmission list (line 40), and send the message downstream
             (line 41).  Then we go back and lock the list again and start
             searching for more messages to retransmit.

             This continues until we are either at the end of the
             retransmission list, or unable to send a message because of
             allocation failure.  With the list still locked, we clear all
             the flags for sent messages (lines 44 and 45).  Finally, we
             unlock the list lock and reschedule a timeout at the next
             valid interval (line 47) and return.





                           Copyright 1994 Novell, Inc.               Page 3













      copyb(D3)                                                  copyb(D3)


            Since we are using itimeout(D3), retransmit will run at the
            specified processor level, plstr.
             1  struct retrns {
             2    mblk_t            *r_mp;        /* message to retransmit */
             3    long        r_address;    /* destination address */
             4    queue_t           *r_outq;      /* output queue */
             5    struct retrns     *r_next;      /* next retransmission */
             6    uchar_t           r_sent;           /* message sent */
             7  };
             8  struct protoheader {
             9    long        h_address;    /* destination address */
                  ...
            10  };
            11  mblk_t *header;
            12  lock_t *retranslck;
            13  struct retrns *rlist;
                ...
            14  retransmit()
            15  {
            16    mblk_t *bp, *mp;
            17    struct retrns *rp;
            18    struct protoheader *php;
            19    pl_t pl;
            20    if (!rlist)
            21          return;
            22  loop:
            23    pl = LOCK(retranslck, plstr);
            24    rp = rlist;
            25    while (rp) {
            26          if (rp->r_sent || !canputnext(rp->r_outq)) {
            27                rp = rp->r_next;
            28                continue;
            29          }
            30          if ((bp = copyb(header)) == NULL)
            31                break;
            32          if ((mp = dupmsg(rp->r_mp)) == NULL) {
            33                freeb(bp);
            34                break;
            35          }
            36          php = (struct protoheader *)bp->b_rptr;
            37          php->h_address = rp->r_address;
            38          bp->bp_cont = mp;
            39          rp->r_sent = 1;
            40          UNLOCK(retranslck, pl);
            41          putnext(rp->r_outq, bp);
            42          goto loop;


                          Copyright 1994 Novell, Inc.               Page 4













       copyb(D3)                                                  copyb(D3)


             43    }
             44    for (rp = rlist; rp; rp = rp->r_next)
             45          rp->r_sent = 0;
             46    UNLOCK(retranslck, pl);
             47    (void) itimeout(retransmit, 0, RETRNS_TIME, plstr);
             48  }

       REFERENCES
             allocb(D3), allocb_physreq(D3), copymsg(D3), msgphysreq(D3),
             msgb(D4)

       NOTICES
          Portability
             All processors

          Applicability
             ddi: 1, 2, 3, 4, 5, 5mp, 6, 6mp, 7, 7mp

             In versions 1, 2, 3, 4, 5, and 5mp, the memory for the data
             buffer returned by copyb will be DMA-able; that is, it will
             satisfy worst-case DMA-ability requirements on systems with
             restricted DMA and will be physically contiguous; see
             phys_dmasize of physreq(D4).  For other versions, there are no
             guarantees on the memory properties.
























                           Copyright 1994 Novell, Inc.               Page 5








Typewritten Software • bear@typewritten.org • Edmonds, WA 98026