'\"macro stdmacro
.if n .pH ddi_dki.testb @(#)testb	40.6 of 10/10/89
.\" Copyright 1989 AT&T
.de IX
.ie '\\n(.z'' .tm .Index: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9	\\n%
.el \\!.IX \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
..
.nr X
.if \nX=0 .ds x} testb D3DK "STREAMS" "DDI/DKI" "\&"
.if \nX=1 .ds x} testb D3DK "STREAMS" "DDI/DKI"
.if \nX=2 .ds x} testb D3DK "" "\&"
.if \nX=3 .ds x} testb "" "" "\&"
.TH \*(x}
.IX "\f4testb\fP(D3DK)"
.SH NAME
\f4testb\f1 \- check for an available buffer
.SH SYNOPSIS
.nf
.na
\f4#include <sys/stream.h>
.sp 0.5
int testb(int\f2 size, \f4int \f2pri\f4);\f1
.ad
.fi
.SH ARGUMENTS
.RS 0n 10
.IP "\f2size\f1" 10n
Size of the requested buffer.
.IP "\f2pri\f1" 10n
Priority of the allocb request.
.RE
.SH DESCRIPTION
\f4testb\f1 checks to see if an \f4allocb\f1(D3DK) call is likely to succeed
if a buffer of \f2size\f1 bytes at priority \f2pri\f1 is requested.
Even if \f4testb\f1 returns successfully,
the call to \f4allocb\f1 can fail.
.SH RETURN VALUE
Returns \f41\f1 if a buffer of the 
requested size is available, and \f40\f1
if one is not.
.SH LEVEL
Base or Interrupt
.SH SEE ALSO
\f2BCI Driver Development Guide\f1, Chapter 7, ``STREAMS''
.P
.na
\f4allocb\f1(D3DK) ,
\f4bufcall\f1(D3DK)
.ad
.SH EXAMPLE
.IX "\f4timeout\fP(D3DK), example"
.IX "\f4srv\fP(D2DK), example"
.IX "\f4putbq\fP(D3DK), example"
.IX "\f4testb\fP(D3DK), example"
.IX "\f4qenable\fP(D3DK), example"
.P
In a \f4srv\f1(D2DK) (service) routine,
if \f4copymsg\f1(D3DK) fails (line 6), the message
is put back on the queue (line 7) and a routine, \f4tryagain\f1, is
scheduled to be run in one tenth of a second (\f4HZ/10\f1).
Then the service routine returns.
.P
When the \f4timeout\f1(D3DK)
function runs, if there is no message on the front of the
queue, it just returns.  Otherwise, for each message
block in the first message, check to see if an allocation
would succeed.  If the number of message blocks equals
the number we can allocate, then enable the service procedure.
Otherwise, reschedule \f4tryagain\f1 to run again in another tenth
of a second.  Note that \f4tryagain\f1 is merely an approximation.
Its accounting may be faulty.  Consider the case of a message
comprised of two 1024-byte message blocks.  If there is
only one free 1024-byte message block and no free 2048-byte
message blocks, then \f4testb\f1 will still succeed twice.  If
no message blocks are freed of these sizes before the service
procedure runs again, then the \f4copymsg\f1(D3DK) will still fail.
The reason \f4testb\f1 is used here is because it is significantly
faster than calling \f4copymsg\f1.  We must minimize the amount
of time spent in a \f4timeout\f1 routine.
.ne 4
.P
.nf
.ft 4
.ps 7
 1  xxxsrv(q)
 2      queue_t *q;
 3  {
 4	mblk_t *mp;
 5	mblk_t *nmp;
        . . .
 6	if ((nmp = copymsg(mp)) == NULL) {
 7		putbq(q, mp);
 8		timeout(tryagain, (long)q, HZ/10);
 9		return;
10	}
	. . .
11  }
12
13  tryagain(q)
14      queue_t *q;
15  {
16	register int can_alloc = 0;
17	register int num_blks = 0;
18	register mblk_t *mp;
19
20	if (!q->q_first)
21		return;
22	for (mp = q->q_first; mp; mp = mp->b_cont) {
23		num_blks++;
24		can_alloc += testb((mp->b_datap->db_lim -
25		    mp->b_datap->db_base), BPRI_MED);
26	}
27	if (num_blks == can_alloc)
28		qenable(q);
29	else
30		timeout(tryagain, (long)q, HZ/10);
31  }
.ps
.ft 1
.fi
.P
.FG "testb \- check for buffer"
