Annotation of coherent/b/STREAMS/conf_79/streams/kmem.c, revision 1.1

1.1     ! root        1: #define        _DDI_DKI        1
        !             2: #define        _SYSV4          1
        !             3: 
        !             4: /*
        !             5:  * STREAMS memory management code.
        !             6:  *
        !             7:  * This is layered on top of the fast first-fit heap allocator whose
        !             8:  * implementation is described in <sys/st_alloc.h>. The particulars of how
        !             9:  * STREAMS memory is allocated (including synchronisation and watermarks)
        !            10:  * is kept here so that the generic allocator is just that, generic.
        !            11:  */
        !            12: 
        !            13: /*
        !            14:  *-IMPORTS:
        !            15:  *     <common/ccompat.h>
        !            16:  *             __USE_PROTO__
        !            17:  *             __ARGS ()
        !            18:  *     <common/ccompat.h>
        !            19:  *             __LOCAL__
        !            20:  *     <sys/debug.h>
        !            21:  *             ASSERT ()
        !            22:  *     <sys/types.h>
        !            23:  *             _VOID
        !            24:  *             size_t
        !            25:  *     <sys/ksynch.h>
        !            26:  *             lock_t
        !            27:  *             LOCK_ALLOC ()
        !            28:  *             LOCK ()
        !            29:  *             UNLOCK ()
        !            30:  *     <sys/cmn_err.h>
        !            31:  *             CE_WARN
        !            32:  *             cmn_err ()
        !            33:  */
        !            34: 
        !            35: #include <common/ccompat.h>
        !            36: #include <kernel/ddi_lock.h>
        !            37: #include <sys/types.h>
        !            38: #include <sys/debug.h>
        !            39: #include <sys/ksynch.h>
        !            40: #include <sys/cmn_err.h>
        !            41: 
        !            42: #include <sys/kmem.h>
        !            43: #include <kernel/strmlib.h>
        !            44: #include <string.h>
        !            45: 
        !            46: 
        !            47: /*
        !            48:  * Number of segments in the streams memory heap.
        !            49:  *
        !            50:  * For now, we'll just specify 256 segments, but this should probably be based
        !            51:  * on the log of the total number of words available.
        !            52:  */
        !            53: 
        !            54: enum { str_segments = 256 };
        !            55: 
        !            56: 
        !            57: /*
        !            58:  * Here we'll define the actual instance of the streams memory control
        !            59:  * structure.
        !            60:  */
        !            61: 
        !            62: struct streams_mem str_mem [1];
        !            63: 
        !            64: 
        !            65: /*
        !            66:  * We need to define information structures for the various locks and
        !            67:  * synchronization variables used in the above.
        !            68:  */
        !            69: 
        !            70: __LOCAL__ lkinfo_t _stream_heap_lkinfo = {
        !            71:        "STREAMS message memory lock", INTERNAL_LOCK
        !            72: };
        !            73: 
        !            74: __LOCAL__ lkinfo_t _stream_seq_lkinfo = {
        !            75:        "STREAMS log sequence-number lock", INTERNAL_LOCK
        !            76: };
        !            77: 
        !            78: __LOCAL__ lkinfo_t _stream_proc_lkinfo = {
        !            79:        "STREAMS qprocsoff () lock", INTERNAL_LOCK
        !            80: };
        !            81: 
        !            82: __LOCAL__ lkinfo_t _stream_dir_lkinfo = {
        !            83:        "STREAM directory read/write lock", INTERNAL_LOCK
        !            84: };
        !            85: 
        !            86: 
        !            87: /*
        !            88:  * This local function gathers some of the aspects of streams message memory
        !            89:  * allocation into a single place (message blocks are allocated in allocb (),
        !            90:  * dupb (), and esballoc ()). We leave the initialization of the newly
        !            91:  * allocated memory up to the caller.
        !            92:  */
        !            93: 
        !            94: #if    __USE_PROTO__
        !            95: mblk_t * (STRMEM_ALLOC) (size_t size, int pri, int flag)
        !            96: #else
        !            97: mblk_t *
        !            98: STRMEM_ALLOC __ARGS ((size, pri, flag))
        !            99: size_t         size;
        !           100: int            pri;
        !           101: int            flag;
        !           102: #endif
        !           103: {
        !           104:        pl_t            prev_pl;
        !           105:        mblk_t        * mblkp;
        !           106: 
        !           107:        ASSERT (size > 0);
        !           108:        ASSERT (flag == KM_SLEEP || flag == KM_NOSLEEP);
        !           109: 
        !           110:        /*
        !           111:         * Note that if the size is one such that it cannot possibly ever be
        !           112:         * satisfied given the allocation watermarks we have set, then we just
        !           113:         * return failure now.
        !           114:         */
        !           115: 
        !           116:        pri = MAP_PRI_LEVEL (pri);
        !           117: 
        !           118:        if (size > str_mem->sm_max [pri])
        !           119:                return NULL;
        !           120: 
        !           121: 
        !           122:        for (;;) {
        !           123:                /*
        !           124:                 * Lock the basic lock protecting access to the memory pool
        !           125:                 * and attempt to acquire the memory we desire.
        !           126:                 */
        !           127: 
        !           128:                prev_pl = LOCK (str_mem->sm_msg_lock, str_msg_pl);
        !           129: 
        !           130: 
        !           131:                /*
        !           132:                 * Before allocating any memory, we check to see that it makes
        !           133:                 * sense to give out that memory to the given priority level.
        !           134:                 */
        !           135: 
        !           136:                if (str_mem->sm_used + size <= str_mem->sm_max [pri]) {
        !           137:                        /*
        !           138:                         * Try to get the memory, and if we do update the
        !           139:                         * priority bookkeeping information to record the
        !           140:                         * amount of memory that we have allowed out.
        !           141:                         */
        !           142: 
        !           143:                        mblkp = (mblk_t *) st_alloc (str_mem->sm_msg_heap,
        !           144:                                                     size);
        !           145: 
        !           146:                        if (mblkp != NULL) {
        !           147: 
        !           148:                                str_mem->sm_used += size;
        !           149:                                break;
        !           150:                        }
        !           151:                }
        !           152: 
        !           153: 
        !           154:                /*
        !           155:                 * Depending on the caller, we may sleep waiting for memory
        !           156:                 * to become available.
        !           157:                 */
        !           158: 
        !           159:                if (flag == KM_NOSLEEP) {
        !           160: 
        !           161:                        mblkp = NULL;
        !           162:                        break;
        !           163:                }
        !           164: 
        !           165: 
        !           166:                /*
        !           167:                 * RESEARCH NOTE: This policy is a guess, no more. We need to
        !           168:                 * do some profiling to find out what effect other policies
        !           169:                 * might have. In particular, the wakeup heuristic could be
        !           170:                 * altered to broadcast when we can satisfy the largest
        !           171:                 * request.
        !           172:                 */
        !           173: 
        !           174:                if (str_mem->sm_msg_needed == 0 ||
        !           175:                    str_mem->sm_msg_needed > size)
        !           176:                        str_mem->sm_msg_needed = size;
        !           177: 
        !           178:                SV_WAIT (str_mem->sm_msg_sv, prilo, str_mem->sm_msg_lock);
        !           179:        }
        !           180: 
        !           181:        UNLOCK (str_mem->sm_msg_lock, prev_pl);
        !           182: 
        !           183:        return mblkp;
        !           184: }
        !           185: 
        !           186: 
        !           187: /*
        !           188:  * This simple function factors out some common code from different calls to
        !           189:  * st_free () inside freeb (). This just reduces some of the cost of all the
        !           190:  * error checking that is my custom, and consolidates the interface to the
        !           191:  * bookkeeping for callback events and so forth.
        !           192:  *
        !           193:  * The streams heap must be locked on entry to this function.
        !           194:  */
        !           195: 
        !           196: #if    __USE_PROTO__
        !           197: void (STRMEM_FREE) (mblk_t * bp, size_t size)
        !           198: #else
        !           199: void
        !           200: STRMEM_FREE __ARGS ((bp, size))
        !           201: mblk_t       * bp;
        !           202: size_t         size;
        !           203: #endif
        !           204: {
        !           205:        int             free_ok;
        !           206: 
        !           207:        ASSERT (TRYLOCK (str_mem->sm_msg_lock, str_msg_pl) == invpl);
        !           208: 
        !           209:        free_ok = st_free (str_mem->sm_msg_heap, bp, size);
        !           210: 
        !           211:        if (free_ok != 0) {
        !           212:                /*
        !           213:                 * The heap manager has a problem with freeing the block that
        !           214:                 * was passed to it, display a console diagnostic. For
        !           215:                 * simplicity we display addresses as longs.
        !           216:                 */
        !           217: 
        !           218:                cmn_err (CE_WARN,
        !           219:                         "MSGB_FREE : st_free () complained with %d freeing %d bytes at %lx",
        !           220:                         free_ok, size, (long) bp);
        !           221:        } else {
        !           222:                /*
        !           223:                 * Update the allocation bookkeeping, and request that the
        !           224:                 * routine that processes bufcall () events be run. This other
        !           225:                 * procedure also has responsibility for waking up message and
        !           226:                 * possibly "other" allocations if there is sufficient memory
        !           227:                 * available.
        !           228:                 */
        !           229: 
        !           230:                str_mem->sm_used -= size;
        !           231: 
        !           232:                SCHEDULE_BUFCALLS ();
        !           233:        }
        !           234: }
        !           235: 
        !           236: 
        !           237: /*
        !           238:  *-STATUS:
        !           239:  *     DDI/DKI
        !           240:  *
        !           241:  *-NAME:
        !           242:  *     kmem_alloc ()   Allocate space from kernel free memory.
        !           243:  *
        !           244:  *-SYNOPSIS:
        !           245:  *     #include <sys/types.h>
        !           246:  *     #include <sys/kmem.h>
        !           247:  *
        !           248:  *     void * kmem_alloc (size_t size, int flag);
        !           249:  *
        !           250:  *-ARGUMENTS:
        !           251:  *     size            Number of bytes to allocate.
        !           252:  *
        !           253:  *     flag            Specifies whether the caller is willing to sleep
        !           254:  *                     waiting for memory. If "flag" is set to KM_SLEEP, the
        !           255:  *                     caller will sleep if necessary until the specified
        !           256:  *                     amount of memory is available. If "flag" is set to
        !           257:  *                     KM_NOSLEEP, the caller will not sleep, but
        !           258:  *                     kmem_alloc () will return NULL if the specified amount
        !           259:  *                     of memory is not immediately available.
        !           260:  *
        !           261:  *-DESCRIPTION:
        !           262:  *     kmem_alloc () allocates "size" bytes of kernel memory and returns a
        !           263:  *     pointer to the allocated memory.
        !           264:  *
        !           265:  *-RETURN VALUE:
        !           266:  *     Upon successful completion, kmem_alloc () returns a pointer to the
        !           267:  *     allocated memory. If KM_NOSLEEP is specified and sufficient memory is
        !           268:  *     not immediately available, kmem_alloc () returns a NULL pointer. If
        !           269:  *     "size" is set to 0, kmem_alloc () always returns NULL regardless of
        !           270:  *     the value of "flag".
        !           271:  *
        !           272:  *-LEVEL:
        !           273:  *     Base only if "flag" is set to KM_SLEEP. Base or interrupt if "flag" is
        !           274:  *     set to KM_NOSLEEP.
        !           275:  *
        !           276:  *-NOTES:
        !           277:  *     May sleep if "flag" is set to KM_SLEEP.
        !           278:  *
        !           279:  *     Driver-defined basic locks and read/write locks may be held across
        !           280:  *     calls to this function if "flag" is KM_NOSLEEP but may not be held if
        !           281:  *     "flag" is KM_SLEEP.
        !           282:  *
        !           283:  *     Driver-defined sleep locks may be held across calls to this function
        !           284:  *     regardless of the value of "flag".
        !           285:  *
        !           286:  *     Kernel memory is a limited resource and should be used judiciously.
        !           287:  *     Memory allocated using kmem_alloc () should be freed as soon as
        !           288:  *     possible. Drivers should not use local freelists for memory or similar
        !           289:  *     schemes that cause the memory to be held for longer than necessary.
        !           290:  *
        !           291:  *     The address returned by a successful call to kmem_alloc () is word-
        !           292:  *     aligned.
        !           293:  *
        !           294:  *-SEE ALSO:
        !           295:  *     kmem_free (), kmem_zalloc ()
        !           296:  */
        !           297: 
        !           298: #if    __USE_PROTO__
        !           299: _VOID * (kmem_alloc) (size_t size, int flag)
        !           300: #else
        !           301: _VOID *
        !           302: kmem_alloc __ARGS ((size, flag))
        !           303: size_t         size;
        !           304: int            flag;
        !           305: #endif
        !           306: {
        !           307:        _VOID         * mem;
        !           308:        pl_t            prev_pl;
        !           309: 
        !           310:        ASSERT (flag == KM_SLEEP || flag == KM_NOSLEEP);
        !           311: 
        !           312:        ASSERT (ATOMIC_FETCH_UCHAR (str_mem->sm_init) ||
        !           313:                str_mem->sm_other_lock != NULL);
        !           314: 
        !           315:        if (size == 0)
        !           316:                return NULL;
        !           317: 
        !           318:        for (;;) {
        !           319:                /*
        !           320:                 * Lock the basic lock protecting access to the memory pool
        !           321:                 * and attempt to acquire the memory we desire.
        !           322:                 */
        !           323: 
        !           324:                if (str_mem->sm_other_lock != NULL)
        !           325:                        prev_pl = LOCK (str_mem->sm_other_lock, str_other_pl);
        !           326: 
        !           327:                if ((mem = st_alloc (str_mem->sm_other_heap, size)) != NULL ||
        !           328:                    flag == KM_NOSLEEP) {
        !           329:                        OTHER_ALLOCED (size);
        !           330:                        break;
        !           331:                }
        !           332: 
        !           333:                /*
        !           334:                 * Since we cannot acquire the memory, but the caller is
        !           335:                 * willing to wait, we wait on a synchronization variable
        !           336:                 * for sufficient memory to be available. We record the
        !           337:                 * minimum amount that will satisfy any outstanding wait so
        !           338:                 * that kmem_free () need not perform broadcasts in a
        !           339:                 * totally needless fashion.
        !           340:                 *
        !           341:                 * We have arbitrarily chosen a low scheduling priority for
        !           342:                 * SV_WAIT ().
        !           343:                 */
        !           344:                /*
        !           345:                 * RESEARCH NOTE: This policy is a guess, no more. We need to
        !           346:                 * do some profiling to find out what effect other policies
        !           347:                 * might have. In particular, the wakeup heuristic could be
        !           348:                 * altered to broadcast when we can satisfy the largest
        !           349:                 * request.
        !           350:                 */
        !           351: 
        !           352:                if (str_mem->sm_other_needed == 0 ||
        !           353:                    str_mem->sm_other_needed > size)
        !           354:                        str_mem->sm_other_needed = size;
        !           355: 
        !           356:                SV_WAIT (str_mem->sm_other_sv, prilo, str_mem->sm_other_lock);
        !           357:        }
        !           358: 
        !           359:        if (str_mem->sm_other_lock != NULL)
        !           360:                UNLOCK (str_mem->sm_other_lock, prev_pl);
        !           361: 
        !           362:        return mem;
        !           363: }
        !           364: 
        !           365: 
        !           366: 
        !           367: /*
        !           368:  *-STATUS:
        !           369:  *     DDI/DKI
        !           370:  *
        !           371:  *-NAME:
        !           372:  *     kmem_free ()    Free previously allocated kernel memory.
        !           373:  *
        !           374:  *-SYNOPSIS:
        !           375:  *     #include <sys/types.h>
        !           376:  *     #include <sys/kmem.h>
        !           377:  *
        !           378:  *     void kmem_free (void * addr, size_t size);
        !           379:  *
        !           380:  *-ARGUMENTS:
        !           381:  *     addr            Address of the allocated memory to be returned. "addr"
        !           382:  *                     must specify the same address that was returned by the
        !           383:  *                     corresponding call to kmem_alloc () or kmem_zalloc ()
        !           384:  *                     which allocated the memory.
        !           385:  *
        !           386:  *     size            Number of bytes to free. The "size" parameter must
        !           387:  *                     specify the same number of bytes as was allocated by
        !           388:  *                     the corresponding call to kmem_alloc () or\
        !           389:  *                     kmem_zalloc ().
        !           390:  *
        !           391:  *-DESCRIPTION:
        !           392:  *     kmem_free () returns "size" bytes of previously allocated kernel
        !           393:  *     memory to the free pool. The "addr" and "size" arguments must specify
        !           394:  *     exactly one complete area of memory that was allocated by a call to
        !           395:  *     kmem_alloc () or kmem_zalloc () (that is, the memory cannot be freed
        !           396:  *     piecemeal).
        !           397:  *
        !           398:  *-RETURN VALUE:
        !           399:  *     None.
        !           400:  *
        !           401:  *-LEVEL:
        !           402:  *     Base or Interrupt.
        !           403:  *
        !           404:  *-NOTES:
        !           405:  *     Does not sleep.
        !           406:  *
        !           407:  *     Driver-defined basic locks, read/write locks and sleep locks may be
        !           408:  *     held across calls to this function.
        !           409:  *
        !           410:  *-SEE ALSO:
        !           411:  *     kmem_alloc (), kmem_zalloc ()
        !           412:  */
        !           413: 
        !           414: #if    __USE_PROTO__
        !           415: void (kmem_free) (_VOID * addr, size_t size)
        !           416: #else
        !           417: void
        !           418: kmem_free __ARGS ((addr, size))
        !           419: _VOID        * addr;
        !           420: size_t         size;
        !           421: #endif
        !           422: {
        !           423:        pl_t            prev_pl;
        !           424:        int             free_ok;
        !           425: 
        !           426:        ASSERT (addr != NULL);
        !           427:        ASSERT (size > 0);
        !           428: 
        !           429:        ASSERT (ATOMIC_FETCH_UCHAR (str_mem->sm_init) ||
        !           430:                str_mem->sm_other_lock != NULL);
        !           431: 
        !           432:        /*
        !           433:         * Acquire the basic lock protecting access to the memory and free
        !           434:         * the caller's area. If there are processes waiting on memory
        !           435:         * becoming available, wake them up via a synchronization variable
        !           436:         * broadcast.
        !           437:         */
        !           438: 
        !           439:        if (str_mem->sm_other_lock != NULL)
        !           440:                prev_pl = LOCK (str_mem->sm_other_lock, str_other_pl);
        !           441: 
        !           442:        OTHER_FREED (size);
        !           443: 
        !           444:        free_ok = st_free (str_mem->sm_other_heap, addr, size);
        !           445: 
        !           446:        if (str_mem->sm_other_needed > 0 &&
        !           447:            str_mem->sm_other_needed <= st_maxavail (str_mem->sm_other_heap)) {
        !           448:                /*
        !           449:                 * Wake up *all* the waiting processes and clear the marker
        !           450:                 * to indicate that there are no waiting processes.
        !           451:                 */
        !           452: 
        !           453:                SV_BROADCAST (str_mem->sm_other_sv, 0);
        !           454:                str_mem->sm_other_needed = 0;
        !           455:        }
        !           456: 
        !           457:        if (str_mem->sm_other_lock != NULL)
        !           458:                UNLOCK (str_mem->sm_other_lock, prev_pl);
        !           459: 
        !           460:        if (free_ok != 0) {
        !           461:                /*
        !           462:                 * The heap manager has a problem with freeing the block that
        !           463:                 * was passed to it, display a console diagnostic. For
        !           464:                 * simplicity we display addresses as longs.
        !           465:                 */
        !           466: 
        !           467:                cmn_err (CE_WARN,
        !           468:                         "kmem_free : st_free () complained with %d freeing %d bytes at %lx",
        !           469:                         free_ok, size, (long) addr);
        !           470:        }
        !           471: }
        !           472: 
        !           473: 
        !           474: 
        !           475: /*
        !           476:  *-STATUS:
        !           477:  *     DDI/DKI
        !           478:  *
        !           479:  *-NAME:
        !           480:  *     kmem_zalloc ()  Allocate and clear space from kernel free memory.
        !           481:  *
        !           482:  *-SYNOPSIS:
        !           483:  *     #include <sys/types.h>
        !           484:  *     #include <sys/kmem.h>
        !           485:  *
        !           486:  *     void * kmem_zalloc (size_t size, int flag);
        !           487:  *
        !           488:  *-ARGUMENTS:
        !           489:  *     size            Number of bytes to allocate.
        !           490:  *
        !           491:  *     flag            Specifies whether the caller is willing to sleep
        !           492:  *                     waiting for memory. If "flag" is set to KM_SLEEP, the
        !           493:  *                     caller will sleep if necessary until the specified
        !           494:  *                     amount of memory is available. If "flag" is set to
        !           495:  *                     KM_NOSLEEP, the caller will not sleep, but
        !           496:  *                     kmem_zalloc () will return NULL if the specified
        !           497:  *                     amount of memory is not immediately available.
        !           498:  *
        !           499:  *-DESCRIPTION:
        !           500:  *     kmem_zalloc () allocates "size" bytes of kernel memory, clears the
        !           501:  *     memory by filling it with zeros, and returns a pointer to the
        !           502:  *     allocated memory.
        !           503:  *
        !           504:  *-RETURN VALUE:
        !           505:  *     Upon successful completion, kmem_zalloc () returns a pointer to the
        !           506:  *     allocated memory. If KM_NOSLEEP is specified and sufficient memory is
        !           507:  *     not immediately available, kmem_zalloc () returns a NULL pointer. If
        !           508:  *     "size" is set to 0, kmem_zalloc () always returns NULL regardless of
        !           509:  *     the value of "flag".
        !           510:  *
        !           511:  *-LEVEL:
        !           512:  *     Base only if "flag" is set to KM_SLEEP. Base or interrupt if "flag" is
        !           513:  *     set to KM_NOSLEEP.
        !           514:  *
        !           515:  *-NOTES:
        !           516:  *     May sleep if "flag" is set to KM_SLEEP.
        !           517:  *
        !           518:  *     Driver-defined basic locks and read/write locks may be held across
        !           519:  *     calls to this function if "flag" is KM_NOSLEEP but may not be held if
        !           520:  *     "flag" is KM_SLEEP.
        !           521:  *
        !           522:  *     Driver-defined sleep locks may be held across calls to this function
        !           523:  *     regardless of the value of "flag".
        !           524:  *
        !           525:  *     Kernel memory is a limited resource and should be used judiciously.
        !           526:  *     Memory allocated using kmem_zalloc () should be freed as soon as
        !           527:  *     possible. Drivers should not use local freelists for memory or similar
        !           528:  *     schemes that cause the memory to be held for longer than necessary.
        !           529:  *
        !           530:  *     The address returned by a successful call to kmem_zalloc () is word-
        !           531:  *     aligned.
        !           532:  *
        !           533:  *-SEE ALSO:
        !           534:  *     kmem_alloc (), kmem_free ()
        !           535:  */
        !           536: 
        !           537: #if    __USE_PROTO__
        !           538: _VOID * (kmem_zalloc) (size_t size, int flag)
        !           539: #else
        !           540: _VOID *
        !           541: kmem_zalloc __ARGS ((size, flag))
        !           542: size_t         size;
        !           543: int            flag;
        !           544: #endif
        !           545: {
        !           546:        _VOID         * mem;
        !           547: 
        !           548:        if ((mem = kmem_alloc (size, flag)) != NULL)
        !           549:                memset (mem, 0, size);
        !           550:        return mem;
        !           551: }
        !           552: 
        !           553: 
        !           554: /*
        !           555:  *-STATUS:
        !           556:  *     Initialisation
        !           557:  *
        !           558:  *-DESCRIPTION:
        !           559:  *     This function initializes the memory subsystem given a region of
        !           560:  *     kernel virtual memory space to manage.
        !           561:  */
        !           562: 
        !           563: __EXTERN_C__
        !           564: #if    __USE_PROTO__
        !           565: int (STRMEM_INIT) (_VOID * addr, size_t size)
        !           566: #else
        !           567: int
        !           568: STRMEM_INIT __ARGS ((addr, size))
        !           569: _VOID        * addr;
        !           570: size_t         size;
        !           571: #endif
        !           572: {
        !           573:        int             i;
        !           574: 
        !           575:        /*
        !           576:         * We use a test-and-set lock operation on the streams memory
        !           577:         * structure so that the initialisation process is multiprocessor-
        !           578:         * safe. We don't use a basic lock since we don't know whether basic
        !           579:         * locks exist yet.
        !           580:         */
        !           581: 
        !           582:        if (ATOMIC_TEST_AND_SET_UCHAR (str_mem->sm_init) != 0) {
        !           583:                /*
        !           584:                 * Presumably we are on a separate processor waiting for the
        !           585:                 * initialization to be completed by someone else. To make
        !           586:                 * this processor's call to STRMEM_INIT () behave with the
        !           587:                 * right semantics, we wait for the other instance to complete
        !           588:                 * the setup process.
        !           589:                 */
        !           590: 
        !           591:                while (ATOMIC_FETCH_UCHAR (str_mem->sm_init) != 0) {
        !           592: #ifdef __UNIPROCESSOR__
        !           593:                        cmn_err (CE_PANIC, "Init startup deadlock???");
        !           594: #endif
        !           595:                }
        !           596:                return 0;
        !           597:        }
        !           598: 
        !           599:        if (str_mem->sm_other_lock != NULL) {
        !           600:                /*
        !           601:                 * The init has already been done, thanks!
        !           602:                 */
        !           603: 
        !           604:                ATOMIC_CLEAR_UCHAR (str_mem->sm_init);
        !           605:                return 0;
        !           606:        }
        !           607: 
        !           608: #ifdef SPLIT_STREAMS_MEMORY
        !           609: #endif
        !           610: 
        !           611:        /*
        !           612:         * Now initialize the fast-first-fit heap manager.
        !           613:         *
        !           614:         * For now, we'll just specify 256 segments, but this
        !           615:         * should probably be based on the log of the total
        !           616:         * number of words available.
        !           617:         */
        !           618: 
        !           619:        str_mem->sm_msg_heap = (_ST_HEAP_CONTROL_P) addr;
        !           620: 
        !           621:        addr = (_VOID *) ((char *) addr +
        !           622:                          _ST_HEAP_CONTROL_SIZE (str_segments));
        !           623: 
        !           624:        size -= _ST_HEAP_CONTROL_SIZE (str_segments);
        !           625: 
        !           626:        st_ctor (str_mem->sm_msg_heap, str_segments,
        !           627:                 size / sizeof (_ST_WORD_T), (_ST_ADDR_T) addr);
        !           628: 
        !           629:        str_mem->sm_msg_lock =
        !           630:                        LOCK_ALLOC (stream_heap_hierarchy, str_other_pl,
        !           631:                                    & _stream_heap_lkinfo, KM_NOSLEEP);
        !           632: 
        !           633:        str_mem->sm_msg_sv = SV_ALLOC (KM_NOSLEEP);
        !           634: 
        !           635: 
        !           636:        /*
        !           637:         * If either of the above allocations failed, we have some kind of
        !           638:         * major problem, so we exit without unlocking the initialization flag
        !           639:         * with an error indication.
        !           640:         */
        !           641: 
        !           642:        if (str_mem->sm_msg_lock == NULL || str_mem->sm_msg_sv == NULL) {
        !           643: 
        !           644: init_error:
        !           645:                cmn_err (CE_PANIC, "Could not initialize STREAMS subsystem");
        !           646:                return -1;
        !           647:        }
        !           648: 
        !           649: 
        !           650:        /*
        !           651:         * Now we can calculate the watermarks... start at the
        !           652:         * top and make each lower one some percentage of the
        !           653:         * next higher one (say, 15/16 or 93%, so that it's
        !           654:         * easy to calculate).
        !           655:         */
        !           656: 
        !           657:        for (i = N_PRI_LEVELS ; i -- > 0 ;) {
        !           658: 
        !           659:                str_mem->sm_max [i] = size;
        !           660: 
        !           661:                size -= size >> 4;      /* - 1/16 */
        !           662:        }
        !           663: 
        !           664: 
        !           665:        /*
        !           666:         * Do other kinds of initialization for the "str_mem" structure.
        !           667:         */
        !           668: 
        !           669:        for (i = N_PRI_LEVELS ; i -- > 0 ; ) {
        !           670: 
        !           671:                if (SELIST_INIT (& str_mem->sm_bcevents [i],
        !           672:                                 KM_SLEEP) == NULL)
        !           673: 
        !           674:                        goto init_error;
        !           675:        }
        !           676: 
        !           677: 
        !           678:        str_mem->sm_seq_lock = LOCK_ALLOC (stream_seq_hierarchy, plstr,
        !           679:                                           & _stream_seq_lkinfo, KM_SLEEP);
        !           680: 
        !           681:        str_mem->sm_head_lock = RW_ALLOC (stream_dir_hierarchy, plstr,
        !           682:                                          & _stream_dir_lkinfo, KM_SLEEP);
        !           683: 
        !           684:        str_mem->sm_proc_lock = LOCK_ALLOC (stream_proc_hierarchy, plstr,
        !           685:                                            & _stream_proc_lkinfo, KM_SLEEP);
        !           686: 
        !           687:        str_mem->sm_proc_sv = SV_ALLOC (KM_SLEEP);
        !           688: 
        !           689:        if (SCHED_INIT (str_mem->sm_sched, KM_SLEEP) == NULL ||
        !           690:            str_mem->sm_seq_lock == NULL || str_mem->sm_head_lock == NULL ||
        !           691:            str_mem->sm_proc_lock == NULL || str_mem->sm_proc_sv == NULL)
        !           692:                goto init_error;
        !           693: 
        !           694:        /*
        !           695:         * All OK, let other CPUs proceed and return success to the caller.
        !           696:         */
        !           697: 
        !           698:        ATOMIC_CLEAR_UCHAR (str_mem->sm_init);
        !           699: 
        !           700:        return 0;               /* all OK */
        !           701: }

unix.superglobalmegacorp.com

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