|
|
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: * This private function gathers some of the aspects of streams message memory ! 49: * allocation into a single place (message blocks are allocated in allocb (), ! 50: * dupb (), and esballoc ()). We leave the initialization of the newly ! 51: * allocated memory up to the caller. ! 52: */ ! 53: ! 54: #if __USE_PROTO__ ! 55: mblk_t * (STRMEM_ALLOC) (size_t size, int pri, int flag) ! 56: #else ! 57: mblk_t * ! 58: STRMEM_ALLOC __ARGS ((size, pri, flag)) ! 59: size_t size; ! 60: int pri; ! 61: int flag; ! 62: #endif ! 63: { ! 64: pl_t prev_pl; ! 65: mblk_t * mblkp; ! 66: ! 67: ASSERT (size > 0); ! 68: ASSERT (flag == KM_SLEEP || flag == KM_NOSLEEP); ! 69: ! 70: /* ! 71: * Note that if the size is one such that it cannot possibly ever be ! 72: * satisfied given the allocation watermarks we have set, then we just ! 73: * return failure now. ! 74: */ ! 75: ! 76: pri = MAP_PRI_LEVEL (pri); ! 77: ! 78: if (size > str_mem->sm_max [pri]) ! 79: return NULL; ! 80: ! 81: ! 82: for (;;) { ! 83: /* ! 84: * Lock the basic lock protecting access to the memory pool ! 85: * and attempt to acquire the memory we desire. ! 86: */ ! 87: ! 88: prev_pl = LOCK (str_mem->sm_msg_lock, str_msg_pl); ! 89: ! 90: ! 91: /* ! 92: * Before allocating any memory, we check to see that it makes ! 93: * sense to give out that memory to the given priority level. ! 94: */ ! 95: ! 96: if (str_mem->sm_used + size <= str_mem->sm_max [pri]) { ! 97: /* ! 98: * Try to get the memory, and if we do update the ! 99: * priority bookkeeping information to record the ! 100: * amount of memory that we have allowed out. ! 101: */ ! 102: ! 103: mblkp = (mblk_t *) st_alloc (str_mem->sm_msg_heap, ! 104: size); ! 105: ! 106: if (mblkp != NULL) { ! 107: ! 108: str_mem->sm_used += size; ! 109: break; ! 110: } ! 111: } ! 112: ! 113: ! 114: /* ! 115: * Depending on the caller, we may sleep waiting for memory ! 116: * to become available. ! 117: */ ! 118: ! 119: if (flag == KM_NOSLEEP) { ! 120: ! 121: mblkp = NULL; ! 122: break; ! 123: } ! 124: ! 125: ! 126: /* ! 127: * RESEARCH NOTE: This policy is a guess, no more. We need to ! 128: * do some profiling to find out what effect other policies ! 129: * might have. In particular, the wakeup heuristic could be ! 130: * altered to broadcast when we can satisfy the largest ! 131: * request. ! 132: */ ! 133: ! 134: if (str_mem->sm_msg_needed == 0 || ! 135: str_mem->sm_msg_needed > size) ! 136: str_mem->sm_msg_needed = size; ! 137: ! 138: SV_WAIT (str_mem->sm_msg_sv, prilo, str_mem->sm_msg_lock); ! 139: } ! 140: ! 141: UNLOCK (str_mem->sm_msg_lock, prev_pl); ! 142: ! 143: return mblkp; ! 144: } ! 145: ! 146: ! 147: /* ! 148: * This simple function factors out some common code from different calls to ! 149: * st_free () inside freeb (). This just reduces some of the cost of all the ! 150: * error checking that is my custom, and consolidates the interface to the ! 151: * bookkeeping for callback events and so forth. ! 152: * ! 153: * The streams heap must be locked on entry to this function. ! 154: */ ! 155: ! 156: #if __USE_PROTO__ ! 157: void (STRMEM_FREE) (mblk_t * bp, size_t size) ! 158: #else ! 159: void ! 160: STRMEM_FREE __ARGS ((bp, size)) ! 161: mblk_t * bp; ! 162: size_t size; ! 163: #endif ! 164: { ! 165: int free_ok; ! 166: ! 167: ASSERT (TRYLOCK (str_mem->sm_msg_lock, str_msg_pl) == invpl); ! 168: ! 169: free_ok = st_free (str_mem->sm_msg_heap, bp, size); ! 170: ! 171: if (free_ok != 0) { ! 172: /* ! 173: * The heap manager has a problem with freeing the block that ! 174: * was passed to it, display a console diagnostic. For ! 175: * simplicity we display addresses as longs. ! 176: */ ! 177: ! 178: cmn_err (CE_WARN, ! 179: "MSGB_FREE : st_free () complained with %d freeing %d bytes at %lx", ! 180: free_ok, size, (long) bp); ! 181: } else { ! 182: /* ! 183: * Update the allocation bookkeeping, and request that the ! 184: * routine that processes bufcall () events be run. This other ! 185: * procedure also has responsibility for waking up message and ! 186: * possibly "other" allocations if there is sufficient memory ! 187: * available. ! 188: */ ! 189: ! 190: str_mem->sm_used -= size; ! 191: ! 192: SCHEDULE_BUFCALLS (); ! 193: } ! 194: } ! 195:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.