root/dev/raidframe/rf_memchunk.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rf_ShutdownMemChunk
  2. rf_ConfigureMemChunk
  3. rf_NewMemChunk
  4. rf_GetMemChunk
  5. rf_ReleaseMemChunk

    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 }

/* [<][>][^][v][top][bottom][index][help] */