|
The purpose of this srv(9E)
service routine is to add a header to all M_DATA messages. Service routines must process all messages on
their queues before returning, or arrange to be rescheduled
While there are messages to be processed (line 13), check to see if
it is a high priority message or a normal priority message that can be sent
on (line 14). Normal priority message that cannot be sent are put back on
the message queue (lie 34). If the message was a high priority one, or if
it was normal priority and canputnext(9F)
succeeded, then send all but M_DATA
messages to the next module with putnext(9F)
(line 16).
For M_DATA messages, try
to allocate a buffer large enough to hold the header (line 18). If no such
buffer is available, the service routine must be rescheduled for a time
when a buffer is available. The original message is put back on the queue
(line 20) and bufcall (line 21) is used to attempt the
rescheduling. It will succeed if the rescheduling succeeds, indicating that
qenable will be called subsequently with the argument q
once a buffer of the specified size (sizeof (struct hdr))
becomes available. If it does, qenable(9F)
will put q on the list of queues to have their
service routines called. If bufcall() fails, timeout(9F)
(line 22) is used to try again in about a half second.
If the buffer allocation was successful, initialize the header (lines
25-28), make the message type M_PROTO (line 29), link the M_DATA
message to it (line 30), and pass it on (line 31).
Note that this example ignores the bookkeeping needed to handle bufcall() and timeout(9F) cancellation
for ones that are still outstanding at close time.
|
1 struct hdr {
2 unsigned int h_size;
3 int h_version;
4 };
5
6 void xxxsrv(q)
7 queue_t *q;
8 {
9 mblk_t *bp;
10 mblk_t *mp;
11 struct hdr *hp;
12
13 while ((mp = getq(q)) != NULL) { /* get next message */
14 if (mp->b_datap->db_type >= QPCTL || /* if high priority */
canputnext(q)) { /* normal & can be passed */
15 if (mp->b_datap->db_type != M_DATA)
16 putnext(q, mp); /* send all but M_DATA */
17 else {
18 bp = allocb(sizeof(struct hdr), BPRI_LO);
19 if (bp == NULL) { /* if unsuccessful */
20 putbq(q, mp); /* put it back */
21 if (!bufcall(sizeof(struct hdr), BPRI_LO,
qenable, q)) /* try to reschedule */
22 timeout(qenable, q, drv_usectohz(500000));
23 return (0);
24 }
25 hp = (struct hdr *)bp->b_wptr;
26 hp->h_size = msgdsize(mp); /* initialize header */
27 hp->h_version = 1;
28 bp->b_wptr += sizeof(struct hdr);
29 bp->b_datap->db_type = M_PROTO; /* make M_PROTO */
30 bp->b_cont = mp; /* link it */
31 putnext(q, bp); /* pass it on */
32 }
33 } else { /* normal priority, canputnext failed */
34 putbq(q, mp); /* put back on the message queue */
35 return (0);
36 }
37 }
return (0);
38 }
|
|