Annotation of coherent/b/STREAMS/conf_79/streams/kmem.c, revision 1.1.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.