Changeset 40117
- Timestamp:
- Aug 11, 2017, 2:18:20 PM (9 years ago)
- File:
-
- 1 edited
-
trunk/Ohana/src/libohana/src/ohana_allocate.c (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Ohana/src/libohana/src/ohana_allocate.c
r39457 r40117 6 6 # include <string.h> 7 7 # include <errno.h> 8 # include <malloc.h> 9 # include <sys/mman.h> 8 10 9 11 # define TEST_SAVE_FREE_BLOCKS 0 10 12 # define TEST_SAVE_DROP_BLOCKS 0 13 # define USE_MMAP_SIZE 0x80000000 14 # define USE_MMAP_LOCAL FALSE 15 /* # define USE_MMAP_SIZE 0x100000 - 1M */ 16 /* USE_MMAP_SIZE is used to tell ohana memory functions to switch to raw mmap/munmap call 17 instead of malloc / realloc / free. This is in an attempt to avoid a poorly-understood 18 bug in malloc which I've identfied. The bug is seen in programs running on linux 19 kernel 3.7.6 for glibc 2.8. 20 This did not work as hoped; instead I've had to prevent the use of MMAP all together by 21 setting M_MMAP_MAX to 0 with mallopt 22 */ 11 23 12 24 # undef OHANA_MEMORY … … 49 61 void *ohana_malloc (const char *file, int line, const char *func, size_t Nelem, size_t esize) { 50 62 63 // we want to call mallopt if we have not yet used the memory system 64 // this disables the use of mmap by malloc and forces it to use on sbrk 65 pthread_mutex_lock(&memBlockListMutex); 66 if (!lastBlock) { 67 mallopt (M_MMAP_MAX, 0); 68 } 69 pthread_mutex_unlock(&memBlockListMutex); 70 51 71 char *ptr; // actual user memory allocated 52 72 OhanaMemblock *new; // new memblock created to track the user memory 53 size_t size; // total number of bytes requested (not items) 54 55 Nelem = MAX (1, Nelem);56 size = Nelem * esize;73 74 size_t myNelem = MAX (1, Nelem); 75 size_t size = myNelem * esize; // total number of bytes requested (not items) 76 size_t fullSize = sizeof(OhanaMemblock) + size + 2*sizeof(void *); // total size is : memblock + data + endpost 57 77 // if (size % 8) size += (8 - size % 8); // do NOT round to 8-byte boundary (did not fix corruption) 58 78 59 // total size is : memblock + data + endpost 60 new = (OhanaMemblock *) malloc (sizeof(OhanaMemblock) + size + 2*sizeof(void *)); 61 if (new == NULL) ohana_memabort ("failed to allocate memory (%s, %d, %s)\n", file, line, func); 79 if (USE_MMAP_LOCAL && (fullSize > USE_MMAP_SIZE)) { 80 fprintf (stderr, "** mmap %ld (%s, %d, %s)\n", fullSize, file, line, func); 81 new = (OhanaMemblock *) mmap (NULL, fullSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 82 if (new == (void *) -1) ohana_memabort ("failed to allocate memory with mmap (%s, %d, %s)\n", file, line, func); 83 } else { 84 new = (OhanaMemblock *) malloc (fullSize); 85 if (new == NULL) ohana_memabort ("failed to allocate memory (%s, %d, %s)\n", file, line, func); 86 } 62 87 // if (errno == ENOMEM) abort(); I should not check the value of errno if new is not NULL 63 88 … … 139 164 size_t oldsize = old->size; 140 165 166 // total size is : memblock + data + endpost 167 size_t fullSize = sizeof(OhanaMemblock) + size + 2*sizeof(void *); 168 size_t oldFullSize = sizeof(OhanaMemblock) + oldsize + 2*sizeof(void *); 169 141 170 pthread_mutex_lock(&memBlockListMutex); 142 171 … … 151 180 // XXX for a test, we are going to always alloc a new block, copy the old data to the new block 152 181 // poison the old block, then free it 153 new = (OhanaMemblock *) malloc (sizeof(OhanaMemblock) + size + 2*sizeof(void *)); 154 if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func); 182 if (USE_MMAP_LOCAL && (fullSize > USE_MMAP_SIZE)) { 183 fprintf (stderr, "** mmap %ld (%s, %d, %s)\n", fullSize, file, line, func); 184 new = (OhanaMemblock *) mmap (NULL, fullSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 185 if (new == (void *) -1) ohana_memabort ("failed to allocate memory with mmap (%s, %d, %s)\n", file, line, func); 186 } else { 187 new = (OhanaMemblock *) malloc (fullSize); 188 if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func); 189 } 155 190 char *ptr_new = (char *) (new + 1); 156 191 char *ptr_old = (char *) (old + 1); … … 165 200 # else 166 201 // ask for new memory 167 // total size is : memblock + data + endpost 168 new = (OhanaMemblock *) realloc (old, sizeof(OhanaMemblock) + size + 2*sizeof(void *)); 169 if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func); 202 203 if (USE_MMAP_LOCAL && (fullSize > USE_MMAP_SIZE)) { 204 if (oldFullSize > USE_MMAP_SIZE) { 205 // new = (OhanaMemblock *) mremap (old, oldFullSize, fullSize, 0); NOTE: mremap is a Linux / GNU only feature 206 // mmap to mmap (allocate new, copy user bytes, free old) 207 fprintf (stderr, "** mmap 1 %ld to %ld (%s, %d, %s)\n", oldFullSize, fullSize, file, line, func); 208 new = (OhanaMemblock *) mmap (NULL, fullSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 209 if (new == (void *) -1) ohana_memabort ("failed to allocate memory with mmap (%s, %d, %s)\n", file, line, func); 210 char *ptr_new = (char *) (new + 1); 211 char *ptr_old = (char *) (old + 1); 212 size_t copy_bytes = old->size < size ? old->size : size; 213 memcpy (ptr_new, ptr_old, copy_bytes); 214 memset (ptr_old, 0x7f, old->size); 215 new->nextBlock = old->nextBlock; 216 new->prevBlock = old->prevBlock; 217 new->startblock = OHANA_MEMMAGIC; 218 new->endblock = OHANA_MEMMAGIC; 219 new->freed = FALSE; 220 fprintf (stderr, "** munmap %ld (%s, %d, %s)\n", oldFullSize, file, line, func); 221 int mstatus = munmap (old, oldFullSize); // XXX ??? 222 if (mstatus != 0) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func); 223 } else { 224 // malloc to mmap (allocate new, copy user bytes, free old) 225 fprintf (stderr, "** mmap 2 %ld to %ld (%s, %d, %s)\n", oldFullSize, fullSize, file, line, func); 226 new = (OhanaMemblock *) mmap (NULL, fullSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 227 if (new == (void *) -1) ohana_memabort ("failed to allocate memory with mmap (%s, %d, %s)\n", file, line, func); 228 char *ptr_new = (char *) (new + 1); 229 char *ptr_old = (char *) (old + 1); 230 size_t copy_bytes = old->size < size ? old->size : size; 231 memcpy (ptr_new, ptr_old, copy_bytes); 232 memset (ptr_old, 0x7f, old->size); 233 new->nextBlock = old->nextBlock; 234 new->prevBlock = old->prevBlock; 235 new->startblock = OHANA_MEMMAGIC; 236 new->endblock = OHANA_MEMMAGIC; 237 new->freed = FALSE; 238 free (old); // XXX ??? 239 } 240 } else { 241 if (USE_MMAP_LOCAL && (oldFullSize > USE_MMAP_SIZE)) { 242 // mmap to malloc (allocate new, copy user bytes, free old) 243 new = (OhanaMemblock *) malloc (fullSize); 244 if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func); 245 char *ptr_new = (char *) (new + 1); 246 char *ptr_old = (char *) (old + 1); 247 size_t copy_bytes = old->size < size ? old->size : size; 248 memcpy (ptr_new, ptr_old, copy_bytes); 249 memset (ptr_old, 0x7f, old->size); 250 new->nextBlock = old->nextBlock; 251 new->prevBlock = old->prevBlock; 252 new->startblock = OHANA_MEMMAGIC; 253 new->endblock = OHANA_MEMMAGIC; 254 new->freed = FALSE; 255 fprintf (stderr, "** munmap %ld (%s, %d, %s)\n", oldFullSize, file, line, func); 256 int mstatus = munmap (old, oldFullSize); // XXX ??? 257 if (mstatus != 0) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func); 258 } else { 259 // mmap to mmap 260 new = (OhanaMemblock *) realloc (old, fullSize); 261 if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func); 262 } 263 } 170 264 char *ptr_new = (char *) (new + 1); 171 265 # endif … … 217 311 } 218 312 313 // XXX this function is only used for memory allocated outside of the ohana_allocate system 219 314 void real_free (void *in) { 220 315 … … 237 332 ref = (OhanaMemblock *) in - 1; 238 333 if (!ref->nextBlock && !ref->prevBlock && (Nblock > 1)) ohana_memabort ("orphan block?? (%s@%d : %s)\n", file, line, func); 334 size_t fullSize = sizeof(OhanaMemblock) + ref->size + 2*sizeof(void *); // total size is : memblock + data + endpost 239 335 240 336 if (ref->freed) ohana_memabort ("memory already freed (%s, %d, %s [%d bytes])\n", ref->file, ref->line, ref->func, ref->size); … … 291 387 # if (!TEST_SAVE_FREE_BLOCKS) 292 388 memset (ref, 0x7f, sizeof(OhanaMemblock)); 293 free (ref); 389 if (USE_MMAP_LOCAL && (fullSize > USE_MMAP_SIZE)) { 390 fprintf (stderr, "** munmap %ld (%s, %d, %s)\n", fullSize, file, line, func); 391 int mstatus = munmap (ref, fullSize); 392 if (mstatus != 0) ohana_memabort ("failed to free memory (%s, %d, %s)\n", file, line, func); 393 } else { 394 free (ref); 395 } 294 396 # endif 295 397
Note:
See TracChangeset
for help on using the changeset viewer.
