|
|
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.