1bufcall(9F)              Kernel Functions for Drivers              bufcall(9F)
2
3
4

NAME

6       bufcall - call a function when a buffer becomes available
7

SYNOPSIS

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

INTERFACE LEVEL

19       Architecture independent level 1 (DDI/DKI).
20

PARAMETERS

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

DESCRIPTION

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

RETURN VALUES

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

CONTEXT

49       The  bufcall()  function  can be called from user, interrupt, or kernel
50       context.
51

EXAMPLES

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

SEE ALSO

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

WARNINGS

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)
Impressum