OpenSS7
SS7 for the
Common Man
© Copyright 1997-2007 OpenSS7 Corporation All Rights Reserved.
Last modified: Sat, 01 Nov 2008 10:41:55 GMT
Home TopIndex FirstPrev Next LastMore Download Info FAQ Mail  Home -> Documentation -> Man Pages -> Manual Page
Quick Links

Download

SCTP

SIGTRAN

SS7

Hardware

STREAMS

Asterisk

Related

Package

Manual

FAQ

Man Pages

Applications

SS7 Stack

ISDN Stack

SIGTRAN Stack

VoIP Stack

MG Stack

SS7/ISDN Devices

IP Transport

Embedded Systems

OS

Documentation

FAQ

SIGTRAN

Design

Conformance

Performance

References

Man Pages

Manuals

Papers

Home

Overview

Status

Documentation

Resources

About

News

Description: Manual Page

Keywords: ss7 ss7/ip ss7 over ip ss7 mtp ss7 sccp ss7 tcap sigtran mtp sccp tcap openss7 acb56 linux telephony pstn linux telephony linux nebs linux compactpci


PUTBQ

Section: Linux Fast-STREAMS DDI/DKI (9)
Updated: 2008-10-31
Index Return to Main Contents

NAME

putbq - put a message back on a STREAMS message queue

SYNOPSIS

#include <sys/stream.h>

int putbq(queue_t *q, mblk_t *mp);

ARGUMENTS

q

the queue onto which to put back the message.
mp
the message to put back on the queue.

INTERFACE

STREAMS.

DESCRIPTION

putbq() places the message pointed to by mp back onto the queue pointed to by q. When the message is placed back on the queue, it is placed on the head of the queue, rather than the tail of the queue as would result from a call to putq(9). The message is placed in the proper order at the head of the priority, normal or specified band, queue counts are adjusted and queue enabling is performed if the message is a high priority message or if the queue has not been disabled with a call to noenable(9).

putbq() is normally called from within queue qi_srvp(9) procedures to place a message back on the queue subsequent to a call to getq(9) that removes a message which it turns out cannot be processed at the moment due to flow restrictions from testing canput(9) or bcanput(9). When putbq() is executed following getq(9) for the same queue, it is guaranteed to succeed.

Flow Control

putbq() enables the queue q under the following circumstances:

-
the message mp is a high priority message;
-
the QWANTR flag is set.

Because mp was typically removed from the queue with getq(9), the QWANTR flag will be clear (because a message was retrieved). The only event that will cause these flags to become set is if the current or another thread removes a message from the queue with getq(9) or rmvq(9).

Because only one thread can be executing a queue's qi_srvp(9) service procedure at a time, if messages are removed from the message queue only in the queue's qi_srvp(9) service procedure, and putbq() is also only called from the procedure, which is normally the case, QWANTR will never be set when putbq() is called.

So, usually, q is only enabled if a high priority message is placed back on the queue with putbq(). Because normal flow control procedures from the qi_srvp(9) procedure prohibit placing a high priority message back on the queue, properly placing a message back on a queue with putbq() will not result in the queue being enabled.

This is in fitting with the purpose of the putbq() utility which is to suspsend operation of a queue qi_srvp(9) service procedure until the queue is back-enabled by a forward flow controlled queue.

USAGE

putbq() is intended to be used from within a STREAMS driver or module qi_srvp(9) procedure.

The basic steps taken by a module qi_srvp(9) procedure are as follows:

(1)
Remove a message from the queue with getq(9).
(2)
If getq(9) returns NULL, return from the procedure.
(3)
If getq(9) retreives a message, check if the message is a high priority (db_type >= QPCTL) message. If it is, process the message and possibly pass it to the next queue with putnext(9).
(4)
If the message is a normal priority (db_type < QPCTL) message, test if the message can be passed along with bcanputnext(9), for the band b_band.
(5)
If bcanputnext(9) returns true, process the message and pass the message along with putnext(9).
(6)
If bcanputnext(9) returns false, place the message back on the queue with putbq() and return.
(7)
Repeat at step (1).

