static int myThread(A_UNUSED void *arg) { size_t i; usemdown(&usem); printf("Thread %d starts\n",gettid()); fflush(stdout); usemup(&usem); for(i = 0; i < 10; i++) sleep(100); usemdown(&usem); printf("Thread %d is done\n",gettid()); fflush(stdout); usemup(&usem); return 0; }
void *realloc(void *addr,size_t size) { ulong *begin; sMemArea *area,*a,*prev; if(addr == NULL) return malloc(size); begin = (ulong*)addr - 3; area = (sMemArea*)begin[0]; /* check guards */ vassert(begin[0] != FREE_MAGIC,"Duplicate free?"); assert(begin[2] == GUARD_MAGIC); assert(begin[begin[1] / sizeof(ulong) + 3] == GUARD_MAGIC); usemdown(&heapSem); /* align and we need 3 ulongs for the guards */ size = ROUND_UP(size,sizeof(ulong)) + sizeof(ulong) * 4; /* ignore shrinks */ if(size < area->size) { usemup(&heapSem); return addr; } a = usableList; prev = NULL; while(a != NULL) { /* found the area behind? */ if((uintptr_t)a->address == (uintptr_t)area->address + area->size) { /* if the size of both is big enough we can use them */ if(area->size + a->size >= size) { /* space left? */ if(size < area->size + a->size) { /* so move the area forward */ a->address = (void*)((uintptr_t)area->address + size); a->size = (area->size + a->size) - size; } /* otherwise we don't need a anymore */ else { /* remove a from usable-list */ if(prev == NULL) usableList = a->next; else prev->next = a->next; /* free a */ a->next = freeList; freeList = a; } area->size = size; /* reset guards */ begin[0] = (ulong)area; begin[1] = size - sizeof(ulong) * 4; begin[2] = GUARD_MAGIC; begin[size / sizeof(ulong) - 1] = GUARD_MAGIC; usemup(&heapSem); return begin + 3; } /* makes no sense to continue since we've found the area behind */ break; } prev = a; a = a->next; } usemup(&heapSem); /* the areas are not big enough, so allocate a new one */ a = malloc(size); if(a == NULL) return NULL; /* copy the old data and free it */ memcpy(a,addr,area->size - sizeof(ulong) * 4); free(addr); return a; }
void *malloc(size_t size) { ulong *begin; sMemArea *area,*prev,*narea; if(size == 0) return NULL; usemdown(&heapSem); /* align and we need 3 ulongs for the guards */ size = ROUND_UP(size,sizeof(ulong)) + sizeof(ulong) * 4; /* find a suitable area */ prev = NULL; area = usableList; while(area != NULL) { if(area->size >= size) break; prev = area; area = area->next; } /* no area found? */ if(area == NULL) { if(!loadNewSpace(size)) { usemup(&heapSem); return NULL; } /* we can assume that it fits */ area = usableList; /* remove from usable-list */ usableList = area->next; } else { /* remove from usable-list */ if(prev == NULL) usableList = area->next; else prev->next = area->next; } /* is there space left? */ if(size < area->size) { if(freeList == NULL) { if(!loadNewAreas()) { /* TODO we may have changed something... */ usemup(&heapSem); return NULL; } } /* split the area */ narea = freeList; freeList = freeList->next; narea->address = (void*)((uintptr_t)area->address + size); narea->size = area->size - size; area->size = size; /* insert in usable-list */ narea->next = usableList; usableList = narea; } #if DEBUG_ALLOC_N_FREE if(DEBUG_ALLOC_N_FREE_PID == -1 || getpid() == DEBUG_ALLOC_N_FREE_PID) { size_t i = 0; uintptr_t *trace = getStackTrace(); debugf("[A] %x %d ",(char*)area->address + 3,area->size); while(*trace && i++ < 10) { debugf("%x",*trace); if(trace[1]) debugf(" "); trace++; } debugf("\n"); } #endif /* add guards */ begin = (ulong*)area->address; begin[0] = (ulong)area; begin[1] = size - sizeof(ulong) * 4; begin[2] = GUARD_MAGIC; begin[size / sizeof(ulong) - 1] = GUARD_MAGIC; usemup(&heapSem); return begin + 3; }
void free(void *addr) { ulong *begin; sMemArea *area,*a,*prev,*next,*nprev,*pprev,*tprev; /* addr may be null */ if(addr == NULL) return; /* check guards */ begin = (ulong*)addr - 3; area = (sMemArea*)begin[0]; vassert(begin[0] != FREE_MAGIC,"Duplicate free of %p?",addr); assert(begin[2] == GUARD_MAGIC); assert(begin[begin[1] / sizeof(ulong) + 3] == GUARD_MAGIC); usemdown(&heapSem); /* mark as free */ begin[0] = FREE_MAGIC; /* find the previous and next free areas */ prev = NULL; next = NULL; tprev = NULL; pprev = NULL; nprev = NULL; a = usableList; while(a != NULL) { if((uintptr_t)a->address + a->size == (uintptr_t)begin) { prev = a; pprev = tprev; } if((uintptr_t)a->address == (uintptr_t)begin + area->size) { next = a; nprev = tprev; } /* do we have both? */ if(prev && next) break; tprev = a; a = a->next; } #if DEBUG_ALLOC_N_FREE if(DEBUG_ALLOC_N_FREE_PID == -1 || getpid() == DEBUG_ALLOC_N_FREE_PID) { size_t i = 0; uintptr_t *trace = getStackTrace(); debugf("[F] %x %d ",addr,area->size); while(*trace && i++ < 10) { debugf("%x",*trace); if(trace[1]) debugf(" "); trace++; } debugf("\n"); } #endif /* see what we have to merge */ if(prev && next) { /* merge prev & area & next */ area->size += prev->size + next->size; area->address = prev->address; /* remove prev and next from the list */ if(nprev) nprev->next = next->next; else usableList = next->next; /* special-case if next is the previous of prev */ if(pprev == next) { if(nprev) nprev->next = prev->next; else usableList = prev->next; } else { if(pprev) pprev->next = prev->next; else usableList = prev->next; } /* put area on the usable-list */ area->next = usableList; usableList = area; /* put prev and next on the freelist */ prev->next = next; next->next = freeList; freeList = prev; } else if(prev) { /* merge preg & area */ prev->size += area->size; /* put area on the freelist */ area->next = freeList; freeList = area; } else if(next) { /* merge area & next */ next->address = area->address; next->size += area->size; /* put area on the freelist */ area->next = freeList; freeList = area; } else { /* insert area in usableList */ area->next = usableList; usableList = area; } usemup(&heapSem); }