OpenSS7
SS7 for the
Common Man
© Copyright 1997-2007 OpenSS7 Corporation All Rights Reserved.
Last modified: Sat, 01 Nov 2008 10:41:56 GMT
Home TopIndex FirstPrev Next LastMore Download Info FAQ Mail  Home -> Documentation -> Man Pages -> Manpage of PUTQ
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

Manpage of PUTQ

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


PUTQ

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

NAME

putq - put a message on a STREAMS message queue

SYNOPSIS

#include <sys/stream.h>

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

ARGUMENTS

q

the queue on which the place the message.
mp
the message to place on the queue.

INTERFACE

STREAMS.

DESCRIPTION

putq() places the message pointed to by mp on the queue q without invoking the queue's qi_putp(9) procedure.

After placing the message on queue q, putq() adjusts the queue's flags and byte counts appropriately and schedules the queue qi_srvp(9) procedure when necessary.

Message Queueing Priority

STREAMS queues messages based on message queueing priority. There are three priority classes for messages that can be tested with pcmsg(9):

1.High Priority(pcmsg(db_type) != 0 && b_band == 0)
2.Normal Priority(pcmsg(db_type) == 0 && b_band >= 0)
3.Ordinary(pcmsg(db_type) == 0 && b_band == 0)

putq() only examines the message class and priority band of the first message block of a message. If a high priority message is passed to putq() with a non-zero b_band value, b_band is reset to zero (0) before placing the message on the queue. If a normal priority message is passed to putq() with b_band value greater than the number of qband(9) structures associated with the queue, putq() attempts to allocate a new qband(9) structure for each band up to and including the band of the message. (But, see COMPATIBILTY , below.)

The message will always be placed in order in the queue. If the message is a high priority message, it will be placed on the queue immediately following other high priority messages and ahead of normal priority and ordinary messages. If the message is a normal priority message with a non-zero b_band, it is placed after other messages in the queue band. If the message is a ordinary message (with a zero b_band), it is placed after all other messages.

Placing the first message for a queue band onto the queue can result in the allocation of a qband(9) structure to provide flow control accounting for the queue band. Failure to allocate a qband(9) structure can cause putq() to fail. Failure can be avoided by ensuring that a qband(9) structure exists for the band, b_band, using strqget(9) or strqset(9).

Whether a qband(9) exists for a given b_band can be determined by examining the q_nband member of the queue(9) structure. When q_nband>=b_band, a structure exists; when q_nband<b_band, one needs to be allocated.

Flow Control

If a high priority message is placed onto the queue, the queue will always be enabled, as with qenable(9); that is, the queue's qi_srvp(9) procedure will be scheduled if it exists (and is not already scheduled). This is true for appq(9), insq(9), putq(), and putbq(9). Because this is true, a high priority message should never be placed back on a queue by the queue's qi_srvp(9) procedure with putbq(9), otherwise and indefinite loop could result.

putq() is allowed to enable the queue (QNOENB is not set) if the message is a normal priority message, or the QWANTR flag is set indicating that the qi_srvp(9) procedure is ready to read the queue.

If a normal priority message with a non-zero b_band is placed onto an empty queue band, the queue will be enabled, as with enableq(9); that is, the queue's qi_srvp(9) procedure will be scheduled if it exists (and is not already scheduled) and the QNOENB flag has not been set for the queue with noenable(9).

If a ordinary message with a zero b_band is placed onto an empty queue and the QWANTR flag is set for the queue, then the queue will be enabled, as with enableq(9); that is, the queue's qi_srvp(9) procedure will be scheduled if it exists (and is not already scheduled) and the QNOENB flag has not been set for the queue with noenable(9). Another way of putting this is that putq() will enable the queue if the queue is not inhibited with noenable(9) and one of the following conditions also holds true:

*
The driver or module has just been opened for the first time: that is, the queue is empty and has always been empty.
*
getq(9) found no message queued on its last call and no message has been queued since.

When an ordinary message is enqueued by putq(), it will cause the qi_srvp(9) procedure to be scheduled only if the queue was previously empty, and a previous getq(9) call returns NULL (that is, the QWANTR flag is set). If there are messages on the queue, putq() presumes that the qi_srvp(9) procedure is blocked by flow control and the procedure will be rescheduled by STREAMS when the block is removed.

As a general rule for appq(9), insq(9), putq(), and putbq(9), the queue is enabled whenever the message placed on the message queue becomes the first message on the queue, unless the message is a normal priority message and the queue has been disabled with noenable(9), or the message was placed with putbq(9).

USAGE

putq() is intended to be used from the qi_putp(9) procedure in the same queue in which the message will be queued.

The based steps taken by a module qi_putp(9) put procedure, for a module with a qi_srvp(9) service procedure, are as follows:

(1)
Check if the passed 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).
(2)
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.
(3)
If bcanputnext(9) returns true, process the message and pass the message along with putnext(9).
(4)
If bcanputnext(9) returns false, place the message on the message queue with putq().
(5)
Return.

