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


PUT

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

NAME

put, puthere, streams_put - invoke the put procedure for a STREAMS driver or module with a STREAMS message

SYNOPSIS

#include <sys/stream.h>

void put(queue_t *q, mblk_t *mp);

ARGUMENTS

q

the queue to which to put the message.
mp
the message to put to the queue.

INTERFACE

STREAMS.

DESCRIPTION

put() 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.

USAGE

put() 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).

RETURN

put() returns void.

ERRORS

put() always succeeds. Any error conditions are handled within the invoked queue qi_putp(9) put procedure.

CONTEXT

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

MP-STREAMS

put() 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.

NOTICES

It 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).

EXAMPLES

Example #1

Following 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 Driver

The 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 ALSO

qi_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).

BUGS

put() has no known bugs.

COMPATIBILITY

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

---
put() called with invalid arguments will have undefined results. LiS fails silently when mp or q is NULL, or q does not reference a valid queue structure, or q->q_info is NULL, or q->q_info->qi_putp is NULL. When LiS fails silently, it frees mp using freemsg(9).
---
put() cannot be invoked while qprocsoff(9) is in effect for q because no other queue has a references to the queue for which qprocsoff(9) has been executed, or for which qprocson(9) has not yet been executed. LiS discards messages passed to lis_safe_putmsg() when qprocsoff(9) has been executed for q. It is invalid to call put() for a queue that has not had qprocson(9) called, or which has called qprocsoff(9), so this difference should not present a problem.
---
put(), putnext(9), qreply(9) will invoke a queue's qi_putp(9) procedure shared and multi-threaded. This is equivalent to Solaris® drivers with the D_MP flag set or with the D_MTPUTSHARED flag set.
---
put() may be called on a Stream frozen with freezestr(9). SVR 4.2 MP DDI/DKI[1], Solaris®[2], SUPER-UX®[3] and UnixWare®[4] do not permit put() to be called on a Stream frozen with freezestr(9). Portable STREAMS drivers and modules should not call put() on a Stream frozen with freezestr(9).
---
Under OSF/1® this function is called puthere().
puthere() is an OSF/1®-specific function and should not be used by portable STREAMS drivers and modules. The more common put() function should be called instead.
---
Under HP-UX® this function is called streams_put().
streams_put() is an HP-UX®-specific function and should not be used by portable STREAMS drivers and modules. The more common put() function should be called instead.
---
Older versions of LiS hold an exclusive nesting queue procedures lock while calling put(). Unfortunately, these locks disable interrupts, meaning that interrupts are disabled while put() executes. LiS lis_safe_putnext(9) and lis_safe_qreply(9) also call this function, meaning that all message passing functions in LiS lock out interrupts until the entire thread of execution completes. LiS drivers and modules calling Linux Fast-STREAMS put() should notice superior interrupt service routine latency and performance. It is normally the case that qi_putp(9) procedures are MP-safe as they normally use only MP-safe queue and message utility functions. Also, most qi_putp(9) procedures are inherently invoked single threaded (from a single-threaded qi_srvp(9) procedure). Lack of locking should not present a problem.
Because LiS also uses this lock for qi_srvp(9) procedures, this means that while the LiS scheduler is running (at kernel thread priority 50), interrupts, timeouts, bottom halves, hi tasklets and soft interrupts are indefinitely postponed. This is not acceptable for soft-real-time performance. Rewrite LiS qi_putp(9) procedures to be MP-safe. LiS behaviour in this regard is not consistent with SVR 4[5].
Portable STREAMS drivers and modules will use Linux Fast-STREAMS instead of LiS.
---
Binary compatibility is not guaranteed.

See STREAMS(9) for additional compatibility information.

CONFORMANCE

put(): SVR 4.2 DDI/DKI[1,6]; puthere(): OSF/1® documentation[7, 8]; streams_put(): HP-UX® documentation[9, 10].

HISTORY

put() 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

[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]
Solaris® 8, STREAMS Programming Guide, August 1999, (Palo Alto, California), Sun Microsystems, Inc., Sun. [Part No: 805-7478-05] <http://docs-pdf.sun.com/>
[3]
SUPER-UX® Release 9.2, SUPER-UX STREAMS Programmers Guide, 1999, NEC Corporation, NEC.
[4]
UnixWare® 7.1.3, UnixWare® 7 STREAMS Programmer's Guide, 2002, (Lindon, Utah), Caldera International, Inc., Caldera. <http://uw713doc.sco.com/>
[5]
SVR 4, UNIX® System V Release 4 STREAMS Programmer's Guide, 1990, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[6]
SVR 4.2, STREAMS Programmer's Guide, 1992, (Englewood Cliffs, New Jersey), AT&T UNIX System Laboratories, Inc., Prentice Hall.
[7]
Digital® UNIX (OSF/1.2), Digital UNIX Documentation Library, 2003, (Palo Alto, California), Digital Equipment Corporation, Hewlett-Packard Company. <http://www.true64unix.compaq.com/docs/>
[8]
Digital® UNIX (OSF/1.2), Digital UNIX: Network Programmers Guide, 1996, (Palo Alto, California), Digital Equipment Corporation, Hewlett-Packard Company. <http://www.true64unix.compaq.com/docs/>
[9]
HP-UX® 11i v2, HP-UX 11i v2 Documentation, 2001, (Palo Alto, California), Hewlett-Packard Company, HP. <http://docs.hp.com/>
[10]
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/>
[11]
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.

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
USAGE
RETURN
ERRORS
CONTEXT
MP-STREAMS
NOTICES
EXAMPLES
Example #1
Example #2 - put() across a Multiplexing Driver
SEE ALSO
BUGS
COMPATIBILITY
CONFORMANCE
HISTORY
REFERENCES
TRADEMARKS
IDENTIFICATION

This document was created by man2html, using the manual pages.
Time: 13:04:45 GMT, May 24, 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.