Annotation of coherent/f/etc/conf/streams/src/poll.c, revision 1.1

1.1     ! root        1: #define        _DDI_DKI        1
        !             2: #define        _SYSV4          1
        !             3: 
        !             4: 
        !             5: /*
        !             6:  * Functions related to device polling support in the DDI/DKI.
        !             7:  */
        !             8: /*
        !             9:  *-IMPORTS:
        !            10:  *     <common/ccompat.h>
        !            11:  *             __USE_PROTO__
        !            12:  *             __ARGS ()
        !            13:  *     <kernel/ddi_cpu.h>
        !            14:  *             ddi_cpu_data ()
        !            15:  *     <kernel/ddi_glob.h>
        !            16:  *             ddi_global_data ()
        !            17:  *     <kernel/ddi_lock.h>
        !            18:  *             pollglob_hierarchy
        !            19:  *             pollglob_priority
        !            20:  *             pollhead_hierarchy
        !            21:  *             pollhead_priority
        !            22:  *             pollwait_hierarchy
        !            23:  *             pollwait_priority
        !            24:  *     <sys/debug.h>
        !            25:  *             ASSERT ()
        !            26:  *     <sys/kmem.h>
        !            27:  *             KM_SLEEP
        !            28:  *             kmem_alloc ()
        !            29:  *             kmem_free ()
        !            30:  *     <sys/ksynch.h>
        !            31:  *             lkinfo_t
        !            32:  *             LOCK ()
        !            33:  *             LOCK_ALLOC ()
        !            34:  *             LOCK_DEALLOC ()
        !            35:  *             SV_ALLOC ()
        !            36:  *             SV_DEALLOC ()
        !            37:  *             SV_WAIT_SIG ()
        !            38:  *             UNLOCK ()
        !            39:  *     <sys/errno.h>
        !            40:  *             EAGAIN
        !            41:  */
        !            42: 
        !            43: #include <common/ccompat.h>
        !            44: #include <kernel/ddi_cpu.h>
        !            45: #include <kernel/ddi_glob.h>
        !            46: #include <kernel/ddi_lock.h>
        !            47: #include <sys/debug.h>
        !            48: #include <sys/kmem.h>
        !            49: #include <sys/ksynch.h>
        !            50: #include <sys/errno.h>
        !            51: 
        !            52: #include <sys/inline.h>
        !            53: #include <stddef.h>
        !            54: #include <limits.h>
        !            55: 
        !            56: #include <common/_poll.h>
        !            57: #include <sys/poll.h>
        !            58: #include <poll.h>
        !            59: #include <stropts.h>
        !            60: 
        !            61: 
        !            62: /*
        !            63:  * The definition of the "pollhead" structure is kept private to this source
        !            64:  * file to avoid the temptation for other code to look at its members or
        !            65:  * allocate their own.
        !            66:  *
        !            67:  * Since we want to keep things fast, we use a circular-list scheme here,
        !            68:  * unlike most other places lists are maintained. For the DDI/DKI polling
        !            69:  * system, this is not a problem because list head items are allocated via
        !            70:  * phalloc (), which ensures that they are properly set up. For the old-style
        !            71:  * Coherent versions, we hope that they have been initialised to NULL and try
        !            72:  * and detect when they need setting up properly.
        !            73:  *
        !            74:  * The 'event_t' structure used in old-style Coherent polling is defined in
        !            75:  * <sys/poll.h>.
        !            76:  */
        !            77: 
        !            78: typedef        struct pollwait pwait_t;
        !            79: typedef        struct pollev   pevent_t;
        !            80: typedef        struct pollhead phead_t;
        !            81: 
        !            82: 
        !            83: /*
        !            84:  * For DDI/DKI polling, drivers get to deal in terms of a head of a list of
        !            85:  * events.
        !            86:  */
        !            87: 
        !            88: struct pollhead {
        !            89:        poll_t          ph_node;
        !            90:        lock_t        * ph_lock;
        !            91: };
        !            92: 
        !            93: 
        !            94: /*
        !            95:  * Structure of a polled event for DDI/DKI polling. Since these structures are
        !            96:  * allocated from a pool in the "pollwait" structure, there is no explicit
        !            97:  * per-process linkage between events.
        !            98:  */
        !            99: 
        !           100: struct pollev {
        !           101:        poll_t          pe_node;
        !           102:        pwait_t       * pe_pwait;
        !           103:        phead_t       * pe_head;
        !           104:        short           pe_events;
        !           105: };
        !           106: 
        !           107: 
        !           108: #if    _OLD_COH_POLLING
        !           109: 
        !           110: /*
        !           111:  * For old-style polling, we need a cell per event being waited on; however,
        !           112:  * since old-style polling only supported POLLIN, POLLOUT, and POLLPRI there
        !           113:  * is a small upper bound on the number we need.
        !           114:  */
        !           115: 
        !           116: typedef        struct old_poll o_event_t;
        !           117: 
        !           118: struct old_poll {
        !           119:        poll_t          op_node;
        !           120:        pwait_t       * op_pwait;
        !           121: };
        !           122: 
        !           123: #endif /* _OLD_COH_POLLING */
        !           124: 
        !           125: 
        !           126: /*
        !           127:  * A polling process allocates a 'pollwait' structure and goes to sleep on it
        !           128:  * after checking with all the items being polled. The 'pollwait' structure
        !           129:  * records if any events have been triggered after being checked but before
        !           130:  * the process has actually gone to sleep (ie, when it is checking other
        !           131:  * devices).
        !           132:  */
        !           133: 
        !           134: enum {
        !           135:        PW_POLLING,
        !           136:        PW_SLEEPING,
        !           137:        PW_WOKEN
        !           138: };
        !           139: 
        !           140: 
        !           141: struct pollwait {
        !           142:        lock_t        * pw_lock;
        !           143:        sv_t          * pw_sleep;
        !           144:        int             pw_sleeping;
        !           145: 
        !           146:        pevent_t      * pw_events;
        !           147:        int             pw_nevents;
        !           148: 
        !           149:        size_t          pw_size;        /* allocated size of structure */
        !           150: 
        !           151: #if    _OLD_COH_POLLING
        !           152:        /*
        !           153:         * The old-style events are allocated down from the top of the same
        !           154:         * chunk of memory used for the new-style events. 'pw_oevents' is the
        !           155:         * current base and is moved down each time a new entry is allocated.
        !           156:         */
        !           157: 
        !           158:        o_event_t     * pw_oevents;
        !           159:        int             pw_noevents;
        !           160: #endif /* _OLD_COH_POLLING */
        !           161: };
        !           162: 
        !           163: 
        !           164: /*
        !           165:  * Declare the lock information structures at file scope.
        !           166:  */
        !           167: 
        !           168: __LOCAL__ lkinfo_t _pollhead_lkinfo = {
        !           169:        "polling pollhead lock", INTERNAL_LOCK
        !           170: };
        !           171: 
        !           172: __LOCAL__ lkinfo_t _pollwait_lkinfo = {
        !           173:        "polling pollwait lock", INTERNAL_LOCK
        !           174: };
        !           175: 
        !           176: 
        !           177: /*
        !           178:  * Utility routine to initialize a 'pnode' for use as a circular list head.
        !           179:  */
        !           180: 
        !           181: #define        INIT_PNODE(pnp) ((pnp)->pn_next = (pnp)->pn_prev = (pnp))
        !           182: 
        !           183: 
        !           184: /*
        !           185:  * Currently, we store the user's "pollwait" structure in the per-CPU data
        !           186:  * area. However, it seems prudent to encapsulate this fact. Note that the
        !           187:  * case to "pwait_t *" in GET_POLLWAIT () exists to satisfy PC-Lint's notion
        !           188:  * of strong typing.
        !           189:  */
        !           190: 
        !           191: #define        GET_POLLWAIT()          ((pwait_t *) ddi_cpu_data ()->dc_pollwait)
        !           192: #define        SET_POLLWAIT(pw)        (void) (ddi_cpu_data ()->dc_pollwait = (pw))
        !           193: 
        !           194: 
        !           195: /*
        !           196:  * Some macros to save typing given the long, descriptive names of the lock-
        !           197:  * related constants.
        !           198:  */
        !           199: 
        !           200: #define        POLLWAIT_LOCK(pw)       LOCK ((pw)->pw_lock, pollwait_priority)
        !           201: #define        POLLWAIT_UNLOCK(pw,p)   UNLOCK ((pw)->pw_lock, (p))
        !           202: 
        !           203: #define        POLLHEAD_LOCK(ph)       LOCK ((ph)->ph_lock, pollhead_priority)
        !           204: #define        POLLHEAD_UNLOCK(ph,p)   UNLOCK ((ph)->ph_lock, (p))
        !           205: 
        !           206: #define        POLL_GLOBAL_LOCK()      LOCK (ddi_global_data ()->dg_polllock, \
        !           207:                                      poll_global_priority)
        !           208: #define        POLL_GLOBAL_UNLOCK(p)   UNLOCK (ddi_global_data ()->dg_polllock, (p))
        !           209: 
        !           210: 
        !           211: #if    1
        !           212: 
        !           213: /*
        !           214:  * Utility routine to fetch the address of the 'pollwait' structure allocated
        !           215:  * by the currently polling process, with extra checking.
        !           216:  */
        !           217: 
        !           218: #if    __USE_PROTO__
        !           219: __LOCAL__ pwait_t * (GET_POLLWAIT) (void)
        !           220: #else
        !           221: __LOCAL__ pwait_t *
        !           222: GET_POLLWAIT __ARGS (())
        !           223: #endif
        !           224: {
        !           225:        pwait_t       * pwaitp;
        !           226: 
        !           227:        /*
        !           228:         * Since the current 'pollwait' value is recorded in the per-CPU data
        !           229:         * area, no locking is really necessary to ensure atomic access to the
        !           230:         * data. Actually, this might not be true for some CPUs such as Intel
        !           231:         * 80x86's, but access to the value is only defined within certain
        !           232:         * limited contexts anyway.
        !           233:         *
        !           234:         * Note that we cast from a "struct pollwait *" to a "pwait_t *" in
        !           235:         * order to be able to satisfy PC-lint's strong typing.
        !           236:         */
        !           237: 
        !           238:        pwaitp = GET_POLLWAIT ();
        !           239: 
        !           240:        ASSERT (pwaitp != NULL);
        !           241: 
        !           242:        return pwaitp;
        !           243: }
        !           244: 
        !           245: #undef GET_POLLWAIT
        !           246: 
        !           247: #endif
        !           248: 
        !           249: 
        !           250: /*
        !           251:  * Utility routine to deal with signalling an event to a process that has
        !           252:  * begun polling (but may not have gone to sleep yet).
        !           253:  */
        !           254: 
        !           255: #if    __USE_PROTO__
        !           256: void (POLL_WAKE) (pwait_t * pwaitp)
        !           257: #else
        !           258: void
        !           259: POLL_WAKE __ARGS ((pwaitp))
        !           260: pwait_t              * pwaitp;
        !           261: #endif
        !           262: {
        !           263:        pl_t            prev_pl;
        !           264: 
        !           265:        prev_pl = POLLWAIT_LOCK (pwaitp);
        !           266: 
        !           267:        if (pwaitp->pw_sleeping == PW_SLEEPING)
        !           268:                SV_SIGNAL (pwaitp->pw_sleep, 0);
        !           269: 
        !           270:        pwaitp->pw_sleeping = PW_WOKEN;
        !           271: 
        !           272:        POLLWAIT_UNLOCK (pwaitp, prev_pl);
        !           273: }
        !           274: 
        !           275: 
        !           276: #if    _OLD_COH_POLLING
        !           277: /*
        !           278:  * The original Coherent polling system allocated event records at the time of
        !           279:  * the first call to pollopen () based on a patchable variable. If the
        !           280:  * patchable value was 0, then more event cells would be allocated (in blocks
        !           281:  * of 32) on demand and added to the event cell pool.
        !           282:  *
        !           283:  * In the new system, event cells are allocated at the time of entry to the
        !           284:  * poll () system call, meaning that there is some fixed allocation overhead
        !           285:  * per system call but that the event cells will be returned to a general
        !           286:  * pool.
        !           287:  */
        !           288: 
        !           289: 
        !           290: /*
        !           291:  * This function (called by old-style device drivers) requests an association
        !           292:  * between the polling process and the device's list of polling processes. The
        !           293:  * contents of the list head and the method of association are opaque, except
        !           294:  * for the "e_procp" member of the event cell and the fact that the list head
        !           295:  * structure is used directly in data structure declarations in the driver
        !           296:  * rather than being managed by constructor/destructor routines.
        !           297:  *
        !           298:  * To get around the initialization problems, we must assume that such driver
        !           299:  * structures will be initially zero-filled.
        !           300:  *
        !           301:  * Callable ONLY from base level within a Coherent old-style device-driver
        !           302:  * poll () entry point.
        !           303:  */
        !           304: 
        !           305: #if    __USE_PROTO__
        !           306: void (pollopen) (event_t * elistp)
        !           307: #else
        !           308: void
        !           309: pollopen __ARGS ((elistp))
        !           310: event_t              * elistp;
        !           311: #endif
        !           312: {
        !           313:        pwait_t       * pwaitp = GET_POLLWAIT ();
        !           314:        o_event_t     * eventp;
        !           315:        pl_t            prev_pl;
        !           316: 
        !           317:        /*
        !           318:         * Detect a zero-filled (hence uninitialised) list head. We use the
        !           319:         * circular list property to detect initialization.
        !           320:         */
        !           321: 
        !           322:        if (elistp->e_node.pn_next == NULL)
        !           323:                INIT_PNODE (& elistp->e_node);
        !           324: 
        !           325:        /*
        !           326:         * Take an event from the 'pollwait' structure.
        !           327:         */
        !           328: 
        !           329:        eventp = -- pwaitp->pw_oevents;
        !           330:        pwaitp->pw_noevents ++;
        !           331: 
        !           332:        ASSERT ((pevent_t *) eventp > & pwaitp->pw_events [pwaitp->pw_nevents]);
        !           333: 
        !           334:        /*
        !           335:         * String it all together. We use interrupt priority level to protect
        !           336:         * the insertion, because code that uses this code isn't going to be
        !           337:         * multiprocessor-safe anyway.
        !           338:         */
        !           339: 
        !           340:        eventp->op_pwait = pwaitp;      /* link to polling process */
        !           341: 
        !           342:        prev_pl = splhi ();
        !           343: 
        !           344:        eventp->op_node.pn_next = elistp->e_node.pn_next;
        !           345:        eventp->op_node.pn_prev = & elistp->e_node;
        !           346:        eventp->op_node.pn_next->pn_prev = & eventp->op_node;
        !           347:        elistp->e_node.pn_next = & eventp->op_node;
        !           348: 
        !           349:        /*
        !           350:         * Set the magic flag.
        !           351:         */
        !           352: 
        !           353:        elistp->e_procp = (__VOID__ *) 1;
        !           354: 
        !           355:        (void) splx (prev_pl);
        !           356: }
        !           357: 
        !           358: 
        !           359: /*
        !           360:  * This routine signals all the polling processes that have been queued on
        !           361:  * this event list by pollopen () that an event they are interested in has
        !           362:  * occurred.
        !           363:  */
        !           364: 
        !           365: #if    __USE_PROTO__
        !           366: void (pollwake) (event_t * elistp)
        !           367: #else
        !           368: void
        !           369: pollwake __ARGS ((elistp))
        !           370: event_t              * elistp;
        !           371: #endif
        !           372: {
        !           373:        poll_t        * pnodep;
        !           374: 
        !           375:        /*
        !           376:         * Since we have to maintain the magic header flag, we may as well use
        !           377:         * it as well.
        !           378:         */
        !           379: 
        !           380:        if (elistp->e_procp == 0)
        !           381:                return;
        !           382: 
        !           383:        elistp->e_procp = 0;
        !           384: 
        !           385: 
        !           386:        /*
        !           387:         * Service circularly-linked polls on device queue. It may be that the
        !           388:         * driver's circular list has not yet been initialized.
        !           389:         *
        !           390:         * We don't take out a lock because this system doesn't support them,
        !           391:         * and we don't need to manipulate interrupts because we don't modify
        !           392:         * the structure.
        !           393:         */
        !           394: 
        !           395:        if ((pnodep = elistp->e_node.pn_next) != NULL) {
        !           396:                /*
        !           397:                 * We detect the end of the list when the circular walk has
        !           398:                 * taken us back to the list head.
        !           399:                 */
        !           400: 
        !           401:                while (pnodep != & elistp->e_node) {
        !           402:                        /*
        !           403:                         * Downcast from the node to the queued event cell,
        !           404:                         * and wake the process.
        !           405:                         */
        !           406: 
        !           407:                        POLL_WAKE (__DOWNCAST (o_event_t, op_node,
        !           408:                                               pnodep)->op_pwait);
        !           409: 
        !           410:                        pnodep = pnodep->pn_next;
        !           411:                }
        !           412:        }
        !           413: }
        !           414: 
        !           415: 
        !           416: /*
        !           417:  * This routine cleans up any old-style events.
        !           418:  */
        !           419: 
        !           420: #if    __USE_PROTO__
        !           421: __LOCAL__ void (oldpollclean) (o_event_t * oevents, int noevents)
        !           422: #else
        !           423: __LOCAL__ void
        !           424: oldpollclean __ARGS ((oevents, noevents))
        !           425: o_event_t     *        oevents;
        !           426: int            noevents;
        !           427: #endif
        !           428: {
        !           429:        pl_t            prev_pl;
        !           430: 
        !           431:        ASSERT (oevents != NULL);
        !           432: 
        !           433:        /*
        !           434:         * Iterate over the list of queued old-style events and dequeue each
        !           435:         * one.
        !           436:         */
        !           437: 
        !           438:        prev_pl = splhi ();
        !           439: 
        !           440:        while (noevents > 0) {
        !           441: 
        !           442:                oevents->op_node.pn_next->pn_prev = oevents->op_node.pn_prev;
        !           443:                oevents->op_node.pn_prev->pn_next = oevents->op_node.pn_next;
        !           444: 
        !           445:                noevents --;
        !           446:                oevents ++;
        !           447:        }
        !           448: 
        !           449:        splx (prev_pl);
        !           450: }
        !           451: 
        !           452: #endif /* _OLD_COH_POLLING */
        !           453: 
        !           454: 
        !           455: /*
        !           456:  *-STATUS:
        !           457:  *     DDI/DKI
        !           458:  *
        !           459:  *-NAME:
        !           460:  *     phalloc         Allocate and initialize a pollhead structure.
        !           461:  *
        !           462:  *-SYNOPSIS:
        !           463:  *     #include <sys/poll.h>
        !           464:  *     #include <sys/kmem.h>
        !           465:  *
        !           466:  *     struct pollhead * phalloc (int flag);
        !           467:  *
        !           468:  *-ARGUMENTS:
        !           469:  *     flag            Specifies whether the caller is willing to sleep
        !           470:  *                     waiting for memory. If "flag" is set to "KM_SLEEP",
        !           471:  *                     the caller will sleep if necessary until sufficient
        !           472:  *                     memory is available. If "flag" is set to "KM_NOSLEEP",
        !           473:  *                     the caller will not sleep, but phalloc () will return
        !           474:  *                     NULL if sufficient memory is not immediately
        !           475:  *                     available.
        !           476:  *
        !           477:  *-DESCRIPTION:
        !           478:  *     phalloc () allocates and initializes a "pollhead" structure for use by
        !           479:  *     non-STREAMS character drivers that wish to support polling. The "flag"
        !           480:  *     argument indicates whether the caller is willing to sleep waiting for
        !           481:  *     memory as described above.
        !           482:  *
        !           483:  *-RETURN VALUE:
        !           484:  *     Upon successful completion, phalloc () returns a pointer to the newly
        !           485:  *     allocated "pollhead" structure. If "KM_NOSLEEP" is specified and
        !           486:  *     sufficient memory is not immediately available, phalloc () returns a
        !           487:  *     NULL pointer.
        !           488:  *
        !           489:  *-LEVEL:
        !           490:  *     Base only if "flag" is set to "KM_SLEEP". Base or interrupt if "flag"
        !           491:  *     is set to "KM_NOSLEEP".
        !           492:  *
        !           493:  *-NOTES:
        !           494:  *     May sleep if slag is set to "KM_SLEEP".
        !           495:  *
        !           496:  *     Driver-defined basic locks and read/write locks may be held across
        !           497:  *     calls to this function if "flag" is "KM_NOSLEEP" but may not be held
        !           498:  *     if "flag" is "KM_SLEEP".
        !           499:  *
        !           500:  *     Driver-defined sleep locks may be held across calls to this function
        !           501:  *     regardless of the value of "flag".
        !           502:  *
        !           503:  *     DDI/DKI conforming drivers may only use "pollhead" structures which
        !           504:  *     have been allocated and initialized using phalloc (). Use of
        !           505:  *     "pollhead" structures which have been obtained by any other means is
        !           506:  *     prohibited.
        !           507:  *
        !           508:  *-SEE ALSO:
        !           509:  *     phfree (), pollwakeup ()
        !           510:  */
        !           511: 
        !           512: #if    __USE_PROTO__
        !           513: struct pollhead * (phalloc) (int flag)
        !           514: #else
        !           515: struct pollhead *
        !           516: phalloc __ARGS ((flag))
        !           517: int            flag;
        !           518: #endif
        !           519: {
        !           520:        struct pollhead * php;
        !           521: 
        !           522:        if ((php = (struct pollhead *) kmem_alloc (sizeof (* php), flag))
        !           523:            != NULL) {
        !           524: 
        !           525:                if ((php->ph_lock = LOCK_ALLOC (pollhead_hierarchy,
        !           526:                                                pollhead_priority,
        !           527:                                                & _pollhead_lkinfo,
        !           528:                                                flag)) == NULL) {
        !           529:                        kmem_free (php, sizeof (* php));
        !           530:                        return NULL;
        !           531:                }
        !           532: 
        !           533:                INIT_PNODE (& php->ph_node);
        !           534:        }
        !           535: 
        !           536:        return php;
        !           537: }
        !           538: 
        !           539: 
        !           540: /*
        !           541:  *-STATUS:
        !           542:  *     DDI/DKI
        !           543:  *
        !           544:  *-NAME:
        !           545:  *     phfree          Free a pollhead structure.
        !           546:  *
        !           547:  *-SYNOPSIS:
        !           548:  *     #include <sys/poll.h>
        !           549:  *
        !           550:  *     void phfree (struct pollhead * php);
        !           551:  *
        !           552:  *-ARGUMENTS:
        !           553:  *     php             Pointer to the "pollhead" structure to be freed. The
        !           554:  *                     structure pointed to by "php" must have been
        !           555:  *                     previously allocated by a call to phalloc ().
        !           556:  *
        !           557:  *-DESCRIPTION:
        !           558:  *     phfree () frees the "pollhead" structure specified by "php".
        !           559:  *
        !           560:  *-RETURN VALUE:
        !           561:  *     None.
        !           562:  *
        !           563:  *-LEVEL:
        !           564:  *     Base or interrupt.
        !           565:  *
        !           566:  *-NOTES:
        !           567:  *     Does not sleep.
        !           568:  *
        !           569:  *     Driver-defined basic locks, read/write locks, and sleep locks may be
        !           570:  *     held across calls to this function.
        !           571:  *
        !           572:  *     DDI/DKI conforming drivers may only use "pollhead" structures which
        !           573:  *     have been allocated and initialized using phalloc (). Use of
        !           574:  *     "pollhead" structures which have been obtained by any other means is
        !           575:  *     prohibited.
        !           576:  *
        !           577:  *-SEE ALSO:
        !           578:  *     phalloc (), pollwakeup ()
        !           579:  */
        !           580: 
        !           581: #if    __USE_PROTO__
        !           582: void (phfree) (struct pollhead * php)
        !           583: #else
        !           584: void
        !           585: phfree __ARGS ((php))
        !           586: struct pollhead * php;
        !           587: #endif
        !           588: {
        !           589:        poll_t        * pnodep;
        !           590:        poll_t        * next;
        !           591: 
        !           592:        ASSERT (php != NULL);
        !           593: 
        !           594:        /*
        !           595:         * Since phalloc () and phfree () are not constrained to be used only
        !           596:         * in driver open/close routines, the possibility exists for a poll
        !           597:         * head structure to be deallocated while processes are waiting on it.
        !           598:         * This isn't very desirable, but it seems to be legal.
        !           599:         *
        !           600:         * After acquiring the global lock, we request a lock on the pollhead
        !           601:         * structure to ensure that all activity on the structure has
        !           602:         * completed before we begin to tear it down. Since the caller has
        !           603:         * requested deallocation of the structure, the caller should be
        !           604:         * confident that no-one will try and access it after any current
        !           605:         * activity has ceased.
        !           606:         *
        !           607:         * We engage in some subterfuge here in order to create a situation
        !           608:         * where we can detect any mistaken access.
        !           609:         */
        !           610: 
        !           611: 
        !           612:        {
        !           613:                pl_t            prev_pl;
        !           614:                lock_t        * lock = php->ph_lock;
        !           615: 
        !           616:                prev_pl = POLL_GLOBAL_LOCK ();
        !           617:                (void) LOCK (lock, pollhead_priority);
        !           618: 
        !           619:                php->ph_lock = NULL;
        !           620: 
        !           621:                POLL_GLOBAL_UNLOCK (pollhead_priority);
        !           622:                UNLOCK (lock, prev_pl);
        !           623: 
        !           624:                LOCK_DEALLOC (lock);
        !           625:        }
        !           626: 
        !           627: 
        !           628:        /*
        !           629:         * Walking over an entire circular list removing all the queue nodes
        !           630:         * allows a few simple optimizations; because we will be touching
        !           631:         * *every* node an dequeueing it, we don't need to engage in any
        !           632:         * real manipulation of the first/next nodes. In fact, since we almost
        !           633:         * immediately deallocate the structure, we don't have to touch the
        !           634:         * list head at all.
        !           635:         */
        !           636: 
        !           637:        next = php->ph_node.pn_next;
        !           638: 
        !           639:        while ((pnodep = next) != & php->ph_node) {
        !           640:                /*
        !           641:                 * Doing this ensures that multiple attempts to dequeue this
        !           642:                 * node (such as from the process polling cleanup routine)
        !           643:                 * will have no effect. We could use the "pe_events" member of
        !           644:                 * the event structure for this, but that would need a
        !           645:                 * downcast and probably wouldn't result in higher
        !           646:                 * performance.
        !           647:                 */
        !           648: 
        !           649:                next = pnodep->pn_next;
        !           650:                pnodep->pn_prev = pnodep->pn_next = pnodep;
        !           651:        }
        !           652: 
        !           653:        kmem_free (php, sizeof (* php));
        !           654: }
        !           655: 
        !           656: 
        !           657: /*
        !           658:  *-STATUS:
        !           659:  *     DDI/DKI
        !           660:  *
        !           661:  *-NAME:
        !           662:  *     pollwakeup      Inform polling process that an event has occurred.
        !           663:  *
        !           664:  *-SYNOPSIS:
        !           665:  *     #include <sys/poll.h>
        !           666:  *
        !           667:  *     void pollwakeup (struct pollhead * php, short event);
        !           668:  *
        !           669:  *-ARGUMENTS:
        !           670:  *     php             Pointer to a "pollhead" structure.
        !           671:  *
        !           672:  *     event           Event to notify the process about.
        !           673:  *
        !           674:  *-DESCRIPTION:
        !           675:  *     The pollwakeup () function provides non-STREAMS character drivers with
        !           676:  *     a way to notify processes polling for the occurrence of an event.
        !           677:  *     pollwakeup () should be called from the driver for each occurrence of
        !           678:  *     an event.
        !           679:  *
        !           680:  *     The "pollhead" structure will usually be associated with the driver's
        !           681:  *     private data structure for the particular minor device where the event
        !           682:  *     has occurred.
        !           683:  *
        !           684:  *-RETURN VALUE:
        !           685:  *     None.
        !           686:  *
        !           687:  *-LEVEL:
        !           688:  *     Base or interrupt.
        !           689:  *
        !           690:  *-NOTES:
        !           691:  *     Does not sleep.
        !           692:  *
        !           693:  *     Driver-defined basic locks, read/write locks, and sleep locks may be
        !           694:  *     held across calls to this function.
        !           695:  *
        !           696:  *     pollwakeup () should only be called with one event at a time.
        !           697:  *
        !           698:  *-SEE ALSO:
        !           699:  *     phalloc (), phfree ()
        !           700:  */
        !           701: 
        !           702: #if    __USE_PROTO__
        !           703: void (pollwakeup) (struct pollhead * php, short event)
        !           704: #else
        !           705: void
        !           706: pollwakeup __ARGS ((php, event))
        !           707: struct pollhead * php;
        !           708: short          event;
        !           709: #endif
        !           710: {
        !           711:        poll_t        * pnodep;
        !           712:        poll_t        * next;
        !           713:        pl_t            prev_pl;
        !           714: 
        !           715:        ASSERT (php != NULL);
        !           716:        ASSERT (event == POLLIN || event == POLLPRI || event == POLLOUT ||
        !           717:                event == POLLRDNORM || event == POLLWRNORM ||
        !           718:                event == POLLRDBAND || event == POLLWRBAND ||
        !           719:                event == POLLERR || event == POLLHUP);
        !           720: 
        !           721:        /*
        !           722:         * Acquire a lock on the pollhead structure after getting a global
        !           723:         * lock on the polling system.
        !           724:         */
        !           725: 
        !           726:        prev_pl = POLL_GLOBAL_LOCK ();
        !           727: 
        !           728:        POLLHEAD_LOCK (php);
        !           729: 
        !           730:        POLL_GLOBAL_UNLOCK (pollhead_priority);
        !           731: 
        !           732: 
        !           733:        /*
        !           734:         * Scan the list of queued processes and wake up (and dequeue) any
        !           735:         * that are waiting for the event being signalled.
        !           736:         */
        !           737: 
        !           738:        next = php->ph_node.pn_next;
        !           739: 
        !           740:        while ((pnodep = next) != & php->ph_node) {
        !           741:                pevent_t      * eventp;
        !           742: 
        !           743:                next = pnodep->pn_next;
        !           744:                eventp = __DOWNCAST (pevent_t, pe_node, pnodep);
        !           745: 
        !           746:                if ((eventp->pe_events & event) != 0) {
        !           747: 
        !           748:                        POLL_WAKE (eventp->pe_pwait);
        !           749: 
        !           750:                        /*
        !           751:                         * Perform a full general dequeue, and also change
        !           752:                         * the node pointers so that a second request to
        !           753:                         * dequeue the node has no effect.
        !           754:                         */
        !           755: 
        !           756:                        next->pn_prev = pnodep->pn_prev;
        !           757:                        pnodep->pn_prev->pn_next = next;
        !           758: 
        !           759:                        pnodep->pn_prev = pnodep->pn_next = pnodep;
        !           760:                }
        !           761:        }
        !           762: 
        !           763:        POLLHEAD_UNLOCK (php, prev_pl);
        !           764: }
        !           765: 
        !           766: 
        !           767: /*
        !           768:  * This internal function allocates and initializes a 'pollwait' structure on
        !           769:  * behalf of a process that wants to perform polling operations. The 'fds'
        !           770:  * argument specifies the number of devices/streams that are being polled.
        !           771:  *
        !           772:  * The newly-allocated structure is recorded in the per-CPU DDI/DKI data area,
        !           773:  * so that it is an error for the caller to sleep between a call to pwalloc ()
        !           774:  * and a call to pwsleep ().
        !           775:  *
        !           776:  * The return value is 0 on success, or an error number on failure (due to
        !           777:  * insufficient kernel memory). This function may sleep for memory to become
        !           778:  * available. Callable from base level only.
        !           779:  */
        !           780: 
        !           781: #define        _max(a,b)               ((a) < (b) ? (b) : (a))
        !           782: 
        !           783: enum {
        !           784: #if    _OLD_COH_POLLING
        !           785:        cellsize = _max (sizeof (pevent_t), 3 * sizeof (o_event_t))
        !           786: #else
        !           787:        cellsize = sizeof (pevent_t)
        !           788: #endif
        !           789: };
        !           790: 
        !           791: #if    __USE_PROTO__
        !           792: int (pwalloc) (int fds)
        !           793: #else
        !           794: int
        !           795: pwalloc __ARGS ((fds))
        !           796: int            fds;
        !           797: #endif
        !           798: {
        !           799:        size_t          size;
        !           800:        pwait_t       * pwaitp;
        !           801: 
        !           802:        ASSERT (fds >= 0 && fds < INT_MAX / cellsize);
        !           803:        ASSERT (GET_POLLWAIT () == NULL);
        !           804: 
        !           805:        /*
        !           806:         * How much memory to allocate; we assume that at most three old-style
        !           807:         * event cells could be allocated per stream, or one new event cell.
        !           808:         */
        !           809: 
        !           810:        size = fds * cellsize + sizeof (pwait_t);
        !           811: 
        !           812:        if ((pwaitp = (pwait_t *) kmem_alloc (size, KM_SLEEP)) != NULL) {
        !           813: 
        !           814:                if ((pwaitp->pw_lock =
        !           815:                                LOCK_ALLOC (pollwait_hierarchy,
        !           816:                                            pollwait_priority,
        !           817:                                            & _pollwait_lkinfo,
        !           818:                                            KM_SLEEP)) != NULL) {
        !           819:                        if ((pwaitp->pw_sleep = SV_ALLOC (KM_SLEEP))
        !           820:                            != NULL) {
        !           821: 
        !           822:                                ASSERT (GET_POLLWAIT () == NULL);
        !           823: 
        !           824:                                pwaitp->pw_sleeping = PW_POLLING;
        !           825:                                pwaitp->pw_events = (pevent_t *) (pwaitp + 1);
        !           826:                                pwaitp->pw_nevents = 0;
        !           827:                                pwaitp->pw_size = size;
        !           828: #if    _OLD_COH_POLLING
        !           829:                                pwaitp->pw_oevents = (o_event_t *)
        !           830:                                        ((char *) pwaitp + size);
        !           831:                                pwaitp->pw_noevents = 0;
        !           832: #endif
        !           833:                                SET_POLLWAIT (pwaitp);
        !           834:                                 return 0;
        !           835:                        }
        !           836: 
        !           837:                        LOCK_DEALLOC (pwaitp->pw_lock);
        !           838:                }
        !           839: 
        !           840:                kmem_free (pwaitp, size);
        !           841:        }
        !           842: 
        !           843:        return EAGAIN;
        !           844: }
        !           845: 
        !           846: 
        !           847: /*
        !           848:  * This internal function is used by user-level polling code to go to sleep
        !           849:  * after checking with each device being polled (thus registering any event
        !           850:  * cells as necessary).
        !           851:  *
        !           852:  * May sleep. Callable from base level only. Returns 0 if woken by an
        !           853:  * indication that an event has occurred, or 1 if woken by a signal.
        !           854:  */
        !           855: 
        !           856: #if    __USE_PROTO__
        !           857: int (pollsleep) (void)
        !           858: #else
        !           859: int
        !           860: pollsleep __ARGS (())
        !           861: #endif
        !           862: {
        !           863:        pwait_t       * pwaitp = GET_POLLWAIT ();
        !           864:        int             sigwake = 0;
        !           865: 
        !           866:        ASSERT (pwaitp != NULL);
        !           867: 
        !           868:        /*
        !           869:         * Lock the structure before checking to see whether we want to go
        !           870:         * to sleep or not.
        !           871:         */
        !           872: 
        !           873:        (void) POLLWAIT_LOCK (pwaitp);
        !           874: 
        !           875:        if (pwaitp->pw_sleeping == PW_POLLING) {
        !           876:                /*
        !           877:                 * No events were triggered while we were scanning all the
        !           878:                 * requested channels, so we do actually have to sleep.
        !           879:                 */
        !           880: 
        !           881:                SET_POLLWAIT (NULL);
        !           882:                pwaitp->pw_sleeping = PW_SLEEPING;
        !           883: 
        !           884:                sigwake = SV_WAIT_SIG (pwaitp->pw_sleep, prilo,
        !           885:                                       pwaitp->pw_lock) == 0;
        !           886: 
        !           887:                ASSERT (GET_POLLWAIT () == NULL);
        !           888: 
        !           889:                pwaitp->pw_sleeping = PW_WOKEN;
        !           890:                SET_POLLWAIT (pwaitp);
        !           891:        } else {
        !           892: 
        !           893:                ASSERT (pwaitp->pw_sleeping == PW_WOKEN);
        !           894: 
        !           895:                POLLWAIT_UNLOCK (pwaitp, plbase);
        !           896:        }
        !           897: 
        !           898:        return sigwake;
        !           899: }
        !           900: 
        !           901: 
        !           902: /*
        !           903:  * This local function deals with dequeuing event cells from device polling
        !           904:  * lists.
        !           905:  */
        !           906: 
        !           907: #if    __USE_PROTO__
        !           908: __LOCAL__ void (pollclean) (pevent_t * events, int nevents)
        !           909: #else
        !           910: __LOCAL__ void
        !           911: pollclean __ARGS ((events, nevents))
        !           912: pevent_t      *        events;
        !           913: int            nevents;
        !           914: #endif
        !           915: {
        !           916:        pl_t            prev_pl;
        !           917: 
        !           918:        ASSERT (events != NULL);
        !           919: 
        !           920:        /*
        !           921:         * Iterate over the list of queued events and dequeue each one.
        !           922:         */
        !           923: 
        !           924:        while (nevents > 0) {
        !           925: 
        !           926:                prev_pl = POLLHEAD_LOCK (events->pe_head);
        !           927: 
        !           928:                events->pe_node.pn_next->pn_prev = events->pe_node.pn_prev;
        !           929:                events->pe_node.pn_prev->pn_next = events->pe_node.pn_next;
        !           930: 
        !           931:                POLLHEAD_UNLOCK (events->pe_head, prev_pl);
        !           932: 
        !           933:                nevents --;
        !           934:                events ++;
        !           935:        }
        !           936: }
        !           937: 
        !           938: 
        !           939: /*
        !           940:  * This function destroys and deallocates all the resources taken up by a
        !           941:  * user poll-wait structure.
        !           942:  */
        !           943: 
        !           944: #if    __USE_PROTO__
        !           945: void (pwfree) (void)
        !           946: #else
        !           947: void
        !           948: pwfree __ARGS (())
        !           949: #endif
        !           950: {
        !           951:        pwait_t       * pwaitp = GET_POLLWAIT ();
        !           952: 
        !           953:        ASSERT (pwaitp != NULL);
        !           954: 
        !           955: #if    _OLD_COH_POLLING
        !           956:        oldpollclean (pwaitp->pw_oevents, pwaitp->pw_noevents);
        !           957: #endif
        !           958: 
        !           959:        pollclean (pwaitp->pw_events, pwaitp->pw_nevents);
        !           960: 
        !           961:        /*
        !           962:         * Now there is no way that an interrupt-level context could try and
        !           963:         * access the pollwait structure, we can safely deallocate it.
        !           964:         */
        !           965: 
        !           966:        SV_DEALLOC (pwaitp->pw_sleep);
        !           967: 
        !           968:        LOCK_DEALLOC (pwaitp->pw_lock);
        !           969: 
        !           970:        kmem_free (pwaitp, pwaitp->pw_size);
        !           971: }

unix.superglobalmegacorp.com

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