A module should not call putq() directly to pass messages to a neighboring module. putq() may be used as the qi_putp(9) procedure value in either or both of a module's qinit(9) structures. This effectively bypasses any qi_putp(9) procedure processing and uses only the module's qi_srvp(9) procedure(s).

putq() should not be called from outside the STREAMS framework, but only from within a queue qi_putp(9) put procedure. Drivers that need to put messages to their own queues from outside the STREAMS framework (asynchronously) should use put(9) instead.

putq() is generally used in a module qi_putp(9) procedure and is used in conjunction with getq(9) and putbq(9) called from a module's qi_srvp(9) procedure.

Normally, a module's qi_srvp(9) procedure reads message from a queue using getq(9) until there are no messages left on the queue (getq(9) returns NULL), or canput(9) or bcanput(9) fails when attempting to pass a message along the Stream.

When canput(9) or bcanput(9) fails (returns false), the module qi_srvp(9) procedure places the message that it was processing back on its queue using putbq(9). At this point the qi_srvp(9) procedure is blocked. When canput(9) or bcanput(9) failed, it set the QWANTW or QB_WANTW flag on the queue or queue band that was full, indicating to getq(9) and rmvq(9) that back-enabling is required when the queue falls to its low water mark.

When getq(9) fails to retrieve a message from an empty queue, it sets the QWANTR flag on the queue to indicate to putq(), [also appq(9) and insq(9)], that it is blocked awaiting messages.

When getq(9) successfully retrieves a message from the queue, it clears the QWANTR flag on the queue to indicate to putq(), [also appq(9) and insq(9)], that it is no longer blocked awaiting messages for those priority bands.

Because each priority band has separate high- and low-water marks and queue band counts, just because there are messages in the queue does not mean that a qi_srvp(9) procedure is blocked on flow control for all bands.

In general, the condition in which putq() can find the queue, and the causes of the conditions, and the action to be taken by putq() can be summarized as follows:

*
When a high priority message is enqueued, the queue is enabled.
*
When a normal priority (b_band>0) or ordinary (b_band=0) message is enqueued, and it becomes the first message in the queue, the queue is enabled. Because normal priority or ordinary messages are queued in order of arrival, this means that the queue band was empty before the message was enqueued, and that there were no higher priority messages already on the queue. This also means that a getq(9) performed on the queue immediately following the putq() will retrieve the message that was enqueued. It is a good policy to enable the queue when the newly enqueued message can be processed immediately by the qi_srvp(9) procedure.
*
When a normal priority or ordinary message is enqueued, and the QWANTR flag was set by rmvq(9) or getq(9), the queue is enabled. In this case, getq(9) has indicated that the queue is not blocked on flow control but has blocked awaiting the availability of any message. The queue qi_srvp(9) procedure can possibly run successfully on enqueued messages, and should be enabled.

RETURN

Upon success, putq() returns true (1) and places the message pointed to by mp on the queue pointed to by q. Upon failure, putq() returns false (0) and does not alter the passed in queue or message.

ERRORS

When putq() fails, it returns false (0). putq() only fails when a qband(9) structure could not be allocated for a banded message arriving at a first use empty band. putq() always succeeds for high priority and ordinary band zero (0) messages.

CONTEXT

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

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

MP-STREAMS

putq() 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 queue pointer, 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 putq() from a non-STREAMS context, any valid queue pointer, q, can be passed to putq(); 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(9) 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(9) and must be cancelled before qi_qclose(9) returns.)

Otherwise, from outside of STREAMS context, it is still 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[1], it is permissible to call putq() on a Stream that is frozen with freezestr(9), and freezestr(9) can be called from any context. putq() 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

It can be guaranteed that putq() will always succeed, even for banded messages, by calling strqget(9) or strqset(9) to set the high and low water marks and packet sizes for all bands used by the driver or module. It is also possible to examine the q_nband member of the queue(9) structure to determine if a qband(9) structure has been allocated for the given priority band message. If q_nband is greater than or equal to the b_band priority of the message, a qband(9) structure has already been allocated; otherwise, putq() will attempt to allocate all of the qband(9) structures between q_nband and b_band (excluding q_nband and including b_band).

When putq() fails and returns zero (0), it is the callers responsibility to address the disposition of the passed in message, mp. One response would be to free the message using freemsg(9). Because the caller is responsible for the message upon failure, the return value from putq() should alway be examined. Portable STREAMS drivers and modules will always examine the return value from putq() and take responsibility for the passed in message if putq() returns failure.

EXAMPLES

