DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
SVR5 and SCO OpenServer 5

copyb(D3str)


copyb -- copy a message block

Synopsis

   #include <sys/stream.h>
   #include <sys/ddi.h>
   

mblk_t *copyb(mblk_t *bp);

Description

copyb allocates a new message block, and copies into it the data from the block pointed to by bp.

Arguments


bp
Pointer to start address of the message block from which data are copied.

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

The copyb( ) function allocates a new block by calling the allocb(D3str) function with pri set to BPRI_MED. The new block will be at least as large as the block being copied. All data between the b_rptr and b_wptr members of the message block are copied to the new block, and these ponters in the new block are given the same offset values they had in the original message block.

DDI 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(D3str) after the copy or using allocb_physreq(D3str) and copying manually.

Context

Base or Interrupt.

Synchronization constraints

Does not block.

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

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(D3str) 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(D3str) to copy a header message block (line 25), and dupmsg(D3str) 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) 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(D3str) on line 26). If either is true, we skip the current retransmission record and continue searching the list. Otherwise, we use copyb(D3str) to copy a header message block (line 30), and dupmsg(D3str) 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.

Since we are using itimeout(D3), retransmit runs 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;
   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  }

Hardware applicability

All

Version applicability

ddi: 1, 2, 3, 4, 5, 5mp, 6, 6mp, 7, 7mp, 7.1, 7.1mp, 8, 8mp
oddi: 1, 2, 2mp, 3, 3mp, 4, 4mp, 5, 5mp, 6, 6mp

Differences between versions

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

References

allocb(D3str), allocb_physreq(D3str), copymsg(D3str), msgphysreq(D3str), msgb(D4str)
19 June 2005
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 6 and UnixWare (SVR5) HDK - June 2005