1
0
Files
irix-657m-src/eoe/man/manD/bufcall.d3
2022-09-29 17:59:04 +03:00

180 lines
5.4 KiB
Plaintext

.if n .pH ddi.rm/d3/gen/bufcall @(#)bufcall 43.12 of 12/1/92
.\" Copyright 1992, 1991 UNIX System Laboratories, Inc.
.TH bufcall D3
.IX "\f4bufcall\fP(D3)"
.SH NAME
\f4bufcall\f1 \- call a function when a buffer becomes available
.SH SYNOPSIS
.nf
.na
.ft 4
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/ddi.h>
.sp 0.4
toid_t bufcall(uint_t \f2size\fP, int \f2pri\fP, void (*\f2func\fP)(), long \f2arg\fP);
.ft 1
.ad
.fi
.SS Arguments
.RS 0
.TP .35i
\f2size\f1
Number of bytes in the buffer to be allocated
(from the failed \f4allocb\fP(D3) request).
.TP
\f2pri\f1
Priority of the \f4allocb\f1 allocation request.
.TP
\f2func\f1
Function or driver routine to be called when a buffer becomes available.
.TP
\f2arg\f1
Argument to the function to be called when a buffer becomes available.
.RE
.SH DESCRIPTION
When a buffer allocation request fails,
the function \f4bufcall\f1 can be used to schedule the routine, \f2func\f1,
to be called with the argument, \f2arg\f1, when a buffer of at least
\f2size\fP bytes becomes available.
\f4bufcall\f1 serves, in effect, as a timeout call of indeterminate length.
.SS "Return Values"
On success, \f4bufcall\f1 returns a non-zero value that identifies
the scheduling request.
On failure, \f4bufcall\f1 returns 0.
.SH USAGE
When \f2func\fP runs, all interrupts from STREAMS devices will be blocked.
On multiprocessor systems,
when \f2func\fP runs
all interrupts from STREAMS devices will be blocked
on the processor on which \f2func\fP is running.
\f2func\fP will have no user context and may not call any function that sleeps.
.P
Even when \f2func\f1 is called,
\f4allocb\f1 can still fail if another module or driver
had allocated the memory before \f2func\f1 was able to call \f4allocb\f1.
.P
The \f2pri\fP argument is no longer used but is retained for
compatibility.
.P
The non-zero identifier returned by \f4bufcall\fP
may be passed to \f4unbufcall\f1(D3) to cancel the request.
.SS Level
Base or Interrupt.
.SS "Synchronization Constraints"
Does not sleep.
.P
Driver-defined basic locks, read/write locks, and sleep locks
may be held across calls to this function.
.SS " Example"
The purpose of this service routine [see \f4srv\f1(D2)]
is to add a header to all
\f4M_DATA\f1 messages. We assume only \f4M_DATA\fP messages
are added to its queue.
Service routines must process all messages on their queues before
returning, or arrange to be rescheduled.
.P
While there are messages to be processed (line 19), we check to see if
we can send the message on in the stream.
If not, we put the message back
on the queue (line 21) and return. The STREAMS flow control mechanism
will re-enable us later when messages can be sent.
If \f4canput\f1(D3) succeeded,
we try to allocate a buffer large enough to
hold the header (line 24).
If no buffer is available, the service routine must be
rescheduled later, when a buffer is available.
We put the original message back on the queue (line 26) and use
\f4bufcall\f1 to attempt the rescheduling (lines 27 and 28).
If \f4bufcall\fP succeeds, we set the \f4m_type\fP field in the module's
private data structure to \f4BUFCALL\fP. If \f4bufcall\fP failed,
we use \f4itimeout\fP(D3) to reschedule us instead (line 30). \f4modcall\fP will be
called in about a half second [\f4drv_usectohz\c
(500000)\f1].
When the rescheduling has been done, we return.
.P
When \f4modcall\fP runs, it will set the \f4m_type\fP field to zero, indicating
that there is no outstanding request. Then the queue's service routine is scheduled to run
by calling \f4qenable\fP(D3).
.P
If the buffer allocation is successful, we initialize the header
(lines 37\-39), make the message type \f4M_PROTO\f1 (line 41), link the
\f4M_DATA\f1 message to it (line 42), and pass it on (line 43).
.P
See \f4unbufcall\fP(D3) for the other half of this example.
.ne 4
.P
.nf
.ft 4
.ps 9
.vs -1
1 struct hdr {
2 uint_t h_size;
3 int h_version;
4 };
5 struct mod {
6 long m_id;
7 char m_type;
...
8 };
9 #define TIMEOUT 1
10 #define BUFCALL 2
...
11 modsrv(q) /* assume only M_DATA messages enqueued here */
12 queue_t *q;
13 {
14 mblk_t *bp;
15 mblk_t *mp;
16 struct hdr *hp;
17 struct mod *modp;
.sp 0.4
18 modp = (struct mod *)q->q_ptr;
19 while ((mp = getq(q)) != NULL) {
20 if (!canput(q->q_next)) {
21 putbq(q, mp);
22 return;
23 }
24 bp = allocb(sizeof(struct hdr), BPRI_MED);
25 if (bp == NULL) {
26 putbq(q, mp);
27 modp->m_id = bufcall(sizeof(struct hdr), BPRI_MED,
28 modcall, (long)q);
29 if (modp->m_id == 0) {
30 modp->m_id = itimeout(modcall, (long)q,
31 drv_usectohz(\&500000), plstr);
32 modp->m_type = TIMEOUT;
33 } else {
34 modp->m_type = BUFCALL;
35 }
36 return;
37 }
38 hp = (struct hdr *)bp->b_wptr;
39 hp->h_size = msgdsize(mp);
40 hp->h_version = 1;
41 bp->b_wptr += sizeof(struct hdr);
42 bp->b_datap->db_type = M_PROTO;
43 bp->b_cont = mp;
44 putnext(q, bp);
45 }
46 }
.sp 0.4
47 modcall(q)
48 queue_t *q;
49 {
50 struct mod *modp;
.sp 0.4
51 modp = (struct mod *)q->q_ptr;
52 modp->m_type = 0;
53 qenable(q);
54 }
.ps
.vs
.SH REFERENCES
.na
\f4allocb\fP(D3),
\f4esballoc\fP(D3),
\f4esbbcall\fP(D3),
\f4itimeout\fP(D3),
\f4unbufcall\fP(D3)
.ad