| OpenSS7 SS7 for the Common Man | © Copyright 1997-2007 OpenSS7 Corporation All Rights Reserved. Last modified: Sat, 01 Nov 2008 10:41:56 GMT | ||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||
| Manpage of PUTQDescription: Manual PageKeywords: 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 compactpciPUTQSection: Linux Fast-STREAMS DDI/DKI (9)Updated: 2008-10-31 Index Return to Main Contents NAMEputq - put a message on a STREAMS message queueSYNOPSIS#include <sys/stream.h>
ARGUMENTS
INTERFACEDESCRIPTIONputq() 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 PrioritySTREAMS queues messages based on message queueing priority. There are three priority classes for messages that can be tested with pcmsg(9):
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 ControlIf 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:
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). USAGEputq() 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:
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:
RETURNUpon 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. ERRORSWhen 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. CONTEXTputq() 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-STREAMSputq() 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 qThe 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 mpValidity 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. NOTICESIt 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. EXAMPLESThe 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 ALSOqenable(9), enableq(9), noenable(9), qband(9), strqget(9), strqset(9), freezestr(9), insq(9), putbq(9), getq(9), rmvq(9). BUGSCOMPATIBILITYputq() is compatible with SVR 4.2 MP DDI/DKI[2], and implementations based on SVR 4[3], with the following portability considerations:
See STREAMS(9) for additional compatibility information. CONFORMANCEHISTORYputq() 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
TRADEMARKS
Other trademarks are the property of their respective owners. IDENTIFICATION
Copyright©1997-2008OpenSS7 Corp.
All Rights Reserved.
Index
This document was created by man2html, using the manual pages. Time: 01:42:35 GMT, May 23, 2013 | ||||||||||||||||||||||||||||||||||
| OpenSS7 SS7 for the Common Man |
| ||||||||||||||||||||||||||||||||||
| Last modified: Sat, 01 Nov 2008 10:41:56 GMT © Copyright 1997-2007 OpenSS7 Corporation All Rights Reserved. | |||||||||||||||||||||||||||||||||||