The following example is an abbreviated version of the qi_putp(9) procedure for the loop(4) driver, from the src/drivers/loop.c source file in the streams-0.9.2.4 distribution directory:

 1  int
 2  loop_wput(queue_t *q, mblk_t *mp)
 3  {
 4      struct loop *p = q->q_ptr, *o;
 5      int err;
 6  
 7      switch (mp->b_datap->db_type) {
 8      case M_IOCTL:
 9          /* ... */
10          break;
11      case M_FLUSH:
12          /* ... */
13          break;
14      default:
15          spin_lock_bh(&loop_lock);
16          if (p->other) {
17              if (!q->q_first) {
18                  queue_t *rq;
19  
20                  rq = p->other->rq;
21                  spin_unlock_bh(&loop_lock);
22                  if (rq) {
23                      if (mp->b_datap->db_type >= QPCTL
24                          || bcanputnext(rq, mp->b_band)) {
25                          putnext(rq, mp);
26                          break;
27                      }
28                  }
29              } else
30                  spin_unlock_bh(&loop_lock);
31              putq(q, mp);
32          } else {
33              spin_unlock_bh(&loop_lock);
34              freemsg(mp);
35              putnextctl2(OTHERQ(q), M_ERROR, ENXIO, ENXIO);
36          }
37          break;
38      }
39      return (0);
40  }

At Line 31, putq() is used when there is no receiving queue or the Stream is flow controlled for the message, to place the message on the message queue and await qi_srvp(9) service procedure scheduling.

SEE ALSO

qenable(9), enableq(9), noenable(9), qband(9), strqget(9), strqset(9), freezestr(9), insq(9), putbq(9), getq(9), rmvq(9).

BUGS

putq() has no known bugs.

COMPATIBILITY

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

---
When a banded message (a normal priority message, with a non-zero b_band) is placed on a queue with putq(), putbq(9), insq(9), or appq(9), and a qband(9) structure does not exist for the band corresponding to b_band, putq() 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 putq() 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], putq() tries to allocate a new qband(9) structure for each band up to and including the band of the message."[4]
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(), 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[1].
Portable STREAMS drivers and modules can rely on intermediate band strutures being allocated when a normal priority message is placed on a queue using putq(), 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[1] instead of LiS[5].
---
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®[6] lists qband(9) structures from lowest to highest priority, without gaps (see consideration of allocation above). LiS[5] 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.
---
putq() is not bug for bug compatible with LiS.
Versions of LiS previous to OpenSS7 Release LiS-2.16.18-17 automatically freed the message on failure. Versions of LiS subsequent to OpenSS7 Release LiS-2.16.18-16 do not free the message on failure in accordance with SVR 4.2 and other implementation documentation. The LiS implementation of putq() stil has bugs related to qprocsoff(9) handling in that it fails while qprocsoff(9) is in effect or if the stream is closing.
Portable STREAMS drivers and modules will not use releases of LiS prior to OpenSS7 Release LiS-2.16.18-17.
---
putq() may be called on a stream frozen with freezestr(9).
Solaris®, SUPER-UX® and UnixWare® do not permit putq() to be called on a stream frozen with freezestr(9)[2,7..9]. (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 putq() 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[10]. 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[2].

HISTORY

putq() appears as part of SVR 4.0 STREAMS[4].

putq() first appeared in SVR 3[11].

putq() was described in Dennis Ritchie's original paper[12].

REFERENCES

[1]
streams-0.9.2, Linux Fast-STREAMS (LfS) 0.9.2 Source Code, Brian Bidulock, ed., OpenSS7 Corporation. <http://www.openss7.org/>
[2]
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.
[3]
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.
[4]
SVR 4, UNIX® System V Release 4 STREAMS Programmer's Guide, 1990, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[5]
LIS 2.18, Linux STREAMS (LiS) 2.18.6 Source Code, Brian Bidulock, ed., OpenSS7 Corporation. <http://www.openss7.org/>
[6]
Solaris® 8, Solaris 8 Docmentation, 2001, (Santa Clara, California), Sun Microsystems, Inc., Sun. <http://docs.sun.com/>
[7]
Solaris® 8, STREAMS Programming Guide, August 1999, (Palo Alto, California), Sun Microsystems, Inc., Sun. [Part No: 805-7478-05] <http://docs-pdf.sun.com/>
[8]
SUPER-UX® Release 9.2, SUPER-UX STREAMS Programmers Guide, 1999, NEC Corporation, NEC.
[9]
UnixWare® 7.1.3, UnixWare® 7 STREAMS Programmer's Guide, 2002, (Lindon, Utah), Caldera International, Inc., Caldera. <http://uw713doc.sco.com/>
[10]
SVR 4.2, STREAMS Programmer's Guide, 1992, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[11]
SVR 3, UNIX® System V Release 3 STREAMS Programmer's Guide, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[12]
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
Message Queueing Priority
Flow Control
USAGE
RETURN
ERRORS
CONTEXT
MP-STREAMS
Validity for q
Validity and Exclusion for mp
NOTICES
EXAMPLES
SEE ALSO
BUGS
COMPATIBILITY
CONFORMANCE
HISTORY
REFERENCES
TRADEMARKS
IDENTIFICATION

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