00001
00002
00003
00004
00005
00006
00007 #include <compiler.h>
00008 #include <stdint.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <mpool.h>
00012
00013 #if MPOOL_POISON
00014 #define POISON(ptr, len) memset(ptr, MPOOL_POISON_PATTERN, len)
00015 #else
00016 #define POISON(ptr, len) do { } while(0);
00017 #endif
00018
00022 struct _mpool {
00024 size_t obj_size;
00026 size_t slab_size;
00028 struct _mpool_hdr *slabs;
00030 void *free;
00031 };
00032
00036 struct _mpool_hdr {
00038 struct _mpool_hdr *next;
00040 void *next_obj;
00042 uint8_t data[0];
00043 };
00044
00058 mpool_t mpool_new(size_t obj_size, unsigned slab_size)
00059 {
00060 struct _mpool *m;
00061
00062
00063 if ( obj_size == 0 )
00064 return NULL;
00065
00066 m = malloc(sizeof(*m));
00067 if ( NULL == m )
00068 return NULL;
00069
00070 if ( obj_size < sizeof(void *) )
00071 obj_size = sizeof(void *);
00072
00073 m->obj_size = obj_size;
00074
00075 if ( slab_size ) {
00076 m->slab_size = sizeof(struct _mpool_hdr) +
00077 (slab_size * obj_size);
00078 }else{
00079
00080 if ( m->obj_size < 8192 ) {
00081 m->slab_size = sizeof(struct _mpool_hdr) +
00082 (8192 - (8192 % m->obj_size));
00083 }else{
00084 m->slab_size = sizeof(struct _mpool_hdr) +
00085 (4 * m->obj_size);
00086 }
00087 }
00088
00089 m->slabs = NULL;
00090 m->free = NULL;
00091
00092 return m;
00093 }
00094
00105 static void *mpool_alloc_slow(struct _mpool *m)
00106 {
00107 struct _mpool_hdr *h;
00108 void *ptr, *ret;
00109
00110 h = ptr = malloc(m->slab_size);
00111 if ( h == NULL )
00112 return NULL;
00113
00114 POISON(ptr, m->slab_size);
00115
00116
00117 ret = ptr + sizeof(*h);
00118 h->next_obj = ret + m->obj_size;
00119
00120
00121 h->next = m->slabs;
00122 m->slabs = h;
00123
00124 return ret;
00125 }
00126
00136 void *mpool_alloc(mpool_t m)
00137 {
00138
00139 if ( unlikely(m->free) ) {
00140 void *ret = m->free;
00141 m->free = *(void **)m->free;
00142 return ret;
00143 }
00144
00145
00146 if ( m->slabs != NULL ) {
00147 void *ret = m->slabs->next_obj;
00148 m->slabs->next_obj += m->obj_size;
00149
00150 if ( m->slabs->next_obj <= ((void *)m->slabs) + m->slab_size )
00151 return ret;
00152 }
00153
00154
00155 return mpool_alloc_slow(m);
00156 }
00157
00165 void mpool_free(mpool_t m)
00166 {
00167 struct _mpool_hdr *h, *f;
00168
00169 if ( NULL == m )
00170 return;
00171
00172 for(h = m->slabs; (f = h); free(f)) {
00173 h = h->next;
00174 POISON(f, m->slab_size);
00175 }
00176
00177 POISON(m, sizeof(*m));
00178 free(m);
00179 }
00180
00190 void mpool_return(mpool_t m, void *obj)
00191 {
00192 if ( unlikely(obj == NULL) )
00193 return;
00194 if ( unlikely(m->obj_size < sizeof(void *)) )
00195 return;
00196 POISON(obj, m->obj_size);
00197 *(void **)obj = m->free;
00198 m->free = obj;
00199 }
00200
00211 void *mpool_alloc0(mpool_t m)
00212 {
00213 void *ret;
00214
00215 ret = mpool_alloc(m);
00216 if ( ret )
00217 memset(ret, 0, m->obj_size);
00218
00219 return ret;
00220 }