Queues that have messages placed back with putbq() from the module qi_srvp(9) procedure will not normally be enabled again by putq(9), or insq(9). Therefore, when a message is placed back on a queue with putbq(), the qi_srvp(9) procedure is considered blocked. Some event is required to re-enable the queue when it is possible to resume processing messages.

In the typical flow control case (see Example#1 , below), a back-enable is scheduled by a forward queue when bcanputnext(9) fails; however, this is not the only mechanism possible. Another example (see Example#2 , below), would be when a buffer cannot be allocated to perform processing (i.e., allocb(9) fails), an explicit call to qenable(9) could be scheduled with bufcall(9), and the message placed back on the queue with putbq(). When the buffer can be allocated, the queue will be enabled and another attempt will be made to allocated the buffer necessary for processing.

RETURN

Upon success, putbq() returns true (1) after placing the message mp back on the head of the queue. Upon failure, putbq() returns false (0) and the message pointed to by mp is unaltered. The return value from putbq() should always be examined.

ERRORS

Upon failure, putbq() returns false (0) and the message pointed to by mp is unaltered. It is the caller's responsibility to free mp if the caller so desires.

CONTEXT

putbq() can be called from any context, including process context, module procedures, callouts, callbacks, soft interrupts (tasklets and bottom halves), and interrupt service routines.

putbq() can be called from a context asynchronous to STREAMS, such as an asynchronous callback, tasklet, bottom half, or interrupt service routine.

MP-STREAMS

putbq() is MP-safe; however, the caller is responsible for the validity of the passed in queue and message pointers, and exclusive access to the passed in messages.

Validity for q

The caller is responsible for the validity of the passed in q. q is valid from all procedures synchronous on q, including qi_qopen(9), qi_qclose(9), qi_putp(9), and qi_srvp(9), procedures and synchronous callback functions.

For process context, asynchronous callback functions, soft interrupts (tasklets and bottom halves), and interrupt service routines, that is, when calling putbq() from a non-STREAMS context, any valid queue pointer, q, can be passed to putbq(); however, the caller must ensure that the queue pointer remains valid across the call. In general, q is valid from the moment that qprocson(9) returns until the moment that qprocsoff(9) is called, so, if the non-STREAMS code sections are passed a pointer from q's qi_qopen() procedure and invalidated by its qi_qclose() procedure, validity can be ensured. (This is the case with timeout(9) and bufcall(9) asynchronous callbacks. These callbacks are passed a queue pointer only after qi_qopen and must be cancelled before qi_qclose returns.)

Otherwise, from outside of STREAMS context, it is possible to derive a queue pointer from a validated queue pointer, provided that the Stream is frozen with a call to freezestr(9). Under Linux Fast-STREAMS, it is permissible to call putbq() on a Stream that is frozen with freezestr(9), and freezestr(9) can be called from any context. putbq() takes a recursive freeze lock that can be acquired by the caller when the Stream is frozen. If another thread has the Stream frozen with freezestr(9), the calling processor will spin until the Stream is thawed by the other thread with unfreezestr(9).

Validity and Exclusion for mp

Validity of the mp pointer and exclusive access to the message pointed to by mp is normally assured in the usual ways: If mp was just allocated using allocb(9) or esballoc(9), or, if mp was just removed from a message queue with getq(9) or rmvq(9), then exclusion and validity is assured.

NOTICES

putbq() only fails if a queue band for mp->b_band does not yet exist and the necessary queue band structures could not be allocated. It can be ensured that putbq() will not fail for the same q for which the message was obtained with getq(9). Otherwise, it can be ensured that the queue band exists by calling strqget(9) or strqset(9) for the band in question before calling putbq(). Whether a band is allocated for a queue can also be tested by examining the q_nband member of the queue structure. This member indicates the highest priority allocated band. If the band in question is less than or equal to q_nband then the band has already been allocated.

Care should be taken not to return with putbq() a high priority message taken off of a queue in a qi_srvp(9) procedure with getq(9). This is because placing the high priority message back on the queue will cause the qi_srvp(9) procedure to re-execute at the earliest opportunity resulting in possible indefinite looping.

EXAMPLES

Following are two examples of the use of putbq(). The first is an example of putbq() where enabling of the queue is scheduled by bcanputnext(9). The second is an example of putbq() where enabling of the queue is scheduled by bufcall(9).

Example #1

Following is a stereotypical example of a null module qi_srvp(9) procedure that simply passes messages along to the next queue without processing:

 1  static int
 2  xxxsrv(queue_t *q)
 3  {
 4      mblk_t *mp;
 5  
 6      while ((mp = getq(q))) {
 7          if (mp->b_datap->db_type >= QPCTL)
 8              putnext(q, mp);
 9          else {
10              if (bcanputnext(q, mp->b_band))
11                  putnext(q, mp);
12              else {
13                  putbq(q, mp);
14                  break;
15              }
16          }
17      }
18      return (0);
19  }

Notice that at Line 13, the return value from putbq() is not examined. This is because the message was removed from the queue using getq(9) and it is guaranteed that a band structure exists for the band of the message, and therefore putbq() cannot fail.

Unless another thread intervenes with a call to getq(9) or (more likely) rmvq(9), placing the message back on the queue will not enable the queue. Also, messages enqueued with putq(9) from the qi_putp(9) procedure will not normally enable the queue in this situation. The queue will usually remain blocked on flow control until it is back-enabled by the forward queue that failed bcanput(9).

Example #2

Following is an example of how to handle a buffer allocation failure using bufcall(9) and putbq():

 1  static int
 2  xxxsrv(queue_t *q)
 3  {
 4      mblk_t *mp;
 5  
 6      while ((mp = getq(q))) {
 7          if (mp->b_datap->db_type >= QPCTL)
 8              putnext(q, mp);
 9          else {
10              if (bcanputnext(q, mp->b_band)) {
11                  mblk_t *db;
12  
13                  if (!(db = allocb(64, BPRI_MED))) {
14                      priv_t *p = (priv_t *) q->q_ptr;
15  
16                      putbq(q, mp);
17                      p->bcid = bufcall(64, BPRI_MED,
18                                        (void (*)(long))
19                                        &qenable, (long) q);
20                      break;
21                  }
22                  /* process mp with db */
23                  linkb(mp, db);
24                  putnext(q, mp);
25              } else {
26                  putbq(q, mp);
27                  break;
28              }
29          }
30      }
31      return (0);
32  }

If the allocation using allocb(9) fails at Line 13, then the message is placed back on the queue using putbq() at Line 16, and a buffer call is issued to enable the queue when a buffer becomes available using bufcall(9) at Line 17.

When the buffer callback is called, the queue will be enabled with qenable(9), and the qi_srvp(9) procedure will execute again and attempt to allocate a buffer once more.

SEE ALSO

putq(9), noenable(9), getq(9), canput(9), bcanput(9), getqstr(9), setqstr(9), qprocsoff(9), freezestr(9), unfreezestr(9).

BUGS

putbq() has no known bugs.

COMPATIBILITY

putbq() is compatible with SVR 4.2 MP DDI/DKI[1], and implementations based on SVR 4[2], with the following portability considerations:

---
When a banded message (a priority message, with a non-zero b_band) is placed on a queue with putq(9), putbq(9), insq(9), or appq(9), and a qband(9) structure does not exist for the band corresponding to b_band, putbq() tries to allocate qband(9) structures for all non-existent bands up to and including the band of the message and places the resulting qband(9) structures into a reverse sorted q_bandp list on the queue(9). q_nband is adjusted accordingly and always reflects the highest allocated band.
This is consistent with the description in the SVR 4 STREAMS Programmer's Guide, which states: "If a mesages is passed to putbq() with a b_band value that is greater than the number of qband(9) structures associated with the queue [member q_nband in the queue(9) structure], putbq() tries to allocate a new qband(9) structure for each band up to and including the band of the message."[3]
Solaris® allocates qband(9) structures up to an including b_band, and maintains the q_nband member of the queue(9) structure. It is safe to assume that other UNIX® implementations based on SVR 4 follow SVR 4 as does Solaris®.
LiS allocates qband(9) structures on demand, links them in a sparse array, and will also reuse qband(9) structures that were previously allocated for bands that are currently empty. This is not a good approach because user established band high- and low-water marks will be reset to those of the queue(9) structure when a subsequent message is place on the reused band. Also, it is difficult to predict when appq(9), insq(9), putq(9), putbq(9), will fail as a result of failure to allocate a qband(9) structure. This LiS bug is not perpetuated in Linux Fast-STREAMS.
Portable STREAMS drivers and modules can rely on intermediate band strutures being allocated when a normal priority message is placed on a queue using putbq(), and may examine the q_nband member of the queue(9) structure to determine whether a qband(9) exists for a given band number.
Portable STREAMS drivers and modules will use Linux Fast-STREAMS instead of LiS.
---
putq() orders the qband(9) structures in the list pointed to by the q_bandp member of the queue(9) structure from highest band number to lowest band number. This ensures that higher priority qband(9) structures can be accessed faster than lower priority qband(9) structures. Solaris®[4] lists qband(9) structures from lowest to highest priority, without gaps (see consideration of allocation above). LiS lists qband(9) structures from most recently allocated/reused to least recently allocated/reused. Neither the Solaris® nor the LiS approach is very efficient.
Portable STREAMS drivers and modules will not depend on the ordering of qband(9) structures within the q_bandp list on the queue(9) structure, and, will not access qband(9) or queue(9) members directly, but will use the portable strqget(9) and strqset(9) utilities instead.
---
HP-UX®[5] lists putbq() as a function that can only be passed a queue in the queue pair currently being synchronized within a module procedure. HP-UX®[5] also lists putbq() as a utility that cannot be called from user functions or non-STREAMS code; that is, contexts asynchronous to the Stream containing q.
HP-UX® compatible drivers and modules will not call putbq() from outside of a qinit(9) routine for the queue pair of q.
---
If putbq() is passed an invalid q or mp argument, the result is undefined. Under LiS, putbq() fails if the passed in message pointer mp is NULL; or, the passed in queue pointer q is NULL, points to a structure other than a queue structure, or refers to a queue that is closing or for which qi_putp(9) and qi_srvp(9) procedure processing has been turned off (e.g. with qprocsoff(9)).
Porable STREAMS drivers and modules will not pass NULL or invalid pointers to putbq().
---
putbq() only fails if mp->b_band refers to a non-existent queue band and a queue band structure could not be allocated. When putbq() returns failure, mp is unchanged. This is consistent with SVR 4.2 DDI/DKI, IRIX®, Solaris® and UnixWare® documentation[4, 6, 7].
---
putbq() is not bug for bug compatible with LiS. Under older versions of LiS, regardless of whether putbq() returns success or failure, the message pointed to by mp is placed on the queue pointed to by q or freed, so that the caller to putbq() always loses ownership of the message pointed to by mp upon return from the call. This was inconsistent with SVR 4.2 DDI/DKI, and was an LiS bug. Current versions of LiS do not free the message.
Portable STREAMS drivers and modules will use Linux Fast-STREAMS in place of LiS.
---
putbq() may be called on a stream frozen with freezestr(9), but it is not recommended. putbq() uses a recursive freeze lock permitting it to be called while the Stream is frozen with freezestr(9) by the caller.
SVR 4.2 MP DDI/DKI, Solaris®, SUPER-UX® and UnixWare® do not permit putbq() to be called on a stream frozen with freezestr(9)[1,8..10]. (But strangely, code inspection reveals that OpenSolaris® permits putq() and getq(9) to be called on a stream frozen with freezestr(9).)
Portable STREAMS drivers and modules will not call putbq() on a stream currently frozen by the caller with freezestr(9). (Linux Fast-STREAMS includes an assertion to enforce this in the SMP environment.)
---
All versions of LiS contain the bug that they keep track of message queue counts, q_count, qb_count, in terms of the sum of the absolute sizes of the data buffers referenced by message blocks, (db_lim - db_base), and not the sizes of the message blocks themselves, (b_wptr - b_rptr), which does not conform to SVR 4.2 STREAMS[11]. See msgsize(9). No other implementation has this bug.
Portable STREAMS applications programs, drivers and modules will use Linux Fast-STREAMS instead of LiS.
---
Binary compatibility is not guaranteed.

See STREAMS(9) for additional compatibility information.

CONFORMANCE

SVR 4.2 MP DDI/DKI[1].

HISTORY

putbq() appears as part of SVR 4.0 STREAMS[3].

putbq() first appeared in SVR 3[12].

putbq() was described in Dennis Ritchie's original paper[13].

REFERENCES

[1]
USL DDI/DKI, Device Driver Interface/Driver-Kernel Interface (DDI/DKI) Reference Manual for Intel Processors, 1992, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[2]
SVR 4 DDI/DKI, UNIX® System V Release 4 Device Driver Interface/Driver-Kernel Interface (DDI/DKI) Reference Manual, 1990, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[3]
SVR 4, UNIX® System V Release 4 STREAMS Programmer's Guide, 1990, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[4]
Solaris® 8, Solaris 8 Docmentation, 2001, (Santa Clara, California), Sun Microsystems, Inc., Sun. <http://docs.sun.com/>
[5]
HP-UX STREAMS, STREAMS Programmer's Guide -- HP 9000 and Integrity Server Computer Systems, October 2005, (Palo Alto, California), Hewlett-Packard Development Company L.P., HP. <http://docs.hp.com/>
[6]
IRIX® 6.5.17, IRIX 6.5 Manual Pages, 2003, (Mountainview, California), Silicon Graphics, Inc., SGI Technical Publications. <http://techpubs.sgi.com/>
[7]
UnixWare® 7.1.3, UnixWare 7.1.3 (OpenUnix 8) Documentation, 2002, (Lindon, Utah), Caldera International, Inc., Caldera. <http://uw713doc.sco.com/>
[8]
Solaris® 8, STREAMS Programming Guide, August 1999, (Palo Alto, California), Sun Microsystems, Inc., Sun. [Part No: 805-7478-05] <http://docs-pdf.sun.com/>
[9]
SUPER-UX® Release 9.2, SUPER-UX STREAMS Programmers Guide, 1999, NEC Corporation, NEC.
[10]
UnixWare® 7.1.3, UnixWare® 7 STREAMS Programmer's Guide, 2002, (Lindon, Utah), Caldera International, Inc., Caldera. <http://uw713doc.sco.com/>
[11]
SVR 4.2, STREAMS Programmer's Guide, 1992, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[12]
SVR 3, UNIX® System V Release 3 STREAMS Programmer's Guide, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[13]
A Stream Input-Output System, AT&T Bell Laboratories Technical Journal, Vol. 63, No. 8, October 1984, (New Jersey), D. M. Ritchie, AT&T. pp. 1879-1910.

TRADEMARKS

OpenSS7tm
is a trademark of OpenSS7 Corporation.
Linux®
is a registered trademark of Linus Torvalds.
UNIX®
is a registered trademark of The Open Group.
Solaris®
is a registered trademark of Sun Microsystems.

Other trademarks are the property of their respective owners.

IDENTIFICATION


Linux Fast-STREAMS: Package streams version 0.9.2.4 released 2008-10-31.

Copyright©1997-2008OpenSS7 Corp. All Rights Reserved.
(See roff source for permission notice.)



Index

NAME
SYNOPSIS
ARGUMENTS
INTERFACE
DESCRIPTION
Flow Control
USAGE
RETURN
ERRORS
CONTEXT
MP-STREAMS
Validity for q
Validity and Exclusion for mp
NOTICES
EXAMPLES
Example #1
Example #2
SEE ALSO
BUGS
COMPATIBILITY
CONFORMANCE
HISTORY
REFERENCES
TRADEMARKS
IDENTIFICATION

This document was created by man2html, using the manual pages.
Time: 18:25:29 GMT, May 23, 2013
OpenSS7
SS7 for the
Common Man
Home TopIndex FirstPrev Next LastMore Download Info FAQ Mail  Home -> Documentation -> Man Pages -> Manual Page
Last modified: Sat, 01 Nov 2008 10:41:55 GMT
© Copyright 1997-2007 OpenSS7 Corporation All Rights Reserved.