1bufcall(9F) Kernel Functions for Drivers bufcall(9F)
2
3
4
6 bufcall - call a function when a buffer becomes available
7
9 #include <sys/types.h>
10 #include <sys/stream.h>
11
12
13
14 bufcall_id_t bufcall(size_t size, uint_t pri, void *funcvoid *arg,
15 void *arg);
16
17
19 Architecture independent level 1 (DDI/DKI).
20
22 size Number of bytes required for the buffer.
23
24
25 pri Priority of the allocb(9F) allocation request (not used).
26
27
28 func Function or driver routine to be called when a buffer becomes
29 available.
30
31
32 arg Argument to the function to be called when a buffer becomes
33 available.
34
35
37 The bufcall() function serves as a timeout(9F) call of indeterminate
38 length. When a buffer allocation request fails, bufcall() can be used
39 to schedule the routine func, to be called with the argument arg when a
40 buffer becomes available. func may call allocb() or it may do something
41 else.
42
44 If successful, bufcall() returns a bufcall ID that can be used in a
45 call to unbufcall() to cancel the request. If the bufcall() scheduling
46 fails, func is never called and 0 is returned.
47
49 The bufcall() function can be called from user, interrupt, or kernel
50 context.
51
53 Example 1 Calling a function when a buffer becomes available:
54
55
56 The purpose of this srv(9E) service routine is to add a header to all
57 M_DATA messages. Service routines must process all messages on their
58 queues before returning, or arrange to be rescheduled
59
60
61
62 While there are messages to be processed (line 13), check to see if it
63 is a high priority message or a normal priority message that can be
64 sent on (line 14). Normal priority message that cannot be sent are put
65 back on the message queue (line 34). If the message was a high priority
66 one, or if it was normal priority and canputnext(9F) succeeded, then
67 send all but M_DATA messages to the next module with putnext(9F) (line
68 16).
69
70
71
72 For M_DATA messages, try to allocate a buffer large enough to hold the
73 header (line 18). If no such buffer is available, the service routine
74 must be rescheduled for a time when a buffer is available. The original
75 message is put back on the queue (line 20) and bufcall (line 21) is
76 used to attempt the rescheduling. It will succeed if the rescheduling
77 succeeds, indicating that qenable will be called subsequently with the
78 argument q once a buffer of the specified size (sizeof (struct hdr))
79 becomes available. If it does, qenable(9F) will put q on the list of
80 queues to have their service routines called. If bufcall() fails, time‐
81 out(9F) (line 22) is used to try again in about a half second.
82
83
84
85 If the buffer allocation was successful, initialize the header (lines
86 25-28), make the message type M_PROTO (line 29), link the M_DATA mes‐
87 sage to it (line 30), and pass it on (line 31).
88
89
90
91 Note that this example ignores the bookkeeping needed to handle buf‐
92 call() and timeout(9F) cancellation for ones that are still outstanding
93 at close time.
94
95
96 1 struct hdr {
97 2 unsigned int h_size;
98 3 int h_version;
99 4 };
100 5
101 6 void xxxsrv(q)
102 7 queue_t *q;
103 8 {
104 9 mblk_t *bp;
105 10 mblk_t *mp;
106 11 struct hdr *hp;
107 12
108 13 while ((mp = getq(q)) != NULL) { /* get next message */
109 14 if (mp->b_datap->db_type >= QPCTL || /* if high priority */
110 canputnext(q)) { /* normal & can be passed */
111 15 if (mp->b_datap->db_type != M_DATA)
112 16 putnext(q, mp); /* send all but M_DATA */
113 17 else {
114 18 bp = allocb(sizeof(struct hdr), BPRI_LO);
115 19 if (bp == NULL) { /* if unsuccessful */
116 20 putbq(q, mp); /* put it back */
117 21 if (!bufcall(sizeof(struct hdr), BPRI_LO,
118 qenable, q)) /* try to reschedule */
119 22 timeout(qenable, q, drv_usectohz(500000));
120 23 return (0);
121 24 }
122 25 hp = (struct hdr *)bp->b_wptr;
123 26 hp->h_size = msgdsize(mp); /* initialize header */
124 27 hp->h_version = 1;
125 28 bp->b_wptr += sizeof(struct hdr);
126 29 bp->b_datap->db_type = M_PROTO;/* make M_PROTO */
127 30 bp->b_cont = mp; /* link it */
128 31 putnext(q, bp); /* pass it on */
129 32 }
130 33 } else { /* normal priority, canputnext failed */
131 34 putbq(q, mp); /* put back on the message queue */
132 35 return (0);
133 36 }
134 37 }
135 return (0);
136 38 }
137
138
140 srv(9E), allocb(9F), canputnext(9F), esballoc(9F), esbbcall(9F), put‐
141 next(9F), qenable(9F), testb(9F), timeout(9F), unbufcall(9F)
142
143
144 Writing Device Drivers
145
146
147 STREAMS Programming Guide
148
150 Even when func is called by bufcall(), allocb(9F) can fail if another
151 module or driver had allocated the memory before func was able to call
152 allocb(9F).
153
154
155
156SunOS 5.11 16 Jan 2006 bufcall(9F)