Annotation of sys/dev/raidframe/rf_memchunk.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rf_memchunk.c,v 1.4 2002/12/16 07:01:04 tdeval Exp $ */
2: /* $NetBSD: rf_memchunk.c,v 1.4 1999/08/13 03:41:56 oster Exp $ */
3: /*
4: * Copyright (c) 1995 Carnegie-Mellon University.
5: * All rights reserved.
6: *
7: * Author: Mark Holland
8: *
9: * Permission to use, copy, modify and distribute this software and
10: * its documentation is hereby granted, provided that both the copyright
11: * notice and this permission notice appear in all copies of the
12: * software, derivative works or modified versions, and any portions
13: * thereof, and that both notices appear in supporting documentation.
14: *
15: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie the
27: * rights to redistribute these changes.
28: */
29:
30: /*********************************************************************************
31: * rf_memchunk.c
32: *
33: * experimental code. I've found that the malloc and free calls in the DAG
34: * creation code are very expensive. Since for any given workload the DAGs
35: * created for different accesses are likely to be similar to each other, the
36: * amount of memory used for any given DAG data structure is likely to be one
37: * of a small number of values. For example, in UNIX, all reads and writes will
38: * be less than 8k and will not span stripe unit boundaries. Thus in the absence
39: * of failure, the only DAGs that will ever get created are single-node reads
40: * and single-stripe-unit atomic read-modify-writes. So, I'm very likely to
41: * be continually asking for chunks of memory equal to the sizes of these two
42: * DAGs.
43: *
44: * This leads to the idea of holding on to these chunks of memory when the DAG is
45: * freed and then, when a new DAG is created, trying to find such a chunk before
46: * calling malloc.
47: *
48: * the "chunk list" is a list of lists. Each header node contains a size value
49: * and a pointer to a list of chunk descriptors, each of which holds a pointer
50: * to a chunk of memory of the indicated size.
51: *
52: * There is currently no way to purge memory out of the chunk list. My
53: * initial thought on this is to have a low-priority thread that wakes up every
54: * 1 or 2 seconds, purges all the chunks with low reuse counts, and sets all
55: * the reuse counts to zero.
56: *
57: * This whole idea may be bad, since malloc may be able to do this more efficiently.
58: * It's worth a try, though, and it can be turned off by setting useMemChunks to 0.
59: *
60: ********************************************************************************/
61:
62: #include "rf_types.h"
63: #include "rf_threadstuff.h"
64: #include "rf_debugMem.h"
65: #include "rf_memchunk.h"
66: #include "rf_general.h"
67: #include "rf_options.h"
68: #include "rf_shutdown.h"
69:
70: typedef struct RF_ChunkHdr_s RF_ChunkHdr_t;
71: struct RF_ChunkHdr_s {
72: int size;
73: RF_ChunkDesc_t *list;
74: RF_ChunkHdr_t *next;
75: };
76:
77: static RF_ChunkHdr_t *chunklist, *chunk_hdr_free_list;
78: static RF_ChunkDesc_t *chunk_desc_free_list;
79: RF_DECLARE_STATIC_MUTEX(chunkmutex);
80: void rf_ShutdownMemChunk(void *);
81: RF_ChunkDesc_t *rf_NewMemChunk(int, char *);
82:
83:
84: void rf_ShutdownMemChunk(ignored)
85: void *ignored;
86: {
87: RF_ChunkDesc_t *pt, *p;
88: RF_ChunkHdr_t *hdr, *ht;
89:
90: if (rf_memChunkDebug)
91: printf("Chunklist:\n");
92: for (hdr = chunklist; hdr;) {
93: for (p = hdr->list; p;) {
94: if (rf_memChunkDebug)
95: printf("Size %d reuse count %d\n", p->size, p->reuse_count);
96: pt = p;
97: p = p->next;
98: RF_Free(pt->buf, pt->size);
99: RF_Free(pt, sizeof(*pt));
100: }
101: ht = hdr;
102: hdr = hdr->next;
103: RF_Free(ht, sizeof(*ht));
104: }
105:
106: rf_mutex_destroy(&chunkmutex);
107: }
108:
109: int
110: rf_ConfigureMemChunk(listp)
111: RF_ShutdownList_t **listp;
112: {
113: int rc;
114:
115: chunklist = NULL;
116: chunk_hdr_free_list = NULL;
117: chunk_desc_free_list = NULL;
118: rc = rf_mutex_init(&chunkmutex);
119: if (rc) {
120: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
121: __LINE__, rc);
122: }
123: rc = rf_ShutdownCreate(listp, rf_ShutdownMemChunk, NULL);
124: if (rc) {
125: RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n", __FILE__,
126: __LINE__, rc);
127: rf_mutex_destroy(&chunkmutex);
128: }
129: return (rc);
130: }
131: /* called to get a chunk descriptor for a newly-allocated chunk of memory
132: * MUTEX MUST BE LOCKED
133: *
134: * free list is not currently used
135: */
136: RF_ChunkDesc_t *
137: rf_NewMemChunk(size, buf)
138: int size;
139: char *buf;
140: {
141: RF_ChunkDesc_t *p;
142:
143: if (chunk_desc_free_list) {
144: p = chunk_desc_free_list;
145: chunk_desc_free_list = p->next;
146: } else
147: RF_Malloc(p, sizeof(RF_ChunkDesc_t), (RF_ChunkDesc_t *));
148: p->size = size;
149: p->buf = buf;
150: p->next = NULL;
151: p->reuse_count = 0;
152: return (p);
153: }
154: /* looks for a chunk of memory of acceptable size. If none, allocates one and returns
155: * a chunk descriptor for it, but does not install anything in the list. This is done
156: * when the chunk is released.
157: */
158: RF_ChunkDesc_t *
159: rf_GetMemChunk(size)
160: int size;
161: {
162: RF_ChunkHdr_t *hdr = chunklist;
163: RF_ChunkDesc_t *p = NULL;
164: char *buf;
165:
166: RF_LOCK_MUTEX(chunkmutex);
167: for (hdr = chunklist; hdr; hdr = hdr->next)
168: if (hdr->size >= size) {
169: p = hdr->list;
170: if (p) {
171: hdr->list = p->next;
172: p->next = NULL;
173: p->reuse_count++;
174: }
175: break;
176: }
177: if (!p) {
178: RF_Malloc(buf, size, (char *));
179: p = rf_NewMemChunk(size, buf);
180: }
181: RF_UNLOCK_MUTEX(chunkmutex);
182: (void) bzero(p->buf, size);
183: return (p);
184: }
185:
186: void
187: rf_ReleaseMemChunk(chunk)
188: RF_ChunkDesc_t *chunk;
189: {
190: RF_ChunkHdr_t *hdr, *ht = NULL, *new;
191:
192: RF_LOCK_MUTEX(chunkmutex);
193: for (hdr = chunklist; hdr && hdr->size < chunk->size; ht = hdr, hdr = hdr->next);
194: if (hdr && hdr->size == chunk->size) {
195: chunk->next = hdr->list;
196: hdr->list = chunk;
197: } else {
198: RF_Malloc(new, sizeof(RF_ChunkHdr_t), (RF_ChunkHdr_t *));
199: new->size = chunk->size;
200: new->list = chunk;
201: chunk->next = NULL;
202: if (ht) {
203: new->next = ht->next;
204: ht->next = new;
205: } else {
206: new->next = hdr;
207: chunklist = new;
208: }
209: }
210: RF_UNLOCK_MUTEX(chunkmutex);
211: }
CVSweb