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