/* $Id: mempool.c,v 10.1 92/10/06 23:10:35 ca Exp $ */ /*LINTLIBRARY*/ /* Storage manager for large quantities of objects that are going to be allocated and freed many times. It uses malloc() to get a largish chunk of memory, then doles pieces of the chunk out until it runs out, at which time it malloc()s another chunk. */ /** Functions include: mp_init() Initialize and return a Mempool structure mp_destroy() Destroy a mempool. mp_alloc() Allocate one of the objects from the pool mp_free() Free an object (return it to the free list) mp_free_all() Put all of the objects on the free list. mp_stat() Print out stats about the memory pool. */ #include #include "q.h" #include "mempool.h" extern char *sim_calloc(), *sim_malloc(); #define TRUE 1 #define FALSE 0 #ifdef MEMPOOL mp_more_mem(mp) register Mempool *mp; { register MemEnvelope *me, *p; register int i; /* get all the memory for this chunk of envelopes */ me = (MemEnvelope *)sim_calloc(mp->mp_how_many * mp->mp_envs_per_rec, sizeof(MemEnvelope)); q_addt(mp->mp_mem_chunks, (caddr_t)me); p = me; for (p = me, i = 0; i < mp->mp_how_many; i++, p += mp->mp_envs_per_rec) qe_addt(mp->mp_free, (caddr_t)p); return(TRUE); } #endif /* MEMPOOL */ Mempool * mp_init(how_many, data_size) int how_many, data_size; { Mempool *mp; mp = (Mempool *)sim_malloc(sizeof (Mempool)); mp->mp_data_size = data_size; mp->mp_how_many = how_many; #ifdef MEMPOOL /* Each record has room for one MemEnvelope + storage for date_size data (in an integral number of MemEnvelopes) */ mp->mp_envs_per_rec = data_size % sizeof(MemEnvelope) ? data_size / sizeof(MemEnvelope) + 2 : data_size / sizeof(MemEnvelope) + 1; mp->mp_free = q_create(); mp->mp_mem_chunks = q_create(); mp_more_mem(mp); /* Initialize q_min to q_max so that q_min will be meaningful later */ mp->mp_free->q_min = mp->mp_free->q_max; #endif /* MEMPOOL */ return(mp); } void mp_destroy(mp) register Mempool *mp; { #ifdef MEMPOOL register MemEnvelope *me; /* Free all of the large chunks of memory allocate in mp_more_mem, and also small amounts of memory used to store the mem_chunk pointers */ while (me = (MemEnvelope *)q_deq(mp->mp_mem_chunks)) { free((char *)me); } /* Free all the lists & queues in the Mempool structure */ free((char *)mp->mp_mem_chunks); free((char *)mp->mp_free); #endif /* MEMPOOL */ free((char *)mp); } /* Put these functions inline if using GCC--see mempool.h */ #ifndef INLINE caddr_t mp_alloc(mp) register Mempool *mp; { #ifdef MEMPOOL register MemEnvelope *me; me = (MemEnvelope *)qe_deq(mp->mp_free); if (!me) { mp_more_mem(mp); me = (MemEnvelope *)qe_deq(mp->mp_free); } /* Skip past header info to return memory */ return((caddr_t)(me + 1)); #else /* MEMPOOL */ return((caddr_t)sim_malloc(mp->mp_data_size)); #endif /* MEMPOOL */ } void mp_free(mp, p) register Mempool *mp; register char *p; { #ifdef MEMPOOL /* P is a pointer to the memory that had been mp_alloc()'ed. To get to the header info, just cast it to a MemEnvelope * and subtract 1 */ register MemEnvelope *me = ((MemEnvelope *)p) - 1; qe_addt(mp->mp_free, me); #else /* MEMPOOL */ free(p); #endif /* MEMPOOL */ } #endif /* not INLINE */ /* Return all of the objects to the free list */ void mp_free_all(mp) Mempool *mp; { #ifdef MEMPOOL register MemEnvelope *p; register q_elt *qe; register int i; /* Wipe out the free queue */ while (qe_deq(mp->mp_free)) ; /* Step through all of the currently allocated chunks of memory, adding all the objects to the free list. */ for (qe = mp->mp_mem_chunks->q_head; qe; qe = qe->qe_next) for (p = (MemEnvelope *)qe->qe_data, i = 0; i < mp->mp_how_many; p += mp->mp_envs_per_rec, i++) qe_addt(mp->mp_free, (caddr_t)p); #else /* MEMPOOL */ /* Can't do it if no pool */ return; #endif /* MEMPOOL */ } void mp_stat(mp) register Mempool *mp; { #ifdef MEMPOOL printf("Allocates chunks of %d (number) x %d (size) (total %d) bytes\n", mp->mp_how_many, mp->mp_envs_per_rec * sizeof(MemEnvelope), mp->mp_how_many * mp->mp_envs_per_rec * sizeof(MemEnvelope)); printf("Number of mallocs: %d\n", mp->mp_mem_chunks->q_len); printf("Free list size %d, min free list size %d\n", mp->mp_free->q_len, mp->mp_free->q_min); #endif /* MEMPOOL */ }