00001
00002
00003
00004 #undef DEBUG
00005 #undef SLOWDEBUG
00006
00007 #ifndef DEBUG
00008 #define NDEBUG
00009 #endif
00010
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <errno.h>
00014 #include <assert.h>
00015
00016 #if _EM_WSIZE == _EM_PSIZE
00017 #define ptrint int
00018 #else
00019 #define ptrint long
00020 #endif
00021
00022 #if _EM_PSIZE == 2
00023 #define BRKSIZE 1024
00024 #else
00025 #define BRKSIZE 4096
00026 #endif
00027 #define PTRSIZE ((int) sizeof(void *))
00028 #define Align(x,a) (((x) + (a - 1)) & ~(a - 1))
00029 #define NextSlot(p) (* (void **) ((p) - PTRSIZE))
00030 #define NextFree(p) (* (void **) (p))
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 extern void *_sbrk(int);
00047 extern int _brk(void *);
00048 static void *_bottom, *_top, *_empty;
00049
00050 static int grow(size_t len)
00051 {
00052 register char *p;
00053
00054 assert(NextSlot((char *)_top) == 0);
00055 if ((char *) _top + len < (char *) _top
00056 || (p = (char *)Align((ptrint)_top + len, BRKSIZE)) < (char *) _top ) {
00057 errno = ENOMEM;
00058 return(0);
00059 }
00060 if (_brk(p) != 0)
00061 return(0);
00062 NextSlot((char *)_top) = p;
00063 NextSlot(p) = 0;
00064 free(_top);
00065 _top = p;
00066 return 1;
00067 }
00068
00069 void *
00070 malloc(size_t size)
00071 {
00072 register char *prev, *p, *next, *new;
00073 register unsigned len, ntries;
00074
00075 if (size == 0)
00076 return NULL;
00077
00078 for (ntries = 0; ntries < 2; ntries++) {
00079 if ((len = Align(size, PTRSIZE) + PTRSIZE) < 2 * PTRSIZE) {
00080 errno = ENOMEM;
00081 return NULL;
00082 }
00083 if (_bottom == 0) {
00084 if ((p = _sbrk(2 * PTRSIZE)) == (char *) -1)
00085 return NULL;
00086 p = (char *) Align((ptrint)p, PTRSIZE);
00087 p += PTRSIZE;
00088 _top = _bottom = p;
00089 NextSlot(p) = 0;
00090 }
00091 #ifdef SLOWDEBUG
00092 for (p = _bottom; (next = NextSlot(p)) != 0; p = next)
00093 assert(next > p);
00094 assert(p == _top);
00095 #endif
00096 for (prev = 0, p = _empty; p != 0; prev = p, p = NextFree(p)) {
00097 next = NextSlot(p);
00098 new = p + len;
00099 if (new > next || new <= p)
00100 continue;
00101 if (new + PTRSIZE < next) {
00102
00103 NextSlot(new) = next;
00104 NextSlot(p) = new;
00105 NextFree(new) = NextFree(p);
00106 NextFree(p) = new;
00107 }
00108 if (prev)
00109 NextFree(prev) = NextFree(p);
00110 else
00111 _empty = NextFree(p);
00112 return p;
00113 }
00114 if (grow(len) == 0)
00115 break;
00116 }
00117 assert(ntries != 2);
00118 return NULL;
00119 }
00120
00121 void *
00122 realloc(void *oldp, size_t size)
00123 {
00124 register char *prev, *p, *next, *new;
00125 char *old = oldp;
00126 register size_t len, n;
00127
00128 if (old == 0)
00129 return malloc(size);
00130 if (size == 0) {
00131 free(old);
00132 return NULL;
00133 }
00134 len = Align(size, PTRSIZE) + PTRSIZE;
00135 next = NextSlot(old);
00136 n = (int)(next - old);
00137
00138
00139
00140 for (prev = 0, p = _empty; p != 0; prev = p, p = NextFree(p)) {
00141 if (p > next)
00142 break;
00143 if (p == next) {
00144 NextSlot(old) = NextSlot(p);
00145 if (prev)
00146 NextFree(prev) = NextFree(p);
00147 else
00148 _empty = NextFree(p);
00149 next = NextSlot(old);
00150 break;
00151 }
00152 }
00153 new = old + len;
00154
00155
00156
00157 if (new <= next && new >= old) {
00158 if (new + PTRSIZE < next) {
00159
00160 NextSlot(new) = next;
00161 NextSlot(old) = new;
00162 free(new);
00163 }
00164 return old;
00165 }
00166 if ((new = malloc(size)) == NULL)
00167 return NULL;
00168 memcpy(new, old, n);
00169 free(old);
00170 return new;
00171 }
00172
00173 void
00174 free(void *ptr)
00175 {
00176 register char *prev, *next;
00177 char *p = ptr;
00178
00179 if (p == 0)
00180 return;
00181
00182 assert(NextSlot(p) > p);
00183 for (prev = 0, next = _empty; next != 0; prev = next, next = NextFree(next))
00184 if (p < next)
00185 break;
00186 NextFree(p) = next;
00187 if (prev)
00188 NextFree(prev) = p;
00189 else
00190 _empty = p;
00191 if (next) {
00192 assert(NextSlot(p) <= next);
00193 if (NextSlot(p) == next) {
00194 NextSlot(p) = NextSlot(next);
00195 NextFree(p) = NextFree(next);
00196 }
00197 }
00198 if (prev) {
00199 assert(NextSlot(prev) <= p);
00200 if (NextSlot(prev) == p) {
00201 NextSlot(prev) = NextSlot(p);
00202 NextFree(prev) = NextFree(p);
00203 }
00204 }
00205 }