Annotation of sys/dev/raidframe/rf_memchunk.c, Revision 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