Annotation of coherent/f/usr/include/kernel/strmlib.h, revision 1.1.1.1

1.1       root        1: #ifndef __KERNEL_STRMLIB_H__
                      2: #define __KERNEL_STRMLIB_H__
                      3: 
                      4: /*
                      5:  * This ^^^^^^^^^^^^^^^^^ symbol is used in the DDI/DKI header <sys/ddi.h> to
                      6:  * determine which #undef directives it is required to perform, on the basis
                      7:  * that it should avoid touching namespaces unless they have been reserved
                      8:  * by the inclusion of a header which reserves such classes of names.
                      9:  */
                     10: 
                     11: /*
                     12:  * This file contains definitions that are be used for the implementation of
                     13:  * the STREAMS standard library routines and scheduling code. Some details
                     14:  * of the interfaces between STREAMS and the rest of the system will also
                     15:  * be dealt with here so as to insulate the STREAMS implementation from the
                     16:  * details of that interface.
                     17:  *
                     18:  * Note that as the contents of this header are for private, system internal
                     19:  * use only, names do not begin with underscores.
                     20:  */
                     21: 
                     22: /*
                     23:  *-IMPORTS:
                     24:  *     <common/ccompat.h>
                     25:  *             __EXTERN_C_BEGIN__
                     26:  *             __EXTERN_C_END__
                     27:  *             __PROTO ()
                     28:  *     <common/xdebug.h>
                     29:  *             __LOCAL__
                     30:  *     <common/__size.h>
                     31:  *             __size_t
                     32:  *     <common/__clock.h>
                     33:  *             __clock_t
                     34:  *     <common/__pid.h>
                     35:  *             __pid_t
                     36:  *     <kernel/st_alloc.h>
                     37:  *             _ST_HEAP_CONTROL
                     38:  *     <kernel/defer.h>
                     39:  *             defer_int_any ()
                     40:  *     <sys/ksynch.h>
                     41:  *             lock_t
                     42:  *             sv_t
                     43:  *     <sys/uio.h>
                     44:  *             uio_t
                     45:  */
                     46: 
                     47: #include <common/ccompat.h>
                     48: #include <common/xdebug.h>
                     49: #include <common/__size.h>
                     50: #include <common/__clock.h>
                     51: #include <common/__pid.h>
                     52: #include <kernel/st_alloc.h>
                     53: #include <kernel/defer.h>
                     54: #include <sys/inline.h>
                     55: #include <sys/ksynch.h>
                     56: #include <sys/uio.h>
                     57: 
                     58: #include <common/_stream.h>
                     59: #include <kernel/ddi_lock.h>
                     60: #include <kernel/ddi_glob.h>
                     61: 
                     62: /*
                     63:  * In order to be able to declare prototypes that refer to structures that are
                     64:  * declared in other headers, we supply incomplete declarations at top-level
                     65:  * to avoid some scoping problems.
                     66:  */
                     67: 
                     68: struct stroptions;
                     69: struct strbuf;
                     70: 
                     71: 
                     72: /*
                     73:  * In onder for freezestr () to work as defined in the Multiprocessor DDI/DKI,
                     74:  * it cannot simply be implemented in terms of the high-level locking
                     75:  * operations defined in <sys/ksynch.h> (the reason being that it is specified
                     76:  * as raising the processor priority level, whereas the "pl" parameter to the
                     77:  * high-level locking functions is specified as setting the level, with a
                     78:  * caution that it not cause the level to be lowered).
                     79:  *
                     80:  * Stream queue freezing cannot really be implemented in terms of high-level
                     81:  * basic locks because of the hierarchy mechanism; the relative priority of
                     82:  * stream head locks is determined by relative position in a stream so that
                     83:  * following the "q_next" member yields increasing (virtual) hierarchy values,
                     84:  * with the additional constraint that a given context may only hold a lock on
                     85:  * one side of a stream at a time.
                     86:  */
                     87: 
                     88: #define        SFREEZE_INIT(q)         ((void) ATOMIC_CLEAR_UCHAR ((q)->q_locked))
                     89: #define        SFREEZE_DESTROY(q)      ((void) 0)
                     90: #define        SFREEZE_LOCK(q,name)    TEST_AND_SET_LOCK ((q)->q_locked, plstr, \
                     91:                                                   (name))
                     92: #define        SFREEZE_UNLOCK(q,pl)    (ATOMIC_CLEAR_UCHAR ((q)->q_locked), \
                     93:                                 (void) splx (pl))
                     94: #define        SFREEZE_ASSERT_FROZEN(q) ASSERT (ATOMIC_FETCH_UCHAR ((q)->q_locked))
                     95: 
                     96: 
                     97: /*
                     98:  * The implementation of allocb () and freeb () deals in terms of "triples"
                     99:  * consisting of an mblk_t, a dblk_t, and the actual data being managed.
                    100:  * (Of course, under esballoc () the data belongs to another subsystem, but
                    101:  * such a double should also be managed by the same system).
                    102:  *
                    103:  * Be aware that changing the definition of any of these things may
                    104:  * invalidate assumptions made by the code in allocb (), freeb (), dupb ()
                    105:  * and esballoc ().
                    106:  */
                    107: 
                    108: /*
                    109:  * Various ways to map between the components of a triple.
                    110:  */
                    111: 
                    112: #define        MB_TO_DB(mp)            ((dblk_t *) (mp + 1))
                    113: #define        DB_TO_MB(db)            (((mblk_t *) db) - 1)
                    114: #define        DB_TO_DATA(db)          ((unsigned char *) (db + 1))
                    115: #define        DATA_TO_DB(d)           (((dblk_t *) d)) - 1)
                    116: 
                    117: 
                    118: /*
                    119:  * Some useful predicates for determining whether various items are actually
                    120:  * parts of triples or not, since there are exceptional cases where the
                    121:  * individual elements of a triple have been scattered to the four winds.
                    122:  *
                    123:  * Note that the SET_MB_TRIPLE () and SET_MB_FREE () exist as a pair, since
                    124:  * they only relate to message blocks that are part of a triple.
                    125:  * SET_MB_TRIPLE () is used when a message block is instantiated, and
                    126:  * SET_MB_FREE () is used when a message block is deallocated but the rest
                    127:  * of the triple is still in use.
                    128:  */
                    129: 
                    130: #define        IS_DB_USER_DATA(db)     (db->db_base != DB_TO_DATA (db))
                    131:                                                /*
                    132:                                                 * Test to see whether the
                    133:                                                 * data referenced by this
                    134:                                                 * block is user-controlled.
                    135:                                                 */
                    136: 
                    137: #define        IS_TRIPLE_TOGETHER(mp)  (mp->b_datap == MB_TO_DB (mp))
                    138:                                                /*
                    139:                                                 * Test to see whether the
                    140:                                                 * data block referenced by
                    141:                                                 * this message block forms
                    142:                                                 * part of the same triple.
                    143:                                                 */
                    144: 
                    145: #define        SET_MB_TRIPLE(mp)       (void) ((mp)->b_flags =\
                    146:                                 ((mp)->b_flags | MSGTRIPLE) & ~ MSGFREE)
                    147:                                                /*
                    148:                                                 * Mark the message block as
                    149:                                                 * part of a triple.
                    150:                                                 */
                    151: 
                    152: #define        IS_MB_TRIPLE(mp)        (((mp)->b_flags & MSGTRIPLE) != 0)
                    153:                                                /*
                    154:                                                 * Test whether the message
                    155:                                                 * block is part of a triple
                    156:                                                 * or is a floating block.
                    157:                                                 */
                    158: 
                    159: #define        SET_MB_FREE(mp)         (void) ((mp)->b_flags |= MSGFREE)
                    160:                                                /*
                    161:                                                 * Indicate that the message
                    162:                                                 * block is no longer in
                    163:                                                 * use. Only for message
                    164:                                                 * blocks in triples.
                    165:                                                 */
                    166: 
                    167: #define        IS_MB_FREE(mp)          ((mp->b_flags & MSGFREE) != 0)
                    168:                                                /*
                    169:                                                 * Test whether the message
                    170:                                                 * block is free or not.
                    171:                                                 */
                    172: 
                    173: /*
                    174:  * STREAMS Local extension: scheduling
                    175:  */
                    176: 
                    177: /*
                    178:  * The methods used in the multiplexing examples in the STREAMS Programmer's
                    179:  * Guide for System V Release 2 are quite inefficient. The following general
                    180:  * STREAMS queue scheduling structures and routines were defined in a visible
                    181:  * manner since
                    182:  *
                    183:  *   (i) It served to better-document the way in which queues are serviced
                    184:  *      within this STREAMS implementation,
                    185:  *
                    186:  *  (ii) Multiplexing drivers (and device drivers which multiplex several
                    187:  *      minor numbers on a single I/O bus, such as an Ethernet or SCSI
                    188:  *      driver) need effcient mechanisms for managing multiple request
                    189:  *      channels,
                    190:  *
                    191:  * (iii) It allows drivers to leverage the multiprocessor locking that is
                    192:  *      built into these primitives.
                    193:  *
                    194:  * Note that allowing drivers access to this facility causes a significant
                    195:  * departure from the standard version of STREAMS, but that driver use of the
                    196:  * macros and data structures below permits other implementations.
                    197:  *
                    198:  * As this system is used internally by this STREAMS implementation, it can
                    199:  * use the "q_link" member of a queue to hold a link to the next STREAM on
                    200:  * a schedule. In addition, some "q_flag" bits can be used to control
                    201:  * whether or not a queue is currently threaded on any schedule. A portable
                    202:  * implementation that does not depend on any reserved parts of STREAMS
                    203:  * data structures may not use these fields, and so may operate under a
                    204:  * different set of constraints. However, since in this case the drivers and
                    205:  * STREAMS itself share common scheduling code, the following restrictions
                    206:  * must be observed:
                    207:  *
                    208:  *   (i) A queue may be requested to be scheduled more than once with no
                    209:  *      effect. If a queue is requested to be scheduled on different
                    210:  *      schedules, then this is probably an error, most likely to occur
                    211:  *      if you define both a STREAMS service routine and a schedule for
                    212:  *      a driver queue; this should not be done under the common scheme.
                    213:  *
                    214:  *  (ii) A queue which has noenable () set on it will still be scheduled.
                    215:  *      The manner in which qenable ()/noenable () work has no bearing on
                    216:  *      this mechanism.
                    217:  *
                    218:  * (iii) Schedules should only be created or destroyed with the schedule
                    219:  *      allocation/deallocation routines in order to guarantee that the
                    220:  *      schedule is multi-processor addressable and is the correct size for
                    221:  *      the selected run-time environment.
                    222:  *
                    223:  *  (iv) When a driver is closed, the queue must not be on any schedule in
                    224:  *      order to prevent list corruption and the dire effects that can
                    225:  *      result from such corruption. A portable implementation of scheduling
                    226:  *      has no way to do this automatically for the driver since the
                    227:  *      close () call is managed by STREAMS.
                    228:  *
                    229:  * Note that in this common implementation, conditions (i), (iii), and (iv)
                    230:  * can be checked by the scheduling system if compiled such that debugging
                    231:  * code is inserted.
                    232:  */
                    233: 
                    234: /*
                    235:  * STREAMS scheduler private per-schedule global data structure.
                    236:  */
                    237: 
                    238: struct __streams_schedule {
                    239:        queue_t       * ss_head;        /* head of list of scheduled queues */
                    240:        queue_t       * ss_tail;        /* tail of list of scheduled queues */
                    241: 
                    242:        lock_t        * ss_locked;      /* lock for schedule */
                    243: };
                    244: 
                    245: 
                    246: extern lkinfo_t        __stream_schedule_lkinfo;
                    247: 
                    248: #define        SCHLOCK_INIT(s,flag) \
                    249:        ((s)->ss_locked = LOCK_ALLOC (stream_schedule_hierarchy, plstr, \
                    250:                                      & __stream_schedule_lkinfo, (flag)))
                    251: 
                    252: #define        SCHLOCK_DESTROY(s)      LOCK_DEALLOC ((s)->ss_locked)
                    253: 
                    254: #define        SCHLOCK_LOCK(s,n)       LOCK ((s)->ss_locked, plstr)
                    255: 
                    256: #define        SCHLOCK_UNLOCK(s,p)     UNLOCK ((s)->ss_locked, p)
                    257: 
                    258: #define        SCHLOCK_ASSERT_LOCKED(s) \
                    259:                ASSERT (TRYLOCK ((s)->ss_locked, plstr) == invpl)
                    260: 
                    261: #define SCHED_INIT(s,flag)     ((s)->ss_head = (s)->ss_tail = NULL, \
                    262:                                 SCHLOCK_INIT (s, flag))
                    263: 
                    264: 
                    265: /*
                    266:  * I use these everywhere that I know which queue side I've got. These
                    267:  * macros duplicate the old-style RD () and WR () functionality, which has
                    268:  * been changed along the path from System V Release 3.2 to System V Release
                    269:  * 4 Multi-Processor. When compiling under the DDI/DKI, these macros are also
                    270:  * converted to functions.
                    271:  */
                    272: 
                    273: #define W(q)           ((q) + 1)
                    274: #define R(q)           ((q) - 1)
                    275: 
                    276: 
                    277: /*
                    278:  * A utility function, for use with STRMEM_ALLOC (), to calculate the size
                    279:  * required for a message triple with "n" bytes of associated data buffer.
                    280:  */
                    281: 
                    282: #define        MSGB_SIZE(n)    ((n) + sizeof (mblk_t) + sizeof (dblk_t))
                    283: 
                    284: 
                    285: /*
                    286:  * The following data type is used to hold registration information for the
                    287:  * SIGPOLL signal. Every process that registers for SIGPOLL signals allocates
                    288:  * one of these structures and threads it on the stream head.
                    289:  */
                    290: 
                    291: typedef struct sigpoll sigpoll_t;
                    292: 
                    293: 
                    294: /*
                    295:  * The following is the internal structure (an "event cell" in STREAMS)
                    296:  * used by the bufcall ()/esbbcall () mechanism to record the necessary
                    297:  * information for calling the user back.
                    298:  *
                    299:  * Note that the real System V bufcall ()/esbbcall () takes a a pointer to
                    300:  * a function with undefined parameters, yet also accepts a parameter which
                    301:  * it will then pass on to the callback. The only way to implement this at
                    302:  * all portably is to use some version of the ISO <stdarg.h> mechanism to
                    303:  * allow bufcall () to take any argument in it's "natural" form and then
                    304:  * pass a maximum-sized chunk of stack into the callback in order to capture
                    305:  * all of the information that the client wanted to pass.
                    306:  *
                    307:  * Of course, doing this is opening a wide door to all kinds of problems,
                    308:  * since while there are some sleazy ways to restrict the size of the extra
                    309:  * argument to something reasonable, there is no way that we can make sure
                    310:  * that the shapes of the argument and the callback parameter really do
                    311:  * match (eg, the callback takes a long but bufcall () is given an int).
                    312:  *
                    313:  * Of course, this is all no worse than the situation AT&T have under the
                    314:  * DDI/DKI, where bufcall () is required to take the callback parameter as
                    315:  * a "long" and clients assume that pointers have the same shape as longs
                    316:  * (if you look at the example in bufcall (D3DK) that is exactly what A&T
                    317:  * seem to be suggesting - blech).
                    318:  *
                    319:  * There is no entirely satisfactory way to get around this evil in plain C,
                    320:  * although we can get at least a partial solution through supplying a range
                    321:  * of supplementary definitions that (at least in an ISO environment) ensure
                    322:  * that the function argument types and argument types will be coerced to
                    323:  * something reasonable.
                    324:  *
                    325:  * Event management is made a little more complex by the availability of the
                    326:  * unbufcall () procedure, which requires us to assign a numeric ID code to
                    327:  * each event cell. It would be nice if this ID code also included some kind
                    328:  * of generation field, and mapped instantly to the desired value.
                    329:  *
                    330:  * Note that this is exactly the same problem faced by the timeout () routine
                    331:  * in implementing untimeout (), and there are numerous possible solutions,
                    332:  * each of which maximizes some desirable property at the cost of losing some
                    333:  * other property.
                    334:  */
                    335: 
                    336: #define        _TOID_MEMBER    1
                    337: 
                    338: typedef void (* se_funcptr_t)  __PROTO ((long _arg));
                    339: 
                    340: typedef struct __stream_event sevent_t;
                    341: 
                    342: struct __stream_event {
                    343:        sevent_t      * se_next;        /* next event in chain */
                    344:        sevent_t      * se_prev;        /* previous event in chain */
                    345:        long            se_arg;         /* argument for function */
                    346:        se_funcptr_t    se_func;        /* function to call */
                    347:        unsigned int    se_size;        /* optional size information */
                    348: #if _TOID_MEMBER
                    349:        toid_t          se_id;          /* timeout id for item */
                    350: #endif
                    351: };
                    352: 
                    353: 
                    354: /*
                    355:  * Of course, we have to thread the above events on a list. We'll create a
                    356:  * structure for this to abstract the details of the locking scheme we'll use
                    357:  * for maintaining the consistency of the event lists.
                    358:  *
                    359:  * We store a generator for the timeout ID codes in the list header so that
                    360:  * the ID generation step can be protected by the same lock as the list
                    361:  * manipulation code. This means that at initialisation time each list header
                    362:  * should have the initial ID code set to its number and that the increment
                    363:  * value used to step between codes is one greater than the total number of
                    364:  * list headers (so that code 0 never appears).
                    365:  *
                    366:  * We have a wide range of possible policies for managing event cells. We need
                    367:  * to get some performance data on each to make a final decision.
                    368:  */
                    369: 
                    370: #define        _FIFO_BUFCALL   1
                    371: 
                    372: typedef struct __stream_event_list selist_t;
                    373: 
                    374: struct __stream_event_list {
                    375:        lock_t        * sl_locked;
                    376:        sevent_t      * sl_head;
                    377: #if _FIFO_BUFCALL
                    378:        sevent_t      * sl_tail;
                    379: #endif
                    380: #if _TOID_MEMBER
                    381:        toid_t          sl_id;
                    382: #endif
                    383: };
                    384: 
                    385: 
                    386: extern lkinfo_t        __stream_event_lkinfo;
                    387: 
                    388: #define        SELIST_INIT(s,flag) \
                    389:        ((s)->sl_head = NULL, \
                    390:         (s)->sl_locked = LOCK_ALLOC (stream_event_hierarchy, plstr, \
                    391:                                      & __stream_event_lkinfo, (flag)))
                    392: 
                    393: #define SELIST_DESTROY(s)      LOCK_DEALLOC ((s)->sl_locked)
                    394: 
                    395: #define        SELIST_LOCK(s)          LOCK ((s)->sl_locked, plstr)
                    396: 
                    397: #define        SELIST_UNLOCK(s,pl)     UNLOCK ((s)->sl_locked, (pl))
                    398: 
                    399: #define        SELIST_ASSERT_LOCKED(s) \
                    400:                ASSERT (TRYLOCK ((s)->sl_locked, plstr) == invpl)
                    401: 
                    402: 
                    403: /*
                    404:  * Some handy requirements for timeout ID generation. We have to define these
                    405:  * numbers such that each list above generates a non-overlapping sequence that
                    406:  * overflows into the same sequence, eg.
                    407:  *     1, k + 1, 2k + 1, ... ik + 1, 1, ...
                    408:  *     2, k + 2, 2k + 2, ... ik + 2, 2, ...
                    409:  *
                    410:  * Since each list generates a distinct and identifiable sequence we can map
                    411:  * from the ID to the list in one step, which somewhat ameliorates the cost
                    412:  * of having to search the list to find the given event.
                    413:  */
                    414: 
                    415: #define        TOID_INCREMENT          (N_PRI_LEVELS + 1)
                    416: #define        TOID_MODULUS            (TOID_MAX - TOID_MAX % TOID_INCREMENT)
                    417: #define        TOID_TO_PRI(id)         ((id) % TOID_INCREMENT - 1)
                    418: 
                    419: 
                    420: /*
                    421:  * Watermark control structures:
                    422:  *
                    423:  * We record here the amount of memory held by each allocation band and the
                    424:  * maximum amount we will permit it to hold. In addition, we record a thread
                    425:  * of structures used by bufcall () and esbbcall () to record information
                    426:  * for callbacks to drivers when memory becomes available.
                    427:  */
                    428: /*
                    429:  * A note on bufcall ()/esbbcall () structures;
                    430:  *
                    431:  * I am not able to conceive of a comprehensive strategy for dealing with
                    432:  * these things that works well under all circumstances. For now, it seems
                    433:  * that keeping a few around in preallocated event cells is a good idea for
                    434:  * when we run out of memory. However, as long as possible the system will
                    435:  * always attempt to satisfy a request for an event cell with a newly
                    436:  * allocated cell, since we expect the usual reason for being unable to
                    437:  * satisfy a request is that memory is merely fragmented rather than fully
                    438:  * occupied.
                    439:  *
                    440:  * Of course, allocating bufcall cells within the heap may increase the
                    441:  * level of fragmentation - which is why we prefer to allocate them from
                    442:  * the "long-term" heap (and indeed, why we have two heaps at all).
                    443:  */
                    444: 
                    445: #define        N_PRI_LEVELS            3       /*
                    446:                                         * Number of buffer priority levels
                    447:                                         */
                    448: #define MAP_PRI_LEVEL(p)       p       /*
                    449:                                         * Map from BPRI_xxx to index.
                    450:                                         */
                    451: 
                    452: /* #define SPLIT_STREAMS_MEMORY */     /*
                    453:                                         * Control whether there are separate
                    454:                                         * arenas for messages and other
                    455:                                         * allocations.
                    456:                                         */
                    457: 
                    458: /*
                    459:  * We keep several lists of stream heads according to the category of the
                    460:  * stream; device, pipe, and possibly FIFO. Various general operations require
                    461:  * iterating over several of the lists, and so we define an array of list
                    462:  * head pointers to simplify things since we don't have the C++ "pointer to
                    463:  * member" types and operations available.
                    464:  */
                    465: 
                    466: typedef        struct __stream_head shead_t;
                    467: 
                    468: typedef enum slist_id {
                    469:        DEV_SLIST,
                    470:        PIPE_SLIST,
                    471:        SLIST_MAX
                    472: } slist_id_t;
                    473: 
                    474: typedef        int             muxid_t;
                    475: 
                    476: 
                    477: /*
                    478:  * This structure grew to its present form before the <kernel/ddi_glob.h>
                    479:  * header took shape. Most of it should eventually be moved there, with
                    480:  * appropriate thought given to what should be fixed and what should be
                    481:  * variable allocations.
                    482:  */
                    483: 
                    484: 
                    485: struct streams_mem {
                    486:        atomic_uchar_t  sm_init;        /* primitive lock for startup */
                    487: 
                    488:        __size_t        sm_used;        /* memory used in the message heap */
                    489:        __size_t        sm_max [N_PRI_LEVELS];
                    490:                                        /*
                    491:                                         * Maximum memory we let a level use
                    492:                                         */
                    493: 
                    494:        toid_t          sm_bcid;        /* id generator for bufcall events */
                    495:        selist_t        sm_bcevents [N_PRI_LEVELS];
                    496:                                        /*
                    497:                                         * Bufcall event linked-list head.
                    498:                                         */
                    499:        ssched_t        sm_sched [1];   /* List of enabled queues. */
                    500: 
                    501:        lock_t        * sm_seq_lock;    /* Lock sequence number registers. */
                    502:        unsigned long   sm_err_seq;     /* error log sequence number */
                    503:        unsigned long   sm_trc_seq;     /* trace log sequence number */
                    504:        unsigned long   sm_con_seq;     /* console log sequence number */
                    505: 
                    506:        queue_t       * sm_log_rq;      /* STREAMS logger device */
                    507: 
                    508:        lock_t        * sm_proc_lock;   /* Basic lock for qprocsoff (). */
                    509:        sv_t          * sm_proc_sv;     /*
                    510:                                         * Synchronization variable for
                    511:                                         * qprocsoff ().
                    512:                                         */
                    513:        queue_t       * sm_log_drvr;    /* Log-driver read side. */
                    514: 
                    515:        rwlock_t      * sm_head_lock;   /* Lock for stream head list */
                    516:        shead_t       * sm_streams [SLIST_MAX];
                    517:                                        /* Chains of stream heads */
                    518: 
                    519:        __size_t        sm_maxctlsize;  /* max. size of control message */
                    520:        __size_t        sm_maxdatasize; /* max. size of data message part */
                    521: 
                    522: 
                    523:        /*---------- Locked by sm_msg_lock ------------*/
                    524:        lock_t        * sm_msg_lock;    /* basic lock for message heap */
                    525:        _ST_HEAP_CONTROL_P sm_msg_heap; /* Memory heap for STREAMS messages */
                    526:        sv_t          * sm_msg_sv;      /*
                    527:                                         * synchronization variable for
                    528:                                         * waiting for free memory.
                    529:                                         */
                    530:        __size_t        sm_msg_needed;  /* Level of free memory required */
                    531: 
                    532: #ifdef SPLIT_STREAMS_MEMORY
                    533:        /*---------- Locked by sm_other_lock ------------*/
                    534: 
                    535:        lock_t        * sm_other_lock;  /* basic lock for "other" heap */
                    536: 
                    537:        _ST_HEAP_CONTROL_P sm_other_heap;/* Memory heap for long-term info */
                    538: 
                    539:        sv_t          * sm_other_sv;    /*
                    540:                                         * synchronization variable for
                    541:                                         * waiting for free memory.
                    542:                                         */
                    543:        __size_t        sm_other_needed;/* Level of free memory required */
                    544: #else
                    545: # define       sm_other_heap   sm_msg_heap
                    546: # define       sm_other_lock   sm_msg_lock
                    547: # define       sm_other_sv     sm_msg_sv
                    548: # define       sm_other_needed sm_msg_needed
                    549: #endif
                    550: };
                    551: 
                    552: 
                    553: /*
                    554:  * These should be the standard priorities to be used with the locks for
                    555:  * controlling access to the various memory pools.
                    556:  */
                    557: 
                    558: #ifdef SPLIT_STREAMS_MEMORY
                    559: 
                    560: # define       str_msg_pl      plstr
                    561: # define       str_other_pl    plhi
                    562: 
                    563: #else
                    564: 
                    565: # define       str_msg_pl      plhi
                    566: # define       str_other_pl    plhi
                    567: 
                    568: #endif
                    569: 
                    570: 
                    571: /*
                    572:  * When someone thinks it might be a good idea to see about running some of
                    573:  * the bufcall routines, we defer a routine to deal with the checking. A
                    574:  * global flag bit protects
                    575:  */
                    576: 
                    577: #define SCHEDULE_BUFCALLS() \
                    578:    (ATOMIC_FETCH_AND_STORE_UCHAR (ddi_global_data ()->dg_run_bufcalls, 1) \
                    579:                        == 1 ? (void) 0 : (void) defer_int_any (RUN_BUFCALLS))
                    580: 
                    581: 
                    582: /*
                    583:  * If all allocations are coming from the same pool, non-message allocations
                    584:  * need to be counted in with the allocation-priority information.
                    585:  *
                    586:  * The "other" pool (which will really be the message pool) should be locked
                    587:  * when these functions are called.
                    588:  */
                    589: 
                    590: #ifdef SPLIT_STREAMS_MEMORY
                    591: 
                    592: # define       OTHER_ALLOCED(size)
                    593: # define       OTHER_FREED(size)
                    594: 
                    595: #else
                    596: 
                    597: # define       OTHER_ALLOCED(size)     (void) (str_mem->sm_used += size)
                    598: # define       OTHER_FREED(size)       ((void) (str_mem->sm_used -= size), \
                    599:                                         SCHEDULE_BUFCALLS ())
                    600: 
                    601: #endif
                    602: 
                    603: 
                    604: /*
                    605:  * We need access to a global instance of the above for managing STREAMS
                    606:  * memory in a consistent manner.
                    607:  */
                    608: 
                    609: extern struct streams_mem str_mem [];
                    610: 
                    611: 
                    612: /*
                    613:  * Category flags for the sh_lock_mask member. This is a collection of flag
                    614:  * bits which correspond to operations on the "sh_wait_sv" synchronization
                    615:  * variable.
                    616:  */
                    617: 
                    618: typedef enum category {
                    619:        SH_NONE         = 0,            /* use for paranoid checking */
                    620:        SH_OPENCLOSE    = 1,
                    621:        SH_IOCTL_LOCK   = 2,
                    622:        SH_READ_LOCK    = 4,            /* NOT NORMALLY USED */
                    623:        SH_WRITE_LOCK   = 8,            /* NOT NORMALLY USED */
                    624:        SH_PEEK_LOCK    = 16,
                    625: 
                    626:        SH_LOCK_MASK    = 31,           /* Mask for lock bits */
                    627: 
                    628: 
                    629:        SH_READ_WAIT    = 32,
                    630:        SH_WRITE_WAIT   = 64,
                    631:        SH_IOCTL_WAIT   = 128,
                    632:        SH_DRAIN_WAIT   = 256,
                    633:        SH_PEEK_WAIT    = 512,
                    634: 
                    635:        SH_WAIT_MASK    = 992,          /* Mask for wait bits */
                    636: 
                    637: 
                    638:        /*
                    639:         * Not a lock mask; just use the extra flag space.
                    640:         */
                    641: 
                    642:        SH_TIMEFLAG     = 8192
                    643: } cat_t;
                    644: 
                    645: 
                    646: /*
                    647:  * Stream head control structure.
                    648:  *
                    649:  * Be careful with locking the stream head; for many operations, it may be
                    650:  * sufficient to freeze the stream head.
                    651:  */
                    652: 
                    653: struct __stream_head {
                    654:        n_dev_t         sh_dev;         /* key for lookup */
                    655:        shead_t       * sh_next;        /* next stream head on chain */
                    656: 
                    657:        queue_t       * sh_head;        /* read queue of stream head */
                    658:        struct streamtab
                    659:                      * sh_tab;         /* initialisation data for driver */
                    660: 
                    661:        __clock_t       sh_cltime;      /* time to wait for close to drain */
                    662: 
                    663:        struct pollhead
                    664:                      * sh_pollhead;    /* for polling support */
                    665: 
                    666:        pid_t           sh_pgrp;        /* foreground TTY process group */
                    667:        __VOID__      * sh_controller;  /* reference to controlling process */
                    668: 
                    669:        int             sh_rerrcode;    /* error code from M_ERROR */
                    670:        int             sh_werrcode;    /* error code from M_ERROR */
                    671: 
                    672:        unsigned short  sh_flags;       /* miscellaneous flags */
                    673: 
                    674:        short           sh_readopt;     /* read options */
                    675:        short           sh_wropt;       /* write options */
                    676: 
                    677:        unsigned short  sh_wroff;       /* write offset */
                    678: 
                    679:        sigpoll_t     * sh_sigs;        /* processes registered for SIGPOLL */
                    680: 
                    681:        toid_t          sh_read_bufcall;/* ID for read bufcall () */
                    682: 
                    683:        shead_t       * sh_linked;      /* head of stream we are linked to */
                    684:        muxid_t         sh_muxid;       /* our ID below that stream */
                    685: 
                    686: 
                    687:        lock_t        * sh_basic_lockp; /* */
                    688: 
                    689:        /*---- For process-level locking and timeout operations ----*/
                    690: 
                    691:        sv_t          * sh_wait_sv;     /* for process lock operations */
                    692: 
                    693:        int             sh_lock_mask;   /* which categories are locked */
                    694: 
                    695:        short           sh_ref_count;   /* references to stream memory */
                    696:        short           sh_open_count;  /* successful open count */
                    697:        short           sh_attach_count;/* attachments to stream */
                    698:        short           sh_lock_count;  /* processes queued or locked */
                    699:        short           sh_time_count;  /* count of timeout checks */
                    700: 
                    701:        __clock_t       sh_timeout_tick;/* current soonest timeout */
                    702:        toid_t          sh_timeout_id;  /* ID of current active timeout */
                    703: 
                    704:        int             sh_ioc_seq;     /* ioctl () sequence number */
                    705:        mblk_t        * sh_ioc_msg;     /* ioctl () messages */
                    706: };
                    707: 
                    708: 
                    709: /*
                    710:  * A collection of functions for dealing with the stream head basic lock.
                    711:  */
                    712: 
                    713: #define        SHEAD_LOCK(sheadp)      LOCK ((sheadp)->sh_basic_lockp, plstr)
                    714: #define        SHEAD_UNLOCK(sheadp,pl) UNLOCK ((sheadp)->sh_basic_lockp, pl)
                    715: #define        SHEAD_ASSERT_LOCKED(sheadp) \
                    716:                ASSERT ((sheadp) != NULL && \
                    717:                        TRYLOCK ((sheadp)->sh_basic_lockp, plstr) == invpl)
                    718: 
                    719: 
                    720: /*
                    721:  * Masks for use with the "sh_flags" member.
                    722:  */
                    723: 
                    724: enum {
                    725:        SH_READMSG      = 0x0001,       /* generate M_READ messages */
                    726:        SH_NDELAY       = 0x0002,       /* non-STREAMS O_NDELAY semantics */
                    727:        SH_TTY          = 0x0004,       /* stream is acting as a tty */
                    728:        SH_TOSTOP       = 0x0008,       /* job control on background writes */
                    729: 
                    730: 
                    731:        SH_HANGUP       = 0x0010,       /* stream has been hung up */
                    732: 
                    733:        SH_PLINK        = 0x0020,       /* stream is permanently linked */
                    734: 
                    735:        /*
                    736:         * Permanent flags set when the stream is created. We do not need a
                    737:         * flag to indicate a pipe, because pipes have a NULL "sh_tab" entry
                    738:         * to mark them.
                    739:         */
                    740: 
                    741:        SH_MASTER       = 0x0100,       /* master end of stream pipe */
                    742: 
                    743: 
                    744:        /*
                    745:         * This flag enables serialization of reads and writes. This is a
                    746:         * local, experimental extension to STREAMS.
                    747:         */
                    748: 
                    749:        SH_RWLOCKING    = 0x0200
                    750: };
                    751: 
                    752: 
                    753: /*
                    754:  * For stream pipes there is a master/slave relationship between the stream
                    755:  * heads at each end. The following macros define some handy relationships
                    756:  * between them to allow quick mapping from one to another.
                    757:  */
                    758: 
                    759: #define        SHEAD_M2SLAVE(m)        ((m) + 1)
                    760: #define        SHEAD_SLAVE2M(s)        ((s) - 1)
                    761: #define        SHEAD_MASTER(sheadp)    (((sheadp)->sh_flags & SH_MASTER) == 0 ? \
                    762:                                 SHEAD_SLAVE2M (sheadp) : (sheadp))
                    763: #define        SHEAD_OTHER(sheadp)     (((sheadp)->sh_flags & SH_MASTER) == 0 ? \
                    764:                                 SHEAD_SLAVE2M (sheadp) : \
                    765:                                 SHEAD_M2SLAVE (sheadp))
                    766: 
                    767: #define        SHEAD_IS_PIPE(sheadp)   ((sheadp)->sh_tab == NULL)
                    768: 
                    769: #define        SHEAD_HANGUP(sheadp)    (((sheadp)->sh_flags & SH_HANGUP) != 0)
                    770: 
                    771: #define        SHEAD_READMSG(sheadp)   (((sheadp)->sh_flags & SH_READMSG) != 0)
                    772: 
                    773: 
                    774: /*
                    775:  * For working in with the abstract filesystem layer, we define a format for
                    776:  * our opaque information.
                    777:  */
                    778: 
                    779: typedef        struct {
                    780:        shead_t       * sheadp;
                    781: } scookie_t;
                    782: 
                    783: 
                    784: 
                    785: __EXTERN_C_BEGIN__
                    786: 
                    787: ssched_t      *        QSCHED_ALLOC    __PROTO ((void));
                    788: void           SSCHED_FREE     __PROTO ((ssched_t * _sched));
                    789: int            QSCHED_SCHEDULE __PROTO ((queue_t * _q, ssched_t * _sched));
                    790: void           QSCHED_UNSCHEDULE
                    791:                                __PROTO ((queue_t * _q, ssched_t * _sched));
                    792: queue_t              * QSCHED_GETFIRST __PROTO ((ssched_t * _sched));
                    793: 
                    794: pl_t           QFREEZE_TRACE   __PROTO ((queue_t * _q,
                    795:                                          __CONST__ char * _name));
                    796: void           QFROZEN_TRACE   __PROTO ((queue_t * _q,
                    797:                                          __CONST__ char * _name));
                    798: void           QUEUE_TRACE     __PROTO ((queue_t * _q,
                    799:                                          __CONST__ char * _name));
                    800: void           QUNFREEZE_TRACE __PROTO ((queue_t * _q, pl_t _pl));
                    801: 
                    802: void           QUEUE_BACKENAB  __PROTO ((queue_t * _q));
                    803: queue_t              * QUEUE_NEXT      __PROTO ((queue_t * _q));
                    804: 
                    805: mblk_t       * STRMEM_ALLOC    __PROTO ((__size_t _size, int _pri,
                    806:                                          int _flag));
                    807: void           STRMEM_FREE     __PROTO ((mblk_t * _bp, __size_t _size));
                    808: 
                    809: mblk_t       * MSGB_ALLOC      __PROTO ((__size_t _size, int _pri,
                    810:                                          int _flag));
                    811: 
                    812: void           SHEAD_WAKE      __PROTO ((shead_t * _sheadp, cat_t _flag));
                    813: void           SHEAD_SIGNAL    __PROTO ((shead_t * _sheadp, uchar_t _sig));
                    814: int            SHEAD_SRDOPT    __PROTO ((shead_t * _sheadp, int _flag));
                    815: void           QBAND_SETOPT    __PROTO ((queue_t * _q,
                    816:                                          struct stroptions * _so));
                    817: 
                    818: qband_t              * QUEUE_BAND      __PROTO ((queue_t * _q, uchar_t _pri));
                    819: qband_t              * QBAND_PREV      __PROTO ((queue_t * _q, qband_t * _qbandp));
                    820: 
                    821: void           RUN_BUFCALLS    __PROTO ((void));
                    822: void           RUN_STREAMS     __PROTO ((void));
                    823: 
                    824: shead_t              * SHEAD_FIND      __PROTO ((n_dev_t _dev, slist_id_t _id));
                    825: 
                    826: int            STREAMS_OPEN    __PROTO ((n_dev_t * _devp,
                    827:                                          struct streamtab * _stabp,
                    828:                                          int _mode, cred_t * _credp));
                    829: int            STREAMS_CLOSE   __PROTO ((shead_t * _sheadp, int _mode,
                    830:                                          cred_t * _credp));
                    831: 
                    832: int            STREAMS_READ    __PROTO ((shead_t * _sheadp, uio_t * _uiop));
                    833: int            STREAMS_WRITE   __PROTO ((shead_t * _sheadp, uio_t * _uiop));
                    834: int            STREAMS_IOCTL   __PROTO ((shead_t * _sheadp, int _cmd,
                    835:                                          _VOID * _arg, int _mode,
                    836:                                          cred_t * _credp, int * _rvalp));
                    837: 
                    838: int            STREAMS_CHPOLL  __PROTO ((shead_t * _sheadp, short _events,
                    839:                                          int _anyyet, short * _reventsp,
                    840:                                          struct pollhead ** _phpp));
                    841: 
                    842: int            STREAMS_GETPMSG __PROTO ((shead_t * _sheadp,
                    843:                                          struct strbuf * _ctlbuf,
                    844:                                          struct strbuf * _databuf,
                    845:                                          int * _bandp, int * _flagsp,
                    846:                                          int _mode, int * _rvalp));
                    847: int            STREAMS_PUTPMSG __PROTO ((shead_t * _sheadp,
                    848:                                          struct strbuf * _ctlbuf,
                    849:                                          struct strbuf * _databuf, int _band,
                    850:                                          int _flags, int _mode,
                    851:                                          int * _rvalp));
                    852: 
                    853: __EXTERN_C_END__
                    854: 
                    855: 
                    856: /*
                    857:  * This internal definition is the dual to QFREEZE_TRACE (), being the
                    858:  * internal implementation of unfreezestr ().
                    859:  */
                    860: 
                    861: #define        QUNFREEZE_TRACE(q,pl)   SFREEZE_UNLOCK (q, pl)
                    862: 
                    863: 
                    864: /*
                    865:  * Dealing with queue priority bands can be a little tricky; in particular,
                    866:  * the definition of the linked-list structure of priority bands has some
                    867:  * characteristics that may be unsuitable for some implementations.
                    868:  * Specifically, the "qband" structure apparently is designed to function as
                    869:  * a member of a singly-linked list rooted in the "queue" structure. This is
                    870:  * flexible, but if there are several priority bands the time spent in
                    871:  * dereferencing the link pointers might outweigh any extra cost involved in
                    872:  * keeping the "band" structures in a vector [While the allocation cost is
                    873:  * neglible in terms of time, there is a potentially high cost in terms of
                    874:  * increasing the likelihood of a failure to allocate a band structure].
                    875:  *
                    876:  * The following internal functions have been defined to abstract away the
                    877:  * details of how band structures are accessed from the queue, allowing a
                    878:  * more time-efficient vector scheme to be used, or even a hybrid scheme
                    879:  * where vectors are preferred but a linked-list fallback is available.
                    880:  *
                    881:  * The SVR4 DDI/DKI used to document the band structure, but that structure is
                    882:  * no longer documented as of the SVR4 MP DDI/DKI.
                    883:  */
                    884: 
                    885: #define        VECTOR_BANDS
                    886: #define        VECTOR_BANDS_TEST               /* test mode for VECTOR_BANDS */
                    887: 
                    888: #ifdef VECTOR_BANDS
                    889: 
                    890: #define        QUEUE_BAND(q,pri)       ((pri) > (q)->q_nband ? NULL : \
                    891:                                        & (q)->q_bandp [pri - 1])
                    892: 
                    893: #define        QBAND_PREV(q,bandp)     ((bandp) > (q)->q_bandp ? (bandp) - 1 : NULL)
                    894: 
                    895: #endif /* defined (VECTOR_BANDS) */
                    896: 
                    897: 
                    898: #endif /* ! __KERNEL_STRMLIB_H__ */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.