[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     ! 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