Annotation of coherent/f/etc/conf/streams/src/struser.c, revision 1.1.1.1

1.1       root        1: #define        _DDI_DKI        1
                      2: #define        _DDI_DKI_IMPL   1
                      3: #define        _SYSV4          1
                      4: 
                      5: /*
                      6:  */
                      7: 
                      8: #include <common/ccompat.h>
                      9: #include <kernel/fhsys.h>
                     10: #include <kernel/strmlib.h>
                     11: #include <sys/confinfo.h>
                     12: #include <sys/types.h>
                     13: #include <sys/kmem.h>
                     14: #include <sys/poll.h>
                     15: #include <sys/ksynch.h>
                     16: #include <sys/file.h>
                     17: #include <sys/uio.h>
                     18: #include <sys/cmn_err.h>
                     19: #include <sys/errno.h>
                     20: #include <sys/signal.h>
                     21: #include <stropts.h>
                     22: #include <string.h>
                     23: #include <poll.h>
                     24: 
                     25: /*
                     26:  * The following function (local to this module) is forward-referenced due to
                     27:  * the mutual recursion between the final close process and the streams unlink
                     28:  * code.
                     29:  */
                     30: 
                     31: __LOCAL__ int  SHEAD_DO_CLOSE  __PROTO ((shead_t * sheadp, int mode,
                     32:                                          cred_t * credp));
                     33: 
                     34: 
                     35: lkinfo_t __stream_schedule_lkinfo = {
                     36:        "STREAMS queue schedule", INTERNAL_LOCK
                     37: };
                     38: 
                     39: lkinfo_t __stream_event_lkinfo = {
                     40:        "STREAMS bufcall ()/esbbcall () event list", INTERNAL_LOCK
                     41: };
                     42: 
                     43: __LOCAL__ lkinfo_t _stream_head_lkinfo = {
                     44:        "stream head lock", INTERNAL_LOCK
                     45: };
                     46: 
                     47: 
                     48: /*
                     49:  * Allocate and initialize a queue pair. This function only performs a partial
                     50:  * initialization; many other fields are filled in by the caller, usually from
                     51:  * fields supplied in the "streamtab" structure.
                     52:  *
                     53:  * Since at initial stream open time we we be allocating at least two queue
                     54:  * pairs and one or two stream head structures, we try to satisfy all those
                     55:  * allocations in one step here.
                     56:  *
                     57:  * The "npairs" argument indicates the number of queue pairs to be allocated.
                     58:  * The "extra" argument is the number of additional bytes to allocate over and
                     59:  * above the memory for the queue pairs.
                     60:  *
                     61:  * Call only from base level. This function may sleep.
                     62:  */
                     63: 
                     64: #if    __USE_PROTO__
                     65: __LOCAL__ queue_t * (QUEUE_ALLOC) (int npairs, size_t extra)
                     66: #else
                     67: __LOCAL__ queue_t *
                     68: QUEUE_ALLOC __ARGS ((npairs, extra))
                     69: int            npairs;
                     70: size_t         extra;
                     71: #endif
                     72: {
                     73:        queue_t       * q;
                     74:        queue_t       * init;
                     75:        int             count;
                     76: 
                     77:        ASSERT (npairs > 0 && npairs < 3);
                     78: 
                     79:        /*
                     80:         * We use kmem_zalloc () to allocate this space so we can sleaze our
                     81:         * way out of most of the initialization work.
                     82:         */
                     83: 
                     84:        if ((q = (queue_t *) kmem_zalloc (2 * npairs * sizeof (* q) + extra,
                     85:                                          KM_SLEEP)) == NULL)
                     86:                return NULL;
                     87: 
                     88:        init = q;
                     89:        count = npairs;
                     90: 
                     91:        do {
                     92:                /*
                     93:                 * First, initialise the read side of the queue. While we are
                     94:                 * at it, we link the "q_next" members of multiple queues for
                     95:                 * a read side; if we treat the value "q" that we are going to
                     96:                 * return to the caller as the stream head, the links run from
                     97:                 * the last entry we initialize towards the first one.
                     98:                 */
                     99: 
                    100:                if (count > 1)
                    101:                        (init + 2)->q_next = init;
                    102: 
                    103:                init->q_flag = QWANTR | QREADR | QPROCSOFF;
                    104: 
                    105:                SFREEZE_INIT (init);
                    106: 
                    107:                init ++;
                    108: 
                    109: 
                    110:                /*
                    111:                 * Next, work on the write side. For multiple queues, the
                    112:                 * write size "q_next" links run from the "head" to the device.
                    113:                 */
                    114: 
                    115:                if (count > 1)
                    116:                        init->q_next = init + 2;
                    117: 
                    118:                init->q_flag = QWANTR | QPROCSOFF;
                    119: 
                    120:                SFREEZE_INIT (init);
                    121: 
                    122:                init ++;
                    123:        } while (-- count > 0);
                    124: 
                    125: 
                    126:        /*
                    127:         * We put a pointer to any "extra" space that the caller requested in
                    128:         * the "q_ptr" fields of the first two queues allocated, since they
                    129:         * will almost always be the stream head queue pair.
                    130:         */
                    131: 
                    132:        if (extra > 0) {
                    133: 
                    134:                q->q_ptr = (char *) q + 2 * sizeof (* q) * npairs;
                    135:                W (q)->q_ptr = q->q_ptr;
                    136:        }
                    137: 
                    138:        return q;
                    139: }
                    140: 
                    141: 
                    142: /*
                    143:  * Set a queue's initial watermark data and some other stuff.
                    144:  */
                    145: 
                    146: #if    __USE_PROTO__
                    147: __LOCAL__ void (QUEUE_INITOPT) (queue_t * q)
                    148: #else
                    149: __LOCAL__ void
                    150: QUEUE_INITOPT __ARGS ((q))
                    151: queue_t              * q;
                    152: #endif
                    153: {
                    154:        struct module_info
                    155:                      * mi = q->q_qinfo->qi_minfo;
                    156: 
                    157:        q->q_minpsz = mi->mi_minpsz;
                    158:        q->q_maxpsz = mi->mi_maxpsz;
                    159:        q->q_hiwat = mi->mi_hiwat;
                    160:        q->q_lowat = mi->mi_lowat;
                    161: }
                    162: 
                    163: 
                    164: /*
                    165:  * Set up a queue pair's initial options.
                    166:  */
                    167: 
                    168: typedef enum {
                    169:        QI_NORMAL,
                    170:        QI_MUX
                    171: } qiflag_t;
                    172: 
                    173: #if    __USE_PROTO__
                    174: __LOCAL__ void (QUEUE_INIT) (queue_t * q, struct streamtab * stab,
                    175:                             qiflag_t mux)
                    176: #else
                    177: void
                    178: QUEUE_INIT __ARGS ((q, stab, mux))
                    179: queue_t              * q;
                    180: struct streamtab
                    181:              * stab;
                    182: qiflag_t       mux;
                    183: #endif
                    184: {
                    185:        q->q_qinfo = mux == QI_NORMAL ? stab->st_rdinit : stab->st_muxrinit;
                    186:        QUEUE_INITOPT (q);
                    187: 
                    188:        q = W (q);
                    189: 
                    190:        q->q_qinfo = mux == QI_NORMAL ? stab->st_wrinit : stab->st_muxwinit;
                    191:        QUEUE_INITOPT (q);
                    192: }
                    193: 
                    194: 
                    195: /*
                    196:  * This function is the dual to the QBAND_ALLOC () function, freeing any
                    197:  * allocated "qband" structures associated with the given queue.
                    198:  *
                    199:  * The caller must have the queue frozen or not linked on any stream.
                    200:  */
                    201: 
                    202: #if    __USE_PROTO__
                    203: void (QBAND_FREE) (queue_t * q)
                    204: #else
                    205: void
                    206: QBAND_FREE __ARGS ((q))
                    207: queue_t              * q;
                    208: #endif
                    209: {
                    210:        qband_t       * scan;
                    211:        qband_t       * prev;
                    212:        int             nbands;
                    213: 
                    214:        QUEUE_TRACE (q, "QBAND_FREE");
                    215: 
                    216:        /*
                    217:         * We use flags in the "qband" entries to locate allocation
                    218:         * boundaries rather than trying to recover this information purely
                    219:         * from comparing addresses (although since the address comparisons
                    220:         * provide an extra check we do that too). In theory, an allocator
                    221:         * might not need extra information stored in the arena yet might
                    222:         * fail if adjacent allocations are coalesced into a single free ().
                    223:         *
                    224:         * I don't know of any allocators with this property, but one might
                    225:         * exist.
                    226:         *
                    227:         * This code will work just fine under the allocation scheme which
                    228:         * keeps the QBAND entries in a single vector, so we don't need to
                    229:         * conditionalize this code at all.
                    230:         */
                    231: 
                    232:        nbands = 0;
                    233: 
                    234:        for (prev = scan = q->q_bandp ; scan != NULL ; scan = scan->qb_next) {
                    235: 
                    236:                if ((scan->qb_flag & QB_FIRST) != 0) {
                    237: 
                    238:                        ASSERT (nbands > 0);
                    239: 
                    240:                        kmem_free (prev, sizeof (* prev) * nbands);
                    241: 
                    242:                        nbands = 1;
                    243:                        prev = scan;
                    244:                } else {
                    245: 
                    246:                        ASSERT (scan == prev + nbands);
                    247:                        nbands ++;
                    248:                }
                    249:        }
                    250: 
                    251:        if (nbands > 0)
                    252:                kmem_free (prev, sizeof (* prev) * nbands);
                    253: }
                    254: 
                    255: 
                    256: /*
                    257:  * Destroy an individual queue.
                    258:  */
                    259: 
                    260: #if    __USE_PROTO__
                    261: __LOCAL__ void (QUEUE_DESTROY) (queue_t * q)
                    262: #else
                    263: __LOCAL__ void
                    264: QUEUE_DESTROY __ARGS ((q))
                    265: queue_t              * q;
                    266: #endif
                    267: {
                    268:        mblk_t        * mp;
                    269:        mblk_t        * next;
                    270: 
                    271:        QSCHED_UNSCHEDULE (q, str_mem->sm_sched);
                    272: 
                    273:        /*
                    274:         * Free all the memory allocated to messages that remain on the queue.
                    275:         */
                    276: 
                    277:        for (mp = q->q_first ; mp != NULL ; mp = next) {
                    278: 
                    279:                next = mp->b_next;
                    280:                freemsg (mp);
                    281:        }
                    282: 
                    283:        if ((q->q_flag & QWANTW) != 0)
                    284:                QUEUE_BACKENAB (q);
                    285: 
                    286:        SFREEZE_DESTROY (q);
                    287: 
                    288:        if (q->q_nband > 0)
                    289:                QBAND_FREE (q);
                    290: }
                    291: 
                    292: 
                    293: /*
                    294:  * Destroy and release the memory for a queue pair or group of pairs. The
                    295:  * arguments passed to this function should match those used to allocate a
                    296:  * pair or group of pairs exactly. This can easily be done by recognising the
                    297:  * various canonical forms for stream structures; modules are always lone
                    298:  * queue pairs, regular streams match a driver and stream head (with
                    299:  * associated extra data for the stream head), and stream pipes consist of
                    300:  * two pairs of queue structures with two head structures.
                    301:  */
                    302: 
                    303: #if    __USE_PROTO__
                    304: __LOCAL__ void (QUEUE_FREE) (queue_t * rq, int npairs, size_t extra)
                    305: #else
                    306: __LOCAL__ void
                    307: QUEUE_FREE __ARGS ((rq, npairs, extra))
                    308: queue_t              * rq;
                    309: int            npairs;
                    310: size_t         extra;
                    311: #endif
                    312: {
                    313:        queue_t       * destroy;
                    314:        int             count;
                    315: 
                    316:        ASSERT (rq != NULL);
                    317:        ASSERT (npairs > 0 && npairs < 3);
                    318: 
                    319:        destroy = rq;
                    320:        count = npairs * 2;
                    321: 
                    322:        do {
                    323: 
                    324:                QUEUE_DESTROY (destroy);
                    325:                destroy ++;
                    326:        } while (-- count > 0);
                    327: 
                    328:        kmem_free (rq, 2 * sizeof (* rq) * npairs + extra);
                    329: }
                    330: 
                    331: 
                    332: /*
                    333:  * STREAM HEAD MANAGEMENT NOTES:
                    334:  *
                    335:  * The management of stream head structures introduces some interesting
                    336:  * synchronization problems arising from the interaction of the rules
                    337:  * associated with driver close routines and the fact that stream head
                    338:  * structures are dynamically allocated.
                    339:  *
                    340:  * The first problem is really one of specification; what does it mean for a
                    341:  * driver close () entry point to return EINTR? System V does not talk about
                    342:  * this case specifically, so we prohibit it by treating error returns from
                    343:  * the close () entry point uniformly by still actually closing the device.
                    344:  *
                    345:  * The second problem is this; a driver should not be re-opened until the
                    346:  * close process has completed. However, completion of the close process will
                    347:  * normally involve deallocation of the stream head (where presumably the
                    348:  * open routines are waiting).
                    349:  *
                    350:  * Our problem is that it is not possible to reliably determine whether there
                    351:  * are any other contexts waiting on a sleep lock. While it might be possible
                    352:  * to do so using SLEEP_LOCKAVAIL (), this would require that the calling
                    353:  * context release the lock. Under a plausible implementation of SLEEP_LOCK ()
                    354:  * where sleep locks are basically implemented with the sleep () and wakeup ()
                    355:  * functions and a "locked" flag, there will be no way for a process to find
                    356:  * out whether there are any functions waiting on the lock, since the unlock
                    357:  * implementation could simply clear the "locked" flag and issue wakeup (),
                    358:  * so that there could be any number of contexts waiting to run and test the
                    359:  * "locked" flag, yet SLEEP_LOCKAVAIL () in the calling context would return
                    360:  * true. Deallocating the lock at this time would be potentially disastrous.
                    361:  *
                    362:  * Actually, even a quality implementation of sleep locks (such as is provided
                    363:  * with this STREAMS system) cannot be easily used this way, since it is very
                    364:  * difficult to ensure that the information returned by SLEEP_LOCKAVAIL () is
                    365:  * current.
                    366:  *
                    367:  * The situation can be resolved by maintaining a count of processes wishing
                    368:  * to lock the item. The count can be maintained by using the basic-lock
                    369:  * action associated with DDI/DKI synchronization variables, and the new
                    370:  * SV_SIGNAL () operation can be used to pass the ownership of the lock to
                    371:  * a waiting process reliably.
                    372:  *
                    373:  * Once this is in place, it becomes clear how the count of waiting processes
                    374:  * can be used to simplify the destruction of stream heads; essentially,
                    375:  * when a process wishes to release the "lock" on the stream head, if both
                    376:  * the open count and the waiting count are 0, then the memory for the item
                    377:  * can be safely released. Otherwise, control simply passes to the next
                    378:  * waiting process.
                    379:  *
                    380:  * So, if a process is performing a final close on a stream, and some open
                    381:  * requests are queued, the close will leave the stream's memory alone and
                    382:  * simply pass it on to the waiting open (which can detect that the stream
                    383:  * needs to be treated as new since the open count is 0). If the waiting open
                    384:  * was interrupted by a signal, it would still have to decrement the count of
                    385:  * waiting processes before it releases its lock, at which time it would know
                    386:  * to remove the item from the directory and release the memory.
                    387:  *
                    388:  * For this to work properly takes some coordination in the policy for the
                    389:  * directory; the basic lock used to guard lock operations should be held
                    390:  * during searches of the directory to ensure that the count value is correct
                    391:  * with respect to all processes; a process that has a pointer to the stream
                    392:  * head (obtained from the directory) which it has not incremented the count
                    393:  * for is an error. Note that this only applies to operations which might
                    394:  * later affect the count, of course.
                    395:  *
                    396:  *
                    397:  * STREAM OPERATIONS AND LOCKS:
                    398:  *
                    399:  * open ()     This operation cannot begin while there is a final close in
                    400:  *             progress. If this operation increments the "open count" before
                    401:  *             calling the device open routines, it is possible that it will
                    402:  *             also have to perform final close duties if a driver or module
                    403:  *             fails the open. This function may cause the creation of a new
                    404:  *             queue pair and directory entry.
                    405:  *
                    406:  *             The multiprocessor DDI/DKI also mandates that a particular
                    407:  *             device number's open () routine only have one instance active
                    408:  *             at any given time.
                    409:  *
                    410:  * close ()    Normally, this does not require extended locking, but the case
                    411:  *             of beginning a final close is special, since only then will
                    412:  *             the queue drain and final close procedures begin. Since there
                    413:  *             cannot be outstanding ioctl ()s during final close, the timer
                    414:  *             code used to control ioctl ()s can be shared with this for
                    415:  *             timing out while waiting for a write queue to drain.
                    416:  *
                    417:  * read (), getmsg (), getpmsg ()
                    418:  *             Under normal circumstances, these functions require no special
                    419:  *             treatment. It would be desirable to support an extension to
                    420:  *             STREAMS which supported "safe" multiple readers, where the
                    421:  *             serialization of reads is guaranteed.
                    422:  *
                    423:  * write (), putmsg (), putpmsg ()
                    424:  *             These functions require little special treatment. It would be
                    425:  *             desirable to support an extension to STREAMS which guaranteed
                    426:  *             serialization of writes, for instance to guarantee unlimited-
                    427:  *             length atomic pipe writes.
                    428:  *
                    429:  * ioctl ()    Depending on the details of the operation, we may need
                    430:  *
                    431:  *                     a read lock on the stream head (eg. I_GETCLTIME).
                    432:  *                     a write lock on the stream head (eg. I_SRDOPT).
                    433:  *                     a block on open and pop (I_PUSH).
                    434:  *                     a block on close and push (I_POP).
                    435:  *                     a long-term lock on the message queue.
                    436:  *
                    437:  *             The long-term lock operations revolve around the operations
                    438:  *             that send messages downstream : I_LINK, I_UNLINK, I_PLINK,
                    439:  *             I_PUNLINK, and I_STR. These operations are also special in
                    440:  *             that they are capable of timing out.
                    441:  *
                    442:  *             Since the close or open routines invoked by an I_PUSH or I_POP
                    443:  *             operation may block, they require analagous locking to the
                    444:  *             open () and close () cases.
                    445:  *
                    446:  * LOCK SUMMARY:
                    447:  *     EXCLUSIVE LONG-TERM LOCK WITH OPTIONAL TIMEOUT:
                    448:  *         open/close category:
                    449:  *             open (), close (), I_PUSH, I_POP
                    450:  *         ioctl category:
                    451:  *             I_LINK, I_UNLINK, I_PLINK, I_PUNLINK, I_STR
                    452:  *
                    453:  *         In theory, a single lock will do. However, once we take into
                    454:  *         account terminal behaviour w.r.t. CLOCAL and other similar
                    455:  *         situations, it seems that creating the subcategories above will
                    456:  *         suit us better.
                    457:  *
                    458:  *         Final close is a special case that blocks all other cases, which
                    459:  *         can be distinguished fairly clearly.
                    460:  *
                    461:  *     STREAM HEAD WRITE LOCK:
                    462:  *             I_SRDOPT, I_SETSIG, I_SWROPT, I_SETCLTIME
                    463:  *             Certain stream head message processing routines may also write
                    464:  *             lock the stream head, such as M_SETOPT processing.
                    465:  *
                    466:  *     All other streams operations should acquire a stream head read lock
                    467:  *     before reading stream head variables.
                    468:  */
                    469: /*
                    470:  * STREAM HEAD WAIT NOTES:
                    471:  *
                    472:  * In addition to the above discussion about locking, there are other
                    473:  * operations that may cause a process to block while at the stream head. For
                    474:  * instance, read (), write (), I_RECVFD, and I_STR operations may cause the
                    475:  * outer context to block until some kind of message arrives.
                    476:  *
                    477:  * The question we are immediately faced with is what level of specificity to
                    478:  * provide in the arrangement of synchronization variables and basic locks.
                    479:  * Until the implementation is complete and we can perform detailed
                    480:  * measurements with a variety of (pathological) loads on a variety of
                    481:  * systems, we really don't know. For simplicity, the current system performs
                    482:  * all stream head blocking by sleeping on the "sh_wait_sv" synchronization
                    483:  * variable that is also used by the above locking operations.
                    484:  *
                    485:  * However, to give some isolation from changes in this scheme, we mandate a
                    486:  * generic layer to deal with this. Not only does this insulate operations
                    487:  * from the details of synchronization, but it allows us to perform some
                    488:  * simple optimizations that may allow this simple scheme to perform better.
                    489:  */
                    490: 
                    491: 
                    492: /*
                    493:  * Initialize a stream head structure, assuming that memory was allocated with
                    494:  * kmem_zalloc () and so NULL pointers and 0-value fields need not be filled
                    495:  * in.
                    496:  *
                    497:  * This function may sleep waiting for memory to become available to allocate
                    498:  * the locks needed by the stream head.
                    499:  */
                    500: 
                    501: #if    __USE_PROTO__
                    502: __LOCAL__ void (SHEAD_INIT) (shead_t * sheadp, struct streamtab * stabp,
                    503:                             n_dev_t dev, queue_t * rq)
                    504: #else
                    505: __LOCAL__ void
                    506: SHEAD_INIT __ARGS ((sheadp, stabp, dev, rq))
                    507: shead_t              * sheadp;
                    508: struct streamtab
                    509:              * stabp;
                    510: n_dev_t                dev;
                    511: queue_t              * rq;
                    512: #endif
                    513: {
                    514:        ASSERT (sheadp != NULL);
                    515:        ASSERT (rq != NULL);
                    516: 
                    517:        /*
                    518:         * The sh_lock_count and sh_time_count members are initialized in the
                    519:         * lock code.
                    520:         */
                    521: 
                    522:        ASSERT (sheadp->sh_open_count == 0);
                    523:        ASSERT (sheadp->sh_attach_count == 0);
                    524:        ASSERT (sheadp->sh_lock_count == 0);
                    525:        ASSERT (sheadp->sh_time_count == 0);
                    526:        ASSERT (sheadp->sh_rerrcode == 0);
                    527:        ASSERT (sheadp->sh_werrcode == 0);
                    528:        ASSERT (sheadp->sh_wroff == 0);
                    529: 
                    530:        ASSERT (sheadp->sh_read_bufcall == 0);
                    531:        ASSERT (sheadp->sh_timeout_id == 0);
                    532: 
                    533:        ASSERT (sheadp->sh_sigs == NULL);
                    534:        ASSERT (sheadp->sh_linked == NULL);
                    535:        ASSERT (sheadp->sh_ioc_msg == NULL);
                    536: 
                    537:        ASSERT (rq->q_ptr == sheadp);
                    538: 
                    539:        sheadp->sh_dev = dev;
                    540:        sheadp->sh_tab = stabp;
                    541:        sheadp->sh_head = rq;
                    542: 
                    543:        sheadp->sh_pollhead = phalloc (KM_SLEEP);
                    544:        sheadp->sh_flags = SH_MASTER;
                    545:        sheadp->sh_readopt = RNORM | RPROTNORM;
                    546: 
                    547:        sheadp->sh_basic_lockp = LOCK_ALLOC (stream_head_hierarchy, plstr,
                    548:                                             & _stream_head_lkinfo, KM_SLEEP);
                    549:        sheadp->sh_wait_sv = SV_ALLOC (KM_SLEEP);
                    550: 
                    551:        ASSERT (sheadp->sh_basic_lockp != NULL || sheadp->sh_wait_sv != NULL);
                    552: 
                    553: 
                    554:        /*
                    555:         * The default time to wait for a queue to drain while closing is 15s.
                    556:         */
                    557: 
                    558:        sheadp->sh_cltime = drv_usectohz (15000000L);
                    559: }
                    560: 
                    561: 
                    562: /*
                    563:  * Turn a stream head structure back into raw bits.
                    564:  */
                    565: 
                    566: #if    __USE_PROTO__
                    567: __LOCAL__ void (SHEAD_DESTROY) (shead_t * sheadp)
                    568: #else
                    569: __LOCAL__ void
                    570: SHEAD_DESTROY __ARGS((sheadp))
                    571: shead_t              * sheadp;
                    572: #endif
                    573: {
                    574:        ASSERT (sheadp != NULL);
                    575:        ASSERT (sheadp->sh_sigs == NULL);
                    576:        ASSERT (sheadp->sh_linked == NULL);
                    577: 
                    578:        ASSERT (sheadp->sh_open_count == 0);
                    579:        ASSERT (sheadp->sh_attach_count == 0);
                    580:        ASSERT (sheadp->sh_lock_count == 0);
                    581: 
                    582:        ASSERT (sheadp->sh_timeout_id == 0);
                    583: 
                    584:        if (sheadp->sh_read_bufcall != 0)
                    585:                unbufcall (sheadp->sh_read_bufcall);
                    586: 
                    587:        LOCK_DEALLOC (sheadp->sh_basic_lockp);
                    588:        SV_DEALLOC (sheadp->sh_wait_sv);
                    589: 
                    590:        phfree (sheadp->sh_pollhead);
                    591: }
                    592: 
                    593: 
                    594: /*
                    595:  * This function attempts to determine the appropriate id queue for a stream
                    596:  * head based on cues in the stream head.
                    597:  */
                    598: 
                    599: #if    __USE_PROTO__
                    600: __LOCAL__ slist_id_t (SHEAD_ID) (shead_t * sheadp)
                    601: #else
                    602: __LOCAL__ slist_id_t
                    603: SHEAD_ID __ARGS ((sheadp))
                    604: shead_t              * sheadp;
                    605: #endif
                    606: {
                    607:        ASSERT (sheadp != NULL);
                    608: 
                    609:        if (SHEAD_IS_PIPE (sheadp))
                    610:                return PIPE_SLIST;
                    611: 
                    612:        return DEV_SLIST;
                    613: }
                    614: 
                    615: 
                    616: /*
                    617:  * This function finds a stream head by looking up its device number, but
                    618:  * nothing else. To call this function, the caller must have good reason to
                    619:  * suspect that an open reference to the stream exists and isn't going to go
                    620:  * away.
                    621:  *
                    622:  * If this routine returns NULL, then that is a serious error (which may be
                    623:  * diagnosed by console messages), because it indicates that the caller has
                    624:  * not got the claimed knowledge of the state of the system!
                    625:  */
                    626: 
                    627: #if    __USE_PROTO__
                    628: shead_t * (SHEAD_FIND) (n_dev_t dev, slist_id_t id)
                    629: #else
                    630: shead_t *
                    631: SHEAD_FIND __ARGS ((dev, id))
                    632: n_dev_t                dev;
                    633: slist_id_t     id;
                    634: #endif
                    635: {
                    636:        shead_t       * scan;
                    637:        pl_t            prev_pl;
                    638: 
                    639:        prev_pl = RW_RDLOCK (str_mem->sm_head_lock, plstr);
                    640: 
                    641:        for (scan = str_mem->sm_streams [id] ; scan != NULL ;
                    642:             scan = scan->sh_next) {
                    643: 
                    644:                if (scan->sh_dev == dev)
                    645:                        break;
                    646:        }
                    647: 
                    648:        RW_UNLOCK (str_mem->sm_head_lock, prev_pl);
                    649: 
                    650:        if (scan == NULL)
                    651:                cmn_err (CE_WARN, "Unable to locate stream in SHEAD_FIND ()");
                    652:        else
                    653:                ASSERT (SHEAD_ID (scan) == id);
                    654: 
                    655:        return scan;
                    656: }
                    657: 
                    658: 
                    659: /*
                    660:  * This function attempts to locate an existing entry and increment its lock
                    661:  * count atomically.
                    662:  */
                    663: 
                    664: #if    __USE_PROTO__
                    665: __LOCAL__ shead_t * (SHEAD_FIND_AND_LOCK) (n_dev_t dev, slist_id_t id)
                    666: #else
                    667: __LOCAL__ shead_t *
                    668: SHEAD_FIND_AND_LOCK __ARGS ((dev, id))
                    669: n_dev_t                dev;
                    670: slist_id_t     id;
                    671: #endif
                    672: {
                    673:        shead_t       * scan;
                    674:        pl_t            prev_pl;
                    675: 
                    676:        prev_pl = RW_RDLOCK (str_mem->sm_head_lock, plstr);
                    677: 
                    678:        for (scan = str_mem->sm_streams [id] ; scan != NULL ;
                    679:             scan = scan->sh_next) {
                    680: 
                    681:                if (scan->sh_dev == dev) {
                    682:                        /*
                    683:                         * Now we have found the entry we want, increment the
                    684:                         * reference count atomically. We know that it will
                    685:                         * not disappear because of the read lock we have on
                    686:                         * the containing list.
                    687:                         */
                    688: 
                    689:                        (void) SHEAD_LOCK (scan);
                    690: 
                    691:                        scan->sh_lock_count ++;
                    692:                        break;
                    693:                }
                    694:        }
                    695: 
                    696:        RW_UNLOCK (str_mem->sm_head_lock, prev_pl);
                    697:        return scan;
                    698: }
                    699: 
                    700: 
                    701: /*
                    702:  * This function adds a stream head to the global list. If an entry with the
                    703:  * same ID is present on the list, this operation fails.
                    704:  *
                    705:  * The stream head should be locked against further opens at this point.
                    706:  *
                    707:  * The return value is 0 on success, -1 on error.
                    708:  */
                    709: 
                    710: #if    __USE_PROTO__
                    711: __LOCAL__ int (SHEAD_ADD) (shead_t * sheadp)
                    712: #else
                    713: __LOCAL__ int
                    714: SHEAD_ADD __ARGS ((sheadp))
                    715: shead_t              * sheadp;
                    716: #endif
                    717: {
                    718:        pl_t            prev_pl;
                    719:        shead_t       * scan;
                    720:        slist_id_t      id;
                    721: 
                    722:        id = SHEAD_ID (sheadp);
                    723: 
                    724:        ASSERT (sheadp->sh_ref_count == 1);
                    725:        ASSERT ((sheadp->sh_lock_mask & SH_OPENCLOSE) != 0);
                    726: 
                    727:        prev_pl = RW_WRLOCK (str_mem->sm_head_lock, plstr);
                    728: 
                    729:        for (scan = str_mem->sm_streams [id] ; scan != NULL ;
                    730:             scan = scan->sh_next)  {
                    731: 
                    732:                if (scan->sh_dev == sheadp->sh_dev) {
                    733:                        /*
                    734:                         * We have found a conflict. Unlock the list and
                    735:                         * return an error.
                    736:                         */
                    737: 
                    738:                        RW_UNLOCK (str_mem->sm_head_lock, prev_pl);
                    739:                        return -1;
                    740:                }
                    741:        }
                    742: 
                    743:        sheadp->sh_next = str_mem->sm_streams [id];
                    744:        str_mem->sm_streams [id] = sheadp;
                    745: 
                    746:        RW_UNLOCK (str_mem->sm_head_lock, prev_pl);
                    747:        return 0;
                    748: }
                    749: 
                    750: 
                    751: /*
                    752:  * This function changes the device number of a stream head for a clone open
                    753:  * situation. The "st_dev" field of the stream head has to be changed with
                    754:  * the stream head list lock held for writing to avoid confusing anyone who
                    755:  * is looking for the original device number.
                    756:  *
                    757:  * Furthermore, the rename can fail because the new number is already in use.
                    758:  * The return value is -1 on error, or 0 on success.
                    759:  */
                    760: 
                    761: #if    __USE_PROTO__
                    762: __LOCAL__ int (SHEAD_RENAME) (shead_t * sheadp, n_dev_t dev)
                    763: #else
                    764: __LOCAL__ int
                    765: SHEAD_RENAME __ARGS ((sheadp, dev))
                    766: shead_t              * sheadp;
                    767: n_dev_t                dev;
                    768: #endif
                    769: {
                    770:        pl_t            prev_pl;
                    771:        shead_t       * scan;
                    772:        int             ok = 0;         /* flag whether stream is on list */
                    773:        slist_id_t      id;
                    774: 
                    775:        id = SHEAD_ID (sheadp);
                    776: 
                    777:        prev_pl = RW_WRLOCK (str_mem->sm_head_lock, plstr);
                    778: 
                    779:        for (scan = str_mem->sm_streams [id] ; scan != NULL ;
                    780:             scan = scan->sh_next) {
                    781: 
                    782:                if (scan->sh_dev == dev) {
                    783:                        /*
                    784:                         * We have found a conflict. Unlock the list and
                    785:                         * return an error.
                    786:                         */
                    787: 
                    788:                        RW_UNLOCK (str_mem->sm_head_lock, prev_pl);
                    789:                        return -1;
                    790:                }
                    791: 
                    792:                if (scan == sheadp)
                    793:                        ok ++;          /* Ok, we saw the item */
                    794:        }
                    795: 
                    796:        /*
                    797:         * All OK, now change the name of the original stream head.
                    798:         */
                    799: 
                    800:        sheadp->sh_dev = dev;
                    801:        RW_UNLOCK (str_mem->sm_head_lock, prev_pl);
                    802: 
                    803:        if (! ok)
                    804:                cmn_err (CE_WARN, "SHEAD_RENAME () of unlisted stream head");
                    805: 
                    806:        return 0;
                    807: }
                    808: 
                    809: 
                    810: /*
                    811:  * This function decrements the link count of the stream head; this may cause
                    812:  * the stream head to become unreferened, which means that the memory will be
                    813:  * reclaimed.
                    814:  */
                    815: 
                    816: #if    __USE_PROTO__
                    817: __LOCAL__ void (SHEAD_UNREFERENCE) (shead_t * sheadp)
                    818: #else
                    819: __LOCAL__ void
                    820: SHEAD_UNREFERENCE __ARGS ((sheadp))
                    821: shead_t              * sheadp;
                    822: #endif
                    823: {
                    824:        slist_id_t      id;
                    825:        int             unlink;
                    826: 
                    827:        SHEAD_ASSERT_LOCKED (sheadp);
                    828:        ASSERT (sheadp == SHEAD_MASTER (sheadp));
                    829:        ASSERT (sheadp->sh_lock_count > 0);
                    830: 
                    831:        id = SHEAD_ID (sheadp);
                    832: 
                    833:        /*
                    834:         * We will delete a stream if there are no references holding it open,
                    835:         * either pending locks or open references. If this is a stream pipe,
                    836:         * then we need to check boths ends of the stream pipe. Because this
                    837:         * function is called from the sleep-locking code, we know that
                    838:         * "sheadp" points to the master end.
                    839:         */
                    840: 
                    841:        unlink = sheadp->sh_open_count == 0 ||
                    842:                        (SHEAD_IS_PIPE (sheadp) &&
                    843:                                SHEAD_M2SLAVE (sheadp->sh_open_count) == 0);
                    844: 
                    845:        /*
                    846:         * We normally assume that we won't be unlinking the stream, because
                    847:         * to do that we need a lock on a global list (which is more expensive
                    848:         * that a list on an individual stream).
                    849:         *
                    850:         * However, due to the relative hierarchy positions of the locks, if
                    851:         * we discover we are likely to be the ones to dequeue the item, we
                    852:         * take out a write lock then.
                    853:         */
                    854: 
                    855:        if (sheadp->sh_lock_count > 1 && ! unlink) {
                    856:                /*
                    857:                 * Take the short path out.
                    858:                 */
                    859: 
                    860:                sheadp->sh_lock_count --;
                    861:                SHEAD_UNLOCK (sheadp, plbase);
                    862:                return;
                    863:        }
                    864: 
                    865:        /*
                    866:         * Escalate to a write lock on the stream head; we will need
                    867:         * to recheck to unlink condition after we escalate.
                    868:         */
                    869: 
                    870:        SHEAD_UNLOCK (sheadp, plbase);
                    871: 
                    872:        (void) RW_WRLOCK (str_mem->sm_head_lock, plstr);
                    873:        (void) SHEAD_LOCK (sheadp);
                    874: 
                    875:        unlink = -- sheadp->sh_lock_count == 0 &&
                    876:                        (sheadp->sh_open_count == 0 ||
                    877:                         (SHEAD_IS_PIPE (sheadp) &&
                    878:                          SHEAD_M2SLAVE (sheadp)->sh_open_count == 0));
                    879: 
                    880:        SHEAD_UNLOCK (sheadp, plstr);
                    881: 
                    882:        if (unlink) {
                    883:                shead_t       * scan;
                    884: 
                    885:                /*
                    886:                 * Remove from the singly-threaded list by searching for the
                    887:                 * immediate predecessor entry in the list (if any).
                    888:                 */
                    889: 
                    890:                if ((scan = str_mem->sm_streams [id]) == sheadp)
                    891:                        str_mem->sm_streams [id] = sheadp->sh_next;
                    892:                else
                    893:                        do {
                    894:                                if (scan->sh_next == sheadp) {
                    895: 
                    896:                                        scan->sh_next = sheadp->sh_next;
                    897:                                        break;
                    898:                                }
                    899:                        } while ((scan = scan->sh_next) != NULL);
                    900: 
                    901:                if (scan == NULL)
                    902:                        cmn_err (CE_WARN, "Failure unlinking stream from global directory");
                    903: 
                    904:                /*
                    905:                 * Note that stream pipes consist of four queues and
                    906:                 * two stream heads!
                    907:                 */
                    908: 
                    909:                SHEAD_DESTROY (sheadp);
                    910: 
                    911:                if (SHEAD_IS_PIPE (sheadp))
                    912:                        QUEUE_FREE (sheadp->sh_head, 4,
                    913:                                    2 * sizeof (* sheadp));
                    914:                else
                    915:                        QUEUE_FREE (sheadp->sh_head, 2, sizeof (* sheadp));
                    916:        }
                    917: 
                    918:        RW_UNLOCK (str_mem->sm_head_lock, plbase);
                    919: }
                    920: 
                    921: 
                    922: /*
                    923:  * This function attempts to locate a stream linked below another stream based
                    924:  * on the multiplexor ID. If the multiplexor ID is -1, then this function
                    925:  * returns the first stream found linked below the given upper stream. In
                    926:  * addition, the "cmd" value is used to distinguish between the persistent and
                    927:  * regular multiplexor ID spaces.
                    928:  */
                    929: 
                    930: #if    __USE_PROTO__
                    931: __LOCAL__ shead_t * (SHEAD_FIND_MUXID) (shead_t * upper, int cmd,
                    932:                                        muxid_t muxid)
                    933: #else
                    934: __LOCAL__ shead_t *
                    935: SHEAD_FIND_MUXID __ARGS ((upper, cmd, muxid))
                    936: shead_t              * upper;
                    937: int            cmd;
                    938: muxid_t                muxid;
                    939: #endif
                    940: {
                    941:        shead_t       * scan;
                    942:        pl_t            prev_pl;
                    943:        int             checklist;
                    944: 
                    945:        /*
                    946:         * Precook "cmd" for easier testing below.
                    947:         */
                    948: 
                    949:        cmd = (cmd == I_PLINK || cmd == I_PUNLINK) ? SH_PLINK : 0;
                    950: 
                    951: 
                    952:        /*
                    953:         * Now take out a lock to protect our list walking.
                    954:         */
                    955: 
                    956:        prev_pl = RW_RDLOCK (str_mem->sm_head_lock, plstr);
                    957: 
                    958:        for (checklist = DEV_SLIST ; checklist < SLIST_MAX ; checklist ++) {
                    959: 
                    960:                for (scan = str_mem->sm_streams [checklist] ; scan != NULL ;
                    961:                     scan = scan->sh_next) {
                    962: 
                    963:                        if (scan->sh_linked == upper &&
                    964:                            (scan->sh_flags & SH_PLINK) == cmd &&
                    965:                            ((scan->sh_muxid == muxid) || muxid == -1)) {
                    966: 
                    967:                                goto done;
                    968:                        }
                    969:                }
                    970:        }
                    971: 
                    972: done:
                    973:        RW_UNLOCK (str_mem->sm_head_lock, prev_pl);
                    974: 
                    975:        return scan;
                    976: }
                    977: 
                    978: 
                    979: /*
                    980:  * A local helper function for stream head timeouts.
                    981:  */
                    982: 
                    983: #if    __USE_PROTO__
                    984: __LOCAL__ void shead_timer_func (_VOID * arg)
                    985: #else
                    986: __LOCAL__ void
                    987: shead_timer_func (arg)
                    988: _VOID        * arg;
                    989: #endif
                    990: {
                    991:        shead_t       * sheadp = (shead_t *) arg;
                    992:        unsigned        locks;
                    993: 
                    994:        SHEAD_ASSERT_LOCKED (sheadp);
                    995: 
                    996:        SV_BROADCAST (sheadp->sh_wait_sv, 0);
                    997: 
                    998:        sheadp->sh_lock_mask &= ~ SH_TIMEFLAG;
                    999:        sheadp->sh_timeout_id = 0;
                   1000:        sheadp->sh_time_count = 0;
                   1001: 
                   1002:        /*
                   1003:         * Note that we advance "sh_time_count" on behalf of the processes
                   1004:         * that have the stream head locked.
                   1005:         */
                   1006: 
                   1007:        locks = sheadp->sh_lock_mask & SH_LOCK_MASK;
                   1008: 
                   1009:        while (locks != 0) {
                   1010: 
                   1011:                if ((locks & 1) != 0)
                   1012:                        sheadp->sh_time_count ++;
                   1013:                locks >>= 1;
                   1014:        }
                   1015: }
                   1016: 
                   1017: 
                   1018: /*
                   1019:  * This function is called when the time has come to actually initiate a
                   1020:  * timeout.
                   1021:  */
                   1022: 
                   1023: #if    __USE_PROTO__
                   1024: int (SHEAD_START_TIMEOUT) (shead_t * sheadp)
                   1025: #else
                   1026: int
                   1027: SHEAD_START_TIMEOUT __ARGS ((sheadp))
                   1028: shead_t              * sheadp;
                   1029: #endif
                   1030: {
                   1031:        __clock_t       the_time;
                   1032: 
                   1033:        SHEAD_ASSERT_LOCKED (sheadp);
                   1034: 
                   1035:        if ((sheadp->sh_lock_mask & SH_TIMEFLAG) == 0 ||
                   1036:            sheadp->sh_timeout_id != 0)
                   1037:                return 1;               /* do nothing */
                   1038: 
                   1039:        (void) drv_getparm (LBOLT, & the_time);
                   1040: 
                   1041:        sheadp->sh_timeout_id = ltimeout (shead_timer_func, sheadp,
                   1042:                                          sheadp->sh_timeout_tick - the_time,
                   1043:                                          sheadp->sh_basic_lockp, plstr);
                   1044: 
                   1045:        /*
                   1046:         * If the timeout could not be scheduled, we return 0 to indicate to
                   1047:         * the caller that it should timeout immediately, and run the timeout
                   1048:         * function to fake a normal timeout.
                   1049:         */
                   1050: 
                   1051:        if (sheadp->sh_timeout_id == 0) {
                   1052: 
                   1053:                shead_timer_func (sheadp);
                   1054:                return 0;
                   1055:        }
                   1056: 
                   1057:        return 1;
                   1058: }
                   1059: 
                   1060: 
                   1061: /*
                   1062:  * Indicate that no timeout will be necessary for this lock item.
                   1063:  */
                   1064: 
                   1065: #if    __USE_PROTO__
                   1066: void (SHEAD_NO_TIMEOUT) (shead_t * sheadp)
                   1067: #else
                   1068: void
                   1069: SHEAD_NO_TIMEOUT __ARGS ((sheadp))
                   1070: shead_t              * sheadp;
                   1071: #endif
                   1072: {
                   1073:        SHEAD_ASSERT_LOCKED (sheadp);
                   1074: 
                   1075:        ASSERT (sheadp->sh_time_count < sheadp->sh_lock_count);
                   1076: 
                   1077:        if (++ sheadp->sh_time_count == sheadp->sh_lock_count) {
                   1078:                /*
                   1079:                 * Since we are the last process to register an end time, we
                   1080:                 * get to actually initiate a timeout for the stream head.
                   1081:                 */
                   1082: 
                   1083:                (void) SHEAD_START_TIMEOUT (sheadp);
                   1084:        }
                   1085: }
                   1086: 
                   1087: 
                   1088: /*
                   1089:  * Indicate that a timeout is desired for this lock item at the given clock
                   1090:  * tick.
                   1091:  */
                   1092: 
                   1093: #if    __USE_PROTO__
                   1094: int (SHEAD_LOCK_TIMEOUT) (shead_t * sheadp, __clock_t end_time)
                   1095: #else
                   1096: int
                   1097: SHEAD_LOCK_TIMEOUT __ARGS ((sheadp, end_time))
                   1098: shead_t              * sheadp;
                   1099: __clock_t      end_time;
                   1100: #endif
                   1101: {
                   1102:        __clock_t       the_time;
                   1103: 
                   1104:        SHEAD_ASSERT_LOCKED (sheadp);
                   1105: 
                   1106:        ASSERT (sheadp->sh_time_count < sheadp->sh_lock_count);
                   1107: 
                   1108: 
                   1109:        /*
                   1110:         * If our horizon falls before the current latest value (or if there
                   1111:         * is no latest value), select our horizon time. If the horizon time
                   1112:         * is *before* the current time, return 0.
                   1113:         *
                   1114:         * Comparing time values introduces the usual problems when dealing
                   1115:         * with sequence spaces in C. While the following expression is not
                   1116:         * as efficient as relying on the semantics of unsigned->signed
                   1117:         * casting, avoiding implementation-defined behaviour is important.
                   1118:         *
                   1119:         * "clock_t" MUST be unsigned for this to work.
                   1120:         */
                   1121: 
                   1122:        ASSERT ((__clock_t) -1 > 0);
                   1123: 
                   1124:        (void) drv_getparm (LBOLT, & the_time);
                   1125: 
                   1126:        if ((__clock_t) (the_time - end_time) < ((__clock_t) -1 >> 1)) {
                   1127:                /*
                   1128:                 * The indicated time has already passed, so we return a
                   1129:                 * timeout indication directly.
                   1130:                 */
                   1131: 
                   1132:                sheadp->sh_time_count ++;
                   1133:                return 0;
                   1134:        }
                   1135: 
                   1136: 
                   1137:        if ((sheadp->sh_lock_mask & SH_TIMEFLAG) == 0 ||
                   1138:            (__clock_t) (sheadp->sh_timeout_tick - end_time) <
                   1139:                        ((__clock_t) -1 >> 1)) {
                   1140:                /*
                   1141:                 * "end_time" will occur before the current latest time. If
                   1142:                 * a timeout has been scheduled, we cancel it because we want
                   1143:                 * to post a more recent one.
                   1144:                 */
                   1145: 
                   1146:                if (sheadp->sh_timeout_id != 0) {
                   1147: 
                   1148:                        untimeout (sheadp->sh_timeout_id);
                   1149:                        sheadp->sh_timeout_id = 0;
                   1150:                }
                   1151: 
                   1152:                sheadp->sh_lock_mask |= SH_TIMEFLAG;
                   1153:        }
                   1154: 
                   1155:        if (++ sheadp->sh_time_count == sheadp->sh_lock_count) {
                   1156:                /*
                   1157:                 * Since we are the last process to register an end time, we
                   1158:                 * get to actually initiate a timeout for the stream head.
                   1159:                 */
                   1160: 
                   1161:                return SHEAD_START_TIMEOUT (sheadp);
                   1162:        } else {
                   1163:                /*
                   1164:                 * We can go to sleep and rely on someone else to actually
                   1165:                 * intiate the timeout.
                   1166:                 */
                   1167: 
                   1168:                return 1;
                   1169:        }
                   1170: }
                   1171: 
                   1172: 
                   1173: /*
                   1174:  * This function is used when a process wants to cancel a timeout after having
                   1175:  * registered one.
                   1176:  */
                   1177: 
                   1178: #if    __USE_PROTO__
                   1179: void (SHEAD_END_TIMEOUT) (shead_t * sheadp)
                   1180: #else
                   1181: void
                   1182: SHEAD_END_TIMEOUT __ARGS ((sheadp))
                   1183: shead_t              * sheadp;
                   1184: #endif
                   1185: {
                   1186:        SHEAD_ASSERT_LOCKED (sheadp);
                   1187: 
                   1188:        if (sheadp->sh_timeout_id != 0) {
                   1189: 
                   1190:                ASSERT (sheadp->sh_time_count == sheadp->sh_lock_count + 1);
                   1191:                sheadp->sh_time_count --;
                   1192:        }
                   1193: }
                   1194: 
                   1195: 
                   1196: /*
                   1197:  * This function is used when a lock holder wishes to sleep waiting for a
                   1198:  * timeout.
                   1199:  */
                   1200: 
                   1201: #if    __USE_PROTO__
                   1202: int (SHEAD_LOCKED_TIMEOUT) (shead_t * sheadp, __clock_t end_time)
                   1203: #else
                   1204: int
                   1205: SHEAD_LOCKED_TIMEOUT __ARGS ((sheadp, end_time))
                   1206: shead_t              * sheadp;
                   1207: __clock_t      end_time;
                   1208: #endif
                   1209: {
                   1210:        SHEAD_ASSERT_LOCKED (sheadp);
                   1211: 
                   1212:        ASSERT (sheadp->sh_time_count > 0);
                   1213: 
                   1214:        sheadp->sh_time_count --;
                   1215: 
                   1216:        return SHEAD_LOCK_TIMEOUT (sheadp, end_time);
                   1217: }
                   1218: 
                   1219: 
                   1220: /*
                   1221:  * Common code to test whether a stream has experienced an error condition.
                   1222:  */
                   1223: 
                   1224: #define        _shead_error(sheadp,mode) \
                   1225:                (SHEAD_ASSERT_LOCKED (sheadp), \
                   1226:                 sheadp->sh_linked != NULL ? EINVAL : \
                   1227:                   ((mode) & FWRITE) != 0 && sheadp->sh_werrcode != 0 ? \
                   1228:                        sheadp->sh_werrcode : \
                   1229:                     ((mode) & FREAD) != 0 ? sheadp->sh_rerrcode : 0)
                   1230: 
                   1231: /*
                   1232:  * This function tests for error or hangup conditions on the stream head given
                   1233:  * by "sheadp". It assumes that the caller holds a basic lock on the stream
                   1234:  * head. If an error or hangup condition exists then the basic lock is
                   1235:  * unlocked and a non-zero error number is returned.
                   1236:  */
                   1237: 
                   1238: #if    __USE_PROTO__
                   1239: __LOCAL__ int (SHEAD_ERRHUP_LOCKED) (shead_t * sheadp, int mode)
                   1240: #else
                   1241: __LOCAL__ int
                   1242: SHEAD_ERRHUP_LOCKED __ARGS ((sheadp, mode))
                   1243: shead_t              * sheadp;
                   1244: int            mode;
                   1245: #endif
                   1246: {
                   1247:        int             retval;
                   1248: 
                   1249:        SHEAD_ASSERT_LOCKED (sheadp);
                   1250: 
                   1251:        if ((retval = _shead_error (sheadp, mode)) != 0 ||
                   1252:            ((mode & (FREAD | FWRITE)) != 0 &&
                   1253:                    (retval = ENXIO, SHEAD_HANGUP (sheadp) != 0))) {
                   1254: 
                   1255:                SHEAD_UNLOCK (sheadp, plbase);
                   1256:                return retval;
                   1257:        }
                   1258: 
                   1259:        return 0;
                   1260: }
                   1261: 
                   1262: 
                   1263: /*
                   1264:  * Definitions use for the "interruptible" parameter to SHEAD_WAIT () and
                   1265:  * SHEAD_LOCK ().
                   1266:  */
                   1267: 
                   1268: enum {
                   1269:        DONT_SIGNAL = 0,
                   1270:        CHECK_SIGNALS = 1
                   1271: };
                   1272: 
                   1273: 
                   1274: /*
                   1275:  * This function is the common interface to waiting for an event at a stream
                   1276:  * head. It borrows the same synchronization variable used by the stream head
                   1277:  * locking code in this implementation.
                   1278:  *
                   1279:  * We return 0 on success or an error number on failure.
                   1280:  */
                   1281: 
                   1282: #if    __USE_PROTO__
                   1283: __LOCAL__ int (SHEAD_WAIT) (shead_t * sheadp, int mode, cat_t category,
                   1284:                            int interruptible)
                   1285: #else
                   1286: __LOCAL__ int
                   1287: SHEAD_WAIT __ARGS ((sheadp, mode, category, interruptible))
                   1288: shead_t              * sheadp;
                   1289: int            mode;
                   1290: cat_t          category;
                   1291: int            interruptible;
                   1292: #endif
                   1293: {
                   1294:        int             retval;
                   1295: 
                   1296:        SHEAD_ASSERT_LOCKED (sheadp);
                   1297: 
                   1298:        /*
                   1299:         * Test for error/hangup conditions before we sleep.
                   1300:         */
                   1301: 
                   1302:        if ((retval = SHEAD_ERRHUP_LOCKED (sheadp, mode)) != 0)
                   1303:                return retval;
                   1304: 
                   1305:        /*
                   1306:         * Register our interest in the kind of event that we are waiting for.
                   1307:         */
                   1308: 
                   1309:        sheadp->sh_lock_mask |= category;
                   1310: 
                   1311:        if (interruptible == CHECK_SIGNALS)
                   1312:                return SV_WAIT_SIG (sheadp->sh_wait_sv, primed,
                   1313:                                    sheadp->sh_basic_lockp) == 0 ? EINTR : 0;
                   1314:        else {
                   1315:                SV_WAIT (sheadp->sh_wait_sv, primed, sheadp->sh_basic_lockp);
                   1316:                return 0;
                   1317:        }
                   1318: }
                   1319: 
                   1320: 
                   1321: /*
                   1322:  * This function is a slightly different interface to SHEAD_WAIT (), used when
                   1323:  * the caller has been examining some property of a queue and wishes to go
                   1324:  * to sleep atomically. A frozen queue is not suitable for passing to
                   1325:  * SV_WAIT_SIG (), so we acquire the stream head global lock and then unfreeze
                   1326:  * the queue on behalf of the caller. This yields correct behaviour because
                   1327:  * SHEAD_WAKE () also attempts to acquire the stream head global lock; any
                   1328:  * modification to a stream queue resulting in a wakeup request will follow
                   1329:  * the same locking sequence.
                   1330:  */
                   1331: 
                   1332: #if    __USE_PROTO__
                   1333: __LOCAL__ int (SHEAD_WAIT_NONBLOCK) (shead_t * sheadp, int mode,
                   1334:                                     cat_t category, int interruptible)
                   1335: #else
                   1336: __LOCAL__ int
                   1337: SHEAD_WAIT_NONBLOCK __ARGS ((sheadp, mode, category, interruptible))
                   1338: shead_t              * sheadp;
                   1339: int            mode;
                   1340: cat_t          category;
                   1341: int            interruptible;
                   1342: #endif
                   1343: {
                   1344:        SHEAD_ASSERT_LOCKED (sheadp);
                   1345: 
                   1346:        if ((mode & (FNDELAY | FNONBLOCK)) != 0) {
                   1347: 
                   1348:                SHEAD_UNLOCK (sheadp, plbase);
                   1349:                return EAGAIN;
                   1350:        }
                   1351: 
                   1352:        return SHEAD_WAIT (sheadp, mode, category, interruptible);
                   1353: }
                   1354: 
                   1355: 
                   1356: /*
                   1357:  * This function is used by lower-level code to signal events to functions
                   1358:  * that have waited via SHEAD_WAIT (), above.
                   1359:  */
                   1360: 
                   1361: #if    __USE_PROTO__
                   1362: void (SHEAD_WAKE) (shead_t * sheadp, cat_t category)
                   1363: #else
                   1364: void
                   1365: SHEAD_WAKE __ARGS ((sheadp, category))
                   1366: shead_t              * sheadp;
                   1367: cat_t          category;
                   1368: #endif
                   1369: {
                   1370:        pl_t            prev_pl;
                   1371: 
                   1372:        prev_pl = SHEAD_LOCK (sheadp);
                   1373: 
                   1374:        if ((sheadp->sh_lock_mask & category) != 0) {
                   1375: 
                   1376:                sheadp->sh_lock_mask &= ~ category;
                   1377:                SV_BROADCAST (sheadp->sh_wait_sv, 0);
                   1378:        }
                   1379: 
                   1380:        SHEAD_UNLOCK (sheadp, prev_pl);
                   1381: }
                   1382: 
                   1383: 
                   1384: /*
                   1385:  * Common code for locking stream head, shared between open-style locks (which
                   1386:  * may need to allocate new head structures and need special coordination
                   1387:  * with the stream head destruction code) and other kinds.
                   1388:  *
                   1389:  * We expect that the caller will have taken out a basic lock on the stream
                   1390:  * head and that the caller will have incremented the lock count of the item
                   1391:  * to prevent it from being deallocated while we wait.
                   1392:  */
                   1393: 
                   1394: #if    __USE_PROTO__
                   1395: int (SHEAD_SLEEP_LOCKED) (shead_t * sheadp, cat_t category, __clock_t timeout,
                   1396:                          int interruptible)
                   1397: #else
                   1398: int
                   1399: SHEAD_SLEEP_LOCKED __ARGS ((sheadp, category, timeout, interruptible))
                   1400: shead_t              * sheadp;
                   1401: cat_t          category;
                   1402: __clock_t      timeout;
                   1403: int            interruptible;
                   1404: #endif
                   1405: {
                   1406:        __clock_t       end_time;       /* LBOLT when we time out */
                   1407:        n_dev_t         devno;
                   1408:        int             retval;
                   1409: 
                   1410:        SHEAD_ASSERT_LOCKED (sheadp);
                   1411: 
                   1412:        /*
                   1413:         * Since we expect the caller to have incremented the lock count, then
                   1414:         * the caller must have selected the master end of the stream pipe.
                   1415:         */
                   1416: 
                   1417:        ASSERT (sheadp == SHEAD_MASTER (sheadp));
                   1418: 
                   1419:        /*
                   1420:         * If we are going to be (possibly) timing out, calculate the time
                   1421:         * when that will happen.
                   1422:         */
                   1423: 
                   1424:        if (timeout > 0) {
                   1425: 
                   1426:                (void) drv_getparm (LBOLT, & end_time);
                   1427:                end_time += timeout;
                   1428:        }
                   1429: 
                   1430: 
                   1431:        /*
                   1432:         * There is a special case that we have to note; in the case of a
                   1433:         * clone open, the device number of a stream head may be altered by
                   1434:         * the driver open routine. In this case, drivers waiting on the old
                   1435:         * number will have to be notified and give up on their lock attempts.
                   1436:         */
                   1437: 
                   1438:        devno = sheadp->sh_dev;
                   1439: 
                   1440: 
                   1441:        /*
                   1442:         * Now we begin the actual business of locking the stream head.
                   1443:         */
                   1444: 
                   1445:        for (;;) {
                   1446:                int             sigflg;
                   1447: 
                   1448:                /*
                   1449:                 * Check to see whether our category is blocked. At this point
                   1450:                 * we hold "global_lock".
                   1451:                 *
                   1452:                 * An earlier verson of this code had an explicit check for
                   1453:                 * final close. I have no idea why, because if a stream is in
                   1454:                 * final close, what else can happen?
                   1455:                 */
                   1456: 
                   1457:                if ((sheadp->sh_lock_mask & category) == 0) {
                   1458:                        /*
                   1459:                         * We can acquire a lock on the stream head in our
                   1460:                         * chosen category, so we do so. Since we will not
                   1461:                         * need a timeout, we increment the timeout count.
                   1462:                         *
                   1463:                         * If during later processing we need a timeout, we
                   1464:                         * hook into this mechanism, but for simplicity we
                   1465:                         * assume we won't.
                   1466:                         */
                   1467: 
                   1468:                        SHEAD_NO_TIMEOUT (sheadp);
                   1469: 
                   1470:                        SHEAD_UNLOCK (sheadp, plbase);
                   1471: 
                   1472:                        sheadp->sh_lock_mask |= category;
                   1473: 
                   1474:                        return 0;
                   1475:                }
                   1476: 
                   1477: 
                   1478:                /*
                   1479:                 * We need to wait, interruptibly. We might also want to time
                   1480:                 * out at some stage.
                   1481:                 *
                   1482:                 * We (optionally) call a function to register the time we
                   1483:                 * want to expire; this function also takes care of checking
                   1484:                 * for timeout expiry.
                   1485:                 */
                   1486: 
                   1487:                if (timeout == 0)
                   1488:                        SHEAD_NO_TIMEOUT (sheadp);
                   1489:                else if (SHEAD_LOCK_TIMEOUT (sheadp, end_time) == 0) {
                   1490:                        /*
                   1491:                         * Our horizon time has passed, so we return ETIME.
                   1492:                         */
                   1493: 
                   1494:                        retval = ETIME;
                   1495:                        break;
                   1496:                }
                   1497: 
                   1498: 
                   1499:                /*
                   1500:                 * Now we can wait. No matter how we wake up, we will need
                   1501:                 * to relock the global basic lock.
                   1502:                 *
                   1503:                 * The caller may not want this wait to be interruptible; this
                   1504:                 * is reasonable when the lock is being acquired in some
                   1505:                 * nested context where things are difficult to back out.
                   1506:                 */
                   1507: 
                   1508:                if (interruptible != DONT_SIGNAL)
                   1509:                        sigflg = SV_WAIT_SIG (sheadp->sh_wait_sv, primed,
                   1510:                                              sheadp->sh_basic_lockp);
                   1511:                else {
                   1512:                        SV_WAIT (sheadp->sh_wait_sv, primed,
                   1513:                                 sheadp->sh_basic_lockp);
                   1514:                        sigflg = 1;
                   1515:                }
                   1516: 
                   1517:                (void) SHEAD_LOCK (sheadp);
                   1518: 
                   1519:                if (sigflg == 0) {
                   1520:                        /*
                   1521:                         * We have been interrupted by a signal, so bang out
                   1522:                         * to the caller with EINTR.
                   1523:                         */
                   1524: 
                   1525:                        retval = EINTR;
                   1526:                        break;
                   1527:                } else if (sheadp->sh_dev != devno) {
                   1528:                        /*
                   1529:                         * The device number has been altered. Flag the fact
                   1530:                         * to the caller and give up this lock attempt.
                   1531:                         */
                   1532: 
                   1533:                        retval = ENODEV;
                   1534:                        break;
                   1535:                }
                   1536: 
                   1537: 
                   1538:                /*
                   1539:                 * Now we have the global basic lock, we can wrap around to
                   1540:                 * the start of the loop to recheck all our conditions.
                   1541:                 */
                   1542:        }
                   1543: 
                   1544: 
                   1545:        /*
                   1546:         * For some reason we are aborting the lock attempt. The code which
                   1547:         * make us take this exit path should have set "* retvalp" with an
                   1548:         * error code.
                   1549:         */
                   1550: 
                   1551:        if (sheadp->sh_time_count > sheadp->sh_lock_count) {
                   1552: 
                   1553:                sheadp->sh_time_count --;
                   1554:                ASSERT (sheadp->sh_time_count == sheadp->sh_lock_count);
                   1555: 
                   1556:                SHEAD_START_TIMEOUT (sheadp);
                   1557:        }
                   1558: 
                   1559:        SHEAD_UNREFERENCE (sheadp);
                   1560:        return retval;
                   1561: }
                   1562: 
                   1563: 
                   1564: /*
                   1565:  * Entry point for the stream head locking system for use by routines that
                   1566:  * already have a reference to the stream head. This entry performs checks for
                   1567:  * routine errors including linked streams.
                   1568:  */
                   1569: 
                   1570: #if    __USE_PROTO__
                   1571: int (SHEAD_SLEEP_LOCK) (shead_t * sheadp, cat_t category, __clock_t timeout,
                   1572:                        int interruptible)
                   1573: #else
                   1574: int
                   1575: SHEAD_SLEEP_LOCK __ARGS ((sheadp, category, timeout, interruptible))
                   1576: shead_t              * sheadp;
                   1577: cat_t          category;
                   1578: __clock_t      timeout;
                   1579: int            interruptible;
                   1580: #endif
                   1581: {
                   1582:        SHEAD_LOCK (sheadp);
                   1583: 
                   1584:        /*
                   1585:         * The read and write lock modes are experimental. We have a mode bit
                   1586:         * that says whether or not we are really interested in honouring
                   1587:         * these lock types.
                   1588:         */
                   1589: 
                   1590:        if (((sheadp->sh_flags & SH_RWLOCKING) == 0 &&
                   1591:             (category & ~ (SH_READ_LOCK | SH_WRITE_LOCK)) == 0)) {
                   1592: 
                   1593:                SHEAD_UNLOCK (sheadp, plbase);
                   1594:                return 0;
                   1595:        }
                   1596: 
                   1597: 
                   1598:        /*
                   1599:         * If the caller wishes to lock a stream head that is part of a stream
                   1600:         * pipe, we direct the lock attempt to the master stream head of the
                   1601:         * pair that form the pipe. This ensures that any attempt to modify
                   1602:         * the state of the pipe from either end will be properly single-
                   1603:         * threaded.
                   1604:         *
                   1605:         * Note that we *must* perform a similar redirection in the unlock.
                   1606:         */
                   1607: 
                   1608:        sheadp = SHEAD_MASTER (sheadp);
                   1609: 
                   1610: 
                   1611:        /*
                   1612:         * We have a pointer to the stream head and hold a global basic lock.
                   1613:         *
                   1614:         * With the protection of the basic lock, we increment the lock count.
                   1615:         */
                   1616: 
                   1617:        sheadp->sh_lock_count ++;
                   1618: 
                   1619:        /*
                   1620:         * Now we begin the actual business of locking the stream head.
                   1621:         */
                   1622: 
                   1623:        return SHEAD_SLEEP_LOCKED (sheadp, category, timeout, interruptible);
                   1624: }
                   1625: 
                   1626: 
                   1627: /*
                   1628:  * This is a special form of the stream head locking code for open () access,
                   1629:  * which specially coordinates with the close code to discover when to
                   1630:  * allocate a new stream head, and carefully avoids the problems that can
                   1631:  * occur if the stream head were to be deallocated which we are waiting for
                   1632:  * it to be unlocked.
                   1633:  *
                   1634:  * We also have to do some funky stuff here because of clone opens.
                   1635:  */
                   1636: 
                   1637: #if    __USE_PROTO__
                   1638: shead_t * (SHEAD_OPEN_LOCK) (n_dev_t dev, struct streamtab * stabp,
                   1639:                             int * retvalp)
                   1640: #else
                   1641: shead_t *
                   1642: SHEAD_OPEN_LOCK __ARGS ((dev, stabp, retvalp))
                   1643: n_dev_t                dev;
                   1644: struct streamtab
                   1645:              * stabp;
                   1646: int          * retvalp;
                   1647: #endif
                   1648: {
                   1649:        shead_t       * sheadp;
                   1650: 
                   1651:        ASSERT (retvalp != NULL);
                   1652: 
                   1653:        /*
                   1654:         * PHASE 1: Locate the stream head. If the stream head did not
                   1655:         * previously exist, we might be able to lock it immediately by virtue
                   1656:         * of being able to create it that way. Of course, simultaneous open
                   1657:         * attempts might result in this looping as only once of the created
                   1658:         * stream heads will be entered in the stream directory.
                   1659:         */
                   1660: 
                   1661:        * retvalp = 0;
                   1662: 
                   1663:        for (;;) {
                   1664:                queue_t       * q;
                   1665: 
                   1666:                /*
                   1667:                 * The first thing we need to do is *find* the stream. We call
                   1668:                 * a find routine that increments a reference count so that
                   1669:                 * we can be sure that the stream will not be deallocated
                   1670:                 * while we wait.
                   1671:                 */
                   1672: 
                   1673:                if ((sheadp = SHEAD_FIND_AND_LOCK (dev, DEV_SLIST)) != NULL) {
                   1674:                        /*
                   1675:                         * Sleep lock time; our call to SHEAD_FIND_AND_LOCK ()
                   1676:                         * will have incremented the lock count of the stream
                   1677:                         * head so it won't disappear underneath us.
                   1678:                         */
                   1679: 
                   1680:                        * retvalp = SHEAD_SLEEP_LOCKED (sheadp, SH_OPENCLOSE,
                   1681:                                                        0, CHECK_SIGNALS);
                   1682: 
                   1683:                        if (retvalp != 0) {
                   1684:                                /*
                   1685:                                 * If the lock attempt failed because of a
                   1686:                                 * clone open changing the stream head's
                   1687:                                 * device number, we need to try again.
                   1688:                                 */
                   1689: 
                   1690:                                sheadp = NULL;
                   1691: 
                   1692:                                if (* retvalp == ENODEV)
                   1693:                                        continue;
                   1694:                        }
                   1695: 
                   1696:                        return sheadp;
                   1697:                }
                   1698: 
                   1699: 
                   1700:                /*
                   1701:                 * There ain't no such stream, so we have to allocate a queue
                   1702:                 * pair.
                   1703:                 */
                   1704: 
                   1705:                if ((q = QUEUE_ALLOC (2, sizeof (* sheadp))) == NULL) {
                   1706: 
                   1707:                        * retvalp = ENFILE;
                   1708:                        return NULL;
                   1709:                }
                   1710: 
                   1711:                sheadp = (shead_t *) q->q_ptr;
                   1712: 
                   1713:                SHEAD_INIT (sheadp, stabp, dev, q);
                   1714: 
                   1715:                sheadp->sh_ref_count = 1;
                   1716:                sheadp->sh_lock_mask = SH_OPENCLOSE;
                   1717:                sheadp->sh_time_count = sheadp->sh_lock_count = 1;
                   1718: 
                   1719:                if (SHEAD_ADD (sheadp) == 0)
                   1720:                        return sheadp;
                   1721: 
                   1722:                /*
                   1723:                 * The new queue could not be added to the stream
                   1724:                 * directory, presumably because of a nearly
                   1725:                 * simultaneous open attempt.
                   1726:                 *
                   1727:                 * We undo the allocation we wrought before retrying.
                   1728:                 */
                   1729: 
                   1730:                SHEAD_DESTROY (sheadp);
                   1731:                QUEUE_FREE (q, 2, sizeof (* sheadp));
                   1732:        }
                   1733: }
                   1734: 
                   1735: 
                   1736: /*
                   1737:  * Unlock a stream head.
                   1738:  */
                   1739: 
                   1740: #if    __USE_PROTO__
                   1741: void (SHEAD_SLEEP_UNLOCK) (shead_t * sheadp, cat_t category)
                   1742: #else
                   1743: void
                   1744: SHEAD_SLEEP_UNLOCK __ARGS ((sheadp, category))
                   1745: shead_t              * sheadp;
                   1746: cat_t          category;
                   1747: #endif
                   1748: {
                   1749:        ASSERT (sheadp != NULL);
                   1750:        ASSERT (category != 0);
                   1751: 
                   1752:        /*
                   1753:         * See if locking is necessary for the read and write operations.
                   1754:         */
                   1755: 
                   1756:        if ((sheadp->sh_flags & SH_RWLOCKING) == 0 &&
                   1757:            (category & ~ (SH_READ_LOCK | SH_WRITE_LOCK)) == 0) {
                   1758:                /*
                   1759:                 * Since we don't actually acquire any locks, we return early.
                   1760:                 */
                   1761: 
                   1762:                ASSERT (sheadp->sh_open_count > 0);
                   1763:                return;
                   1764:        }
                   1765: 
                   1766:        ASSERT (sheadp->sh_lock_count > 0);
                   1767:        ASSERT ((sheadp->sh_lock_mask & category) == category);
                   1768: 
                   1769: 
                   1770:        /*
                   1771:         * We direct all locking operations on the slave part of a stream pipe
                   1772:         * to the master end.
                   1773:         */
                   1774: 
                   1775:        sheadp = SHEAD_MASTER (sheadp);
                   1776: 
                   1777:        (void) SHEAD_LOCK (sheadp);
                   1778: 
                   1779: 
                   1780:        /*
                   1781:         * Unlike SHEAD_WAKE (), we can assume that our category mask will not
                   1782:         * be NULL because of the difference in interpretation between lock
                   1783:         * flags (indicating a holder) and wait flags (indicating a waiter).
                   1784:         */
                   1785: 
                   1786:        sheadp->sh_lock_mask &= ~ category;
                   1787:        SV_BROADCAST (sheadp->sh_wait_sv, 0);
                   1788: 
                   1789: 
                   1790:        /*
                   1791:         * We don't use SHEAD_END_TIMEOUT () here since we are a lock holder
                   1792:         * and shead_time_func () makes sure to keep our "sh_time_count" entry
                   1793:         * greater than 0.
                   1794:         */
                   1795: 
                   1796:        ASSERT (sheadp->sh_time_count > 0);
                   1797:        sheadp->sh_time_count --;
                   1798: 
                   1799:        if (sheadp->sh_time_count == 0 && sheadp->sh_timeout_id != 0) {
                   1800:                /*
                   1801:                 * Since there is no-one waiting for anything, cancel any
                   1802:                 * pending timeouts.
                   1803:                 */
                   1804: 
                   1805:                untimeout (sheadp->sh_timeout_id);
                   1806: 
                   1807:                sheadp->sh_lock_mask &= SH_TIMEFLAG;
                   1808:                sheadp->sh_timeout_id = 0;
                   1809:        }
                   1810: 
                   1811: 
                   1812:        /*
                   1813:         * Now that we have done everything that requires access to the stream
                   1814:         * head, decrement the lock count.
                   1815:         */
                   1816: 
                   1817:         SHEAD_UNREFERENCE (sheadp);
                   1818: }
                   1819: 
                   1820: 
                   1821: /*
                   1822:  * This local function asserts that the caller holds a lock on the stream head.
                   1823:  * Since we can't really determine that, we actually just assert that someone
                   1824:  * has a lock on the stream head.
                   1825:  */
                   1826: 
                   1827: #if    __USE_PROTO__
                   1828: __LOCAL__ void (ASSERT_SLEEP_LOCKED) (shead_t * sheadp, cat_t category)
                   1829: #else
                   1830: __LOCAL__ void
                   1831: ASSERT_SLEEP_LOCKED __ARGS ((sheadp, category))
                   1832: shead_t              * sheadp;
                   1833: cat_t          category;
                   1834: #endif
                   1835: {
                   1836:        ASSERT (sheadp != NULL);
                   1837: 
                   1838:        if (SHEAD_IS_PIPE (sheadp))
                   1839:                sheadp = SHEAD_MASTER (sheadp);
                   1840: 
                   1841:        ASSERT ((sheadp->sh_lock_mask & category) == category);
                   1842: }
                   1843: 
                   1844: 
                   1845: /*
                   1846:  * Wait for a queue to drain. The caller must have the stream head locked when
                   1847:  * calling this function.
                   1848:  */
                   1849: 
                   1850: #if    __USE_PROTO__
                   1851: __LOCAL__ void (DRAIN_QUEUE) (shead_t * sheadp, queue_t * q)
                   1852: #else
                   1853: __LOCAL__ void
                   1854: DRAIN_QUEUE __ARGS ((sheadp, q))
                   1855: shead_t              * sheadp;
                   1856: queue_t              * q;
                   1857: #endif
                   1858: {
                   1859:        __clock_t       end_time;
                   1860: 
                   1861:        ASSERT_SLEEP_LOCKED (sheadp, SH_OPENCLOSE);
                   1862: 
                   1863:        /*
                   1864:         * When we are in final close, the STREAMS specification says we
                   1865:         * should wait for up to 15 seconds for the write-side queue to be
                   1866:         * drained of data, unless we are in O_NONBLOCK mode.
                   1867:         *
                   1868:         * If we can't post the timeout, then don't wait.
                   1869:         */
                   1870: 
                   1871:        if (sheadp->sh_cltime == 0)
                   1872:                return;
                   1873: 
                   1874:        (void) drv_getparm (LBOLT, & end_time);
                   1875:        end_time += sheadp->sh_cltime;
                   1876: 
                   1877:        for (;;) {
                   1878:                /*
                   1879:                 * We need to acquire a basic lock to pass to SV_WAIT (), and
                   1880:                 * the code that wakes us up will attempt to acquire the same
                   1881:                 * lock (see QUEUE_DRAINED ()). Since the wakeup code must
                   1882:                 * acquire the lock while holding the stream frozen, we must
                   1883:                 * do things in the same order to prevent the possibility of
                   1884:                 * deadlock.
                   1885:                 */
                   1886: 
                   1887:                (void) QFREEZE_TRACE (q, "DRAIN_QUEUE");
                   1888: 
                   1889:                if (q->q_first == NULL) {
                   1890:                        /*
                   1891:                         * No messages on the queue => our job is done.
                   1892:                         */
                   1893: 
                   1894:                        QUNFREEZE_TRACE (q, plbase);
                   1895:                        break;
                   1896:                }
                   1897: 
                   1898: 
                   1899:                /*
                   1900:                 * We are going to wait for this queue to become empty, so we
                   1901:                 * set a flag to indicate that we are interested in finding
                   1902:                 * out when that happens. Note that we don't ever clear the
                   1903:                 * flag in this routine; that is the responsibility of the
                   1904:                 * code which will wake us up.
                   1905:                 */
                   1906: 
                   1907:                q->q_flag |= QDRAIN;
                   1908: 
                   1909: 
                   1910:                /*
                   1911:                 * We don't build on SHEAD_WAIT (), although we do expect to
                   1912:                 * be woken up via SHEAD_WAKE (). We transfer our lock from
                   1913:                 * the queue to the stream head.
                   1914:                 */
                   1915: 
                   1916:                (void) SHEAD_LOCK (sheadp);
                   1917: 
                   1918:                QUNFREEZE_TRACE (q, plstr);
                   1919: 
                   1920: 
                   1921:                /*
                   1922:                 * Register when we want to time out. If that time has already
                   1923:                 * passed, then exit to the caller.
                   1924:                 */
                   1925: 
                   1926:                if (SHEAD_LOCKED_TIMEOUT (sheadp, end_time) == 0) {
                   1927: 
                   1928:                        SHEAD_UNLOCK (sheadp, plbase);
                   1929:                        return;
                   1930:                }
                   1931: 
                   1932:                sheadp->sh_lock_mask |= SH_DRAIN_WAIT;
                   1933: 
                   1934:                SV_WAIT (sheadp->sh_wait_sv, primed, sheadp->sh_basic_lockp);
                   1935: 
                   1936:                /*
                   1937:                 * We were signalled, so we try again.
                   1938:                 */
                   1939:        }
                   1940: }
                   1941: 
                   1942: 
                   1943: /*
                   1944:  * This function (used in the implementation of I_LIST ioctl ()) returns a
                   1945:  * count of the number of modules on the stream, including the topmost driver.
                   1946:  */
                   1947: 
                   1948: #if    __USE_PROTO__
                   1949: __LOCAL__ int (SHEAD_MODCOUNT) (shead_t * sheadp)
                   1950: #else
                   1951: __LOCAL__ int
                   1952: SHEAD_MODCOUNT __ARGS ((sheadp))
                   1953: shead_t              * sheadp;
                   1954: #endif
                   1955: {
                   1956:        pl_t            prev_pl;
                   1957:        int             count;
                   1958:        queue_t       * scan;
                   1959: 
                   1960:        ASSERT (sheadp != NULL);
                   1961: 
                   1962:        /*
                   1963:         * Note that we use SHEAD_MASTER () because this walk can be affected
                   1964:         * by attempts to push or pop queues from either end of a stream pipe.
                   1965:         * Using a single lock at the master end avoids problems with this.
                   1966:         */
                   1967: 
                   1968:        prev_pl = SHEAD_LOCK (SHEAD_MASTER (sheadp));
                   1969: 
                   1970:        count = 0;
                   1971: 
                   1972:        for (scan = W (sheadp->sh_head)->q_next ; scan != NULL ;
                   1973:             scan = scan->q_next) {
                   1974: 
                   1975:                if ((scan->q_flag & QPROCSOFF) == 0)
                   1976:                        count ++;
                   1977:        }
                   1978: 
                   1979:        SHEAD_UNLOCK (SHEAD_MASTER (sheadp), prev_pl);
                   1980: 
                   1981:        return count;
                   1982: }
                   1983: 
                   1984: 
                   1985: /*
                   1986:  * Utility routine to return the next write queue below the stream head. This
                   1987:  * routine deals with locking the stream head for the duration of the walk and
                   1988:  * also check whether the queue has been disabled with qprocsoff ().
                   1989:  */
                   1990: 
                   1991: #if    __USE_PROTO__
                   1992: __LOCAL__ queue_t * (TOP_QUEUE) (shead_t * sheadp)
                   1993: #else
                   1994: __LOCAL__ queue_t *
                   1995: TOP_QUEUE __ARGS ((sheadp))
                   1996: shead_t              * sheadp;
                   1997: #endif
                   1998: {
                   1999:        pl_t            prev_pl;
                   2000:        queue_t       * scan;
                   2001: 
                   2002:        ASSERT (sheadp != NULL);
                   2003: 
                   2004:        /*
                   2005:         * Note that we use SHEAD_MASTER () because this walk can be affected
                   2006:         * by attempts to push or pop queues from either end of a stream pipe.
                   2007:         * Using a single lock at the master end avoids problems with this.
                   2008:         */
                   2009: 
                   2010:        prev_pl = SHEAD_LOCK (SHEAD_MASTER (sheadp));
                   2011: 
                   2012:        scan = W (sheadp->sh_head)->q_next;
                   2013: 
                   2014:        while ((scan->q_flag & QPROCSOFF) != 0)
                   2015:                if ((scan = scan->q_next) == NULL)
                   2016:                        cmn_err (CE_PANIC, "Off end of stream in TOP_QUEUE ()");
                   2017: 
                   2018:        SHEAD_UNLOCK (SHEAD_MASTER (sheadp), prev_pl);
                   2019: 
                   2020:        return scan;
                   2021: }
                   2022: 
                   2023: 
                   2024: /*
                   2025:  * Utility routine for POP_MODULE () and the I_LOOK processing code that finds
                   2026:  * the queue entry for the first module on the stream (if any).
                   2027:  */
                   2028: 
                   2029: #if    __USE_PROTO__
                   2030: __LOCAL__ queue_t * (TOP_MODULE) (shead_t * sheadp)
                   2031: #else
                   2032: __LOCAL__ queue_t *
                   2033: TOP_MODULE __ARGS ((sheadp))
                   2034: shead_t              * sheadp;
                   2035: #endif
                   2036: {
                   2037:        queue_t       * scan;           /* module queue */
                   2038: 
                   2039:        /*
                   2040:         * We return the queue pointer if and only if the thing below the
                   2041:         * stream head is a module (not a driver) AND the module's read and
                   2042:         * write queues are not interchanged (as they would be at the
                   2043:         * crossover point of a STREAMS-based FIFO).
                   2044:         */
                   2045: 
                   2046:        scan = TOP_QUEUE (sheadp);
                   2047: 
                   2048:        if ((scan->q_flag & QREADR) !=
                   2049:                        (W (sheadp->sh_head)->q_flag & QREADR))
                   2050:                return NULL;
                   2051: 
                   2052:        /*
                   2053:         * The test to see whether "scan" is a module or driver does not need
                   2054:         * to involve QUEUE_NEXT (), since the exact value of 'q->q_next'
                   2055:         * isn't important to us, just whether or not it's NULL.
                   2056:         */
                   2057: 
                   2058:        {
                   2059:                pl_t            prev_pl;
                   2060:                queue_t       * next;
                   2061: 
                   2062:                prev_pl = QFREEZE_TRACE (scan, "TOP_MODULE");
                   2063: 
                   2064:                next = scan->q_next;
                   2065: 
                   2066:                QUNFREEZE_TRACE (scan, prev_pl);
                   2067: 
                   2068:                if (next == NULL)
                   2069:                        return NULL;
                   2070:        }
                   2071: 
                   2072:        return R (scan);
                   2073: }
                   2074: 
                   2075: 
                   2076: /*
                   2077:  * Code common to both POP_MODULE () and PUSH_MODULE () for removing and
                   2078:  * deallocating a queue pair from a stream.
                   2079:  */
                   2080: 
                   2081: #if    __USE_PROTO__
                   2082: __LOCAL__ void (POP_AND_FREE) (shead_t * sheadp, queue_t * module)
                   2083: #else
                   2084: __LOCAL__ void
                   2085: POP_AND_FREE __ARGS ((sheadp, module))
                   2086: shead_t              * sheadp;
                   2087: queue_t              * module;
                   2088: #endif
                   2089: {
                   2090:        pl_t            prev_pl;
                   2091:        pl_t            q_pl;
                   2092:        queue_t       * next;
                   2093: 
                   2094: 
                   2095:        /*
                   2096:         * Now we must unlink the module queue from the stream. To do this, we
                   2097:         * freeze each queue before we change it. However, that is not enough
                   2098:         * if we are on a stream pipe, since the stream head at the other end
                   2099:         * of the pipe could be trying to modify the same stream, and thus the
                   2100:         * same queue pointers that we are going to change.
                   2101:         *
                   2102:         * We work our way around this by defining a master/slave relationship
                   2103:         * between the ends of a pipe, and requiring that the slave end
                   2104:         * acquire an exclusive lock on the "sh_rwlockp" lock belonging to the
                   2105:         * master. Since the master and slave contend for the same lock, we
                   2106:         * can be confident no other concurrent modifications to the stream
                   2107:         * are possible.
                   2108:         */
                   2109: 
                   2110:        prev_pl = SHEAD_LOCK (SHEAD_MASTER (sheadp));
                   2111: 
                   2112:        next = W (sheadp->sh_head);
                   2113: 
                   2114:        ASSERT (next->q_next == W (module));
                   2115: 
                   2116:        q_pl = QFREEZE_TRACE (next, "POP_AND_FREE");
                   2117:        next->q_next = W (module)->q_next;
                   2118:        QUNFREEZE_TRACE (next, q_pl);
                   2119: 
                   2120: 
                   2121:        next = OTHERQ (next->q_next);
                   2122: 
                   2123:        ASSERT (next->q_next == module);
                   2124: 
                   2125:        q_pl = QFREEZE_TRACE (next, "POP_AND_FREE");
                   2126:        next->q_next = sheadp->sh_head;
                   2127:        QUNFREEZE_TRACE (next, q_pl);
                   2128: 
                   2129: 
                   2130:        SHEAD_UNLOCK (SHEAD_MASTER (sheadp), prev_pl);
                   2131: 
                   2132: 
                   2133:        /*
                   2134:         * Now we can de-initialize the queue pair and free the memory.
                   2135:         */
                   2136: 
                   2137:        QUEUE_FREE (module, 1, 0);
                   2138: }
                   2139: 
                   2140: 
                   2141: /*
                   2142:  * Pop a module from a stream. In order to request this, the caller must have
                   2143:  * the stream head sleep-locked for modification (see SHEAD_SLEEP_LOCK ()
                   2144:  * above).
                   2145:  *
                   2146:  * Returns 0 on success or an error number on failure.
                   2147:  */
                   2148: 
                   2149: #if    __USE_PROTO__
                   2150: int (POP_MODULE) (shead_t * sheadp, queue_t * q, int mode, cred_t * credp)
                   2151: #else
                   2152: int
                   2153: POP_MODULE __ARGS ((sheadp, q, mode, credp))
                   2154: shead_t              * sheadp;
                   2155: queue_t              * q;
                   2156: int            mode;
                   2157: cred_t       * credp;
                   2158: #endif
                   2159: {
                   2160:        int             retval;
                   2161: 
                   2162:        ASSERT (q != NULL);
                   2163:        ASSERT_SLEEP_LOCKED (sheadp, SH_OPENCLOSE);
                   2164: 
                   2165:        /*
                   2166:         * When a module is popped, it is blown away. If the module needs to
                   2167:         * be drained first (as in final close) then the caller has to do it.
                   2168:         */
                   2169: 
                   2170:        retval = (* q->q_qinfo->qi_qclose) (q, mode, credp);
                   2171: 
                   2172:        if (retval != 0)
                   2173:                cmn_err (CE_WARN, "module close returned %d in POP_MODULE",
                   2174:                         retval);
                   2175: 
                   2176:        /*
                   2177:         * In case the module didn't turn off put and service routines.
                   2178:         */
                   2179: 
                   2180:        if ((q->q_flag & QPROCSOFF) == 0) {
                   2181: 
                   2182:                cmn_err (CE_WARN, "Module %s did not call qprocsoff ()",
                   2183:                         q->q_qinfo->qi_minfo->mi_idname);
                   2184:                qprocsoff (q);
                   2185:        }
                   2186: 
                   2187: 
                   2188:        /*
                   2189:         * And now we can release the module. We do this whether or not the
                   2190:         * caller returned an error.
                   2191:         */
                   2192: 
                   2193:        POP_AND_FREE (sheadp, q);
                   2194: 
                   2195:        return retval;
                   2196: }
                   2197: 
                   2198: 
                   2199: /*
                   2200:  * This function pushes the indicated module onto a stream. The caller must
                   2201:  * have the stream head sleep-locked for modification.
                   2202:  */
                   2203: 
                   2204: #if    __USE_PROTO__
                   2205: int (PUSH_MODULE) (shead_t * sheadp, int mode, cred_t * credp,
                   2206:                   modsw_t * module)
                   2207: #else
                   2208: int
                   2209: PUSH_MODULE __ARGS ((sheadp, mode, credp, module))
                   2210: shead_t              * sheadp;
                   2211: int            mode;
                   2212: cred_t       * credp;
                   2213: modsw_t              * module;
                   2214: #endif
                   2215: {
                   2216:        queue_t       * q;
                   2217:        queue_t       * prev;
                   2218:        pl_t            prev_pl;
                   2219:        pl_t            q_pl;
                   2220:        int             retval;
                   2221:        n_dev_t         dev;
                   2222:        char          * modname;
                   2223: 
                   2224:        ASSERT (module != NULL);
                   2225:        ASSERT_SLEEP_LOCKED (sheadp, SH_OPENCLOSE);
                   2226: 
                   2227:        if ((q = QUEUE_ALLOC (1, 0)) == NULL)
                   2228:                return ENOSR;
                   2229: 
                   2230:        QUEUE_INIT (q, module->mod_stream, QI_NORMAL);
                   2231: 
                   2232:        /*
                   2233:         * First we have to link the module into the stream. The newly
                   2234:         * allocated queues will have the QPROCSOFF flag set so that they are
                   2235:         * ignored by other stream elements until the new module has been
                   2236:         * opened.
                   2237:         *
                   2238:         * As above in POP_MODULE (), we acquire a write lock on the stream
                   2239:         * head, which must be a master end if a stream pipe.
                   2240:         */
                   2241: 
                   2242:        prev_pl = SHEAD_LOCK (SHEAD_MASTER (sheadp));
                   2243: 
                   2244:        prev = W (sheadp->sh_head);
                   2245:        W (q)->q_next = prev->q_next;
                   2246: 
                   2247:        q_pl = QFREEZE_TRACE (prev, "PUSH_MODULE");
                   2248:        prev->q_next = W (q);
                   2249:        QUNFREEZE_TRACE (prev, q_pl);
                   2250: 
                   2251:        prev = OTHERQ (W (q)->q_next);
                   2252:        q->q_next = sheadp->sh_head;
                   2253: 
                   2254:        ASSERT (prev->q_next == sheadp->sh_head);
                   2255: 
                   2256:        q_pl = QFREEZE_TRACE (prev, "PUSH_MODULE");
                   2257:        prev->q_next = q;
                   2258:        QUNFREEZE_TRACE (prev, q_pl);
                   2259: 
                   2260:        SHEAD_UNLOCK (SHEAD_MASTER (sheadp), prev_pl);
                   2261: 
                   2262: 
                   2263:        /*
                   2264:         * Ask the module to set itself up.
                   2265:         */
                   2266: 
                   2267:        dev = sheadp->sh_dev;
                   2268: 
                   2269:        retval = (* q->q_qinfo->qi_qopen) (q, & dev, mode, MODOPEN,
                   2270:                                           credp);
                   2271: 
                   2272:        modname = q->q_qinfo->qi_minfo->mi_idname;
                   2273: 
                   2274:        if (dev != sheadp->sh_dev)
                   2275:                cmn_err (CE_WARN, "Module \"%s\" altered its \"dev\" parameter",
                   2276:                         modname);
                   2277: 
                   2278:        if (retval != 0) {
                   2279:                /*
                   2280:                 * OK, don't really open this. The module should not have
                   2281:                 * turned on it's put and service routines.
                   2282:                 */
                   2283: 
                   2284:                if ((q->q_flag & QPROCSOFF) == 0) {
                   2285: 
                   2286:                        cmn_err (CE_WARN, "PUSH_MODULE () : Module %s enabled queue!",
                   2287:                                 modname);
                   2288:                        qprocson (q);
                   2289:                }
                   2290: 
                   2291:                POP_AND_FREE (sheadp, q);
                   2292:        } else if ((q->q_flag & QPROCSOFF) != 0) {
                   2293: 
                   2294:                cmn_err (CE_WARN, "PUSH_MODULE () : Module %s did not enable queue!",
                   2295:                         modname);
                   2296:                qprocson (q);
                   2297:        }
                   2298: 
                   2299:        return retval;
                   2300: }
                   2301: 
                   2302: 
                   2303: /*
                   2304:  * This function sends an IOCTL message downstream, then blocks until either
                   2305:  * a reply arrives at the stream head, the (optional) timeout has expired, or
                   2306:  * a signal is received.
                   2307:  *
                   2308:  * The caller must have the stream head locked for ioctl () processing.
                   2309:  */
                   2310: 
                   2311: #if    __USE_PROTO__
                   2312: mblk_t * (IOCTL_SEND) (shead_t * sheadp, int mode, mblk_t * msg,
                   2313:                       int * errretp, __clock_t timeout_time)
                   2314: #else
                   2315: mblk_t *
                   2316: IOCTL_SEND __ARGS ((sheadp, mode, msg, errretp, timeout_time))
                   2317: shead_t              * sheadp;
                   2318: int            mode;
                   2319: mblk_t       * msg;
                   2320: int          * errretp;
                   2321: __clock_t      timeout_time;
                   2322: #endif
                   2323: {
                   2324:        __clock_t       end_time;
                   2325:        int             retval;
                   2326: 
                   2327:        ASSERT_SLEEP_LOCKED (sheadp, SH_IOCTL_LOCK);
                   2328:        ASSERT (errretp != NULL);
                   2329:        ASSERT (msg != NULL);
                   2330: 
                   2331:        /*
                   2332:         * Set the optional timeout up first. If the timeout cannot be
                   2333:         * allocated, we have to return failure.
                   2334:         */
                   2335: 
                   2336:        if (timeout_time > 0) {
                   2337: 
                   2338:                (void) drv_getparm (LBOLT, & end_time);
                   2339:                end_time += timeout_time;
                   2340:        }
                   2341: 
                   2342: 
                   2343:        /*
                   2344:         * Now send the client's message downstream. We queue the message on
                   2345:         * the write queue rather than directly putting it to avoid the
                   2346:         * possibility of deadlock if an acknowledgement is sent back to us
                   2347:         * while we are holding the basic lock below.
                   2348:         *
                   2349:         * We also have to check for the possibility that an error has occurred
                   2350:         * on the stream.
                   2351:         */
                   2352: 
                   2353:        (void) SHEAD_LOCK (sheadp);
                   2354: 
                   2355:        for (;;) {
                   2356:                if (sheadp->sh_ioc_msg != NULL) {
                   2357:                        /*
                   2358:                         * If there is some stale ioctl () message lying
                   2359:                         * around, dispose of it.
                   2360:                         */
                   2361: 
                   2362:                        freemsg (sheadp->sh_ioc_msg);
                   2363:                        sheadp->sh_ioc_msg = NULL;
                   2364:                }
                   2365: 
                   2366:                if (msg != NULL)
                   2367:                        putq (W (sheadp->sh_head), msg);
                   2368: 
                   2369:                msg = NULL;
                   2370: 
                   2371: 
                   2372:                /*
                   2373:                 * Before we go to sleep, we schedule our timeout.
                   2374:                 */
                   2375: 
                   2376:                if (timeout_time > 0 &&
                   2377:                    SHEAD_LOCKED_TIMEOUT (sheadp, end_time) == 0) {
                   2378:                        /*
                   2379:                         * We have timed out.
                   2380:                         */
                   2381: 
                   2382:                        retval = ETIME;
                   2383:                        break;
                   2384:                }
                   2385: 
                   2386: 
                   2387:                if (sheadp->sh_open_count == 0) {
                   2388:                        /*
                   2389:                         * This is a kernel-generated ioctl () and signalling
                   2390:                         * is not allowed to interrupt us. We pass a NULL mode
                   2391:                         * to avoid detecting errors.
                   2392:                         */
                   2393: 
                   2394:                        ASSERT_SLEEP_LOCKED (sheadp, SH_OPENCLOSE);
                   2395: 
                   2396:                        retval = SHEAD_WAIT (sheadp, 0, SH_IOCTL_WAIT,
                   2397:                                             DONT_SIGNAL);
                   2398:                } else {
                   2399:                        /*
                   2400:                         * SHEAD_WAIT () checks for hangups as well, if the
                   2401:                         * mode includes read or write.
                   2402:                         */
                   2403: 
                   2404:                        ASSERT ((mode & (FREAD | FWRITE)) != 0);
                   2405: 
                   2406:                        retval = SHEAD_WAIT (sheadp, mode, SH_IOCTL_WAIT,
                   2407:                                             CHECK_SIGNALS);
                   2408:                }
                   2409: 
                   2410: 
                   2411:                /*
                   2412:                 * We take out the basic lock here again so we can read
                   2413:                 * "sheadp->sh_ioc_msg" atomically.
                   2414:                 */
                   2415: 
                   2416:                (void) SHEAD_LOCK (sheadp);
                   2417: 
                   2418:                msg = sheadp->sh_ioc_msg;
                   2419:                sheadp->sh_ioc_msg = NULL;
                   2420: 
                   2421:                if (retval != 0 || msg != NULL)
                   2422:                        break;
                   2423: 
                   2424:                /*
                   2425:                 * We have been woken up either by a timeout, or for some
                   2426:                 * activity at the stream head not related to us. We loop to
                   2427:                 * deal with this.
                   2428:                 */
                   2429:        }
                   2430: 
                   2431:        if (retval != 0) {
                   2432: 
                   2433:                if (errretp != NULL)
                   2434:                        * errretp = retval;
                   2435: 
                   2436:                if (msg != NULL)
                   2437:                        freemsg (msg);
                   2438: 
                   2439:                msg = NULL;
                   2440:        }
                   2441: 
                   2442:        SHEAD_UNLOCK (sheadp, plbase);
                   2443: 
                   2444:        return msg;
                   2445: }
                   2446: 
                   2447: 
                   2448: /*
                   2449:  * This function manages transparent ioctl () processing; it sets itself up
                   2450:  * to service M_COPYIN and M_COPYOUT requests from a driver until it sees an
                   2451:  * M_IOCACK or M_IOCNAK.
                   2452:  */
                   2453: 
                   2454: typedef union {
                   2455:        struct iocblk   ioc;
                   2456:        struct copyreq  req;
                   2457:        struct copyresp resp;
                   2458: } x_ioc_t;
                   2459: 
                   2460: #if    __USE_PROTO__
                   2461: __LOCAL__ int (TRANSPARENT_IOCTL) (shead_t * sheadp, int mode, int cmd,
                   2462:                                   _VOID * arg, cred_t * credp, int * rvalp)
                   2463: #else
                   2464: __LOCAL__ int
                   2465: TRANSPARENT_IOCTL __ARGS ((sheadp, mode, cmd, arg, credp, rvalp))
                   2466: shead_t              * sheadp;
                   2467: int            mode;
                   2468: int            cmd;
                   2469: _VOID        * arg;
                   2470: cred_t       * credp;
                   2471: int          * rvalp;
                   2472: #endif
                   2473: {
                   2474:        mblk_t        * msg;
                   2475:        mblk_t        * data;
                   2476:        int             retval;
                   2477:        x_ioc_t       * ioc;
                   2478: 
                   2479:        ASSERT_SLEEP_LOCKED (sheadp, SH_IOCTL_LOCK);
                   2480: 
                   2481:        /*
                   2482:         * The message block allocated for a transparent ioctl () must be
                   2483:         * large enough to hold any of the ioctl-related message types so that
                   2484:         * modules and drivers (and the stream head) can just change the
                   2485:         * message type to reply to a message.
                   2486:         */
                   2487: 
                   2488:        if ((msg = MSGB_ALLOC (sizeof (* ioc), BPRI_LO, KM_SLEEP)) == NULL)
                   2489:                return ENOSR;
                   2490: 
                   2491:        ioc = (x_ioc_t *) msg->b_rptr;
                   2492:        msg->b_wptr = (unsigned char *) (ioc + 1);
                   2493: 
                   2494:        msg->b_datap->db_type = M_IOCTL;
                   2495: 
                   2496:        ioc->ioc.ioc_cmd = cmd;
                   2497:        ioc->ioc.ioc_cr = credp;
                   2498:        ioc->ioc.ioc_id = ++ sheadp->sh_ioc_seq;
                   2499:        ioc->ioc.ioc_count = TRANSPARENT;
                   2500:        ioc->ioc.ioc_rval = ioc->ioc.ioc_error = 0;
                   2501: 
                   2502: 
                   2503:        /*
                   2504:         * A transparent ioctl () gets a single data block containing the
                   2505:         * value of "arg".
                   2506:         */
                   2507: 
                   2508:        if ((data = MSGB_ALLOC (sizeof (arg), BPRI_LO, KM_SLEEP)) == NULL) {
                   2509: 
                   2510:                retval = ENOSR;
                   2511:                goto done;
                   2512:        }
                   2513: 
                   2514:        * (_VOID **) data->b_rptr = arg;
                   2515:        data->b_wptr += sizeof (arg);
                   2516: 
                   2517: 
                   2518:        for (;;) {
                   2519:                /*
                   2520:                 * Now we send the ioctl () and wait for the acknowledgement.
                   2521:                 * Transparent ioctl ()'s wait forever, but M_ERROR and
                   2522:                 * hangup events are interesting to us, so we can blow out.
                   2523:                 */
                   2524: 
                   2525:                if ((msg = IOCTL_SEND (sheadp, mode, msg, & retval,
                   2526:                                       0)) == NULL)
                   2527:                        return retval;
                   2528: 
                   2529: 
                   2530:                /*
                   2531:                 * Transparent ioctl ()'s dont have to worry about data coming
                   2532:                 * back in the M_IOCACK message, they just have to process the
                   2533:                 * M_COPYIN and M_COPYOUT requests.
                   2534:                 */
                   2535: 
                   2536:                switch (msg->b_datap->db_type) {
                   2537: 
                   2538:                case M_IOCNAK:
                   2539:                        retval = ioc->ioc.ioc_error;
                   2540:                        goto done;
                   2541: 
                   2542:                case M_IOCACK:
                   2543:                        * rvalp = ioc->ioc.ioc_rval;
                   2544:                        retval = ioc->ioc.ioc_error;
                   2545: 
                   2546:                        if (ioc->ioc.ioc_count > 0)
                   2547:                                cmn_err (CE_WARN, "Transparent ioctl () processing forbids data in M_IOCACK");
                   2548:                        goto done;
                   2549: 
                   2550:                case M_COPYIN:
                   2551:                        if ((data = msg->b_cont) != NULL)
                   2552:                                freemsg (data);
                   2553: 
                   2554:                        /*
                   2555:                         * The STREAMS documentation is unclear as to whether
                   2556:                         * these blocks are split up or not, but it seems
                   2557:                         * unlikely.
                   2558:                         */
                   2559: 
                   2560:                        if ((data = MSGB_ALLOC (ioc->req.cq_size, BPRI_LO,
                   2561:                                                KM_SLEEP)) == NULL)
                   2562:                                retval = ENOSR;
                   2563:                        else if (copyin (ioc->req.cq_addr, data->b_rptr,
                   2564:                                         ioc->req.cq_size) != 0) {
                   2565:                                freemsg (data);
                   2566:                                data = NULL;
                   2567:                                retval = EFAULT;
                   2568:                        } else {
                   2569: 
                   2570:                                data->b_wptr = data->b_rptr +
                   2571:                                                ioc->req.cq_size;
                   2572:                                retval = 0;
                   2573:                        }
                   2574: 
                   2575:                        msg->b_cont = data;
                   2576:                        break;
                   2577: 
                   2578:                case M_COPYOUT:
                   2579:                        retval = 0;
                   2580: 
                   2581:                        while (ioc->req.cq_size > 0 &&
                   2582:                               (data = msg->b_cont) != NULL) {
                   2583:                                size_t          unit;
                   2584: 
                   2585:                                /*
                   2586:                                 * Copy a single M_DATA block at a time. After
                   2587:                                 * copying, we free the block.
                   2588:                                 */
                   2589: 
                   2590:                                unit = data->b_wptr - data->b_rptr;
                   2591:                                if (unit > ioc->req.cq_size)
                   2592:                                        unit = ioc->req.cq_size;
                   2593: 
                   2594:                                if (copyout (data->b_rptr, ioc->req.cq_addr,
                   2595:                                             unit) != 0) {
                   2596:                                        retval = EFAULT;
                   2597:                                        break;
                   2598:                                }
                   2599: 
                   2600:                                ioc->req.cq_size -= unit;
                   2601:                                ioc->req.cq_addr += unit;
                   2602: 
                   2603:                                msg->b_cont = data->b_cont;
                   2604:                                freeb (data);
                   2605:                        }
                   2606: 
                   2607:                        /*
                   2608:                         * Throw away uncopied extra data.
                   2609:                         */
                   2610: 
                   2611:                        if ((data = msg->b_cont) != NULL)
                   2612:                                freemsg (data);
                   2613: 
                   2614:                        msg->b_cont = NULL;
                   2615:                        break;
                   2616: 
                   2617:                default:
                   2618:                        cmn_err (CE_WARN, "Invalid message type %d received during unlink processing",
                   2619:                                 msg->b_datap->db_type);
                   2620:                        retval = ENXIO;
                   2621:                        goto done;
                   2622:                }
                   2623: 
                   2624:                /*
                   2625:                 * In common code for M_COPYIN and M_COPYOUT, we turn around
                   2626:                 * the request message. If the request succeeded, we wrap
                   2627:                 * around to the top of the loop to serve the next request;
                   2628:                 * it there has been an error, we just put the message and
                   2629:                 * bail out.
                   2630:                 */
                   2631: 
                   2632:                msg->b_datap->db_type = M_IOCDATA;
                   2633:                ioc->resp.cp_rval = (caddr_t) retval;
                   2634: 
                   2635:                if (retval != 0) {
                   2636: 
                   2637:                        putq (W (sheadp->sh_head), msg);
                   2638:                        break;
                   2639:                }
                   2640:        }
                   2641: 
                   2642: done:
                   2643:        freemsg (msg);
                   2644: 
                   2645:        return retval;
                   2646: }
                   2647: 
                   2648: 
                   2649: /*
                   2650:  * This function contains code common to the ioctl () message processing for
                   2651:  * stream link and unlink commands. These ioctl ()s send messages downstream
                   2652:  * which are all of a single common form.
                   2653:  */
                   2654: 
                   2655: #if    __USE_PROTO__
                   2656: __LOCAL__ int (LINK_MESSAGE) (shead_t * upper, int mode, shead_t * lower,
                   2657:                              int cmd, int muxid, cred_t * credp,
                   2658:                              int * retvalp)
                   2659: #else
                   2660: __LOCAL__ int
                   2661: LINK_MESSAGE __ARGS ((upper, mode, lower, cmd, muxid, credp, retvalp))
                   2662: shead_t              * upper;
                   2663: int            mode;
                   2664: shead_t              * lower;
                   2665: int            cmd;
                   2666: int            muxid;
                   2667: cred_t       * credp;
                   2668: int          * retvalp;
                   2669: #endif
                   2670: {
                   2671:        mblk_t        * msg;
                   2672:        struct iocblk * ioc;
                   2673:        struct linkblk * linkblk;
                   2674:        int             ackflag;
                   2675:        queue_t       * q;
                   2676: 
                   2677:        ASSERT_SLEEP_LOCKED (upper, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   2678:        ASSERT_SLEEP_LOCKED (lower, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   2679:        ASSERT (credp != NULL);
                   2680: 
                   2681:        /*
                   2682:         * Set ourselves up for a STREAMS ioctl (). Note that since we keep
                   2683:         * transparent ioctl () processing separate from normal I_STR code, we
                   2684:         * don't have to allocate an initial message block that can be turned
                   2685:         * into a "copyreq" or "copyresp" structure.
                   2686:         */
                   2687: 
                   2688: 
                   2689:        if ((msg = MSGB_ALLOC (sizeof (* ioc), BPRI_LO, KM_SLEEP)) == NULL)
                   2690:                return ENOSR;
                   2691: 
                   2692:        ioc = (struct iocblk *) msg->b_rptr;
                   2693:        msg->b_wptr = (unsigned char *) (ioc + 1);
                   2694: 
                   2695:        msg->b_datap->db_type = M_IOCTL;
                   2696: 
                   2697:        ioc->ioc_cmd = cmd;
                   2698:        ioc->ioc_cr = credp;
                   2699:        ioc->ioc_id = ++ upper->sh_ioc_seq;
                   2700:        ioc->ioc_count = sizeof (struct linkblk);
                   2701:        ioc->ioc_rval = ioc->ioc_error = 0;
                   2702: 
                   2703: 
                   2704:        /*
                   2705:         * Now we allocate and fill in the data part of the I_...LINK message.
                   2706:         */
                   2707: 
                   2708:        if ((msg->b_cont = MSGB_ALLOC (sizeof (struct linkblk), BPRI_LO,
                   2709:                                       KM_SLEEP)) == NULL) {
                   2710:                freeb (msg);
                   2711:                return ENOSR;
                   2712:        }
                   2713: 
                   2714:        linkblk = (struct linkblk *) msg->b_cont->b_rptr;
                   2715:        msg->b_cont->b_wptr = (unsigned char *) (linkblk + 1);
                   2716: 
                   2717: 
                   2718:        /*
                   2719:         * Find the bottom-most write queue on the upper stream. To make this
                   2720:         * walk of the queue safe with respect to I_PUSH and I_POP, we take
                   2721:         * out a read lock on the stream head. See the PUSH_MODULE () and
                   2722:         * POP_MODULE () routines for more details on this.
                   2723:         *
                   2724:         * We don't use QUEUE_NEXT () because the intermediate modules are of
                   2725:         * no interest to us; we just want the driver at the bottom.
                   2726:         */
                   2727: 
                   2728:        {
                   2729:                queue_t       * next;
                   2730: 
                   2731:                (void) SHEAD_LOCK (upper);
                   2732: 
                   2733:                next = W (upper->sh_head);
                   2734: 
                   2735:                do {
                   2736:                        q = next;
                   2737: 
                   2738:                        (void) QFREEZE_TRACE (q, "LINK_MESSAGE");
                   2739: 
                   2740:                        next = q->q_next;
                   2741: 
                   2742:                        QUNFREEZE_TRACE (q, plbase);
                   2743:                } while (next != NULL);
                   2744: 
                   2745:                SHEAD_UNLOCK (upper, plbase);
                   2746:        }
                   2747: 
                   2748:        linkblk->l_qtop = q;
                   2749:        linkblk->l_qbot = lower->sh_head;
                   2750:        linkblk->l_index = muxid;
                   2751: 
                   2752: 
                   2753:        /*
                   2754:         * Now we send the ioctl () and wait for the acknowledgement. Since
                   2755:         * there is no mechanism for managing this timeout, we will use the
                   2756:         * close timeout (which is appropriate given that this operation will
                   2757:         * often be performed as the result of a close ()).
                   2758:         */
                   2759: 
                   2760:        if ((msg = IOCTL_SEND (upper, mode, msg, retvalp,
                   2761:                               upper->sh_cltime)) == NULL)
                   2762:                return 0;               /* counts as a negative ack */
                   2763: 
                   2764:        /*
                   2765:         * Now we see what kind of message the driver has send to us.
                   2766:         */
                   2767: 
                   2768:        ioc = (struct iocblk *) msg->b_rptr;
                   2769: 
                   2770:        if (retvalp != NULL)
                   2771:                * retvalp = ioc->ioc_error;
                   2772: 
                   2773:        switch (msg->b_datap->db_type) {
                   2774: 
                   2775:        case M_IOCNAK:
                   2776:                ackflag = 0;
                   2777:                break;
                   2778: 
                   2779:        case M_IOCACK:
                   2780:                /*
                   2781:                 * We do not copy the "ioc_rval" member out because it is not
                   2782:                 * documented as forming the return value from such a link-
                   2783:                 * style ioctl () request.
                   2784:                 */
                   2785: 
                   2786:                /*
                   2787:                 * Since "arg" for an I_UNLINK or I_PUNLINK is not a pointer,
                   2788:                 * it makes no sense for a driver to attempt to return data
                   2789:                 * for the user. Since the canonical multiplexing driver code
                   2790:                 * clears ioc_count and simply turns around the message, it
                   2791:                 * is not a problem for there to be M_DATA messages following
                   2792:                 * the M_IOCACK, but it is a problem if "ioc_count" is greater
                   2793:                 * than 0.
                   2794:                 */
                   2795: 
                   2796:                ackflag = 1;
                   2797: 
                   2798:                if (ioc->ioc_count > 0)
                   2799:                        cmn_err (CE_WARN, "Driver %s returned data with link/unlink ioctl ()",
                   2800:                                 q->q_qinfo->qi_minfo->mi_idname);
                   2801: 
                   2802:                break;
                   2803: 
                   2804:        default:
                   2805:                cmn_err (CE_WARN, "Invalid message type %d received during link/unlink processing",
                   2806:                         msg->b_datap->db_type);
                   2807:                * retvalp = ENXIO;
                   2808: 
                   2809:                ackflag = 0;            /* treat as a negative ack */
                   2810:                break;
                   2811:        }
                   2812: 
                   2813:        freemsg (msg);
                   2814: 
                   2815:        return ackflag;
                   2816: }
                   2817: 
                   2818: 
                   2819: /*
                   2820:  * Helper function for the link/unlink process to restore a stream to the
                   2821:  * unlinked state.
                   2822:  */
                   2823: 
                   2824: #if    __USE_PROTO__
                   2825: __LOCAL__ int (SHEAD_INIT_UNLINKED) (shead_t * sheadp)
                   2826: #else
                   2827: __LOCAL__ int
                   2828: SHEAD_INIT_UNLINKED __ARGS ((sheadp))
                   2829: shead_t              * sheadp;
                   2830: #endif
                   2831: {
                   2832:        pl_t            prev_pl;
                   2833:        int             final_close;
                   2834: 
                   2835:        ASSERT_SLEEP_LOCKED (sheadp, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   2836: 
                   2837:        /*
                   2838:         * The driver is no longer using this stream; restore it to normal
                   2839:         * operation. Note that we have to reset "q_ptr" back to point at the
                   2840:         * stream head!
                   2841:         */
                   2842: 
                   2843:        prev_pl = SHEAD_LOCK (sheadp);
                   2844: 
                   2845:        sheadp->sh_linked = NULL;
                   2846:        sheadp->sh_flags &= ~ SH_PLINK;
                   2847: 
                   2848:        final_close = -- sheadp->sh_open_count == 0;
                   2849: 
                   2850:        SHEAD_UNLOCK (sheadp, prev_pl);
                   2851: 
                   2852: 
                   2853:        prev_pl = QFREEZE_TRACE (sheadp->sh_head, "SHEAD_INIT_UNLINKED");
                   2854: 
                   2855:        sheadp->sh_head->q_ptr = sheadp;
                   2856:        W (sheadp->sh_head)->q_ptr = sheadp;
                   2857: 
                   2858:        QUEUE_INIT (sheadp->sh_head, sheadp->sh_tab, QI_NORMAL);
                   2859: 
                   2860:        QUNFREEZE_TRACE (sheadp->sh_head, prev_pl);
                   2861: 
                   2862:        return final_close;
                   2863: }
                   2864: 
                   2865: 
                   2866: /*
                   2867:  * This function takes care of unlinking a lower stream from an upper stream.
                   2868:  *
                   2869:  * The caller should have both the upper and lower stream heads locked for
                   2870:  * open/close processing.
                   2871:  */
                   2872: 
                   2873: #if    __USE_PROTO__
                   2874: __LOCAL__ int (LOCKED_UNLINK) (shead_t * upper, int mode, shead_t * lower,
                   2875:                               int cmd, cred_t * credp, int * retvalp)
                   2876: #else
                   2877: __LOCAL__ int
                   2878: LOCKED_UNLINK __ARGS ((upper, mode, lower, cmd, credp, retvalp))
                   2879: shead_t              * upper;
                   2880: int            mode;
                   2881: shead_t              * lower;
                   2882: int            cmd;
                   2883: cred_t       * credp;
                   2884: int          * retvalp;
                   2885: #endif
                   2886: {
                   2887:        ASSERT_SLEEP_LOCKED (upper, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   2888:        ASSERT_SLEEP_LOCKED (lower, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   2889: 
                   2890:        /*
                   2891:         * Check that the right kind of unlink command is being issued.
                   2892:         */
                   2893: 
                   2894:        if (lower->sh_linked != upper ||
                   2895:            ((lower->sh_flags & SH_PLINK) != 0) == (cmd == I_PUNLINK))
                   2896:                return EINVAL;
                   2897: 
                   2898:        /*
                   2899:         * Send the message downstream and get the return result.
                   2900:         */
                   2901: 
                   2902:        if (LINK_MESSAGE (upper, mode, lower, cmd, lower->sh_muxid, credp,
                   2903:                          retvalp)) {
                   2904:                /*
                   2905:                 * The unlink was properly acknowledged. Note that this may
                   2906:                 * cause the lower stream to close.
                   2907:                 */
                   2908: 
                   2909:                if (SHEAD_INIT_UNLINKED (lower) != 0)
                   2910:                        SHEAD_DO_CLOSE (lower, mode, credp);
                   2911: 
                   2912:                return 1;
                   2913:        }
                   2914: 
                   2915:        return 0;
                   2916: }
                   2917: 
                   2918: 
                   2919: /*
                   2920:  * This function wraps up part of the required client functionality for
                   2921:  * callers of SHEAD_UNLINK () by dealing with locking the lower stream head
                   2922:  * and making appropriate calls to see if it needs closing.
                   2923:  */
                   2924: 
                   2925: #if    __USE_PROTO__
                   2926: __LOCAL__ int (SHEAD_UNLINK) (shead_t * upper, shead_t * lower, int cmd,
                   2927:                              int mode, cred_t * credp, int * retvalp)
                   2928: #else
                   2929: __LOCAL__ int
                   2930: SHEAD_UNLINK __ARGS ((upper, lower, cmd, mode, credp, retvalp))
                   2931: shead_t              * upper;
                   2932: shead_t              * lower;
                   2933: int            cmd;
                   2934: int            mode;
                   2935: cred_t       * credp;
                   2936: int          * retvalp;
                   2937: #endif
                   2938: {
                   2939:        int             success;
                   2940: 
                   2941:        /*
                   2942:         * In order to unlink this lower stream we first have to lock it. This
                   2943:         * is necessary not only to ensure that we don't trip up other
                   2944:         * operations affecting this stream (since there may be open file
                   2945:         * descriptors referring to it, and/or it may be a stream pipe) but
                   2946:         * since stream deallocations are checked for in the unlock code this
                   2947:         * is necessary to ensure that an unlink of an otherwise unreferenced
                   2948:         * stream does the right thing.
                   2949:         */
                   2950: 
                   2951:        if ((* retvalp = SHEAD_SLEEP_LOCK (lower,
                   2952:                                           SH_OPENCLOSE | SH_IOCTL_LOCK, 0,
                   2953:                                           DONT_SIGNAL)) != 0) {
                   2954: 
                   2955:                cmn_err (CE_WARN, "Unable to lock stream in SHEAD_UNLINK (), error %d",
                   2956:                         * retvalp);
                   2957:                return 1;
                   2958:        }
                   2959: 
                   2960: 
                   2961:        /*
                   2962:         * OK, we unlink this lower stream, and do all the stuff we
                   2963:         * need to do to ensure that the lower stream gets closed if
                   2964:         * its time has come.
                   2965:         */
                   2966: 
                   2967:        success = LOCKED_UNLINK (upper, mode, lower, cmd, credp, retvalp);
                   2968: 
                   2969:        SHEAD_SLEEP_UNLOCK (lower, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   2970: 
                   2971:        return success;
                   2972: }
                   2973: 
                   2974: 
                   2975: /*
                   2976:  * Loop-detection algorithm for use in SHEAD_LINK ().
                   2977:  *
                   2978:  * The STREAMS documentation is very vague about what constitutes a cycle in
                   2979:  * the link graph, probably deliberately.
                   2980:  *
                   2981:  * For our purposes we consider a cycle to be caused by any path of links
                   2982:  * which lead upwards (to user level) from the *device* indicated by "upper"
                   2983:  * to the *device* indicated by "lower".
                   2984:  *
                   2985:  * Frankly, given the nature of multiplexing drivers in terms of routing
                   2986:  * information, I really don't see much advantage in this; it is perfectly
                   2987:  * easy for messages cycles to form other ways, and given the typical nature
                   2988:  * of multiplexor services interfaces a cycle in the hierarchy need not cause
                   2989:  * a loop. Still, that's the way it's specified.
                   2990:  *
                   2991:  * THIS IS A RECURSIVE ALGORITHM FOR DEPTH-FIRST SEARCH. This fact does not
                   2992:  * really worry me in the slightest, because the depth of the recursion here
                   2993:  * is no worse than the possible recursive depth of the multiplexor put ()
                   2994:  * calls themselves.
                   2995:  */
                   2996: 
                   2997: #if    __USE_PROTO__
                   2998: __LOCAL__ int (DETECT_LOOP) (shead_t * upper, shead_t * lower)
                   2999: #else
                   3000: __LOCAL__ int
                   3001: DETECT_LOOP __ARGS ((upper, lower))
                   3002: shead_t              * upper;
                   3003: shead_t              * lower;
                   3004: #endif
                   3005: {
                   3006:        shead_t       * scan;
                   3007: 
                   3008:        /*
                   3009:         * We base our comparisons on the "sh_tab" member of the stream head
                   3010:         * structure, since that is equivalent to the major part of the
                   3011:         * (internal) device number.
                   3012:         */
                   3013: 
                   3014:        if (upper->sh_tab == lower->sh_tab)
                   3015:                return 1;
                   3016: 
                   3017:        /*
                   3018:         * Now recursively work upward through the multiplexing configuration
                   3019:         * calling DETECT_LOOP () for all the linked streams with the "sh_tab"
                   3020:         * entry of the stream which "upper" is linked to (if "upper" is in
                   3021:         * fact linked below another multiplexor).
                   3022:         *
                   3023:         * Since only device streams can be multiplexors, we only scan the
                   3024:         * device stream list.
                   3025:         */
                   3026: 
                   3027:        if ((upper = upper->sh_linked) == NULL)
                   3028:                return 0;
                   3029: 
                   3030:        for (scan = str_mem->sm_streams [DEV_SLIST] ; scan != NULL ;
                   3031:             scan = scan->sh_next) {
                   3032: 
                   3033:                if (scan->sh_tab == upper->sh_tab &&
                   3034:                    DETECT_LOOP (scan, lower))
                   3035:                        return 1;
                   3036:        }
                   3037: 
                   3038:        return 0;
                   3039: }
                   3040: 
                   3041: 
                   3042: /*
                   3043:  * This function deals with linking one stream below another. There are
                   3044:  * numerous conditions which might prevent this from happening, including a
                   3045:  * refusal from the multiplexing driver.
                   3046:  *
                   3047:  * The upper stream must be locked for open/close operations. The lower stream
                   3048:  * will also be locked by this routine.
                   3049:  */
                   3050: 
                   3051: #if    __USE_PROTO__
                   3052: int (SHEAD_LINK) (shead_t * upper, int mode, shead_t * lower, int cmd,
                   3053:                  cred_t * credp)
                   3054: #else
                   3055: int
                   3056: SHEAD_LINK __ARGS ((upper, mode, lower, cmd, credp))
                   3057: shead_t              * upper;
                   3058: int            mode;
                   3059: shead_t              * lower;
                   3060: int            cmd;
                   3061: cred_t       * credp;
                   3062: #endif
                   3063: {
                   3064:        int             retval;
                   3065:        muxid_t         muxid;
                   3066: 
                   3067:        ASSERT (lower != NULL);
                   3068: 
                   3069:        ASSERT_SLEEP_LOCKED (upper, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   3070: 
                   3071:        if (SHEAD_IS_PIPE (upper) ||
                   3072:            upper->sh_tab->st_muxrinit == NULL ||
                   3073:            upper->sh_tab->st_muxwinit == NULL)
                   3074:                return EINVAL;
                   3075: 
                   3076:        /*
                   3077:         * Perform some of the non-recursive setup (mainly locking) for the
                   3078:         * cycle-detection algorithm. We use the read/write lock on the stream
                   3079:         * head since the detection algorithm walks over the global stream
                   3080:         * list many times. Note that this single-threads checking operations,
                   3081:         * which we would also have to do if were were pushing marker bits
                   3082:         * around in a non-recursive implementation.
                   3083:         */
                   3084: 
                   3085:        (void) RW_WRLOCK (str_mem->sm_head_lock, plstr);
                   3086: 
                   3087:        retval = DETECT_LOOP (upper, lower);
                   3088: 
                   3089:        RW_UNLOCK (str_mem->sm_head_lock, plbase);
                   3090: 
                   3091:        if (retval != 0)
                   3092:                return EINVAL;
                   3093: 
                   3094:        /*
                   3095:         * Generate a suitable multiplexor ID for the link. We use the device
                   3096:         * number of the lower stream as a suitable seed point.
                   3097:         */
                   3098: 
                   3099:        for (muxid = (muxid_t) lower->sh_dev ;
                   3100:             SHEAD_FIND_MUXID (upper, cmd, muxid) != NULL ; muxid ++)
                   3101:                ; /* DO NOTHING */
                   3102: 
                   3103:        /*
                   3104:         * We set up the lower now, before we send the I_LINK, so that by the
                   3105:         * time the driver sees the I_LINK the stream is ready for use. We
                   3106:         * NULL out the "q_ptr" member of the lower queue so that messages
                   3107:         * arriving early can be correctly handled.
                   3108:         *
                   3109:         * We take a sleep lock on the lower stream. If we can't lock it,
                   3110:         * return EINVAL since whatever error caused the failure isn't really
                   3111:         * relevant to the stream the caller is dealing with.
                   3112:         */
                   3113: 
                   3114:        if ((retval = SHEAD_SLEEP_LOCK (lower, SH_OPENCLOSE | SH_IOCTL_LOCK,
                   3115:                                        0, DONT_SIGNAL)) != 0)
                   3116:                return EINVAL;
                   3117: 
                   3118:        /*
                   3119:         * Note that the "q_ptr" field of the queue gets zeroed to avoid
                   3120:         * communicating our state to the driver. In addition, we have to
                   3121:         * count the link as an extra open now.
                   3122:         *
                   3123:         * Paranoia time; we check for errors, hangups and whether the lower
                   3124:         * stream is linked at this late stage so the cutover is atomic. This
                   3125:         * requires some cooperation from the stream head read side service
                   3126:         * routine; look to see that it tests for "sh_linked" in the service
                   3127:         * routine somewhere...
                   3128:         */
                   3129: 
                   3130:        (void) SHEAD_LOCK (lower);
                   3131: 
                   3132:        if (SHEAD_HANGUP (lower) || _shead_error (lower, FREAD | FWRITE)) {
                   3133: 
                   3134:                SHEAD_UNLOCK (lower, plbase);
                   3135:                SHEAD_SLEEP_UNLOCK (lower, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   3136:                return EINVAL;
                   3137:        }
                   3138: 
                   3139:        lower->sh_open_count ++;        /* duplicate reference */
                   3140: 
                   3141:        lower->sh_linked = upper;
                   3142:        lower->sh_muxid = muxid;
                   3143: 
                   3144:        if (cmd == I_PLINK)
                   3145:                lower->sh_flags |= SH_PLINK;
                   3146: 
                   3147:        SHEAD_UNLOCK (lower, plbase);
                   3148: 
                   3149: 
                   3150:        (void) QFREEZE_TRACE (lower->sh_head, "LINK_STREAMS");
                   3151: 
                   3152:        lower->sh_head->q_ptr = NULL;
                   3153:        W (lower->sh_head)->q_ptr = NULL;
                   3154: 
                   3155:        QUEUE_INIT (lower->sh_head, lower->sh_tab, QI_MUX);
                   3156: 
                   3157:        QUNFREEZE_TRACE (lower->sh_head, plbase);
                   3158: 
                   3159: 
                   3160:        /*
                   3161:         * Send the message downstream and get the return result.
                   3162:         */
                   3163: 
                   3164:        if (LINK_MESSAGE (upper, mode, lower, cmd, muxid, credp,
                   3165:                          & retval) == 0) {
                   3166:                int             final;
                   3167: 
                   3168:                /*
                   3169:                 * The driver failed the link; restore the lower stream. This
                   3170:                 * won't cause the stream to close (because of our open
                   3171:                 * reference) but we take care to ensure that the counts are
                   3172:                 * properly maintained.
                   3173:                 */
                   3174: 
                   3175:                final = SHEAD_INIT_UNLINKED (lower);
                   3176: 
                   3177:                if (final != 0)
                   3178:                        cmn_err (CE_WARN, "Final close in SHEAD_LINK () ????");
                   3179:        }
                   3180: 
                   3181: 
                   3182:        /*
                   3183:         * Unlock the lower stream for proper symmetry.
                   3184:         */
                   3185: 
                   3186:        SHEAD_SLEEP_UNLOCK (lower, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   3187:        return retval;
                   3188: }
                   3189: 
                   3190: 
                   3191: /*
                   3192:  * This function deals with a special case in SHEAD_DO_CLOSE () below where
                   3193:  * the last close of a stream pipe end causes the other end to be detached
                   3194:  * from all the filesystem entries it has been mounted over.
                   3195:  */
                   3196: 
                   3197: #if    __USE_PROTO__
                   3198: __LOCAL__ void (SHEAD_PIPE_DETACH) (shead_t * __NOTUSED (other))
                   3199: #else
                   3200: __LOCAL__ void
                   3201: SHEAD_PIPE_DETACH __ARGS ((other))
                   3202: shead_t              * other;
                   3203: #endif
                   3204: {
                   3205:        /*
                   3206:         * Until we know how attachments are going to be performed and what
                   3207:         * kind of structure exists, we cannot implement this function.
                   3208:         */
                   3209: 
                   3210:        cmn_err (CE_PANIC, "UNIMPLEMENTED : SHEAD_PIPE_DETACH ()");
                   3211: }
                   3212: 
                   3213: 
                   3214: /*
                   3215:  * This module factors out some code from SHEAD_DO_CLOSE (). The final
                   3216:  * close processing for a stream head is complicated a little because when a
                   3217:  * stream pipe end is closed that side of the pipe is not actually closed
                   3218:  * until the other end also closes.
                   3219:  */
                   3220: 
                   3221: #if    __USE_PROTO__
                   3222: __LOCAL__ void (SHEAD_FINAL_CLOSE) (shead_t * sheadp, int mode,
                   3223:                                    cred_t * credp)
                   3224: #else
                   3225: __LOCAL__ void
                   3226: SHEAD_FINAL_CLOSE __ARGS ((sheadp, mode, credp))
                   3227: shead_t              * sheadp;
                   3228: int            mode;
                   3229: cred_t       * credp;
                   3230: #endif
                   3231: {
                   3232:        shead_t       * scan;
                   3233:        queue_t       * q;
                   3234:        int             retval;
                   3235: 
                   3236:        /*
                   3237:         * Final close of a stream; the close steps are to be performed in
                   3238:         * this order, as given in the DDI/DDK entry for close(D2DK).
                   3239:         *      Non-persistent multiplexor links are unlinked.
                   3240:         *      For each module and driver from the head to the driver:
                   3241:         *              Wait for the write queue to drain.
                   3242:         *              Call close () routine.
                   3243:         *              Remove module/driver from stream.
                   3244:         *              Free remaining messages.
                   3245:         *              Deallocate queue pair.
                   3246:         *
                   3247:         * Here we can behave as if we have an ioctl () lock on the stream
                   3248:         * because during final close no other process can legitimately hold
                   3249:         * another lock on the stream head (no other legal references to the
                   3250:         * stream exist).
                   3251:         */
                   3252: 
                   3253:        while ((scan = SHEAD_FIND_MUXID (sheadp, I_UNLINK, -1)) != NULL) {
                   3254: 
                   3255:                if (SHEAD_UNLINK (sheadp, scan, I_UNLINK, mode, credp,
                   3256:                                  & retval) == 0) {
                   3257:                        /*
                   3258:                         * There is no good reason for a driver to fail an
                   3259:                         * I_UNLINK request.
                   3260:                         */
                   3261: 
                   3262:                        cmn_err (CE_WARN, "Driver failed unlink () during final close (%d)",
                   3263:                                 retval);
                   3264:                        scan->sh_linked = NULL;
                   3265:                }
                   3266:        }
                   3267: 
                   3268: 
                   3269:        /*
                   3270:         * Before draining the write side modules, drain the stream head.
                   3271:         */
                   3272: 
                   3273:        DRAIN_QUEUE (sheadp, W (sheadp->sh_head));
                   3274: 
                   3275: 
                   3276:        /*
                   3277:         * Now pop all the modules from the stream.
                   3278:         */
                   3279: 
                   3280:        while ((q = TOP_MODULE (sheadp)) != NULL) {
                   3281: 
                   3282:                DRAIN_QUEUE (sheadp, W (q));
                   3283: 
                   3284:                (void) POP_MODULE (sheadp, q, mode, credp);
                   3285:        }
                   3286: 
                   3287: 
                   3288:        /*
                   3289:         * Now close the driver, unless this is a pipe. Once this has been
                   3290:         * done there is no reason for any context to reference this object
                   3291:         * except to unlock it.
                   3292:         */
                   3293: 
                   3294:        if (! SHEAD_IS_PIPE (sheadp)) {
                   3295:                q = TOP_QUEUE (sheadp);
                   3296: 
                   3297:                DRAIN_QUEUE (sheadp, q);
                   3298: 
                   3299:                q = R (q);
                   3300: 
                   3301:                retval = (* q->q_qinfo->qi_qclose) (q, mode, credp);
                   3302: 
                   3303:                if (retval != 0)
                   3304:                        cmn_err (CE_WARN, "Driver close returned %d", retval);
                   3305: 
                   3306:                if ((q->q_flag & QPROCSOFF) == 0) {
                   3307: 
                   3308:                        cmn_err (CE_WARN, "Driver %s did not call qprocsoff ()",
                   3309:                                 q->q_qinfo->qi_minfo->mi_idname);
                   3310:                        qprocsoff (q);
                   3311:                }
                   3312:        }
                   3313: }
                   3314: 
                   3315: 
                   3316: /*
                   3317:  * This function does most of the close processing for a stream head. It is
                   3318:  * used by regular stream close, and by stream open code if certain
                   3319:  * irregularities are detected.
                   3320:  *
                   3321:  * The caller must have the stream head locked for close operations. If the
                   3322:  * stream head being operated on is a pipe, that means both ends must be
                   3323:  * locked (so that the caller can sequence the lock order on the basis of the
                   3324:  * master/slave bits).
                   3325:  */
                   3326: 
                   3327: #if    __USE_PROTO__
                   3328: __LOCAL__ int (SHEAD_DO_CLOSE) (shead_t * sheadp, int mode, cred_t * credp)
                   3329: #else
                   3330: __LOCAL__ int
                   3331: SHEAD_DO_CLOSE __ARGS ((sheadp, mode, credp))
                   3332: shead_t              * sheadp;
                   3333: int            mode;
                   3334: cred_t       * credp;
                   3335: #endif
                   3336: {
                   3337:        ASSERT (credp != NULL);
                   3338:        ASSERT_SLEEP_LOCKED (sheadp, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   3339: 
                   3340:        /*
                   3341:         * If other processes have references to this stream head, then we can
                   3342:         * just return doing no more work. Note that we keep the notion of
                   3343:         * number of open references, number of filesystem attachments, and
                   3344:         * multiplexor links completely separate, but any one qualifies as
                   3345:         * a reason for keeping the stream around.
                   3346:         *
                   3347:         * Therefore, it follows that any code which manipulates any of these
                   3348:         * quantities such that the next expression might become false needs
                   3349:         * to call this function to ensure that the stream memory will be
                   3350:         * properly reclaimed.
                   3351:         */
                   3352: 
                   3353:        ASSERT (sheadp->sh_open_count == 0);
                   3354: 
                   3355:        if (SHEAD_IS_PIPE (sheadp)) {
                   3356:                shead_t       * other = SHEAD_OTHER (sheadp);
                   3357: 
                   3358:                /*
                   3359:                 * If this is a pipe, there are some extra things we should
                   3360:                 * worry about. First, the first end of a stream pipe to close
                   3361:                 * should send an M_HANGUP message to the other end rather
                   3362:                 * than actually closing. The other end then gets to destroy
                   3363:                 * both sides of the pipe when it finally closes.
                   3364:                 *
                   3365:                 * The second exception is that when an unattached end of a
                   3366:                 * streams pipe is closed, the other end is automatically
                   3367:                 * detached.
                   3368:                 *
                   3369:                 * Note that if the other end of the pipe is linked below a
                   3370:                 * multiplexor, we do not attempt to automatically unlink it.
                   3371:                 * This might seem entirely reasonable, but we cannot attempt
                   3372:                 * this without introducing a possibility of deadlock.
                   3373:                 */
                   3374: 
                   3375:                if (other->sh_attach_count > 0)
                   3376:                        SHEAD_PIPE_DETACH (other);
                   3377: 
                   3378:                if (other->sh_open_count > 0) {
                   3379:                        /*
                   3380:                         * The last close/detach/unlink of the other end will
                   3381:                         * clean everything up.
                   3382:                         */
                   3383: 
                   3384:                        putctl (W (other->sh_head), M_HANGUP);
                   3385:                        return 0;
                   3386:                }
                   3387: 
                   3388:                /*
                   3389:                 * Now we clean up the "other" end.
                   3390:                 */
                   3391: 
                   3392:                SHEAD_FINAL_CLOSE (other, mode, credp);
                   3393:        }
                   3394: 
                   3395:        SHEAD_FINAL_CLOSE (sheadp, mode, credp);
                   3396: 
                   3397:        /*
                   3398:         * We leave the last part of the cleanup (dallocating the queue pair
                   3399:         * and any remaining messages) to the unlock call which the caller
                   3400:         * will perform.
                   3401:         */
                   3402: 
                   3403:        return 0;
                   3404: }
                   3405: 
                   3406: 
                   3407: /*
                   3408:  * This function builds and send an M_FLUSH message down the stream.
                   3409:  */
                   3410: 
                   3411: #if    __USE_PROTO__
                   3412: __LOCAL__ int (SHEAD_FLUSH) (shead_t * sheadp, int flag, uchar_t band)
                   3413: #else
                   3414: __LOCAL__ int
                   3415: SHEAD_FLUSH __ARGS ((sheadp, flag, band))
                   3416: shead_t              * sheadp;
                   3417: int            flag;
                   3418: uchar_t                band;
                   3419: #endif
                   3420: {
                   3421:        mblk_t        * msg;
                   3422: 
                   3423:        if ((flag & FLUSHRW) == 0 || (flag & ~ FLUSHRW) != 0)
                   3424:                return EINVAL;
                   3425:        else if ((msg = MSGB_ALLOC (2, BPRI_LO, KM_SLEEP)) == NULL)
                   3426:                return ENOSR;
                   3427:        else {
                   3428:                /*
                   3429:                 * Send the message downstream...
                   3430:                 */
                   3431: 
                   3432:                if (band > 0)
                   3433:                        flag |= FLUSHBAND;
                   3434: 
                   3435:                msg->b_datap->db_type = M_FLUSH;
                   3436:                * msg->b_wptr ++ = (unsigned char) flag;
                   3437: 
                   3438:                if (band > 0)
                   3439:                        * msg->b_wptr ++ = band;
                   3440: 
                   3441:                put (W (sheadp->sh_head), msg);
                   3442:        }
                   3443: 
                   3444:        return 0;
                   3445: }
                   3446: 
                   3447: 
                   3448: /*
                   3449:  * This function locates a module's streamtab entry given the name. Only the
                   3450:  * first FMNAMESZ characters are considered significant.
                   3451:  */
                   3452: 
                   3453: #if    __USE_PROTO__
                   3454: modsw_t * (FIND_MODULE) (__CONST__ char * modname)
                   3455: #else
                   3456: modsw_t *
                   3457: FIND_MODULE __ARGS ((modname))
                   3458: __CONST__ char * modname;
                   3459: #endif
                   3460: {
                   3461:        modsw_t       * scan;
                   3462:        modsw_t       * end;
                   3463: 
                   3464:        for (scan = modsw, end = scan + nmodsw ; scan != end ; scan ++) {
                   3465:                __CONST__ char * name;
                   3466: 
                   3467:                name = scan->mod_stream->st_rdinit->qi_minfo->mi_idname;
                   3468: 
                   3469:                if (name != NULL && strncmp (modname, name, FMNAMESZ) == 0)
                   3470:                        return scan;
                   3471:        }
                   3472: 
                   3473:        return NULL;
                   3474: }
                   3475: 
                   3476: 
                   3477: /*
                   3478:  * This function holds code to process an I_STR ioctl ().
                   3479:  */
                   3480: 
                   3481: #if    __USE_PROTO__
                   3482: __LOCAL__ int (ISTR_IOCTL) (shead_t * sheadp, int mode,
                   3483:                            struct strioctl * strioc, cred_t * credp,
                   3484:                            int * rvalp)
                   3485: #else
                   3486: __LOCAL__ int
                   3487: ISTR_IOCTL __ARGS ((sheadp, mode, strioc, credp, rvalp))
                   3488: shead_t              * sheadp;
                   3489: int            mode;
                   3490: struct strioctl
                   3491:              * strioc;
                   3492: cred_t       * credp;
                   3493: int          * rvalp;
                   3494: #endif
                   3495: {
                   3496:        __clock_t       ticks;
                   3497:        mblk_t        * msg;
                   3498:        mblk_t        * data;
                   3499:        struct iocblk * ioc;
                   3500:         int            retval;
                   3501: 
                   3502:        ASSERT_SLEEP_LOCKED (sheadp, SH_IOCTL_LOCK);
                   3503: 
                   3504:        /*
                   3505:         * Set up timeout; "ic_timeout" == -1 means infinite
                   3506:         * timeout, while "ic_timeout" == 0 means default
                   3507:         * (which is infinite).
                   3508:         */
                   3509: 
                   3510:        if (strioc->ic_timeout != -1 && strioc->ic_timeout != 0) {
                   3511:                /*
                   3512:                 * We take care to deal with overflow here.
                   3513:                 */
                   3514: 
                   3515:                if ((ticks = strioc->ic_timeout) > (__clock_t) -1 / 1000000L)
                   3516:                        ticks = (__clock_t) -1;
                   3517: 
                   3518:                ticks = drv_usectohz (ticks * 1000000L);
                   3519:        } else
                   3520:                ticks = 0;
                   3521: 
                   3522:        if ((msg = MSGB_ALLOC (sizeof (* ioc), BPRI_LO, KM_SLEEP)) == NULL)
                   3523:                return ENOSR;
                   3524: 
                   3525:        ioc = (struct iocblk *) msg->b_rptr;
                   3526:        msg->b_wptr = (unsigned char *) (ioc + 1);
                   3527: 
                   3528:        msg->b_datap->db_type = M_IOCTL;
                   3529: 
                   3530:        ioc->ioc_cmd = strioc->ic_cmd;
                   3531:        ioc->ioc_cr = credp;
                   3532:        ioc->ioc_id = ++ sheadp->sh_ioc_seq;
                   3533:        ioc->ioc_count = strioc->ic_len;
                   3534:        ioc->ioc_rval = ioc->ioc_error = 0;
                   3535: 
                   3536: 
                   3537:        /*
                   3538:         * If there is data to be sent downstream, we allocate a buffer to
                   3539:         * hold it and copy the data into that buffer.
                   3540:         */
                   3541: 
                   3542:        if (ioc->ioc_count > 0) {
                   3543: 
                   3544:                if ((data = MSGB_ALLOC (strioc->ic_len, BPRI_LO,
                   3545:                                        KM_SLEEP)) == NULL) {
                   3546: 
                   3547:                        retval = ENOSR;
                   3548:                        goto done;
                   3549:                }
                   3550: 
                   3551:                msg->b_cont = data;
                   3552:                data->b_wptr += strioc->ic_len;
                   3553: 
                   3554:                if (copyin (strioc->ic_dp, data->b_rptr,
                   3555:                            strioc->ic_len) != 0) {
                   3556: 
                   3557:                        retval = EFAULT;
                   3558:                        goto done;
                   3559:                }
                   3560:        }
                   3561: 
                   3562:        /*
                   3563:         * Now we send the ioctl () and wait for the acknowledgement.
                   3564:         */
                   3565: 
                   3566:        if ((msg = IOCTL_SEND (sheadp, mode, msg, & retval, ticks)) == NULL)
                   3567:                return retval;
                   3568: 
                   3569: 
                   3570:        /*
                   3571:         * What do we do with the results? We copy at most "ioc_count" bytes
                   3572:         * of data back into the user's address space if this is M_IOCACK.
                   3573:         */
                   3574: 
                   3575:        ioc = (struct iocblk *) msg->b_rptr;
                   3576: 
                   3577:        switch (msg->b_datap->db_type) {
                   3578: 
                   3579:        case M_IOCNAK:
                   3580:                retval = ioc->ioc_error;
                   3581:                break;
                   3582: 
                   3583:        case M_IOCACK:
                   3584:                * rvalp = ioc->ioc_rval;
                   3585:                retval = ioc->ioc_error;
                   3586: 
                   3587:                data = msg->b_cont;
                   3588: 
                   3589:                while (ioc->ioc_count > 0) {
                   3590:                        size_t          len;
                   3591: 
                   3592:                        if (data == NULL) {
                   3593: 
                   3594:                                cmn_err (CE_WARN, "ISTR_IOCTL : Insufficient M_DATA blocks for ioc_count");
                   3595:                                break;
                   3596:                        }
                   3597: 
                   3598:                        len = data->b_wptr - data->b_rptr;
                   3599: 
                   3600:                        if (len > ioc->ioc_count)
                   3601:                                len = ioc->ioc_count;
                   3602: 
                   3603:                        if (len > 0 &&
                   3604:                            copyout (data->b_rptr, strioc->ic_dp,
                   3605:                                     len) != 0) {
                   3606: 
                   3607:                                retval = EFAULT;
                   3608:                                goto done;
                   3609:                        }
                   3610: 
                   3611:                        ioc->ioc_count -= len;
                   3612:                        data = data->b_cont;
                   3613:                        strioc->ic_dp += len;
                   3614:                }
                   3615:                break;
                   3616: 
                   3617:        default:
                   3618:                cmn_err (CE_WARN, "Invalid message type %d received during unlink processing",
                   3619:                         msg->b_datap->db_type);
                   3620:                retval = ENXIO;
                   3621:                break;
                   3622:        }
                   3623: 
                   3624: done:
                   3625:        freemsg (msg);
                   3626: 
                   3627:        return retval;
                   3628: }
                   3629: 
                   3630: 
                   3631: /*
                   3632:  * Here are the details of the implementation of sigpoll_t.
                   3633:  */
                   3634: 
                   3635: struct sigpoll {
                   3636:        sigpoll_t     * sp_next;        /* single-threaded */
                   3637:        _VOID         * sp_proc;        /* from proc_ref () */
                   3638:        short           sp_events;      /* events to signal per <stropts.h> */
                   3639: };
                   3640: 
                   3641: 
                   3642: /*
                   3643:  * This function is used when an M_SIG or M_PCSIG message is processed at the
                   3644:  * stream head.
                   3645:  */
                   3646: 
                   3647: #if    __USE_PROTO__
                   3648: void (SHEAD_SIGNAL) (shead_t * sheadp, uchar_t signal)
                   3649: #else
                   3650: void
                   3651: SHEAD_SIGNAL __ARGS ((sheadp, signal))
                   3652: shead_t              * sheadp;
                   3653: uchar_t                signal;
                   3654: #endif
                   3655: {
                   3656:        pl_t            prev_pl;
                   3657: 
                   3658:        prev_pl = SHEAD_LOCK (sheadp);
                   3659: 
                   3660:        if (signal == SIGPOLL) {
                   3661:                sigpoll_t     * sigs;
                   3662: 
                   3663:                /*
                   3664:                 * SIGPOLL is only sent to those processes that have
                   3665:                 * registered to receive it with I_SETSIG.
                   3666:                 */
                   3667: 
                   3668: 
                   3669:                for (sigs = sheadp->sh_sigs ; sigs != NULL ;
                   3670:                     sigs = sigs->sp_next) {
                   3671: 
                   3672:                        if ((sigs->sp_events & S_MSG) != 0)
                   3673:                                proc_signal (sigs->sp_proc, signal);
                   3674:                }
                   3675:        } else {
                   3676:                /*
                   3677:                 * Send a signal to the controlling process group for this
                   3678:                 * stream; if this stream is not a controlling tty, then no
                   3679:                 * signal is sent.
                   3680:                 */
                   3681: 
                   3682:                if (sheadp->sh_pgrp != 0)
                   3683:                        proc_kill_group (sheadp->sh_pgrp, signal);
                   3684:        }
                   3685: 
                   3686:        SHEAD_UNLOCK (sheadp, prev_pl);
                   3687: }
                   3688: 
                   3689: 
                   3690: /*
                   3691:  * This function encapsulates all user-level access to the front of the stream
                   3692:  * head message queue. It deals with ensuring that the STREAMS scheduling
                   3693:  * policy works (by managing QWANTR) and some other details such as dealing
                   3694:  * with in-band processing of M_SIG messages.
                   3695:  *
                   3696:  * The stream head read queue should be frozen by the caller.
                   3697:  */
                   3698: 
                   3699: #if    __USE_PROTO__
                   3700: __LOCAL__ mblk_t * (SHEAD_FIRSTMSG) (shead_t * sheadp)
                   3701: #else
                   3702: __LOCAL__ mblk_t *
                   3703: SHEAD_FIRSTMSG __ARGS ((sheadp))
                   3704: shead_t              * sheadp;
                   3705: #endif
                   3706: {
                   3707:        mblk_t        * msg;
                   3708: 
                   3709:        QFROZEN_TRACE (sheadp->sh_head, "SHEAD_FIRSTMSG");
                   3710: 
                   3711:        while ((msg = sheadp->sh_head->q_first) != NULL) {
                   3712: 
                   3713:                if (msg->b_datap->db_type != M_SIG)
                   3714:                        return msg;
                   3715: 
                   3716:                rmvq (sheadp->sh_head, msg);
                   3717:                SHEAD_SIGNAL (sheadp, * msg->b_rptr);
                   3718:                freemsg (msg);
                   3719:        }
                   3720: 
                   3721:        sheadp->sh_head->q_flag |= QWANTR;
                   3722: 
                   3723:        return NULL;
                   3724: }
                   3725: 
                   3726: 
                   3727: /*
                   3728:  * This function does the necessary work to implement POLLWRBAND, which tests
                   3729:  * to see if any of the previously written-to bands of flow in the next
                   3730:  * downstream queue with a service procedure are not flow controlled.
                   3731:  */
                   3732: 
                   3733: #if    __USE_PROTO__
                   3734: __LOCAL__ int (POLL_WRBAND) (queue_t * q)
                   3735: #else
                   3736: __LOCAL__ int
                   3737: POLL_WRBAND __ARGS ((q))
                   3738: queue_t              * q;
                   3739: #endif
                   3740: {
                   3741:        pl_t            prev_pl;
                   3742:        qband_t       * qbandp;
                   3743: 
                   3744:        prev_pl = QFREEZE_TRACE (q, "POLL_WRBAND");
                   3745: 
                   3746:        do {
                   3747:                q = QUEUE_NEXT (q);
                   3748: 
                   3749:                if (q == NULL)
                   3750:                        return 1;
                   3751: 
                   3752:        } while (q->q_qinfo->qi_srvp == NULL);
                   3753: 
                   3754: 
                   3755:        /*
                   3756:         * We have found a queue with a service procedure, and have it frozen.
                   3757:         * If there are no bands, then we can write a band...
                   3758:         */
                   3759: 
                   3760:        if (q->q_nband == 0) {
                   3761: 
                   3762:                QUNFREEZE_TRACE (q, prev_pl);
                   3763:                return 1;
                   3764:        }
                   3765: 
                   3766:        qbandp = QUEUE_BAND (q, q->q_nband);
                   3767: 
                   3768:        ASSERT (qbandp != NULL);
                   3769: 
                   3770:        /*
                   3771:         * Since if a band is blocked implies lower bands are blocked, we can
                   3772:         * simply test the highest-numbered band.
                   3773:         */
                   3774: 
                   3775:        if ((qbandp->qb_flag & QB_FULL) != 0) {
                   3776: 
                   3777:                QUNFREEZE_TRACE (q, prev_pl);
                   3778:                return 1;
                   3779:        }
                   3780: 
                   3781: 
                   3782:        /*
                   3783:         * If all are full, request notification via back-enabling when the
                   3784:         * highest band becomes writeable.
                   3785:         */
                   3786: 
                   3787:        qbandp->qb_flag |= QB_WANTW;
                   3788: 
                   3789:        QUNFREEZE_TRACE (q, prev_pl);
                   3790:        return 0;
                   3791: }
                   3792: 
                   3793: 
                   3794: /*
                   3795:  * This function has responsibility for checking to see whether the event mask
                   3796:  * for this SIGPOLL request is immediately satisfied.
                   3797:  */
                   3798: 
                   3799: #if    __USE_PROTO__
                   3800: __LOCAL__ short (SHEAD_POLL_CHECK) (shead_t * sheadp, short events)
                   3801: #else
                   3802: __LOCAL__ short
                   3803: SHEAD_POLL_CHECK __ARGS ((sheadp, events))
                   3804: shead_t              * sheadp;
                   3805: short          events;
                   3806: #endif
                   3807: {
                   3808:        short           revents = 0;
                   3809:        pl_t            prev_pl;
                   3810:        mblk_t        * msg;
                   3811: 
                   3812: 
                   3813:        /*
                   3814:         * Check the conditions that do not depend on the status of the first
                   3815:         * queued message (if any).
                   3816:         *
                   3817:         * For S_OUTPUT, using canputnext () is important because it sets the
                   3818:         * back-enable flag so that we will be properly notified when the
                   3819:         * condition becomes true.
                   3820:         *
                   3821:         * For S_WRBAND, things are a little more complex; this tests whether
                   3822:         * *any* downstream priority band is writeable, which involves walking
                   3823:         * over all the 'qband' structures allocated to the next stream with
                   3824:         * a service procedure.
                   3825:         */
                   3826: 
                   3827:        if ((events & __POLL_OUTPUT) != 0 && canputnext (W (sheadp->sh_head)))
                   3828:                revents |= __POLL_OUTPUT;
                   3829: 
                   3830:        if ((events & __POLL_WRBAND) != 0 &&
                   3831:            POLL_WRBAND (W (sheadp->sh_head)))
                   3832:                revents |= __POLL_WRBAND;
                   3833: 
                   3834: 
                   3835:        prev_pl = SHEAD_LOCK (sheadp);
                   3836: 
                   3837:        if ((events & S_ERROR) != 0 &&
                   3838:            (sheadp->sh_rerrcode != 0 || sheadp->sh_werrcode != 0))
                   3839:                revents |= POLLERR;
                   3840: 
                   3841:        if ((events & S_HANGUP) != 0 && (sheadp->sh_flags & SH_HANGUP) != 0)
                   3842:                revents = (revents | POLLHUP) &
                   3843:                                ~ (__POLL_OUTPUT | __POLL_WRBAND);
                   3844: 
                   3845:        SHEAD_UNLOCK (sheadp, prev_pl);
                   3846: 
                   3847: 
                   3848:        prev_pl = QFREEZE_TRACE (sheadp->sh_head, "SHEAD_POLL_CHECK");
                   3849: 
                   3850:        if ((msg = SHEAD_FIRSTMSG (sheadp)) != NULL &&
                   3851:            datamsg (msg->b_datap->db_type)) {
                   3852: 
                   3853:                if (! pcmsg (msg->b_datap->db_type)) {
                   3854: 
                   3855:                        if ((events & __POLL_INPUT) != 0)
                   3856:                                revents |= __POLL_INPUT;
                   3857: 
                   3858:                        if ((events & __POLL_RDNORM) != 0 && msg->b_band == 0)
                   3859:                                revents |= __POLL_RDNORM;
                   3860: 
                   3861:                        if ((events & __POLL_RDBAND) != 0 && msg->b_band > 0)
                   3862:                                revents |= __POLL_RDBAND;
                   3863:                } else if ((events & __POLL_HIPRI) != 0)
                   3864:                        revents |= __POLL_HIPRI;
                   3865:        }
                   3866: 
                   3867:        QUNFREEZE_TRACE (sheadp->sh_head, prev_pl);
                   3868: 
                   3869:        return revents;
                   3870: }
                   3871: 
                   3872: 
                   3873: /*
                   3874:  * This function attempts to locate any sigpoll record for the current
                   3875:  * process. The stream head needs to be locked out against modification of
                   3876:  * the signal list, which means an IOCTL lock is sufficient.
                   3877:  */
                   3878: 
                   3879: #if    __USE_PROTO__
                   3880: __LOCAL__ sigpoll_t * (FIND_SIGPOLL) (shead_t * sheadp)
                   3881: #else
                   3882: __LOCAL__ sigpoll_t *
                   3883: FIND_SIGPOLL __ARGS ((sheadp))
                   3884: shead_t              * sheadp;
                   3885: #endif
                   3886: {
                   3887:        _VOID         * proc;
                   3888:        sigpoll_t     * scan;
                   3889: 
                   3890:        ASSERT_SLEEP_LOCKED (sheadp, SH_IOCTL_LOCK);
                   3891: 
                   3892:        /*
                   3893:         * See if the process is already registered (so that we can modify or
                   3894:         * free an existing record).
                   3895:         */
                   3896: 
                   3897:        proc = proc_ref ();
                   3898: 
                   3899:        for (scan = sheadp->sh_sigs ; scan != NULL ; scan ++)
                   3900:                if (scan->sp_proc == proc)
                   3901:                        break;
                   3902: 
                   3903:        proc_unref (proc);
                   3904: 
                   3905:        return scan;
                   3906: }
                   3907: 
                   3908: 
                   3909: /*
                   3910:  * This function deals with (de)registering a process for SIGPOLL. The caller
                   3911:  * should have an IOCTL lock on the stream head so that there are no other
                   3912:  * contexts which could modify the list of registered signals.
                   3913:  */
                   3914: 
                   3915: #if    __USE_PROTO__
                   3916: __LOCAL__ int (REGISTER_SIGPOLL) (shead_t * sheadp, short events)
                   3917: #else
                   3918: __LOCAL__ int
                   3919: REGISTER_SIGPOLL __ARGS ((sheadp, events))
                   3920: shead_t              * sheadp;
                   3921: short          events;
                   3922: #endif
                   3923: {
                   3924:        _VOID         * proc;
                   3925:        sigpoll_t     * scan;
                   3926:        sigpoll_t     * prev;
                   3927: 
                   3928:        ASSERT_SLEEP_LOCKED (sheadp, SH_IOCTL_LOCK);
                   3929: 
                   3930:        /*
                   3931:         * See if the process is already registered (so that we can modify or
                   3932:         * free an existing record). We don't use the FIND_SIGPOLL () routine
                   3933:         * because we want to locate the previous record also.
                   3934:         */
                   3935: 
                   3936:        proc = proc_ref ();
                   3937: 
                   3938:        for (prev = NULL, scan = sheadp->sh_sigs ; scan != NULL ;
                   3939:             prev = scan, scan ++) {
                   3940: 
                   3941:                if (scan->sp_proc == proc) {
                   3942:                        /*
                   3943:                         * We have found a preexisting record... now modify
                   3944:                         * or free it.
                   3945:                         */
                   3946: 
                   3947:                        proc_unref (proc);
                   3948: 
                   3949:                        (void) SHEAD_LOCK (sheadp);
                   3950: 
                   3951:                        if ((scan->sp_events = events) == 0) {
                   3952:                                /*
                   3953:                                 * Free the cell after unlinking it from the
                   3954:                                 * list of registered processes. We take out
                   3955:                                 * a lock on the stream head to protect
                   3956:                                 * against streams-level contexts walking the
                   3957:                                 * list.
                   3958:                                 */
                   3959: 
                   3960:                                if (prev == NULL)
                   3961:                                        sheadp->sh_sigs = scan->sp_next;
                   3962:                                else
                   3963:                                        prev->sp_next = scan->sp_next;
                   3964: 
                   3965:                                SHEAD_UNLOCK (sheadp, plbase);
                   3966: 
                   3967:                                /*
                   3968:                                 * We unlock the stream head before calling
                   3969:                                 * the heap manager as a matter of courtesy.
                   3970:                                 */
                   3971: 
                   3972:                                kmem_free (scan, sizeof (* scan));
                   3973:                                proc_unref (proc);
                   3974:                                return 0;
                   3975:                        }
                   3976: 
                   3977:                        SHEAD_UNLOCK (sheadp, plbase);
                   3978:                        goto sigcheck;
                   3979:                }
                   3980:        }
                   3981: 
                   3982: 
                   3983:        if (events == 0) {
                   3984:                /*
                   3985:                 * Not found, nothing to do. That is an error according to the
                   3986:                 * streamio (7) man pages.
                   3987:                 */
                   3988: 
                   3989:                return EINVAL;
                   3990:        }
                   3991: 
                   3992: 
                   3993:        /*
                   3994:         * We need to make a new event.
                   3995:         */
                   3996: 
                   3997:        if ((scan = (sigpoll_t *) kmem_alloc (sizeof (* scan),
                   3998:                                              KM_SLEEP)) == NULL) {
                   3999: 
                   4000:                proc_unref (proc);
                   4001:                return EAGAIN;
                   4002:        }
                   4003: 
                   4004:        scan->sp_proc = proc;
                   4005:        scan->sp_events = events;
                   4006:        scan->sp_next = sheadp->sh_sigs;
                   4007: 
                   4008:        /*
                   4009:         * Since we are the only process context modifying the list, we only
                   4010:         * need to lock the last stage of the insert against interrupt-level
                   4011:         * contexts walking the list.
                   4012:         */
                   4013: 
                   4014:        (void) SHEAD_LOCK (sheadp);
                   4015: 
                   4016:        sheadp->sh_sigs = scan;
                   4017: 
                   4018:        SHEAD_UNLOCK (sheadp, plbase);
                   4019: 
                   4020: sigcheck:
                   4021:        if ((events = SHEAD_POLL_CHECK (sheadp, scan->sp_events)) != 0) {
                   4022:                /*
                   4023:                 * We have a winner! Check for the SIGURG special case, and
                   4024:                 * otherwise/also send SIGPOLL via proc_signal ().
                   4025:                 */
                   4026: 
                   4027:                if ((events & __POLL_RDBAND) != 0 &&
                   4028:                    (scan->sp_events & S_BANDURG) != 0) {
                   4029: 
                   4030:                        proc_signal (scan->sp_proc, SIGURG);
                   4031:                        events &= ~ __POLL_RDBAND;
                   4032:                }
                   4033: 
                   4034:                if (events != 0)
                   4035:                        proc_signal (scan->sp_proc, SIGPOLL);
                   4036:        }
                   4037: 
                   4038:        return 0;
                   4039: }
                   4040: 
                   4041: 
                   4042: /*
                   4043:  * This function maps a file descriptor into a stream head by calling upon the
                   4044:  * abstract file-description functions declared in <sys/fhsys.h>. The caller
                   4045:  * must lock the stream somehow.
                   4046:  */
                   4047: 
                   4048: #if    ! _NO_INSTALLABLE_FILESYSTEMS
                   4049: 
                   4050: extern fprocs_t                streams_fsys;
                   4051: 
                   4052: #endif
                   4053: 
                   4054: 
                   4055: #if    __USE_PROTO__
                   4056: __LOCAL__ shead_t * (FH_TO_STREAM) (int fd, int * retvalp)
                   4057: #else
                   4058: __LOCAL__ shead_t *
                   4059: FH_TO_STREAM __ARGS ((fd, retvalp))
                   4060: int            fd;
                   4061: int          * retvalp;
                   4062: #endif
                   4063: {
                   4064:        fhandle_t     * handle;
                   4065:        scookie_t     * cookie;
                   4066: 
                   4067:        ASSERT (retvalp != NULL);
                   4068: 
                   4069:        if ((handle = fd_get_handle (fd)) == NULL) {
                   4070: 
                   4071:                * retvalp = EBADF;
                   4072:                return NULL;
                   4073: #if    ! _NO_INSTALLABLE_FILESYSTEMS
                   4074:        } else if (fh_procs (handle) == & streams_fsys) {
                   4075: 
                   4076:                * retvalp = EINVAL;
                   4077:                return NULL;
                   4078: #endif
                   4079:        }
                   4080: 
                   4081:        cookie = (scookie_t *) fh_get_cookie (handle);
                   4082: 
                   4083:        ASSERT (cookie != NULL);
                   4084: 
                   4085:        if (cookie->sheadp == NULL)
                   4086:                cmn_err (CE_WARN, "Bad cookie in streams");
                   4087: 
                   4088:        return cookie->sheadp;
                   4089: }
                   4090: 
                   4091: 
                   4092: /*
                   4093:  * The following structure is used by the routines below to deal with the
                   4094:  * M_PASSFP message type. The structure of the data contained in that message
                   4095:  * is completely opaque to STREAMS routines, so we keep the definition local.
                   4096:  */
                   4097: 
                   4098: struct passfp {
                   4099:        sftab_t       * sftab;  /* system file table entry address */
                   4100:        n_uid_t         uid;
                   4101:        n_gid_t         gid;
                   4102: };
                   4103: 
                   4104: 
                   4105: /*
                   4106:  * This function attempts to retrieve a file descriptor sent by an I_SENDFD
                   4107:  * ioctl () and create a local file descriptor referring to the same file.
                   4108:  */
                   4109: 
                   4110: #if    __USE_PROTO__
                   4111: __LOCAL__ int (FH_RECV) (shead_t * sheadp, int mode, struct strrecvfd * recvp)
                   4112: #else
                   4113: __LOCAL__ int
                   4114: FH_RECV __ARGS ((sheadp, mode, recvp))
                   4115: shead_t              * sheadp;
                   4116: int            mode;
                   4117: struct strrecvfd
                   4118:              * recvp;
                   4119: #endif
                   4120: {
                   4121:        mblk_t        * msg;
                   4122:        struct passfp * fp;
                   4123:        int             retval;
                   4124: 
                   4125:        ASSERT (sheadp != NULL);
                   4126:        ASSERT (recvp != NULL);
                   4127: 
                   4128:        if (! SHEAD_IS_PIPE (sheadp))
                   4129:                return EINVAL;
                   4130: 
                   4131:        if ((mode & FREAD) == 0)
                   4132:                return EBADF;
                   4133: 
                   4134:        mode &= ~ FWRITE;
                   4135: 
                   4136: 
                   4137:        /*
                   4138:         * Look at the stream head to see if a message is present.
                   4139:         */
                   4140: 
                   4141:        for (;;) {
                   4142:                int             retval;
                   4143: 
                   4144:                (void) QFREEZE_TRACE (sheadp->sh_head, "FH_RECV");
                   4145: 
                   4146:                if ((msg = SHEAD_FIRSTMSG (sheadp)) != NULL)
                   4147:                        break;
                   4148: 
                   4149:                /*
                   4150:                 * Use the STREAMS flag to indicate that we have found the
                   4151:                 * queue empty.
                   4152:                 */
                   4153: 
                   4154:                (void) SHEAD_LOCK (sheadp);
                   4155: 
                   4156:                QUNFREEZE_TRACE (sheadp->sh_head, plstr);
                   4157: 
                   4158:                /*
                   4159:                 * We need to wait (unless O_NDELAY or O_NONBLOCK has been
                   4160:                 * specified), or the stream has been hung up.
                   4161:                 */
                   4162: 
                   4163:                if ((retval = SHEAD_WAIT_NONBLOCK (sheadp, mode, SH_READ_WAIT,
                   4164:                                                   CHECK_SIGNALS)) != 0)
                   4165:                        return retval;
                   4166: 
                   4167:                /*
                   4168:                 * Check again...
                   4169:                 */
                   4170:        }
                   4171: 
                   4172:        if (msg->b_datap->db_type != M_PASSFP)
                   4173:                retval = EBADMSG;
                   4174:        else if (! fd_can_add ())
                   4175:                retval = EMFILE;
                   4176:        else {
                   4177: 
                   4178:                retval = 0;
                   4179:                rmvq (sheadp->sh_head, msg);
                   4180:        }
                   4181: 
                   4182:        QUNFREEZE_TRACE (sheadp->sh_head, plbase);
                   4183: 
                   4184:        if (retval != 0)
                   4185:                return retval;
                   4186: 
                   4187:        /*
                   4188:         * After this point, "msg" is our responsibility and we either have to
                   4189:         * free it or put it back if there is an error.
                   4190:         */
                   4191: 
                   4192:        fp = (struct passfp *) msg->b_rptr;
                   4193: 
                   4194:        if ((retval = fd_add_sftab (fp->sftab, & recvp->fd)) == 0 &&
                   4195:            ((recvp->uid = (o_uid_t) fp->uid) != fp->uid ||
                   4196:             (recvp->gid = (o_gid_t) fp->gid) != fp->gid))
                   4197:                retval = EOVERFLOW;
                   4198: 
                   4199:        freemsg (msg);
                   4200:        return retval;
                   4201: }
                   4202: 
                   4203: 
                   4204: /*
                   4205:  * This function attempts to send a file descriptor to another process at the
                   4206:  * other end of a stream pipe.
                   4207:  */
                   4208: 
                   4209: #if    __USE_PROTO__
                   4210: __LOCAL__ int (FH_SEND) (shead_t * sheadp, int fd, cred_t * credp)
                   4211: #else
                   4212: __LOCAL__ int
                   4213: FH_SEND __ARGS ((sheadp, fd, credp))
                   4214: shead_t              * sheadp;
                   4215: int            fd;
                   4216: cred_t       * credp;
                   4217: #endif
                   4218: {
                   4219:        mblk_t        * msg;
                   4220:        struct passfp * fp;
                   4221:        sftab_t       * sftab;
                   4222:        shead_t       * other;
                   4223:        int             retval;
                   4224: 
                   4225:        ASSERT (sheadp != NULL);
                   4226:        ASSERT (credp != NULL);
                   4227: 
                   4228:        if (! SHEAD_IS_PIPE (sheadp))
                   4229:                return EINVAL;
                   4230: 
                   4231:        /*
                   4232:         * We are passed a file descriptor (a user-level abstract entity);
                   4233:         * here we turn that into a kernel-level abstract entity.
                   4234:         */
                   4235: 
                   4236:        if ((sftab = fd_get_sftab (fd)) == NULL)
                   4237:                return EBADF;
                   4238: 
                   4239:        other = SHEAD_OTHER (sheadp);
                   4240: 
                   4241:        if (! canput (W (other->sh_head)) ||
                   4242:            (msg = MSGB_ALLOC (sizeof (* fp), BPRI_LO, KM_SLEEP)) == NULL)
                   4243:                return EAGAIN;
                   4244: 
                   4245:        /*
                   4246:         * Fill in the new message block and put the message to the other
                   4247:         * side. After this point we have to free the message block if there
                   4248:         * is a problem.
                   4249:         */
                   4250: 
                   4251:        fp = (struct passfp *) msg->b_rptr;
                   4252:        msg->b_wptr = (unsigned char *) (fp + 1);
                   4253: 
                   4254:        msg->b_datap->db_type = M_PASSFP;
                   4255: 
                   4256:        fp->sftab = sftab;
                   4257:        fp->uid = credp->cr_uid;
                   4258:        fp->gid = credp->cr_gid;
                   4259: 
                   4260:        (void) SHEAD_LOCK (sheadp);
                   4261: 
                   4262:        if ((retval = SHEAD_ERRHUP_LOCKED (sheadp, FWRITE)) == 0) {
                   4263: 
                   4264:                putq (W (other->sh_head), msg);
                   4265: 
                   4266:                SHEAD_UNLOCK (sheadp, plbase);
                   4267:        } else
                   4268:                freemsg (msg);
                   4269: 
                   4270:        return retval;
                   4271: }
                   4272: 
                   4273: 
                   4274: /*
                   4275:  * This function factors out the details of copying data out from kernel space
                   4276:  * into a "strbuf" stream buffer structure in user space.
                   4277:  *
                   4278:  * The return value of this function is 0 on success or -1 on error.
                   4279:  */
                   4280: 
                   4281: enum {
                   4282:        CONTROL_PART,
                   4283:        DATA_PART
                   4284: };
                   4285: 
                   4286: #if    __USE_PROTO__
                   4287: __LOCAL__ int (COPYOUT_BUF) (struct strbuf * bufp, mblk_t ** mpp, int data)
                   4288: #else
                   4289: __LOCAL__ int
                   4290: COPYOUT_BUF __ARGS ((bufp, mpp, data))
                   4291: struct strbuf *        bufp;
                   4292: mblk_t      ** mpp;
                   4293: int            data;
                   4294: #endif
                   4295: {
                   4296:        mblk_t        * prev;
                   4297:        mblk_t        * scan;
                   4298:        int             remaining;
                   4299:        caddr_t         outaddr;
                   4300: 
                   4301:        ASSERT (mpp != NULL);
                   4302: 
                   4303:        /*
                   4304:         * The first thing we do is check some special values; if a "strbuf"
                   4305:         * entry is NULL or has its "maxlen" member set to "-1", we do nothing
                   4306:         * with the message.
                   4307:         */
                   4308: 
                   4309:        if (bufp == NULL || bufp->maxlen == -1)
                   4310:                return 0;
                   4311: 
                   4312:        /*
                   4313:         * Next, if this is a data-part copy, skip any intial M_PROTO or
                   4314:         * M_PCPROTO message blocks. There *should* only ever be one of these
                   4315:         * at the front of a message, but we are required to effectively
                   4316:         * coalesce multiple control blocks.
                   4317:         */
                   4318: 
                   4319:        prev = NULL;
                   4320:        scan = * mpp;
                   4321: 
                   4322:        if (data == DATA_PART) {
                   4323:                /*
                   4324:                 * Find the data portion of the message, if any.
                   4325:                 */
                   4326: 
                   4327:                while (scan != NULL) {
                   4328: 
                   4329:                        if (scan->b_datap->db_type == M_DATA)
                   4330:                                break;
                   4331:                        scan = (prev = scan)->b_cont;
                   4332:                }
                   4333:        } else
                   4334:                if (scan->b_datap->db_type == M_DATA)
                   4335:                        scan = NULL;
                   4336: 
                   4337:        /*
                   4338:         * If there is no control (or data, as appropriate) part to the
                   4339:         * message, then we set the "len" member of the "strbuf" to -1.
                   4340:         */
                   4341: 
                   4342:        if (scan == NULL) {
                   4343: 
                   4344:                bufp->len = -1;
                   4345:                return 0;
                   4346:        }
                   4347: 
                   4348: 
                   4349:        /*
                   4350:         * Now be do the actual copy; the form of this loop is organized so
                   4351:         * that zero-length message blocks will be consumed if "maxlen" is
                   4352:         * set to 0. This is important not only to comply with the manual page
                   4353:         * for getmsg ()/getpmsg (), but also ensures that trailing zero-
                   4354:         * length blocks at the end of a message get cleaned up properly.
                   4355:         */
                   4356: 
                   4357:        bufp->len = 0;
                   4358:        remaining = bufp->maxlen;
                   4359:        outaddr = (caddr_t) bufp->buf;
                   4360: 
                   4361:        for (;;) {
                   4362:                size_t          copylen = scan->b_wptr - scan->b_rptr;
                   4363:                mblk_t        * next;
                   4364: 
                   4365:                if (copylen > remaining)
                   4366:                        copylen = remaining;
                   4367: 
                   4368:                if (copylen > 0) {
                   4369:                        /*
                   4370:                         * Copy the data to the user. Don't forget that
                   4371:                         * copyout () is like bcopy () in that the arguments
                   4372:                         * are src, dest, len !
                   4373:                         */
                   4374: 
                   4375:                        if (copyout (scan->b_rptr, outaddr, copylen) != 0)
                   4376:                                return EFAULT;
                   4377: 
                   4378:                        bufp->len += copylen;
                   4379:                        scan->b_rptr += copylen;
                   4380:                        remaining -= copylen;
                   4381:                }
                   4382: 
                   4383:                if (scan->b_rptr != scan->b_wptr) {
                   4384:                        /*
                   4385:                         * Since this message block was not fully consumed, we
                   4386:                         * can infer that we have copied all the data we can.
                   4387:                         */
                   4388: 
                   4389:                        ASSERT (remaining == 0);
                   4390:                        break;
                   4391:                }
                   4392: 
                   4393: 
                   4394:                /*
                   4395:                 * This message block has been consumed; unlink and free it.
                   4396:                 */
                   4397: 
                   4398:                next = scan->b_cont;
                   4399:                if (prev == NULL)
                   4400:                        * mpp = next;
                   4401:                else
                   4402:                        prev->b_cont = next;
                   4403:                freeb (scan);
                   4404: 
                   4405: 
                   4406:                /*
                   4407:                 * Get ready to go around the loop again; if we are copying
                   4408:                 * the control part of a message, we have to test for the end
                   4409:                 * of the control part here.
                   4410:                 */
                   4411: 
                   4412:                if ((scan = next) == NULL)
                   4413:                        break;
                   4414: 
                   4415:                if (data == CONTROL_PART && scan->b_datap->db_type == M_DATA)
                   4416:                        break;
                   4417:        }
                   4418: 
                   4419:        return 0;
                   4420: }
                   4421: 
                   4422: 
                   4423: /*
                   4424:  * This is a buffer callback function used by SHEAD_PEEK () to deal with
                   4425:  * dupmsg () failures via bufcall ().
                   4426:  */
                   4427: 
                   4428: #if    __USE_PROTO__
                   4429: __LOCAL__ void peek_bufcall_func (_VOID * arg)
                   4430: #else
                   4431: __LOCAL__ void
                   4432: peek_bufcall_func (arg)
                   4433: _VOID        * arg;
                   4434: #endif
                   4435: {
                   4436:        pl_t            prev_pl;
                   4437:        shead_t       * sheadp = (shead_t *) arg;
                   4438: 
                   4439:        /*
                   4440:         * We freeze the stream head read queue to synchronize ourselves with
                   4441:         * the SHEAD_PEEK () and avoid race conditions where we try and wake
                   4442:         * up the process that scheduled us before they have slept.
                   4443:         */
                   4444: 
                   4445:        prev_pl = QFREEZE_TRACE (sheadp->sh_head, "peek_bufcall_func");
                   4446: 
                   4447:        sheadp->sh_read_bufcall = 0;
                   4448: 
                   4449:        SHEAD_WAKE (sheadp, SH_PEEK_WAIT);
                   4450: 
                   4451:        QUNFREEZE_TRACE (sheadp->sh_head, prev_pl);
                   4452: }
                   4453: 
                   4454: 
                   4455: /*
                   4456:  * This is a helper function for I_PEEK and read ()-like functions who want
                   4457:  * to recover from an out-of-memory situation by performing a short sleep.
                   4458:  *
                   4459:  * This function takes care of scheduling and cancelling the bufcall. The
                   4460:  * caller must have the stream head locked when calling this function.
                   4461:  *
                   4462:  * This function returns with the stream head read queue unlocked, and with
                   4463:  * the value 0 on success and an error number on error.
                   4464:  */
                   4465: 
                   4466: #if    __USE_PROTO__
                   4467: __LOCAL__ int (SHEAD_READ_BUFCALL) (shead_t * sheadp, int __NOTUSED (mode))
                   4468: #else
                   4469: __LOCAL__ int
                   4470: SHEAD_READ_BUFCALL __ARGS ((sheadp, mode))
                   4471: shead_t              * sheadp;
                   4472: int            mode;
                   4473: #endif
                   4474: {
                   4475:        SHEAD_ASSERT_LOCKED (sheadp);
                   4476: 
                   4477:        if (sheadp->sh_read_bufcall == 0 &&
                   4478:            (sheadp->sh_read_bufcall = bufcall (1024, BPRI_LO,
                   4479:                                                peek_bufcall_func,
                   4480:                                                sheadp)) == 0) {
                   4481:                SHEAD_UNLOCK (sheadp, plbase);
                   4482:                return ENOSR;
                   4483:        }
                   4484: 
                   4485:        return SHEAD_WAIT_NONBLOCK (sheadp, FREAD, SH_PEEK_WAIT,
                   4486:                                    CHECK_SIGNALS);
                   4487: }
                   4488: 
                   4489: 
                   4490: /*
                   4491:  * This function implements I_PEEK read-ahead for streams. The caller should
                   4492:  * have the stream head locked for read/write access.
                   4493:  */
                   4494: 
                   4495: #if    __USE_PROTO__
                   4496: __LOCAL__ int (SHEAD_PEEK) (shead_t * sheadp, struct strpeek * peek,
                   4497:                            int * rvalp)
                   4498: #else
                   4499: __LOCAL__ int
                   4500: SHEAD_PEEK __ARGS ((sheadp, peek, rvalp))
                   4501: shead_t              * sheadp;
                   4502: struct strpeek * peek;
                   4503: int          * rvalp;
                   4504: #endif
                   4505: {
                   4506:        mblk_t        * msg;
                   4507:        int             retval;
                   4508: 
                   4509:        ASSERT (sheadp != NULL);
                   4510:        ASSERT (peek != NULL);
                   4511:        ASSERT (rvalp != NULL);
                   4512: 
                   4513:        if (peek->flags != 0 && peek->flags != RS_HIPRI)
                   4514:                return EINVAL;
                   4515: 
                   4516:        /*
                   4517:         * Look at the stream head to see if there are any queued messages.
                   4518:         *
                   4519:         * Some notes about this are in order; as mentioned in the discussion
                   4520:         * on locking elsewhere, the possibility of page fault resolution
                   4521:         * during copies to user space complicates life, because copy routines
                   4522:         * may sleep while a page is made resident.
                   4523:         *
                   4524:         * This affects routines which read from the stream head in various
                   4525:         * ways, some of which are outlined in the general section on locking.
                   4526:         * Other than data consistency, it also affects the way message are
                   4527:         * deallocated; this routine wants to take a copy of the data in a
                   4528:         * message, but we need to ensure that the message will not be
                   4529:         * deallocated not just by other processes but also by actions at the
                   4530:         * stream level such as M_FLUSH.
                   4531:         *
                   4532:         * Other than getting into a web of locking flags and reference counts
                   4533:         * (there are already too many of those), the simplest ways of dealing
                   4534:         * with this are a) create a duplicate reference to the message data
                   4535:         * with dupmsg (), and b) simply dequeue the message and put it back
                   4536:         * when we're done.
                   4537:         *
                   4538:         * Neither alternative is without unpleasant consequences; a) has to
                   4539:         * deal with a lack of available storage to duplicate the message
                   4540:         * blocks, and b) has to deal with such things as reads blocking while
                   4541:         * the message is dequeued.
                   4542:         *
                   4543:         * a) and b) seem to have more-or-less equal implementation costs, but
                   4544:         * while a) is guaranteed to maintain the semantics of all stream
                   4545:         * operations, b) is not. Unless we can predict all the consequences
                   4546:         * of b) and either work around them or determine that they are benign
                   4547:         * then a) seems preferable.
                   4548:         */
                   4549: 
                   4550:        for (;;) {
                   4551:                (void) QFREEZE_TRACE (sheadp->sh_head, "SHEAD_PEEK");
                   4552: 
                   4553:                if ((msg = SHEAD_FIRSTMSG (sheadp)) == NULL) {
                   4554: no_message:
                   4555:                        /*
                   4556:                         * No go; arrange for the value 0 to be returned to
                   4557:                         * the caller of the ioctl ().
                   4558:                         */
                   4559: 
                   4560:                        QUNFREEZE_TRACE (sheadp->sh_head, plbase);
                   4561:                        * rvalp = 0;
                   4562: 
                   4563:                        return 0;
                   4564:                }
                   4565: 
                   4566:                switch (msg->b_datap->db_type) {
                   4567: 
                   4568:                case M_DATA:
                   4569:                case M_PROTO:
                   4570:                        /*
                   4571:                         * If the caller has asked for high-priority messages
                   4572:                         * only, then we arrange to return 0.
                   4573:                         */
                   4574: 
                   4575:                        if ((peek->flags & RS_HIPRI) != 0)
                   4576:                                goto no_message;
                   4577:                        break;
                   4578: 
                   4579:                case M_PCPROTO:
                   4580:                        break;
                   4581: 
                   4582:                default:
                   4583:                        QUNFREEZE_TRACE (sheadp->sh_head, plbase);
                   4584:                        return EBADMSG;
                   4585:                }
                   4586: 
                   4587: 
                   4588:                /*
                   4589:                 * Attempt to obtain a duplicate reference to this message.
                   4590:                 */
                   4591: 
                   4592:                if ((msg = dupmsg (msg)) != NULL) {
                   4593: 
                   4594:                        QUNFREEZE_TRACE (sheadp->sh_head, plbase);
                   4595:                        break;
                   4596:                }
                   4597: 
                   4598: 
                   4599:                /*
                   4600:                 * Wait a short time for buffers to be available. To do this,
                   4601:                 * we transfer our locking attention from the queue to the
                   4602:                 * stream head.
                   4603:                 */
                   4604: 
                   4605:                (void) SHEAD_LOCK (sheadp);
                   4606: 
                   4607:                QUNFREEZE_TRACE (sheadp->sh_head, plstr);
                   4608: 
                   4609:                if ((retval = SHEAD_READ_BUFCALL (sheadp, FREAD)) != 0)
                   4610:                        return retval;
                   4611:        }
                   4612: 
                   4613: 
                   4614:        /*
                   4615:         * Now we have a duplicate copy of a message to transfer to user
                   4616:         * space. From this point on, any attempt to exit from this routine
                   4617:         * must take care of freeing this message. However, we don't have to
                   4618:         * touch the queue again.
                   4619:         */
                   4620: 
                   4621:        peek->flags = msg->b_datap->db_type == M_PCPROTO ? RS_HIPRI : 0;
                   4622: 
                   4623:        retval = (COPYOUT_BUF (& peek->ctlbuf, & msg, CONTROL_PART) != 0 ||
                   4624:                  COPYOUT_BUF (& peek->databuf, & msg,
                   4625:                               DATA_PART) != 0) ? EFAULT : 0;
                   4626: 
                   4627:        if (msg != NULL)
                   4628:                freemsg (msg);
                   4629: 
                   4630:        * rvalp = 1;
                   4631: 
                   4632:        return retval;
                   4633: }
                   4634: 
                   4635: 
                   4636: /*
                   4637:  * Helper function to atomically read the stream head write offset.
                   4638:  */
                   4639: 
                   4640: #if    __USE_PROTO__
                   4641: __LOCAL__ short (SHEAD_WRITEOFFSET) (shead_t * sheadp)
                   4642: #else
                   4643: __LOCAL__ short
                   4644: SHEAD_WRITEOFFSET __ARGS ((sheadp))
                   4645: shead_t              * sheadp;
                   4646: #endif
                   4647: {
                   4648:        pl_t            prev_pl;
                   4649:        short           opt;
                   4650: 
                   4651:        prev_pl = SHEAD_LOCK (sheadp);
                   4652: 
                   4653:        opt = sheadp->sh_readopt;
                   4654: 
                   4655:        SHEAD_UNLOCK (sheadp, prev_pl);
                   4656: 
                   4657:        return opt;
                   4658: }
                   4659: 
                   4660: 
                   4661: /*
                   4662:  * This function tests for errors on a stream and optionally also waits for
                   4663:  * flow control to be relieved.
                   4664:  */
                   4665: 
                   4666: #if    __USE_PROTO__
                   4667: __LOCAL__ int (SHEAD_WRITE_TEST) (shead_t * sheadp, int mode, int band,
                   4668:                                   int hipri)
                   4669: #else
                   4670: __LOCAL__ int
                   4671: SHEAD_WRITE_TEST __ARGS ((sheadp, mode, band, hipri))
                   4672: shead_t              * sheadp;
                   4673: int            mode;
                   4674: int            band;
                   4675: int            hipri;
                   4676: #endif
                   4677: {
                   4678:        int             retval;
                   4679: 
                   4680:        do {
                   4681:                (void) SHEAD_LOCK (sheadp);
                   4682: 
                   4683:                if ((retval = SHEAD_ERRHUP_LOCKED (sheadp, mode)) != 0)
                   4684:                        break;
                   4685: 
                   4686:                if (hipri != 0 || bcanputnext (W (sheadp->sh_head), band)) {
                   4687: 
                   4688:                        SHEAD_UNLOCK (sheadp, plbase);
                   4689:                        break;
                   4690:                }
                   4691:        } while ((retval = SHEAD_WAIT_NONBLOCK (sheadp, mode, SH_WRITE_WAIT,
                   4692:                                                CHECK_SIGNALS)) == 0);
                   4693: 
                   4694:        return retval;
                   4695: }
                   4696: 
                   4697: 
                   4698: /*
                   4699:  * This function deals with all the grunge of creating a message for sending
                   4700:  * down a stream. There are many conditions that need to be checked, including
                   4701:  * whether the message fits within the size limits given by the downstream
                   4702:  * queue.
                   4703:  *
                   4704:  * Since the message is going to be written to the stream, we also deal with
                   4705:  * waiting for flow control here. We only allocate memory for the user's data
                   4706:  * when we have an indication that it will be valid to write it... this may
                   4707:  * not be an optimal choice for a high-performance system with vast amounts
                   4708:  * of STREAMS buffer space.
                   4709:  */
                   4710: 
                   4711: #if    __USE_PROTO__
                   4712: __LOCAL__ mblk_t * (SHEAD_MAKEMSG) (shead_t * sheadp, int mode,
                   4713:                                    struct strbuf * ctlbuf,
                   4714:                                    struct strbuf * databuf,
                   4715:                                    int flags, int band, int * retvalp)
                   4716: #else
                   4717: __LOCAL__ mblk_t *
                   4718: SHEAD_MAKEMSG __ARGS ((sheadp, mode, ctlbuf, databuf, flags, band, retvalp))
                   4719: shead_t              * sheadp;
                   4720: int            mode;
                   4721: struct strbuf *        ctlbuf;
                   4722: struct strbuf *        databuf;
                   4723: int            flags;
                   4724: int            band;
                   4725: int          * retvalp;
                   4726: #endif
                   4727: {
                   4728:        queue_t       * q;
                   4729:        int             ctlsize;
                   4730:        int             datasize;
                   4731:        int             wroff;
                   4732:        mblk_t        * ctlmsg;
                   4733:        mblk_t        * datamsg;
                   4734: 
                   4735:        ASSERT (sheadp != NULL);
                   4736:        ASSERT (retvalp != NULL);
                   4737: 
                   4738:        /*
                   4739:         * The "flags" value specifies one of the constants MSG_BAND or
                   4740:         * MSG_HIPRI. Despite being arranged as flags, only one is allowed to
                   4741:         * be given.
                   4742:         */
                   4743: 
                   4744:        if (flags != MSG_BAND && flags != MSG_HIPRI) {
                   4745: 
                   4746:                * retvalp = EINVAL;
                   4747:                return NULL;
                   4748:        }
                   4749: 
                   4750:        if ((mode & FWRITE) == 0) {
                   4751: 
                   4752:                * retvalp = EBADF;
                   4753:                return NULL;
                   4754:        }
                   4755: 
                   4756:        mode &= ~ FREAD;
                   4757: 
                   4758: 
                   4759:        /*
                   4760:         * The absolute maximum possible size for the control or data parts of
                   4761:         * a STREAMS message are configured system-wide.
                   4762:         */
                   4763: 
                   4764:        ctlsize = ctlbuf == NULL ? -1 : ctlbuf->len;
                   4765:        datasize = databuf == NULL ? -1 : databuf->len;
                   4766:        wroff = SHEAD_WRITEOFFSET (sheadp);
                   4767: 
                   4768:        q = TOP_QUEUE (sheadp);
                   4769: 
                   4770:        if (ctlsize > str_mem->sm_maxctlsize ||
                   4771:            (datasize + wroff) > str_mem->sm_maxdatasize ||
                   4772:            (datasize + wroff) < q->q_minpsz ||
                   4773:            (datasize + wroff) > q->q_maxpsz) {
                   4774: 
                   4775:                * retvalp = ERANGE;
                   4776:                return NULL;
                   4777:        }
                   4778: 
                   4779: 
                   4780:        /*
                   4781:         * You can't send a high-priority message without a control part, or a
                   4782:         * high-priority message with a non-zero band number.
                   4783:         *
                   4784:         * Otherwise, if no data at all is specified, then no message will be
                   4785:         * sent.
                   4786:         */
                   4787: 
                   4788:        if (flags == MSG_HIPRI) {
                   4789: 
                   4790:                if (ctlsize < 0 || band != 0) {
                   4791: 
                   4792:                        * retvalp = EINVAL;
                   4793:                        return NULL;
                   4794:                }
                   4795:        } else if (datasize < 0 && ctlsize < 0) {
                   4796: 
                   4797:                * retvalp = 0;
                   4798:                return NULL;
                   4799:        }
                   4800: 
                   4801: 
                   4802:        /*
                   4803:         * Let's see if the stream is flow controlled; if it is, we either
                   4804:         * block or return EAGAIN depending on the FNDELAY/FNONBLOCK setting.
                   4805:         */
                   4806: 
                   4807:        if ((* retvalp = SHEAD_WRITE_TEST (sheadp, mode, band, flags)) != 0)
                   4808:                return NULL;
                   4809: 
                   4810:        /*
                   4811:         * Now we allocate data space for the messages. If the size of a
                   4812:         * component is -1, then we don't allocate any space for that part,
                   4813:         * otherwise we allocate a component of length 0.
                   4814:         *
                   4815:         * Don't forget that copyin () has arguments in the bcopy () order,
                   4816:         * ie. src, dest, len
                   4817:         */
                   4818: 
                   4819:        if (ctlsize >= 0) {
                   4820:                /*
                   4821:                 * Special case; the stream head is required to ensure that
                   4822:                 * the control part of any message has at least 64 bytes of
                   4823:                 * space. This is specified in the putmsg (2) manual page!
                   4824:                 */
                   4825: 
                   4826:                if ((ctlmsg = MSGB_ALLOC (ctlsize < 64 ? 64 : ctlsize,
                   4827:                                          BPRI_LO, KM_SLEEP)) == NULL) {
                   4828:                        * retvalp = ENOSR;
                   4829:                        return NULL;
                   4830:                }
                   4831: 
                   4832:                ctlmsg->b_datap->db_type = flags == MSG_HIPRI ? M_PCPROTO :
                   4833:                                                                M_PROTO;
                   4834:                ctlmsg->b_band = band;
                   4835: 
                   4836:                if (ctlsize > 0 &&
                   4837:                    copyin (ctlbuf->buf, ctlmsg->b_rptr, ctlsize) != 0) {
                   4838: 
                   4839:                        freeb (ctlmsg);
                   4840:                        * retvalp = EFAULT;
                   4841:                        return NULL;
                   4842:                }
                   4843: 
                   4844:                ctlmsg->b_wptr += ctlsize;
                   4845:        } else
                   4846:                ctlmsg = NULL;          /* paranoia */
                   4847: 
                   4848:        if (datasize >= 0) {
                   4849: 
                   4850:                if ((datamsg = MSGB_ALLOC (datasize + wroff, BPRI_LO,
                   4851:                                           KM_SLEEP)) == NULL) {
                   4852:                        if (ctlsize >= 0)
                   4853:                                freeb (ctlmsg);
                   4854: 
                   4855:                        * retvalp = ENOSR;
                   4856:                        return NULL;
                   4857:                }
                   4858: 
                   4859:                if (ctlsize < 0)
                   4860:                        ctlmsg = datamsg;
                   4861:                else
                   4862:                        ctlmsg->b_cont = datamsg;
                   4863: 
                   4864:                datamsg->b_band = band;
                   4865:                datamsg->b_wptr = datamsg->b_wptr = datamsg->b_rptr + wroff;
                   4866: 
                   4867:                if (datasize > 0 &&
                   4868:                    copyin (databuf->buf, datamsg->b_rptr, datasize) != 0) {
                   4869: 
                   4870:                        freemsg (ctlmsg);
                   4871: 
                   4872:                        * retvalp = EFAULT;
                   4873:                        return NULL;
                   4874:                }
                   4875: 
                   4876:                datamsg->b_wptr += datasize;
                   4877:        }
                   4878: 
                   4879: 
                   4880:        /*
                   4881:         * Since the allocation requests could have blocked for memory to
                   4882:         * become available, and the copy requests could have blocked to
                   4883:         * resolve page faults, we could actually be a fair way down the track
                   4884:         * by now.
                   4885:         *
                   4886:         * If we were paranoid, we would recheck the flow control parameters
                   4887:         * and a bunch of other stuff, but there doesn't seem to be a whole
                   4888:         * lot of point to that. As long as we don't use data that could have
                   4889:         * changed while we waited, we're fine.
                   4890:         */
                   4891: 
                   4892:        * retvalp = 0;
                   4893:        return ctlmsg;
                   4894: }
                   4895: 
                   4896: 
                   4897: /*
                   4898:  * This function implements the I_FDINSERT ioctl ().
                   4899:  */
                   4900: 
                   4901: #if    __USE_PROTO__
                   4902: __LOCAL__ int (SHEAD_FDINSERT) (shead_t * sheadp, int mode,
                   4903:                                struct strfdinsert * fdinsp)
                   4904: #else
                   4905: __LOCAL__ int
                   4906: SHEAD_FDINSERT __ARGS ((sheadp, mode, fdinsp))
                   4907: shead_t              * sheadp;
                   4908: int            mode;
                   4909: struct strfdinsert
                   4910:              * fdinsp;
                   4911: #endif
                   4912: {
                   4913:        int             retval;
                   4914:        shead_t       * other;
                   4915:        mblk_t        * msg;
                   4916: 
                   4917:        ASSERT (sheadp != NULL);
                   4918:        ASSERT (fdinsp != NULL);
                   4919: 
                   4920:        /*
                   4921:         * There are a large number of error conditions to check for this
                   4922:         * function. Don't lose sight of the fact that the big set of chained
                   4923:         * conditions below computes "other" for us.
                   4924:         */
                   4925:        /*
                   4926:         * ALIGNMENT-DEPENDENT CODE.
                   4927:         */
                   4928: 
                   4929:        if ((fdinsp->flags != 0 && fdinsp->flags != RS_HIPRI) ||
                   4930:            ((unsigned) fdinsp->offset & ~ sizeof (int)) != 0 ||
                   4931:            fdinsp->offset + sizeof (queue_t *) > fdinsp->ctlbuf.len ||
                   4932:            (other = FH_TO_STREAM (fdinsp->fildes, & retval)) != 0) {
                   4933:                /*
                   4934:                 * A failure of any of the above returns EINVAL; according to
                   4935:                 * streamio (7) EINVAL rather than EBADF results from a bad
                   4936:                 * file descriptor.
                   4937:                 */
                   4938: 
                   4939:                return EINVAL;
                   4940:        }
                   4941: 
                   4942:        /*
                   4943:         * Make a band 0 message (possibly high-priority). This can fail if
                   4944:         * the requested message is too large for the advertised limits set
                   4945:         * by the next thing downstream.
                   4946:         *
                   4947:         * IMPORANT: we *rely* on this function making a message with a single
                   4948:         * large control block at least as big as the advertised size. If we
                   4949:         * cannot rely on this function we have to do lots of extra checking
                   4950:         * which I'd rather avoid.
                   4951:         */
                   4952: 
                   4953:        msg = SHEAD_MAKEMSG (sheadp, mode, & fdinsp->ctlbuf,
                   4954:                             & fdinsp->databuf,
                   4955:                             fdinsp->flags ? MSG_HIPRI : MSG_BAND, 0,
                   4956:                             & retval);
                   4957:        if (msg == NULL)
                   4958:                return retval;
                   4959: 
                   4960:        /*
                   4961:         * Note that we don't recheck for hangups even though we could have
                   4962:         * waited a poentially long time in SHEAD_MAKEMSG (). The hangup
                   4963:         * condition has plenty of slop in it with the time it takes write
                   4964:         * messages to move down the queue anyway; drivers and modules have to
                   4965:         * be able to cope.
                   4966:         */
                   4967: 
                   4968:        * (queue_t **) (msg->b_rptr + fdinsp->offset) = other->sh_head;
                   4969: 
                   4970:        putq (W (sheadp->sh_head), msg);
                   4971: 
                   4972:        return 0;
                   4973: }
                   4974: 
                   4975: 
                   4976: /*
                   4977:  * This function implements the I_FIND ioctl ().
                   4978:  */
                   4979: 
                   4980: #if    __USE_PROTO__
                   4981: __LOCAL__ int (SHEAD_FIND_MODINFO) (shead_t * sheadp, char * modname,
                   4982:                                    int * rvalp)
                   4983: #else
                   4984: __LOCAL__ int
                   4985: SHEAD_FIND_MODINFO __ARGS ((sheadp, modname, rvalp))
                   4986: shead_t              * sheadp;
                   4987: char         * modname;
                   4988: int          * rvalp;
                   4989: #endif
                   4990: {
                   4991:        modsw_t       * module;
                   4992: 
                   4993:        /*
                   4994:         * First try to find the module in the global list of modules, then
                   4995:         * attempt to find that module's info on the stream.
                   4996:         */
                   4997: 
                   4998:        if ((module = FIND_MODULE (modname)) == NULL)
                   4999:                return EINVAL;
                   5000:        else {
                   5001:                queue_t       * scan;
                   5002:                pl_t            prev_pl;
                   5003: 
                   5004:                /*
                   5005:                 * Walk down the write side of the stream until either the
                   5006:                 * write side module info matches -or- a cross-point is found.
                   5007:                 */
                   5008: 
                   5009:                scan = W (sheadp->sh_head);
                   5010: 
                   5011:                prev_pl = SHEAD_LOCK (sheadp);
                   5012: 
                   5013:                while (scan->q_next != NULL) {
                   5014:                        if ((scan->q_flag & QREADR) !=
                   5015:                            (scan->q_next->q_flag & QREADR)) {
                   5016:                                /*
                   5017:                                 * Set scan to NULL to flag an unsuccessful
                   5018:                                 * search.
                   5019:                                 */
                   5020: 
                   5021:                                scan = NULL;
                   5022:                                break;
                   5023:                        }
                   5024: 
                   5025:                        scan = scan->q_next;
                   5026: 
                   5027:                        if ((scan->q_flag & QPROCSOFF) != 0)
                   5028:                                continue;
                   5029: 
                   5030:                        if (scan->q_qinfo == module->mod_stream->st_wrinit)
                   5031:                                break;
                   5032:                }
                   5033: 
                   5034:                SHEAD_UNLOCK (sheadp, prev_pl);
                   5035: 
                   5036:                * rvalp = scan != NULL;
                   5037:        }
                   5038: 
                   5039:        return 0;
                   5040: }
                   5041: 
                   5042: 
                   5043: /*
                   5044:  * This function implements the I_LIST ioctl () for the case where the user
                   5045:  * supplies a buffer to copy the module/driver names into.
                   5046:  */
                   5047: 
                   5048: #if    __USE_PROTO__
                   5049: __LOCAL__ int (SHEAD_LIST) (shead_t * sheadp, struct str_list * slistp,
                   5050:                            int * rvalp)
                   5051: #else
                   5052: __LOCAL__ int
                   5053: SHEAD_LIST __ARGS ((sheadp, slistp, rvalp))
                   5054: shead_t              * sheadp;
                   5055: struct str_list
                   5056:              * slistp;
                   5057: int          * rvalp;
                   5058: #endif
                   5059: {
                   5060:        queue_t       * scan;
                   5061:        int             modcount;
                   5062:        int             i;
                   5063:        struct str_mlist
                   5064:                      * buf;
                   5065:        struct str_mlist
                   5066:                      * temp;
                   5067: 
                   5068:        if (slistp->sl_nmods < 1)
                   5069:                return EINVAL;
                   5070: 
                   5071:        /*
                   5072:         * The EAGAIN error documented for I_LIST in streamio (7) is
                   5073:         * suggestive of how it is implemented; rather than get involved in
                   5074:         * tricky synchronization issues, copy the module names into a kernel
                   5075:         * buffer and then copy that to user level.
                   5076:         */
                   5077: 
                   5078:        modcount = SHEAD_MODCOUNT (sheadp);
                   5079: 
                   5080:        if (modcount > slistp->sl_nmods)
                   5081:                modcount = slistp->sl_nmods;
                   5082: 
                   5083: 
                   5084:        /*
                   5085:         * If we were paranoid, we'd user kmem_zalloc () to ensure that the
                   5086:         * data we copy to user space contains no sensitive information. As it
                   5087:         * happens, because of the fact we user strncpy () to fill the buffer
                   5088:         * with data, we are guaranteed that we have overwritten all of the
                   5089:         * contents.
                   5090:         */
                   5091: 
                   5092:        if ((buf = (struct str_mlist *) kmem_alloc (modcount * sizeof (* buf),
                   5093:                                                    KM_SLEEP)) == NULL)
                   5094:                return EAGAIN;
                   5095: 
                   5096:        /*
                   5097:         * Now fill the buffer in by moving down the stream. We don't worry
                   5098:         * about the race between the calculation of the buffer size and the
                   5099:         * time we fill it in, because the problem also exists for the user;
                   5100:         * in order to know how much space to allocate at user level, some
                   5101:         * arrangement must have been made to ensure things are stable.
                   5102:         */
                   5103: 
                   5104:        i = 0;
                   5105:        scan = W (sheadp->sh_head);
                   5106:        temp = buf;
                   5107: 
                   5108:        (void) SHEAD_LOCK (sheadp);
                   5109: 
                   5110:        while (scan->q_next != NULL &&
                   5111:               ((scan->q_flag & QREADR) == (scan->q_next->q_flag & QREADR))) {
                   5112: 
                   5113:                scan = scan->q_next;
                   5114: 
                   5115:                if ((scan->q_flag & QPROCSOFF) != 0)
                   5116:                        continue;
                   5117: 
                   5118:                if (i ++ > modcount)
                   5119:                        break;
                   5120: 
                   5121:                /*
                   5122:                 * Now actually copy the module name. Note that we count on
                   5123:                 * strncpy () null-padding the target for security.
                   5124:                 */
                   5125: 
                   5126:                strncpy (temp->l_name, scan->q_qinfo->qi_minfo->mi_idname,
                   5127:                         sizeof (temp->l_name) - 1);
                   5128:                temp->l_name [sizeof (temp->l_name) - 1] = 0;
                   5129:        }
                   5130: 
                   5131:        SHEAD_UNLOCK (sheadp, plbase);
                   5132: 
                   5133:        /*
                   5134:         * After unlocking we can safely call copyout (), which we could not
                   5135:         * use inside the loop because it may sleep resolving a page fault.
                   5136:         * Don't forget that copyout () is like bcopy (), not memcpy ()!
                   5137:         */
                   5138: 
                   5139:        * rvalp = i;
                   5140: 
                   5141:        i = copyout (buf, slistp->sl_modlist, i * sizeof (* buf));
                   5142: 
                   5143:        kmem_free (buf, modcount * sizeof (* buf));
                   5144: 
                   5145:        return i == 0 ? 0 : EFAULT;
                   5146: }
                   5147: 
                   5148: 
                   5149: /*
                   5150:  * This function deals with setting the stream head read mode flag bits in
                   5151:  * M_SETOPT messages or from an I_SRDOPT ioctl ().
                   5152:  */
                   5153: 
                   5154: #if    __USE_PROTO__
                   5155: int (SHEAD_SRDOPT) (shead_t * sheadp, int flag)
                   5156: #else
                   5157: int
                   5158: SHEAD_SRDOPT __ARGS ((sheadp, flag))
                   5159: shead_t              * sheadp;
                   5160: int            flag;
                   5161: #endif
                   5162: {
                   5163:        int             newflag;
                   5164: 
                   5165:        SHEAD_ASSERT_LOCKED (sheadp);
                   5166: 
                   5167:        if ((newflag = flag & RMODEMASK) == __RINVAL)
                   5168:                return EINVAL;
                   5169: 
                   5170:        /*
                   5171:         * The streamio (7) man pages seem ambiguous about whether an
                   5172:         * application is permitted to, has to, or cannot diagnose a request
                   5173:         * to set multiple read options.
                   5174:         *
                   5175:         * Arbitrarily, we choose not to.
                   5176:         */
                   5177: 
                   5178:        newflag |= (flag & RPROTNORM) != 0 ? RPROTNORM :
                   5179:                   (flag & RPROTDAT) != 0 ? RPROTDAT :
                   5180:                   (flag & RPROTDIS) != 0 ? RPROTDIS :
                   5181:                        (sheadp->sh_readopt & ~ RMODEMASK);
                   5182: 
                   5183:        sheadp->sh_readopt = newflag;
                   5184: 
                   5185:        return 0;
                   5186: }
                   5187: 
                   5188: 
                   5189: /*
                   5190:  * This table determines how many bytes to copy from user space at the start
                   5191:  * of ioctl () processing and how many bytes to copy to user space at the end
                   5192:  * of processing (presuming no other errors have occurred yet).
                   5193:  */
                   5194: 
                   5195: #define        BADLEN          ((unsigned short) -1)
                   5196: 
                   5197: typedef enum {
                   5198:        IO_NOLOCK = 0,
                   5199:        IO_BASIC_LOCK,
                   5200:        IO_READFREEZE,
                   5201:        IO_SLEEP_LOCK
                   5202: } iolock_t;
                   5203: 
                   5204: enum { NOHUP,
                   5205:        HUP
                   5206: };
                   5207: 
                   5208: static struct ioinfo {
                   5209:        iolock_t        lock;           /* lock type */
                   5210:        cat_t           cat;            /* category flag */
                   5211:        unsigned short  in_len;         /* bytes to copy in */
                   5212:        unsigned short  out_len;        /* bytes to copy out */
                   5213:        unsigned char   hup_chk;        /* check for hangup */
                   5214: } _ioctl_table [] = {
                   5215:        { IO_NOLOCK, SH_NONE, BADLEN, BADLEN, NOHUP },
                   5216:                                        /* illegal */
                   5217:        { IO_READFREEZE, SH_NONE, sizeof (size_t), NOHUP },
                   5218:                                                /* I_NREAD */
                   5219:        { IO_SLEEP_LOCK, SH_OPENCLOSE | SH_IOCTL_LOCK,
                   5220:                FMNAMESZ + 1, 0, HUP },         /* I_PUSH */
                   5221:        { IO_SLEEP_LOCK, SH_OPENCLOSE | SH_IOCTL_LOCK, 0, 0, HUP },
                   5222:                                                /* I_POP */
                   5223:        { IO_NOLOCK, SH_NONE, FMNAMESZ + 1, FMNAMESZ + 1, NOHUP },
                   5224:                                                /* I_LOOK */
                   5225:        { IO_NOLOCK, SH_NONE, 0, 0, HUP },      /* I_FLUSH */
                   5226:        { IO_BASIC_LOCK, SH_NONE, 0, 0, NOHUP },/* I_SRDOPT */
                   5227:        { IO_BASIC_LOCK, SH_NONE, 0, sizeof (int), NOHUP },
                   5228:                                                /* I_GRDOPT */
                   5229:        { IO_SLEEP_LOCK, SH_IOCTL_LOCK, sizeof (struct strioctl),
                   5230:                sizeof (struct strioctl), HUP },/* I_STR */
                   5231:        { IO_SLEEP_LOCK, SH_IOCTL_LOCK, 0, 0, NOHUP },
                   5232:                                                /* I_SETSIG */
                   5233:        { IO_SLEEP_LOCK, SH_IOCTL_LOCK, 0, sizeof (int), NOHUP },
                   5234:                                                /* I_GETSIG */
                   5235:        { IO_NOLOCK, SH_NONE, FMNAMESZ + 1, 0, NOHUP },
                   5236:                                                /* I_FIND */
                   5237:        { IO_SLEEP_LOCK, SH_IOCTL_LOCK, 0, 0, HUP },
                   5238:                                                /* I_LINK */
                   5239:        { IO_SLEEP_LOCK, SH_IOCTL_LOCK, 0, 0, HUP },
                   5240:                                                /* I_UNLINK */
                   5241:        { IO_SLEEP_LOCK, SH_READ_LOCK, 0, sizeof (struct strrecvfd), HUP },
                   5242:                                                /* I_RECVFD */
                   5243:        { IO_SLEEP_LOCK, SH_READ_LOCK, sizeof (struct strpeek),
                   5244:                sizeof (struct strpeek), NOHUP },/* I_PEEK */
                   5245:        { IO_NOLOCK, SH_NONE, sizeof (struct strfdinsert), 0, NOHUP },
                   5246:                                                /* I_FDINSERT */
                   5247:        { IO_NOLOCK, SH_NONE, 0, 0, HUP },      /* I_SENDFD */
                   5248:        { IO_NOLOCK, SH_NONE, BADLEN, BADLEN, NOHUP },
                   5249:                                        /* --- */
                   5250:        { IO_BASIC_LOCK, SH_NONE, 0, 0, NOHUP },/* I_SWROPT */
                   5251:        { IO_BASIC_LOCK, SH_NONE, 0, sizeof (int), NOHUP },
                   5252:                                                /* I_GWROPT */
                   5253:        { IO_NOLOCK, SH_NONE, 0, 0, NOHUP },    /* I_LIST */ /* special */
                   5254:        { IO_BASIC_LOCK, SH_OPENCLOSE | SH_IOCTL_LOCK, 0, 0, HUP },
                   5255:                                                /* I_PLINK */
                   5256:        { IO_BASIC_LOCK, SH_OPENCLOSE | SH_IOCTL_LOCK, 0, 0, HUP },
                   5257:                                                /* I_PUNLINK */
                   5258:        { IO_NOLOCK, SH_NONE, BADLEN, BADLEN, NOHUP },
                   5259:                                        /* I_SETEV */
                   5260:        { IO_NOLOCK, SH_NONE, BADLEN, BADLEN, NOHUP },
                   5261:                                        /* I_GETEV */
                   5262:        { IO_NOLOCK, SH_NONE, BADLEN, BADLEN, NOHUP },
                   5263:                                        /* I_STREV */
                   5264:        { IO_NOLOCK, SH_NONE, BADLEN, BADLEN, NOHUP },
                   5265:                                        /* I_UNSTREV */
                   5266:        { IO_NOLOCK, SH_NONE, sizeof (struct bandinfo), 0, HUP },
                   5267:                                                /* I_FLUSHBAND */
                   5268:        { IO_READFREEZE, SH_NONE, 0, 0, NOHUP },/* I_CKBAND */
                   5269:        { IO_READFREEZE, SH_NONE, 0, sizeof (int), NOHUP },
                   5270:                                                /* I_GETBAND */
                   5271:        { IO_READFREEZE, SH_NONE, 0, 0, NOHUP },/* I_ATMARK */
                   5272:        { IO_BASIC_LOCK, SH_NONE, sizeof (__clock_t), 0, NOHUP },
                   5273:                                                /* I_SETCLTIME */
                   5274:        { IO_BASIC_LOCK, SH_NONE, 0, sizeof (__clock_t), NOHUP },
                   5275:                                                /* I_GETCLTIME */
                   5276:        { IO_NOLOCK, SH_NONE, 0, 0, HUP }       /* I_CANPUT */
                   5277: };
                   5278: 
                   5279: struct ioinfo  _transparent = {
                   5280:        IO_SLEEP_LOCK, SH_IOCTL_LOCK, 0, 0, HUP
                   5281: };
                   5282: 
                   5283: 
                   5284: /*
                   5285:  * Symbol for accessing the default ioctl () and close timeouts. Consider
                   5286:  * making this a static variable and initializing it at boot time.
                   5287:  */
                   5288: 
                   5289: #define        IOCTL_TIMEOUT   drv_usectohz ((__clock_t) 15000000L)
                   5290: 
                   5291: 
                   5292: /*
                   5293:  * Main ioctl () processing for STREAMS files and pipes.
                   5294:  *
                   5295:  * This switch+table is an abomination, but trying to emulate C++ style in C
                   5296:  * to subsume the switch and the above table would probably kill me. This
                   5297:  * probably is about as short as it can really be.
                   5298:  */
                   5299: 
                   5300: #if    __USE_PROTO__
                   5301: int (STREAMS_IOCTL) (shead_t * sheadp, int cmd, _VOID * arg, int mode,
                   5302:                     cred_t * credp, int * rvalp)
                   5303: #else
                   5304: int
                   5305: STREAMS_IOCTL (sheadp, cmd, arg, mode, credp, rvalp)
                   5306: shead_t              * sheadp;
                   5307: int            cmd;
                   5308: _VOID        * arg;
                   5309: int            mode;
                   5310: cred_t       * credp;
                   5311: int          * rvalp;
                   5312: #endif
                   5313: {
                   5314:        union {
                   5315:                int             i_int;
                   5316:                __clock_t       i_clock;
                   5317:                size_t          i_size;
                   5318:                char            i_modname [FMNAMESZ + 1];
                   5319:                struct strioctl i_strioc;
                   5320:                struct strrecvfd i_recvfd;
                   5321:                struct strbuf   i_strbuf;
                   5322:                struct strfdinsert
                   5323:                                i_fdinsert;
                   5324:                struct str_list i_list;
                   5325:                struct bandinfo i_band;
                   5326:                struct strpeek  i_peek;
                   5327:        } iocbuf;
                   5328:        int             retval;
                   5329:        struct ioinfo * info;
                   5330: 
                   5331:        ASSERT (sheadp != NULL);
                   5332: 
                   5333:        /*
                   5334:         * We start out by copying in the data specified by the table, which
                   5335:         * means we also get to range-check the ioctl entry if it has the
                   5336:         * magic STREAMS id.
                   5337:         */
                   5338: 
                   5339:        if ((cmd & ~ 0xFF) == STREAM_I) {
                   5340:                int             index = cmd & 0xFF;
                   5341: 
                   5342:                if (index >= sizeof (_ioctl_table) / sizeof (* info))
                   5343:                        return EINVAL;
                   5344: 
                   5345:                info = & _ioctl_table [index];
                   5346:        } else
                   5347:                info = & _transparent;
                   5348: 
                   5349:        if (info->in_len == BADLEN)
                   5350:                return EINVAL;
                   5351: 
                   5352:        /*
                   5353:         * We *must* do the copy before the lock! Never forget that
                   5354:         * copyin ()/copyout () can block in page fault resolution.
                   5355:         */
                   5356: 
                   5357:        if (info->in_len > 0 && copyin (arg, & iocbuf, info->in_len) != 0)
                   5358:                return EFAULT;
                   5359: 
                   5360:        /*
                   5361:         * We may wish to check for a hangup or error before proceeding.
                   5362:         */
                   5363: 
                   5364:        (void) SHEAD_LOCK (sheadp);
                   5365: 
                   5366:        if (info->hup_chk == HUP &&
                   5367:            (retval = SHEAD_ERRHUP_LOCKED (sheadp, mode)) != 0)
                   5368:                return ENXIO;
                   5369: 
                   5370:        if (info->lock != IO_BASIC_LOCK)
                   5371:                SHEAD_UNLOCK (sheadp, plbase);
                   5372: 
                   5373:        switch (info->lock) {
                   5374: 
                   5375:        case IO_BASIC_LOCK:
                   5376:                /* stay holding on to the basic lock */
                   5377:                break;
                   5378: 
                   5379:        case IO_READFREEZE:
                   5380:                (void) QFREEZE_TRACE (sheadp->sh_head, "STREAMS_IOCTL");
                   5381:                break;
                   5382: 
                   5383:        case IO_SLEEP_LOCK:
                   5384:                if ((retval = SHEAD_SLEEP_LOCK (sheadp, info->cat,
                   5385:                                                IOCTL_TIMEOUT,
                   5386:                                                CHECK_SIGNALS)) != 0)
                   5387:                        return retval;
                   5388:                break;
                   5389: 
                   5390:        default:
                   5391:                break;
                   5392:        }
                   5393: 
                   5394:        retval = 0;
                   5395: 
                   5396:        switch (cmd) {
                   5397: 
                   5398:        case I_NREAD:           /* Get message length, count */
                   5399:                {
                   5400:                        mblk_t        * scan;
                   5401:                        mblk_t        * first = NULL;
                   5402: 
                   5403:                        * rvalp = 0;
                   5404: 
                   5405:                        for (scan = SHEAD_FIRSTMSG (sheadp) ; scan != NULL ;
                   5406:                             scan = scan->b_next) {
                   5407: 
                   5408:                                if (datamsg (scan->b_datap->db_type)) {
                   5409: 
                   5410:                                        if (first == NULL)
                   5411:                                                first = scan;
                   5412:                                        (* rvalp) ++;
                   5413:                                }
                   5414:                        }
                   5415: 
                   5416:                        if (first != NULL)
                   5417:                                iocbuf.i_int = msgdsize (first);
                   5418:                        else
                   5419:                                iocbuf.i_int = 0;
                   5420:                }
                   5421:                break;
                   5422: 
                   5423:        case I_PUSH:            /* push named module */
                   5424:                {
                   5425:                        modsw_t       * module;
                   5426: 
                   5427:                        if ((module = FIND_MODULE (iocbuf.i_modname)) == NULL)
                   5428:                                retval = EINVAL;
                   5429:                        else
                   5430:                                retval = PUSH_MODULE (sheadp, mode, credp,
                   5431:                                                      module);
                   5432:                }
                   5433:                break;
                   5434: 
                   5435:        case I_POP:             /* pop topmost module */
                   5436:                {
                   5437:                        queue_t       * q;
                   5438: 
                   5439:                        if ((q = TOP_MODULE (sheadp)) == NULL)
                   5440:                                retval = EINVAL;
                   5441:                        else
                   5442:                                retval = POP_MODULE (sheadp, q, mode, credp);
                   5443:                }
                   5444:                break;
                   5445: 
                   5446:        case I_LOOK:            /* get topmost module name */
                   5447:                {
                   5448:                        queue_t       * q;
                   5449: 
                   5450:                        if ((q = TOP_MODULE (sheadp)) == NULL)
                   5451:                                retval = EINVAL;
                   5452:                        else {
                   5453:                                /*
                   5454:                                 * Copy the module name, taking care to
                   5455:                                 * 0-terminate it at FMNAMESZ bytes long.
                   5456:                                 */
                   5457: 
                   5458:                                strncpy (iocbuf.i_modname,
                   5459:                                         q->q_qinfo->qi_minfo->mi_idname,
                   5460:                                         FMNAMESZ);
                   5461:                                iocbuf.i_modname [FMNAMESZ] = 0;
                   5462:                        }
                   5463:                }
                   5464:                break;
                   5465: 
                   5466:        case I_FLUSH:           /* flush read and/or write side */
                   5467:                retval = SHEAD_FLUSH (sheadp, (int) arg, 0);
                   5468:                break;
                   5469: 
                   5470:        case I_SRDOPT:          /* set read options */
                   5471:                retval = SHEAD_SRDOPT (sheadp, (int) arg);
                   5472:                break;
                   5473: 
                   5474:        case I_GRDOPT:          /* retrieve read options */
                   5475:                iocbuf.i_int = sheadp->sh_readopt;
                   5476:                break;
                   5477: 
                   5478:        case I_STR:             /* send ioctl () data down a stream */
                   5479:                if ((iocbuf.i_strioc.ic_cmd & ~ 0xFF) == STREAM_I ||
                   5480:                    (unsigned) iocbuf.i_strioc.ic_len == TRANSPARENT) {
                   5481:                        /*
                   5482:                         * We do not permit I_STR to send STREAMS ioctl ()
                   5483:                         * codes downstream; in certain cases such as I_LINK
                   5484:                         * this could produce disastrous results.
                   5485:                         *
                   5486:                         * We also do not permit TRANSPARENT length I_STR
                   5487:                         * messages. While the STREAMS documentation neither
                   5488:                         * explicitly permits or forbids this, we keep the
                   5489:                         * transparent ioctl () behaviour separate.
                   5490:                         */
                   5491: 
                   5492:                        retval = EINVAL;
                   5493:                        break;
                   5494: 
                   5495:                }
                   5496: 
                   5497:                retval = ISTR_IOCTL (sheadp, mode, & iocbuf.i_strioc, credp,
                   5498:                                     rvalp);
                   5499:                break;
                   5500: 
                   5501:        case I_SETSIG:          /* register events for SIGPOLL signal */
                   5502:                {
                   5503:                        int             events = (short) (ulong_t) arg;
                   5504: 
                   5505:                        if ((events & ~ __POLL_MASK) != 0)
                   5506:                                retval = EINVAL;
                   5507:                        else
                   5508:                                retval = REGISTER_SIGPOLL (sheadp, events);
                   5509:                }
                   5510:                break;
                   5511: 
                   5512:        case I_GETSIG:          /* return registered event mask */
                   5513:                {
                   5514:                        sigpoll_t     * sigs;
                   5515: 
                   5516:                        if ((sigs = FIND_SIGPOLL (sheadp)) == NULL)
                   5517:                                retval = EINVAL;
                   5518:                        else
                   5519:                                * rvalp = sigs->sp_events;
                   5520:                }
                   5521:                break;
                   5522: 
                   5523:        case I_FIND:            /* determine if module exists on stream */
                   5524:                retval = SHEAD_FIND_MODINFO (sheadp, iocbuf.i_modname, rvalp);
                   5525:                break;
                   5526: 
                   5527:        case I_LINK:            /* link stream below another */
                   5528:        case I_PLINK:           /* create a persistent link */
                   5529:                {
                   5530:                        shead_t       * lower;
                   5531: 
                   5532:                        if ((lower = FH_TO_STREAM ((int) arg,
                   5533:                                                   & retval)) != NULL) {
                   5534:                                retval = SHEAD_LINK (sheadp, mode, lower, cmd,
                   5535:                                                     credp);
                   5536: 
                   5537:                                if (retval == 0)
                   5538:                                        * rvalp = lower->sh_muxid;
                   5539:                        }
                   5540:                }
                   5541:                break;
                   5542: 
                   5543:        case I_UNLINK:          /* remove a (or all) link(s) below a stream */
                   5544:        case I_PUNLINK:         /* undo a single or all persistent link(s) */
                   5545:                do {
                   5546:                        shead_t       * lower;
                   5547: 
                   5548:                        if ((lower = SHEAD_FIND_MUXID (sheadp, cmd,
                   5549:                                                       (int) arg)) == NULL) {
                   5550:                                /*
                   5551:                                 * We return EINVAL if a specific mux ID was
                   5552:                                 * given, 0 otherwise.
                   5553:                                 */
                   5554: 
                   5555:                                retval = (int) arg == -1 ? 0 : EINVAL;
                   5556:                                break;
                   5557: 
                   5558:                        }
                   5559: 
                   5560:                        (void) SHEAD_UNLINK (sheadp, lower, cmd, mode, credp,
                   5561:                                             & retval);
                   5562:                } while ((int) arg == -1);
                   5563:                break;
                   5564: 
                   5565:        case I_RECVFD:          /* receive a file descriptor from stream */
                   5566:                retval = FH_RECV (sheadp, mode, & iocbuf.i_recvfd);
                   5567:                break;
                   5568: 
                   5569:        case I_PEEK:            /* examine data at stream head */
                   5570:                retval = SHEAD_PEEK (sheadp, & iocbuf.i_peek, rvalp);
                   5571:                break;
                   5572: 
                   5573:        case I_FDINSERT:        /* send read queue pointer down stream */
                   5574:                retval = SHEAD_FDINSERT (sheadp, mode, & iocbuf.i_fdinsert);
                   5575:                break;
                   5576: 
                   5577:        case I_SENDFD:          /* send a file descriptor down a pipe */
                   5578:                retval = FH_SEND (sheadp, (int) arg, credp);
                   5579:                break;
                   5580: 
                   5581:        case I_SWROPT:          /* set write options for stream */
                   5582:                {
                   5583:                        int             flag = (int) arg;
                   5584: 
                   5585:                        if ((flag & ~ SNDZERO) != 0)
                   5586:                                retval = EINVAL;
                   5587:                        else
                   5588:                                sheadp->sh_wropt = flag;
                   5589:                }
                   5590:                break;
                   5591: 
                   5592:        case I_GWROPT:          /* retrieve write options for stream */
                   5593:                iocbuf.i_int = sheadp->sh_wropt;
                   5594:                break;
                   5595: 
                   5596:        case I_LIST:            /* get names of all modules/drivers */
                   5597:                /*
                   5598:                 * The value of "arg" is a pointer to a structure for this
                   5599:                 * entry, but since a NULL value is legal we don't copy the
                   5600:                 * data in automatically.
                   5601:                 *
                   5602:                 * Here we select the call type and copy in the structure for
                   5603:                 * the non-NULL case.
                   5604:                 */
                   5605: 
                   5606:                if (arg == NULL)
                   5607:                        * rvalp = SHEAD_MODCOUNT (sheadp);
                   5608:                else if (copyin (arg, & iocbuf, sizeof (iocbuf.i_list)) != 0)
                   5609:                        retval = EFAULT;
                   5610:                else
                   5611:                        retval = SHEAD_LIST (sheadp, & iocbuf.i_list, rvalp);
                   5612:                break;
                   5613: 
                   5614:        case I_SETEV:           /* The meaning of these ioctl ()'s is not */
                   5615:        case I_GETEV:           /* documented, although their names and */
                   5616:        case I_STREV:           /* numeric values are given in the System */
                   5617:        case I_UNSTREV:         /* V ABI. */
                   5618:                retval = EINVAL;
                   5619:                break;
                   5620: 
                   5621:        case I_FLUSHBAND:       /* flush messages in a priority band */
                   5622:                retval = SHEAD_FLUSH (sheadp, iocbuf.i_band.bi_flag,
                   5623:                                      iocbuf.i_band.bi_pri);
                   5624:                break;
                   5625: 
                   5626:        case I_CKBAND:          /* check for existence of band on stream */
                   5627:                if ((uchar_t) (ulong_t) arg != (ulong_t) arg)
                   5628:                        retval = EINVAL;
                   5629:                else {
                   5630:                        mblk_t        * scan;
                   5631: 
                   5632:                        for (scan = SHEAD_FIRSTMSG (sheadp) ; scan != NULL ;
                   5633:                             scan = scan->b_next)
                   5634:                                if (datamsg (scan->b_datap->db_type) &&
                   5635:                                    scan->b_band == (uchar_t) (ulong_t) arg)
                   5636:                                        break;
                   5637: 
                   5638:                        * rvalp = scan != NULL;
                   5639:                }
                   5640:                break;
                   5641: 
                   5642:        case I_GETBAND:         /* get the band number of the first message */
                   5643:                {
                   5644:                        mblk_t       *  scan;
                   5645: 
                   5646:                        for (scan = SHEAD_FIRSTMSG (sheadp) ; scan != NULL ;
                   5647:                             scan = scan->b_next) {
                   5648: 
                   5649:                                if (datamsg (scan->b_datap->db_type))
                   5650:                                        break;
                   5651:                        }
                   5652: 
                   5653:                        if (scan == NULL)
                   5654:                                retval = ENODATA;
                   5655:                        else
                   5656:                                iocbuf.i_int = scan->b_band;
                   5657:                }
                   5658:                break;
                   5659: 
                   5660:        case I_ATMARK:          /* test for (last) mark on messages */
                   5661:                {
                   5662:                        mblk_t        * scan = SHEAD_FIRSTMSG (sheadp);
                   5663: 
                   5664:                        if ((ulong_t) arg != ANYMARK &&
                   5665:                            (ulong_t) arg != LASTMARK) {
                   5666: 
                   5667:                                retval = EINVAL;
                   5668:                                break;
                   5669:                        }
                   5670: 
                   5671:                        if (scan == NULL || (scan->b_flag & MSGMARK) == 0) {
                   5672: 
                   5673:                                * rvalp = 0;
                   5674:                                break;
                   5675:                        }
                   5676: 
                   5677:                        * rvalp = 1;
                   5678: 
                   5679:                        if ((ulong_t) arg == LASTMARK)
                   5680:                                while ((scan = scan->b_next) != NULL)
                   5681:                                        if ((scan->b_flag & MSGMARK) != 0) {
                   5682:                                                * rvalp = 0;
                   5683:                                                break;
                   5684:                                        }
                   5685:                }
                   5686:                break;
                   5687: 
                   5688:        case I_SETCLTIME:       /* set close timeout for stream */
                   5689:                if (iocbuf.i_clock != 0)
                   5690:                        sheadp->sh_cltime = iocbuf.i_clock;
                   5691:                else
                   5692:                        retval = EINVAL;
                   5693:                break;
                   5694: 
                   5695:        case I_GETCLTIME:       /* retrieve current close timeout */
                   5696:                iocbuf.i_clock = sheadp->sh_cltime;
                   5697:                break;
                   5698: 
                   5699:        case I_CANPUT:          /* test if band is writeable */
                   5700:                if ((uchar_t) (ulong_t) arg != (ulong_t) arg)
                   5701:                        retval = EINVAL;
                   5702:                else
                   5703:                        * rvalp = bcanputnext (W (sheadp->sh_head),
                   5704:                                               (uchar_t) (ulong_t) arg);
                   5705:                break;
                   5706: 
                   5707:        default:
                   5708:                ASSERT (info == & _transparent);
                   5709: 
                   5710:                retval = TRANSPARENT_IOCTL (sheadp, mode, cmd, arg, credp,
                   5711:                                            rvalp);
                   5712:                break;
                   5713:        }
                   5714: 
                   5715: 
                   5716:        /*
                   5717:         * Perform any necessary unlocking operations and copy back any
                   5718:         * results into the data area pointed to by "arg" (if this is a
                   5719:         * STREAMS-specific ioctl ()).
                   5720:         */
                   5721: 
                   5722:        switch (info->lock) {
                   5723: 
                   5724:        case IO_BASIC_LOCK:
                   5725:                SHEAD_UNLOCK (sheadp, plbase);
                   5726:                break;
                   5727: 
                   5728:        case IO_READFREEZE:
                   5729:                (void) QUNFREEZE_TRACE (sheadp->sh_head, plbase);
                   5730:                break;
                   5731: 
                   5732:        case IO_SLEEP_LOCK:
                   5733:                SHEAD_SLEEP_UNLOCK (sheadp, info->cat);
                   5734:                break;
                   5735: 
                   5736:        default:
                   5737:                break;
                   5738:        }
                   5739: 
                   5740: 
                   5741:        /*
                   5742:         * We only copy out results if there is no error. We have to
                   5743:         * do this *after* unlocking, above; copyout () can block in
                   5744:         * page fault resolution!
                   5745:         */
                   5746: 
                   5747:        if (retval == 0 && info->out_len > 0 &&
                   5748:            copyout (& iocbuf, arg, info->out_len) != 0)
                   5749:                retval = EFAULT;
                   5750: 
                   5751:        return retval;
                   5752: }
                   5753: 
                   5754: 
                   5755: /*
                   5756:  * Helper function to atomically read the stream head read options.
                   5757:  */
                   5758: 
                   5759: #if    __USE_PROTO__
                   5760: __LOCAL__ short (SHEAD_READOPT) (shead_t * sheadp)
                   5761: #else
                   5762: __LOCAL__ short
                   5763: SHEAD_READOPT __ARGS ((sheadp))
                   5764: shead_t              * sheadp;
                   5765: #endif
                   5766: {
                   5767:        pl_t            prev_pl;
                   5768:        short           opt;
                   5769: 
                   5770:        prev_pl = SHEAD_LOCK (sheadp);
                   5771: 
                   5772:        opt = sheadp->sh_readopt;
                   5773: 
                   5774:        SHEAD_UNLOCK (sheadp, prev_pl);
                   5775: 
                   5776:        return opt;
                   5777: }
                   5778: 
                   5779: 
                   5780: /*
                   5781:  * Stream head user-level getmsg () processing.
                   5782:  *
                   5783:  * This is way too many parameters; this should be bundled into a block like
                   5784:  * the "uio" structure is.
                   5785:  */
                   5786: 
                   5787: #if    __USE_PROTO__
                   5788: int (STREAMS_GETPMSG) (shead_t * sheadp, struct strbuf * ctlbuf,
                   5789:                       struct strbuf * databuf, int * bandp, int * flagsp,
                   5790:                       int mode, int * rvalp)
                   5791: #else
                   5792: int
                   5793: STREAMS_GETPMSG __ARGS ((sheadp, ctlbuf, databuf, bandp, flagsp, mode, rvalp))
                   5794: shead_t              * sheadp;
                   5795: int            mode;
                   5796: struct strbuf *        ctlbuf;
                   5797: struct strbuf *        databuf;
                   5798: int          * bandp;
                   5799: int          * flagsp;
                   5800: int          * rvalp;
                   5801: #endif
                   5802: {
                   5803:        mblk_t        * msg;
                   5804:        mblk_t        * scan;
                   5805:        int             retval;
                   5806: 
                   5807:        if ((mode & FREAD) == 0)
                   5808:                return EBADF;
                   5809: 
                   5810:        mode &= ~ FWRITE;
                   5811: 
                   5812: 
                   5813:        /*
                   5814:         * As discussed in the general comment on read synchronization and in
                   5815:         * the I_PEEK documentation, there are some warts when it comes to
                   5816:         * read locking. Here we can solve things by dequeueing a message,
                   5817:         * modifying at, and writing it back without worrying about any nasty
                   5818:         * unintended effects.
                   5819:         *
                   5820:         * Because getmsg ()/getpmsg () always honours message boundaries,
                   5821:         * there is no real value in single-threading this.
                   5822:         */
                   5823: 
                   5824:        /*
                   5825:         * Look at the stream head to see if a message is present. Note that
                   5826:         * we freeze the read queue before acquiring the stream head basic
                   5827:         * lock because that's our canonical ordering.
                   5828:         */
                   5829: 
                   5830:        for (;;) {
                   5831:                (void) QFREEZE_TRACE (sheadp->sh_head, "SHEAD_GETPMSG");
                   5832: 
                   5833:                (void) SHEAD_LOCK (sheadp);
                   5834: 
                   5835:                if ((retval = SHEAD_ERRHUP_LOCKED (sheadp, FREAD)) != 0) {
                   5836: 
                   5837:                        QUNFREEZE_TRACE (sheadp->sh_head, plbase);
                   5838:                        return retval;
                   5839:                }
                   5840: 
                   5841: 
                   5842:                if ((msg = SHEAD_FIRSTMSG (sheadp)) != NULL) {
                   5843: 
                   5844:                        switch (msg->b_datap->db_type) {
                   5845: 
                   5846:                        case M_DATA:
                   5847:                        case M_PROTO:
                   5848: 
                   5849:                                if (* flagsp == MSG_HIPRI ||
                   5850:                                    (* flagsp == MSG_BAND &&
                   5851:                                     msg->b_band < * bandp)) {
                   5852: 
                   5853:                                        sheadp->sh_head->q_lastband =
                   5854:                                                msg->b_band;
                   5855:                                        msg = NULL;
                   5856:                                        break;
                   5857:                                }
                   5858: 
                   5859:                                /* FALL THROUGH */
                   5860: 
                   5861:                        case M_PCPROTO:
                   5862:                                rmvq (sheadp->sh_head, msg);
                   5863:                                break;
                   5864: 
                   5865:                        default:
                   5866:                                retval = EBADMSG;
                   5867:                                break;
                   5868:                        }
                   5869:                }
                   5870: 
                   5871:                QUNFREEZE_TRACE (sheadp->sh_head, plbase);
                   5872: 
                   5873:                if (retval != 0)
                   5874:                        return retval;
                   5875: 
                   5876:                if (msg != NULL)
                   5877:                        break;
                   5878: 
                   5879:                /*
                   5880:                 * We need to wait (unless O_NDELAY or O_NONBLOCK has been
                   5881:                 * specified). We don't wait any more if the stream has been
                   5882:                 * hung up.
                   5883:                 */
                   5884: 
                   5885:                if (SHEAD_HANGUP (sheadp)) {
                   5886:                        /*
                   5887:                         * Hangups are not an error for getpmsg ().
                   5888:                         */
                   5889: 
                   5890:                        if (ctlbuf != NULL)
                   5891:                                ctlbuf->len = 0;
                   5892:                        if (databuf != NULL)
                   5893:                                databuf->len = 0;
                   5894: 
                   5895:                        * rvalp = 0;
                   5896:                        return 0;
                   5897:                }
                   5898: 
                   5899:                if ((retval = SHEAD_WAIT_NONBLOCK (sheadp, FREAD,
                   5900:                                                   SH_READ_WAIT,
                   5901:                                                   CHECK_SIGNALS)) != 0)
                   5902:                        return retval;
                   5903:        }
                   5904: 
                   5905: 
                   5906:        /*
                   5907:         * After this point, "msg" is our responsibility and we either have to
                   5908:         * free it or put it back if there is an error.
                   5909:         */
                   5910: 
                   5911:        * bandp = msg->b_band;
                   5912:        * flagsp = msg->b_datap->db_type == M_PCPROTO ? MSG_HIPRI : MSG_BAND;
                   5913: 
                   5914:        retval = (COPYOUT_BUF (ctlbuf, & msg, CONTROL_PART) != 0 ||
                   5915:                  COPYOUT_BUF (databuf, & msg,
                   5916:                               DATA_PART) != 0) ? EFAULT : 0;
                   5917: 
                   5918:        /*
                   5919:         * Formulate a return mask indicating what components of the message
                   5920:         * being transferred have not been fully consumed.
                   5921:         */
                   5922: 
                   5923:        * rvalp = 0;
                   5924: 
                   5925:        for (scan = msg ; scan != NULL ; scan = scan->b_cont)
                   5926:                * rvalp |= scan->b_datap->db_type == M_DATA ? MOREDATA
                   5927:                                                            : MORECTL;
                   5928: 
                   5929:        if (msg != NULL)
                   5930:                putbq (sheadp->sh_head, msg);
                   5931: 
                   5932:        return retval;
                   5933: }
                   5934: 
                   5935: 
                   5936: /*
                   5937:  * In order to keep the logic of SHEAD_READ () manageable, this section of
                   5938:  * code has been factored into a separate function. Here we wait for data to
                   5939:  * become available at the stream head for reading.
                   5940:  *
                   5941:  * We return 0 on success, or an error number on failure. The value of "mpp"
                   5942:  * is only valid if 0 is returned.
                   5943:  */
                   5944: 
                   5945: #if    __USE_PROTO__
                   5946: __LOCAL__ int (SHEAD_READ_DATA) (shead_t * sheadp, int mode, mblk_t ** mpp,
                   5947:                                 int resid)
                   5948: #else
                   5949: __LOCAL__ int
                   5950: SHEAD_READ_DATA __ARGS ((sheadp, mode, mpp, resid))
                   5951: shead_t              * sheadp;
                   5952: int            mode;
                   5953: mblk_t      ** mpp;
                   5954: int            resid;
                   5955: #endif
                   5956: {
                   5957:        int             retval;
                   5958: 
                   5959:        for (;;) {
                   5960:                (void) QFREEZE_TRACE (sheadp->sh_head, "SHEAD_READ");
                   5961: 
                   5962:                (void) SHEAD_LOCK (sheadp);
                   5963: 
                   5964:                if ((retval = SHEAD_ERRHUP_LOCKED (sheadp, FREAD)) != 0) {
                   5965: 
                   5966:                        QUNFREEZE_TRACE (sheadp->sh_head, plbase);
                   5967:                        return retval;
                   5968:                }
                   5969: 
                   5970: 
                   5971:                if ((* mpp = SHEAD_FIRSTMSG (sheadp)) != NULL) {
                   5972: 
                   5973:                        switch ((* mpp)->b_datap->db_type) {
                   5974: 
                   5975:                        case M_PROTO:
                   5976:                        case M_PCPROTO:
                   5977:                                /*
                   5978:                                 * These are valid depending on the read mode
                   5979:                                 * of the stream.
                   5980:                                 */
                   5981: 
                   5982:                                if ((sheadp->sh_readopt & RPROTNORM) != 0) {
                   5983: 
                   5984:                                        retval = EBADMSG;
                   5985:                                        break;
                   5986:                                }
                   5987: 
                   5988:                                /* FALL THROUGH */
                   5989: 
                   5990:                        case M_DATA:
                   5991:                                rmvq (sheadp->sh_head, * mpp);
                   5992:                                break;
                   5993: 
                   5994:                        default:
                   5995:                                retval = EBADMSG;
                   5996:                                break;
                   5997:                        }
                   5998:                }
                   5999: 
                   6000:                QUNFREEZE_TRACE (sheadp->sh_head, plbase);
                   6001: 
                   6002:                if (retval != 0 || * mpp != NULL) {
                   6003: 
                   6004:                        SHEAD_UNLOCK (sheadp, plbase);
                   6005:                        return retval;
                   6006:                }
                   6007: 
                   6008: 
                   6009:                /*
                   6010:                 * Since we are going to sleep on a read (), this is the place
                   6011:                 * to generate M_READ messages if that is how this stream has
                   6012:                 * been configured.
                   6013:                 *
                   6014:                 * If we can't generate an M_READ message, schedule a bufcall.
                   6015:                 * If we can't do that, return EAGAIN???
                   6016:                 */
                   6017: 
                   6018:                if (SHEAD_READMSG (sheadp)) {
                   6019:                        mblk_t        * msg;
                   6020: 
                   6021:                        if ((msg = MSGB_ALLOC (sizeof (int), BPRI_LO,
                   6022:                                               KM_NOSLEEP)) == NULL) {
                   6023:                                /*
                   6024:                                 * Execute a short wait for buffer memory for
                   6025:                                 * the M_READ, then retry the loop. Note that
                   6026:                                 * SHEAD_READ_BUFCALL () unlocks the stream
                   6027:                                 * head for us.
                   6028:                                 */
                   6029: 
                   6030:                                if ((retval = SHEAD_READ_BUFCALL (sheadp,
                   6031:                                                                  mode)) != 0)
                   6032:                                        return retval;
                   6033: 
                   6034:                                continue;
                   6035:                        }
                   6036: 
                   6037:                        msg->b_datap->db_type = M_READ;
                   6038:                        * (int *) msg->b_rptr = resid;
                   6039:                        msg->b_wptr += sizeof (int);
                   6040: 
                   6041:                        putq (W (sheadp->sh_head), msg);
                   6042:                }
                   6043: 
                   6044:                if ((retval = SHEAD_WAIT_NONBLOCK (sheadp, mode, SH_READ_WAIT,
                   6045:                                                   CHECK_SIGNALS)) != 0)
                   6046:                        return retval;
                   6047:        }
                   6048: 
                   6049: }
                   6050: 
                   6051: 
                   6052: /*
                   6053:  * In order to keep the logic of SHEAD_READ () manageable, this section of
                   6054:  * code has been factored into this routine, which manages the transfer of
                   6055:  * message data to the user.
                   6056:  *
                   6057:  * We return EAGAIN to the user if more data needs to be read, 0 if the read
                   6058:  * has successfully completed, or some other error number on failure.
                   6059:  */
                   6060: 
                   6061: #if    __USE_PROTO__
                   6062: __LOCAL__ int (SHEAD_READ_MOVE) (shead_t * sheadp, uio_t * uiop,
                   6063:                                 mblk_t * msg)
                   6064: #else
                   6065: __LOCAL__ int
                   6066: SHEAD_READ_MOVE __ARGS ((sheadp, uiop, msg))
                   6067: shead_t              * sheadp;
                   6068: uio_t        * uiop;
                   6069: mblk_t       * msg;
                   6070: #endif
                   6071: {
                   6072:        int             readopt = SHEAD_READOPT (sheadp);
                   6073:        mblk_t        * scan;
                   6074: 
                   6075:        if ((readopt & RMODEMASK) == RNORM &&
                   6076:            (msg->b_cont == NULL && msg->b_rptr == msg->b_wptr)) {
                   6077:                /*
                   6078:                 * We have run into a zero-length message. Put it
                   6079:                 * back and terminate the read.
                   6080:                 */
                   6081: 
                   6082:                putbq (sheadp->sh_head, msg);
                   6083:                return 0;
                   6084:        }
                   6085: 
                   6086:        if ((readopt & RPROTDIS) != 0) {
                   6087: 
                   6088:                while (msg != NULL && msg->b_datap->db_type != M_DATA) {
                   6089:                        /*
                   6090:                         * Consume the control part of the message.
                   6091:                         */
                   6092: 
                   6093:                        scan = msg->b_cont;
                   6094:                        freeb (msg);
                   6095:                        msg = scan;
                   6096:                }
                   6097: 
                   6098:                if (msg == NULL)
                   6099:                        return EAGAIN;
                   6100:        }
                   6101: 
                   6102: 
                   6103:        /*
                   6104:         * Actual data transfer time; copy each message segment to the user
                   6105:         * with uiomove ().
                   6106:         */
                   6107: 
                   6108:        do {
                   6109:                size_t          unit = msg->b_wptr - msg->b_rptr;
                   6110: 
                   6111:                if (unit > uiop->uio_resid)
                   6112:                        unit = uiop->uio_resid;
                   6113: 
                   6114:                if (unit > 0 &&
                   6115:                    uiomove (msg->b_rptr, unit, UIO_READ, uiop) != 0) {
                   6116:                        /*
                   6117:                         * Address fault time. But first, put back the data.
                   6118:                         */
                   6119: 
                   6120:                        putbq (sheadp->sh_head, msg);
                   6121: 
                   6122:                        return EFAULT;
                   6123:                }
                   6124: 
                   6125:                msg->b_rptr += unit;
                   6126: 
                   6127:                if (msg->b_wptr != msg->b_rptr) {
                   6128:                        /*
                   6129:                         * Since we didn't finish this message block, we must
                   6130:                         * be finished with the read (). If we are in message-
                   6131:                         * discard mode we throw away the remaining data.
                   6132:                         */
                   6133: 
                   6134:                        ASSERT (uiop->uio_resid == 0);
                   6135: 
                   6136:                        if ((readopt & RMODEMASK) == RMSGD)
                   6137:                                freemsg (msg);
                   6138:                        else
                   6139:                                putbq (sheadp->sh_head, msg);
                   6140: 
                   6141:                        return 0;
                   6142:                }
                   6143: 
                   6144:                scan = msg->b_cont;
                   6145:                freeb (msg);
                   6146:        } while ((msg = scan) != NULL);
                   6147: 
                   6148: 
                   6149:        /*
                   6150:         * We have run out of message; what now? If in byte-stream mode, look
                   6151:         * for more data, otherwise exit.
                   6152:         */
                   6153: 
                   6154:        return (readopt & RMODEMASK) == RNORM ? EAGAIN : 0;
                   6155: }
                   6156: 
                   6157: 
                   6158: /*
                   6159:  * Stream head user-level read processing.
                   6160:  *
                   6161:  * I apologise for the abysmal structure of this code; the gotos should be
                   6162:  * replaced by proper loops and the major subsections factored into auxiliary
                   6163:  * functions, but this code is the victim of time pressure and several
                   6164:  * rewrites. By all means encourage the author to improve this in case he has
                   6165:  * forgotten to come back and fix it.
                   6166:  */
                   6167: 
                   6168: #if    __USE_PROTO__
                   6169: int (STREAMS_READ) (shead_t * sheadp, uio_t * uiop)
                   6170: #else
                   6171: int
                   6172: STREAMS_READ __ARGS ((sheadp, uiop))
                   6173: shead_t              * sheadp;
                   6174: uio_t        * uiop;
                   6175: #endif
                   6176: {
                   6177:        mblk_t        * msg;
                   6178:        int             retval;
                   6179:        int             mode;
                   6180:        int             readcount = uiop->uio_resid;
                   6181: 
                   6182:        if ((uiop->uio_fmode & FREAD) == 0)
                   6183:                return EBADF;
                   6184: 
                   6185:        mode = uiop->uio_fmode & ~ FWRITE;
                   6186: 
                   6187: 
                   6188:        /*
                   6189:         * We (optionally) take out a lock on the stream head to single-thread
                   6190:         * reads. This is important because in byte-stream mode we may want
                   6191:         * to guarantee atomicity of reads. This is only relevant to byte-
                   6192:         * stream mode because modes which honor message boundaries cannot
                   6193:         * be protected against multiple readers anyway.
                   6194:         */
                   6195: 
                   6196:        if ((retval = SHEAD_SLEEP_LOCK (sheadp, SH_READ_LOCK, 0,
                   6197:                                        CHECK_SIGNALS)) != 0)
                   6198:                return retval;
                   6199: 
                   6200:        do {
                   6201:                if ((retval = SHEAD_READ_DATA (sheadp, mode, & msg,
                   6202:                                               uiop->uio_resid)) != 0)
                   6203:                        break;
                   6204: 
                   6205:                /*
                   6206:                 * After this point, "msg" is our responsibility and we either
                   6207:                 * have to free it or put it back if there is an error.
                   6208:                 */
                   6209: 
                   6210:        } while ((retval = SHEAD_READ_MOVE (sheadp, uiop, msg)) == EAGAIN);
                   6211: 
                   6212: 
                   6213:        /*
                   6214:         * If a partial read has been done, we return a short read rather than
                   6215:         * reporting an error immediately.
                   6216:         */
                   6217: 
                   6218:        if (retval != 0 && readcount != uiop->uio_resid)
                   6219:                retval = 0;
                   6220: 
                   6221:        SHEAD_SLEEP_UNLOCK (sheadp, SH_READ_LOCK);
                   6222:        return retval;
                   6223: }
                   6224: 
                   6225: 
                   6226: /*
                   6227:  * Helper function to atomically read the stream head write options.
                   6228:  */
                   6229: 
                   6230: #if    __USE_PROTO__
                   6231: __LOCAL__ short (SHEAD_WRITEOPT) (shead_t * sheadp)
                   6232: #else
                   6233: __LOCAL__ short
                   6234: SHEAD_WRITEOPT __ARGS ((sheadp))
                   6235: shead_t              * sheadp;
                   6236: #endif
                   6237: {
                   6238:        pl_t            prev_pl;
                   6239:        short           opt;
                   6240: 
                   6241:        prev_pl = SHEAD_LOCK (sheadp);
                   6242: 
                   6243:        opt = sheadp->sh_wropt;
                   6244: 
                   6245:        SHEAD_UNLOCK (sheadp, prev_pl);
                   6246: 
                   6247:        return opt;
                   6248: }
                   6249: 
                   6250: 
                   6251: /*
                   6252:  * Stream head user level putpmsg () processing. As with getmsg (), there are
                   6253:  * enough parameters being passed that this should be abstracted into a
                   6254:  * structure like uio(D4DK).
                   6255:  */
                   6256: 
                   6257: #if    __USE_PROTO__
                   6258: int (STREAMS_PUTPMSG) (shead_t * sheadp, struct strbuf * ctlbuf,
                   6259:                       struct strbuf * databuf, int band, int flags,
                   6260:                       int mode, int * rvalp)
                   6261: #else
                   6262: int
                   6263: STREAMS_PUTPMSG __ARGS ((sheadp, ctlbuf, databuf, band, flags, mode, rvalp))
                   6264: shead_t              * sheadp;
                   6265: int            mode;
                   6266: struct strbuf *        ctlbuf;
                   6267: struct strbuf *        databuf;
                   6268: int            band;
                   6269: int            flags;
                   6270: int          * rvalp;
                   6271: #endif
                   6272: {
                   6273:        mblk_t        * msg;
                   6274:        int             retval;
                   6275: 
                   6276:        /*
                   6277:         * Make a message (possibly high-priority). This can fail if the
                   6278:         * requested message is too large for the advertised limits set by the
                   6279:         * next thing downstream. SHEAD_MAKEMSG () also checks for error and
                   6280:         * hangup conditions, FNDELAY/FNONBLOCK, and flow control.
                   6281:         */
                   6282: 
                   6283:        msg = SHEAD_MAKEMSG (sheadp, mode, ctlbuf, databuf, flags, band,
                   6284:                             & retval);
                   6285: 
                   6286:        if (msg == NULL)
                   6287:                return retval;
                   6288: 
                   6289:        /*
                   6290:         * Note that we don't recheck for hangups even though we could have
                   6291:         * waited a poentially long time in SHEAD_MAKEMSG (). The hangup
                   6292:         * condition has plenty of slop in it with the time it takes write
                   6293:         * messages to move down the queue anyway; drivers and modules have to
                   6294:         * be able to cope.
                   6295:         */
                   6296: 
                   6297:        putq (W (sheadp->sh_head), msg);
                   6298: 
                   6299:        * rvalp = 0;
                   6300:        return 0;
                   6301: }
                   6302: 
                   6303: 
                   6304: /*
                   6305:  * Stream head user-level write processing.
                   6306:  *
                   6307:  * I apologise for the abysmal structure of this code; the gotos should be
                   6308:  * replaced by proper loops and the major subsections factored into auxiliary
                   6309:  * functions, but this code is the victim of time pressure and several
                   6310:  * rewrites. By all means encourage the author to improve this in case he has
                   6311:  * forgotten to come back and fix it.
                   6312:  */
                   6313: 
                   6314: #if    __USE_PROTO__
                   6315: int (STREAMS_WRITE) (shead_t * sheadp, uio_t * uiop)
                   6316: #else
                   6317: int
                   6318: STREAMS_WRITE __ARGS ((sheadp, uiop))
                   6319: shead_t              * sheadp;
                   6320: uio_t        * uiop;
                   6321: #endif
                   6322: {
                   6323:        queue_t       * q;
                   6324:        short           wropt = SHEAD_WRITEOPT (sheadp);
                   6325:        mblk_t        * datamsg;
                   6326:        int             datasize;
                   6327:        int             wroff;
                   6328:        int             retval;
                   6329:        int             mode;
                   6330:        int             writecount;
                   6331: 
                   6332:        if ((uiop->uio_fmode & FWRITE) == 0)
                   6333:                return EBADF;
                   6334: 
                   6335:        mode = uiop->uio_fmode & ~ FREAD;
                   6336: 
                   6337: 
                   6338:        /*
                   6339:         * Deal with the zero-length-message special case.
                   6340:         */
                   6341: 
                   6342:        if ((writecount = uiop->uio_resid) == 0 && (wropt & SNDZERO) == 0)
                   6343:                return 0;
                   6344: 
                   6345:        /*
                   6346:         * Unlike putmsg ()/putpmsg (), write () can potentially spread the
                   6347:         * data it writes over multiple messages and take a considerable time
                   6348:         * to do it, we allow for the possibility of locking the stream head
                   6349:         * so that only one write () is in progress at any time.
                   6350:         *
                   6351:         * The primary purpose of this is to allow PIPE_BUF to be effectively
                   6352:         * unlimited. This is an experimental idea, though.
                   6353:         */
                   6354: 
                   6355:        if ((retval = SHEAD_SLEEP_LOCK (sheadp, SH_WRITE_LOCK, 0,
                   6356:                                        CHECK_SIGNALS)) != 0)
                   6357:                return retval;
                   6358: 
                   6359:        wroff = SHEAD_WRITEOFFSET (sheadp);
                   6360: 
                   6361:        q = TOP_QUEUE (sheadp);
                   6362: 
                   6363:        do {
                   6364: 
                   6365:                if ((datasize = uiop->uio_resid) + wroff > q->q_maxpsz) {
                   6366:                        /*
                   6367:                         * Special case (documented on the write (2) manual
                   6368:                         * page; if we can't fit within the max/min range and
                   6369:                         * the minimum is greater than 0, return ERANGE.
                   6370:                         */
                   6371: 
                   6372:                        if (q->q_minpsz > 0) {
                   6373: 
                   6374:                                retval = ERANGE;
                   6375:                                break;
                   6376:                        }
                   6377: 
                   6378:                        datasize = q->q_maxpsz - wroff;
                   6379:                } else if (datasize + wroff < q->q_minpsz) {
                   6380: 
                   6381:                        retval = ERANGE;
                   6382:                        break;
                   6383:                }
                   6384: 
                   6385: 
                   6386:                /*
                   6387:                 * Let's see if the stream is flow controlled; if it is, we
                   6388:                 * either block or return EAGAIN depending on the
                   6389:                 * FNDELAY/FNONBLOCK setting.
                   6390:                 */
                   6391: 
                   6392:                if ((retval = SHEAD_WRITE_TEST (sheadp, mode, 0, 0)) != 0)
                   6393:                        break;
                   6394: 
                   6395:                if ((datamsg = MSGB_ALLOC (datasize + wroff, BPRI_LO,
                   6396:                                           KM_SLEEP)) == NULL) {
                   6397:                        retval = ENOSR;
                   6398:                        break;
                   6399:                }
                   6400: 
                   6401:                datamsg->b_wptr = datamsg->b_rptr = datamsg->b_rptr + wroff;
                   6402: 
                   6403:                if (datasize > 0 &&
                   6404:                    uiomove (datamsg->b_rptr, datasize, UIO_WRITE,
                   6405:                             uiop) != 0) {
                   6406: 
                   6407:                        freemsg (datamsg);
                   6408: 
                   6409:                        retval = EFAULT;
                   6410:                        break;
                   6411:                }
                   6412: 
                   6413:                datamsg->b_wptr += datasize;
                   6414: 
                   6415:                /*
                   6416:                 * Now do the write, and see if there is more data.
                   6417:                 */
                   6418: 
                   6419:                putq (W (sheadp->sh_head), datamsg);
                   6420: 
                   6421:        } while (uiop->uio_resid > 0);
                   6422: 
                   6423: 
                   6424:        /*
                   6425:         * If there has been an error after some data was actually written
                   6426:         * we return a short read rather than report the error immediately.
                   6427:         */
                   6428: 
                   6429:        if (retval != 0 && uiop->uio_resid != writecount)
                   6430:                retval = 0;
                   6431: 
                   6432:        SHEAD_SLEEP_UNLOCK (sheadp, SH_WRITE_LOCK);
                   6433:        return retval;
                   6434: }
                   6435: 
                   6436: 
                   6437: /*
                   6438:  * Stream head user-level open processing.
                   6439:  */
                   6440: 
                   6441: extern struct streamtab headinfo;
                   6442: 
                   6443: #if    __USE_PROTO__
                   6444: int (STREAMS_OPEN) (n_dev_t * devp, struct streamtab * stabp, int mode,
                   6445:                    cred_t * credp)
                   6446: #else
                   6447: int
                   6448: STREAMS_OPEN (devp, stabp, mode, credp)
                   6449: n_dev_t              * devp;
                   6450: struct streamtab
                   6451:              * stabp;
                   6452: int            mode;
                   6453: cred_t       * credp;
                   6454: #endif
                   6455: {
                   6456:        shead_t       * sheadp;
                   6457:        queue_t       * q;
                   6458:        int             retval;
                   6459:        n_dev_t         dev;
                   6460: 
                   6461:        ASSERT (devp != NULL);
                   6462:        ASSERT (stabp != NULL);
                   6463:        ASSERT (credp != NULL);
                   6464: 
                   6465: 
                   6466:        dev = * devp;
                   6467: 
                   6468:        if ((sheadp = SHEAD_OPEN_LOCK (* devp, stabp, & retval)) == NULL)
                   6469:                return retval;
                   6470: 
                   6471:        /*
                   6472:         * If this is the first open of the stream, set up the stream head
                   6473:         * entry points and the driver entry points.
                   6474:         */
                   6475: 
                   6476:        q = W (sheadp->sh_head)->q_next;
                   6477: 
                   6478:        if (sheadp->sh_open_count == 0) {
                   6479: 
                   6480:                QUEUE_INIT (sheadp->sh_head, & headinfo, QI_NORMAL);
                   6481:                qprocson (sheadp->sh_head);
                   6482: 
                   6483:                QUEUE_INIT (R (q), stabp, QI_NORMAL);
                   6484:        }
                   6485: 
                   6486: 
                   6487:        /*
                   6488:         * Now we have a stream head (locked, no less), we can call the open
                   6489:         * entry points of all the modules and the driver. In the special case
                   6490:         * where the open count of the entry is 0, we allow the driver to
                   6491:         * change the "dev_t" value to a previously unused number.
                   6492:         */
                   6493: 
                   6494:        do {
                   6495:                retval = (* R (q)->q_qinfo->qi_qopen)
                   6496:                                (R (q), & dev, mode,
                   6497:                                 q->q_next == NULL ? 0 : MODOPEN, credp);
                   6498: 
                   6499:                if (dev != * devp && q->q_next != NULL) {
                   6500:                        /*
                   6501:                         * A module has changed the device number that we
                   6502:                         * passed a pointer to. This is not valid!
                   6503:                         */
                   6504: 
                   6505:                        cmn_err (CE_WARN, "Module \"%s\" changed its device number",
                   6506:                                 q->q_qinfo->qi_minfo->mi_idname);
                   6507:                        retval = ENXIO;
                   6508:                }
                   6509: 
                   6510:                if (retval != 0)
                   6511:                        goto failure;
                   6512:        } while ((q = q->q_next) != NULL);
                   6513: 
                   6514: 
                   6515:        /*
                   6516:         * The modules and driver have all OK'ed the open, so increment the
                   6517:         * open count. Here we also check for the clone case.
                   6518:         *
                   6519:         * If we want to detect an error after this point, we should execute
                   6520:         * a close.
                   6521:         */
                   6522: 
                   6523:        sheadp->sh_open_count ++;
                   6524: 
                   6525:        if (dev != * devp) {
                   6526:                /*
                   6527:                 * The driver has requested that the device number of the
                   6528:                 * queue be assigned differently than the initial device
                   6529:                 * number. This is only really valid if this is the first open
                   6530:                 * of the given queue.
                   6531:                 */
                   6532: 
                   6533:                if (sheadp->sh_open_count > 1) {
                   6534: 
                   6535:                        cmn_err (CE_WARN, "Driver \"%s\" changed its device number after inital open",
                   6536:                                 q->q_qinfo->qi_minfo->mi_idname);
                   6537: 
                   6538:                        sheadp->sh_open_count --;
                   6539: 
                   6540:                        retval = ENXIO;
                   6541:                        goto failure;
                   6542:                }
                   6543: 
                   6544: 
                   6545:                /*
                   6546:                 * Other open attempts may be waiting on the stream head for
                   6547:                 * the original device number; they need a wakeup.
                   6548:                 */
                   6549: 
                   6550:                if (SHEAD_RENAME (sheadp, dev) != 0) {
                   6551: 
                   6552:                        cmn_err (CE_WARN, "Clone device number chosen by driver \"%s\"is in use",
                   6553:                                 q->q_qinfo->qi_minfo->mi_idname);
                   6554: 
                   6555:                        if (-- sheadp->sh_open_count == 0)
                   6556:                                SHEAD_DO_CLOSE (sheadp, mode, credp);
                   6557: 
                   6558:                        retval = ENXIO;
                   6559:                        goto failure;
                   6560:                }
                   6561: 
                   6562:                * devp = dev;
                   6563:        }
                   6564: 
                   6565: failure:
                   6566:        /*
                   6567:         * The module or driver has failed the open request. We unlock the
                   6568:         * stream head, which may deallocate the stream head if the open count
                   6569:         * is 0.
                   6570:         */
                   6571: 
                   6572:        SHEAD_SLEEP_UNLOCK (sheadp, SH_OPENCLOSE);
                   6573:        return retval;
                   6574: }
                   6575: 
                   6576: 
                   6577: /*
                   6578:  * Stream head interface to generic polling.
                   6579:  */
                   6580: 
                   6581: #if    __USE_PROTO__
                   6582: int (STREAMS_CHPOLL) (shead_t * sheadp, short events, int anyyet,
                   6583:                      short * reventsp, struct pollhead ** phpp)
                   6584: #else
                   6585: int
                   6586: STREAMS_CHPOLL __ARGS ((sheadp, events, anyyet, reventsp, phpp))
                   6587: shead_t              * sheadp;
                   6588: short          events;
                   6589: int            anyyet;
                   6590: short        * reventsp;
                   6591: struct pollhead
                   6592:             ** phpp;
                   6593: #endif
                   6594: {
                   6595:        short           my_events;
                   6596: 
                   6597:        /*
                   6598:         * The chpoll () entry point uses the POLL... constants rather than
                   6599:         * the S_... constants that I_SETSIG uses. We convert to the S_...
                   6600:         * form for our internal use... see <sys/poll.h>
                   6601:         */
                   6602: 
                   6603:        my_events = (events & (__POLL_INPUT | __POLL_HIPRI | __POLL_OUTPUT |
                   6604:                               __POLL_RDNORM | __POLL_OUTPUT |
                   6605:                               __POLL_RDBAND | __POLL_WRBAND));
                   6606: 
                   6607:        if ((events & POLLERR) != 0)
                   6608:                my_events = S_ERROR;
                   6609:        if ((events & POLLHUP) != 0)
                   6610:                my_events = S_HANGUP;
                   6611: 
                   6612:        if ((my_events = SHEAD_POLL_CHECK (sheadp, my_events)) == 0) {
                   6613: 
                   6614:                * reventsp = 0;
                   6615: 
                   6616:                if (anyyet == 0)
                   6617:                        * phpp = sheadp->sh_pollhead;
                   6618:        } else
                   6619:                * reventsp = my_events;
                   6620: 
                   6621:        return 0;
                   6622: }
                   6623: 
                   6624: 
                   6625: /*
                   6626:  * Stream head user-level close processing.
                   6627:  */
                   6628: 
                   6629: #if    __USE_PROTO__
                   6630: int (STREAMS_CLOSE) (shead_t * sheadp, int mode, cred_t * credp)
                   6631: #else
                   6632: int
                   6633: STREAMS_CLOSE __ARGS ((sheadp, mode, credp))
                   6634: shead_t              * sheadp;
                   6635: int            mode;
                   6636: cred_t       * credp;
                   6637: #endif
                   6638: {
                   6639:        int             retval;
                   6640: 
                   6641:        if ((retval = SHEAD_SLEEP_LOCK (sheadp, SH_OPENCLOSE | SH_IOCTL_LOCK,
                   6642:                                        0, CHECK_SIGNALS)) != 0)
                   6643:                return retval;
                   6644: 
                   6645:        if (-- sheadp->sh_open_count == 0)
                   6646:                SHEAD_DO_CLOSE (sheadp, mode, credp);
                   6647: 
                   6648:        SHEAD_SLEEP_UNLOCK (sheadp, SH_OPENCLOSE | SH_IOCTL_LOCK);
                   6649: 
                   6650:        return 0;
                   6651: }

unix.superglobalmegacorp.com

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