|
|
#include <sys/stream.h> #include <sys/ddi.h>mblk_t *copyb(mblk_t *bp);
On success, copyb returns a pointer to the newly allocated message block containing the copied data. On failure, it returns a NULL pointer.
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.
Driver-defined basic locks, read/write locks, and sleep locks may be held across calls to this function.
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 }
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 }
phys_dmasize
of the
physreq(D4)
structure.
For other versions, there are no guarantees on the memory properties.