| OpenSS7 SS7 for the Common Man | © Copyright 1997-2007 OpenSS7 Corporation All Rights Reserved. Last modified: Sat, 01 Nov 2008 10:41:55 GMT | ||||||||||||||||
| |||||||||||||||||
| Description: 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 compactpciPUTSection: Linux Fast-STREAMS DDI/DKI (9)Updated: 2008-10-31 Index Return to Main Contents NAMEput, puthere, streams_put - invoke the put procedure for a STREAMS driver or module with a STREAMS messageSYNOPSIS#include <sys/stream.h>
ARGUMENTS
INTERFACEDESCRIPTIONput() calls the q->q_info->qi_putp procedure associated with the passed in queue, with the arguments q and mp. As a side-effect, put() will wake up any processes waiting with qwait(9) or qwait_sig(9) on the specified queue. USAGEput() is used by a device, pseudo-device, or multiplexing driver to place a message on one of its own queues: either an upper multiplex read queue or a lower multiplex write queue. put() can be called from outside the STREAMS framework, for example, from an interrupt service procedure. For guidelines on writing module put procedures, see qi_putp(9). RETURNERRORSput() always succeeds. Any error conditions are handled within the invoked queue qi_putp(9) put procedure. CONTEXTput() can be called from any context, including user context, module procedures, callouts, callbacks, soft interrupts (tasklets and bottom halves), and interrupt service routines. MP-STREAMSput() is MP-safe when called from any context; however, the caller is responsible for the validity of the passed in queue pointer, q , across the call, and exclusive access to the passed in message, mp . The validity of either queue in the pair, and either q_next pointer for a queue in the pair, for the queue pointer passed to a module procedure, callout or synchronous callback functions, is guaranteed by Linux Fast-STREAMS. Any queue pointer in the pair passed as an argument to an asynchronous callback function are also valid, providing the driver or module observes the rules for cancellation of asynchronous callbacks on close. Linux Fast-STREAMS also provides that a queue pointer in the pair within whose procedures an asynchronous callback was invoked, and either q_next pointer, are also valid in an asynchronous callback. The driver or module qi_putp(9) procedures invoked must also be MP-safe, either by design or through synchronization [see mp-streams(9)]. Under Linux Fast-STREAMS any qi_putp(9) procedure could be executed concurrently with any queue qi_qopen(9), qi_qclose(9), qi_putp(9), qi_srvp(9) procedure, esbbcall(9), bufcall(9), qbufcall(9), timeout(9), qtimeout(9) callback function, soft interrupt (tasklets or bottom halves), or interrupt service routine. The qi_putp(9) procedure itself must perform its own mutual exclusion on data structures shared across these procedures. Although put(q->q_next) is functionally equivalent to putnext(q), for the put() form, the dereference of the q->q_next pointer is not protected on some implementations of STREAMS for MP architectures: on which q_next may change as a result of a concurrent reconfiguration of the Stream (e.g., an I_PUSH(7) or I_POP(7) streamio(7) operation). For MP operation, portable STREAMS drivers and modules will always call putnext(9) instead of put(q->q_next). For maximum portability and compatibility, put(q->q_next) under Linux Fast-STREAMS is always MP-safe from a module procedure or callout, or synchronous callback function that was passed q, or the queue pair containing q, (and is even safe for an asynchronous callback function passing q or q->q_next that was invoked from a procedure, callout or synchronous callback on q). See mp-streams(9) for general MP-STREAMS considerations. NOTICESIt is the responsibility of a STREAMS driver passing a normal priority message to a driver queue to check for flow control, using bcanput(9) or bcanputnext(9), before passing the message with put() or putnext(9). EXAMPLESExample #1Following is an example of canonical qi_putp(9) procedure processing for drivers or modules:
1 int
2 xxx_put(queue_t *q, mblk_t *mp)
3 {
4 if (pcmsg(mp->b_datap->db_type)
5 || q->q_count == 0) {
6 priv_t p;
7
8 p = q->q_ptr;
9 switch (mp->b_datap->db_type) {
10 case M_FLUSH:
11 {
12 /*
13 * perform canonial M_FLUSH handling without locks
14 */
15 return (0);
16 }
17 case M_DATA:
18 case M_PROTO:
19 case M_PCPROTO:
20 {
21 pl_t pl;
22
23 if ((pl =
24 TRYLOCK(&p->priv_lock,
25 plstr)) == invpl)
26 putq(q, mp);
27 else {
28 /*
29 * process message
30 */
31 UNLOCK(&p->priv_lock, pl);
32 }
33 return (0);
34 }
35 }
36 }
37 putq(q, mp);
38 return (0);
39 }
Note that checking q->q_count in this fashion introduces a race condition between messages arriving at the queue from other concurrent invocations of xxx_put, however, if such concurrent execution can occur, then the message ordering is of no consequence, or can already be disrupted. Note that if the driver or module does not have a qi_srvp(9) procedure, LOCK(9) should be used instead of TRYLOCK(9). Of course, reader writer locks, synchronization levels, or any other non-blocking mutual exclusion mechanism could have been used. Example #2 - put() across a Multiplexing DriverThe following example illustrates the use of put() and bcanput(9) used across a multiplexing driver instead of putnext(9) and bcanputnext(9) that should only be invoked within one of q's procedures (put or service). Following is the lower multiplex read queue put procedure:
1 static int
2 mux_lrput(queue_t *q, mblk_t *mp)
3 {
4 struct mux *mux = q->q_ptr;
5
6 switch (mp->b_datap->db_type) {
7 case M_FLUSH:
8 /* left as an exercise */
9 /* ... */
10 break;
11 default:
12 if (!q->q_first && !(q->q_flag & QSVCBUSY)) {
13 read_lock(&mux_lock);
14 if (mux->other) {
15 queue_t *rq;
16
17 if ((rq = mux->other->rq)
18 && (mp->b_datap->db_type >= QPCTL
19 || bcanput(rq, mp->b_band))) {
20 put(rq, mp);
21 read_unlock(&mux_lock);
22 return (0);
23 }
24 }
25 read_unlock(&mux_lock);
26 }
27 putq(q, mp);
28 break;
29 }
30 return (0);
31 }
Note that at Line 17 through Line 20, bcanput(9) is use to test flow control on the upper multiplexer read queue (that has a service procedure). put() is used to pass the message on the upper multiplexer read qi_putp(9) put procedure. Following is the lower multiplex service procedure:
1 static int
2 mux_lrsrv(queue_t *q)
3 {
4 struct mux *mux = q->q_ptr;
5 queue_t *rq = NULL;
6 mblk_t *mp;
7
8 read_lock(&mux_lock);
9 if (mux->other && (rq = mux->other->rq)) {
10 while ((mp = getq(q))) {
11 if (mp->b_datap->db_type >= QPCTL
12 || bcanput(rq, mp->b_band)) {
13 put(rq, mp);
14 continue;
15 }
16 putbq(q, mp);
17 break;
18 }
19 } else
20 noenable(q);
21 read_unlock(&mux_lock);
22 return (0);
23 }
Note also that at Line 11 through Line 14, bcanput(9) and put() are used again to test and pass messages across the multiplexing driver. The following is the upper multiplex read put procedure:
1 static int
2 mux_urput(queue_t *q, mblk_t *mp)
3 {
4 if (mp->b_datap->db_type >= QPCTL ||
5 (!q->q_first && !(q->q_flag & QSVCBUSY)
6 && bcanputnext(q, mp->b_band))) {
7 putnext(q, mp);
8 return (0);
9 }
10 putq(q, mp);
11 return (0);
12 }
Now, within the upper Stream procedures, sychronous to the upper Stream, the procedure can use the bcanputnext(9) and putnext(9) utilities. Following is the upper multiplex read service procedure:
1 static int
2 mux_ursrv(queue_t *q)
3 {
4 {
5 mblk_t *mp;
6
7 /* first drain the queue */
8 while ((mp = getq(q))) {
9 if (mp->b_datap->db_type >= QPCTL
10 || bcanputnext(q, mp->b_band)) {
11 putnext(q, mp);
12 continue;
13 }
14 putbq(q, mp);
15 return (0);
16 }
17 }
18 {
19 struct mux *mux = q->q_ptr;
20 struct mux *bot;
21 bool found = false;
22
23 /* Find the lower queues feeding this one and
24 enable them. */
25 read_lock(&mux_lock);
26 for (bot = mux_links; bot; bot = bot->next)
27 if (bot->other == mux) {
28 qenable(bot->rq);
29 found = true;
30 }
31 read_unlock(&mux_lock);
32
33 /* echo behaviour otherwise */
34 if (!found)
35 qenable(WR(q));
36
37 return (0);
38 }
39 }
The service procedure can also use bcanputnext(9) and putnext(9). The lower part of the procedure above is used to enable flow control across the multiplexing driver. If the upper read queue service procedure ever runs until the message queue is empty, it will manually enable the lower multiplex read queue. SEE ALSOqi_qopen(9), qi_qclose(9), qprocson(9), qprocsoff(9), freezestr(9), unfreezestr(9), qi_srvp(9), esbbcall(9), bufcall(9), qbufcall(9), timeout(9), qtimeout(9). BUGSCOMPATIBILITYput() is compatible with SVR 4.2 DDI/DKI[1], and implementations based on SVR 4, with the following portability considerations:
See STREAMS(9) for additional compatibility information. CONFORMANCEput(): SVR 4.2 DDI/DKI[1,6]; puthere(): OSF/1® documentation[7, 8]; streams_put(): HP-UX® documentation[9, 10]. HISTORYput() first appeared in SVR 4.0 MP and SVR 4.2 MP[1,11]; puthere() first appeared in OSF/1®; streams_put() first appeared in HP-UX®. 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: 13:04:45 GMT, May 24, 2013 | ||||||||||||||||
| OpenSS7 SS7 for the Common Man |
| ||||||||||||||||
| Last modified: Sat, 01 Nov 2008 10:41:55 GMT © Copyright 1997-2007 OpenSS7 Corporation All Rights Reserved. |