[BACK]Return to rf_memchunk.c CVS log [TXT][DIR] Up to [local] / sys / dev / raidframe

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