00001
00002
00003
00004
00005
00006 #include <compiler.h>
00007 #include <stdint.h>
00008 #include <string.h>
00009 #include <stdlib.h>
00010 #include <gang.h>
00011
00012 #if GANG_POISON
00013 #define POISON(ptr, len) memset(ptr, GANG_POISON_PATTERN, len)
00014 #else
00015 #define POISON(ptr, len) do { } while(0);
00016 #endif
00017
00018 struct _slab {
00019 struct _slab *s_next;
00020 uint8_t s_data[0];
00021 };
00022
00023 struct _gang {
00024 size_t g_align;
00025 size_t g_alloc;
00026 struct _slab *g_slab;
00027 uint8_t *g_ptr;
00028 };
00029
00030 gang_t gang_new(size_t alloc, size_t align)
00031 {
00032 struct _gang *g;
00033
00034 g = malloc(sizeof(*g));
00035 if ( NULL == g )
00036 return NULL;
00037
00038 g->g_align = align;
00039 g->g_alloc = (0 == alloc) ? GANG_DEFAULT_ALLOC : alloc;
00040 g->g_slab = NULL;
00041 g->g_ptr = NULL;
00042
00043 return g;
00044 }
00045
00046 static uint8_t *ptr_align(uint8_t *ptr, size_t sz)
00047 {
00048
00049 return ptr;
00050 }
00051
00052 static void *do_alloc_slow(struct _gang *g, size_t sz, size_t align)
00053 {
00054 struct _slab *s;
00055 uint8_t *ret;
00056
00057 s = malloc(g->g_alloc);
00058 if ( NULL == s )
00059 return NULL;
00060
00061 POISON(s, g->g_alloc);
00062
00063 ret = ptr_align(s->s_data, align);
00064 if ( ret + sz > (uint8_t *)s + g->g_alloc ) {
00065 free(s);
00066 return NULL;
00067 }
00068
00069 s->s_next = g->g_slab;
00070 g->g_slab = s;
00071 g->g_ptr = ret + sz;
00072
00073 return ret;
00074 }
00075
00076 static void *do_alloc(struct _gang *g, size_t sz, size_t align)
00077 {
00078 uint8_t *nxt;
00079
00080 if ( NULL == g->g_ptr )
00081 return do_alloc_slow(g, sz, align);
00082
00083 nxt = ptr_align(g->g_ptr, align);
00084 if ( nxt + sz >= (uint8_t *)g->g_slab + g->g_alloc )
00085 return do_alloc_slow(g, sz, align);
00086
00087 g->g_ptr += sz;
00088 return nxt;
00089 }
00090
00091 void *gang_alloc(gang_t g, size_t sz)
00092 {
00093 return do_alloc(g, sz, g->g_align);
00094 }
00095
00096 void *gang_alloc_a(gang_t g, size_t sz, size_t align)
00097 {
00098 return do_alloc(g, sz, align);
00099 }
00100
00101 void *gang_alloc0(gang_t g, size_t sz)
00102 {
00103 void *ret;
00104 ret = do_alloc(g, sz, g->g_align);
00105 if ( ret )
00106 memset(ret, 0, sz);
00107 return ret;
00108 }
00109
00110 void *gang_alloc0_a(gang_t g, size_t sz, size_t align)
00111 {
00112 void *ret;
00113 ret = do_alloc(g, sz, align);
00114 if ( ret )
00115 memset(ret, 0, sz);
00116 return ret;
00117 }
00118
00119 void gang_free(gang_t g)
00120 {
00121 struct _slab *s, *tmp;
00122
00123 if ( NULL == g )
00124 return;
00125
00126 for(s = g->g_slab; (tmp = s); free(tmp)) {
00127 s = s->s_next;
00128 POISON(tmp, g->g_alloc);
00129 }
00130
00131 POISON(g, sizeof(*g));
00132 free(g);
00133 }