void* _shm_resize( void* p , unsigned int s) #endif { #ifdef VQ_MALLOC struct vqm_frag *f; #endif if (p==0) { DBG("WARNING:vqm_resize: resize(0) called\n"); return shm_malloc( s ); } # ifdef DBG_QM_MALLOC # ifdef VQ_MALLOC f=(struct vqm_frag*) ((char*)p-sizeof(struct vqm_frag)); MDBG("_shm_resize(%p, %d), called from %s: %s(%d)\n", p, s, file, func, line); VQM_DEBUG_FRAG(shm_block, f); if (p>(void *)shm_block->core_end || p<(void*)shm_block->init_core){ LOG(L_CRIT, "BUG: vqm_free: bad pointer %p (out of memory block!) - " "aborting\n", p); abort(); } #endif # endif return sh_realloc( p, s ); }
void vqm_free(struct vqm_block* qm, void* p) #endif { struct vqm_frag *f, *next, *prev, *first_big; unsigned char b; #ifdef DBG_QM_MALLOC DBG("vqm_free(%p, %p), called from %s: %s(%d)\n", qm, p, file, func, line); if (p>(void *)qm->core_end || p<(void*)qm->init_core){ LOG(L_CRIT, "BUG: vqm_free: bad pointer %p (out of memory block!) - " "aborting\n", p); abort(); } #endif if (p==0) { DBG("WARNING:vqm_free: free(0) called\n"); return; } f=(struct vqm_frag*) ((char*)p-sizeof(struct vqm_frag)); b=f->u.inuse.bucket; #ifdef DBG_QM_MALLOC VQM_DEBUG_FRAG(qm, f); if ( ! FRAG_ISUSED(f) ) { LOG(L_CRIT, "BUG: vqm_free: freeing already freed pointer," " first freed: %s: %s(%d) - aborting\n", f->file, f->func, f->line); abort(); } if ( b>MAX_BUCKET ) { LOG(L_CRIT, "BUG: vqm_free: fragment with too high bucket nr: " "%d, allocated: %s: %s(%d) - aborting\n", b, f->file, f->func, f->line); abort(); } DBG("vqm_free: freeing %d bucket block alloc'ed from %s: %s(%d)\n", f->u.inuse.bucket, f->file, f->func, f->line); f->file=file; f->func=func; f->line=line; qm->usage[ f->u.inuse.bucket ]--; #endif if (IS_BIGBUCKET(qm,b)) { next=FRAG_NEXT(f); if ((char *)next +sizeof( struct vqm_frag) < qm->core_end) { VQM_DEBUG_FRAG(qm, next); if (! FRAG_ISUSED(next)) { /* coalesce with next fragment */ DBG("vqm_free: coalesced with next\n"); vqm_detach_free(qm, next); f->size+=next->size; FRAG_END(f)->size=f->size; } } first_big = qm->next_free[b]; if (first_big && f>first_big) { prev=FRAG_PREV(f); VQM_DEBUG_FRAG(qm, prev); if (!FRAG_ISUSED(prev)) { /* coalesce with prev fragment */ DBG("vqm_free: coalesced with prev\n"); vqm_detach_free(qm, prev ); prev->size+=f->size; f=prev; FRAG_END(f)->size=f->size; } } if ((char *)f==qm->big_chunks) { /* release unused core */ DBG("vqm_free: big chunk released\n"); qm->free_core+=f->size; qm->big_chunks+=f->size; return; } first_big = qm->next_free[b]; /* fix reverse link (used only for BIG_BUCKET */ if (first_big) FRAG_END(first_big)->prv_free=f; FRAG_END(f)->prv_free=0; } else first_big = qm->next_free[b]; f->u.nxt_free = first_big; /* also clobbers magic */ qm->next_free[b] = f; }
void* vqm_malloc(struct vqm_block* qm, unsigned int size) #endif { struct vqm_frag *new_chunk, *f; unsigned char bucket; #ifdef DBG_QM_MALLOC unsigned int demanded_size; DBG("vqm_malloc(%p, %d) called from %s: %s(%d)\n", qm, size, file, func, line); demanded_size = size; #endif new_chunk=0; /* what's the bucket? what's the total size incl. overhead? */ bucket = size2bucket( qm, &size ); if (IS_BIGBUCKET(qm, bucket)) { /* the kilo-bucket uses first-fit */ #ifdef DBG_QM_MALLOC DBG("vqm_malloc: processing a big fragment\n"); #endif for (f=qm->next_free[bucket] ; f; f=f->u.nxt_free ) if (f->size>=size) { /* first-fit */ new_chunk=f; VQM_DEBUG_FRAG(qm, f); vqm_detach_free(qm,f); break; } } else if ( (new_chunk=qm->next_free[ bucket ]) ) { /*fixed size bucket*/ VQM_DEBUG_FRAG(qm, new_chunk); /*detach it from the head of bucket's free list*/ qm->next_free[ bucket ] = new_chunk->u.nxt_free; } if (!new_chunk) { /* no chunk can be reused; slice one from the core */ new_chunk=MORE_CORE( qm, bucket, size ); if (!new_chunk) { #ifdef DBG_QM_MALLOC LOG(L_DBG, "vqm_malloc(%p, %d) called from %s: %s(%d)\n", qm, size, file, func, line); #else LOG(L_DBG, "vqm_malloc(%p, %d) called from %s: %s(%d)\n", qm, size); #endif return 0; } } new_chunk->u.inuse.magic = FR_USED; new_chunk->u.inuse.bucket=bucket; #ifdef DBG_QM_MALLOC new_chunk->file=file; new_chunk->func=func; new_chunk->line=line; new_chunk->demanded_size=demanded_size; qm->usage[ bucket ]++; DBG("vqm_malloc( %p, %d ) returns address %p in bucket %d, real-size %d\n", qm, demanded_size, (char*)new_chunk+sizeof(struct vqm_frag), bucket, size ); new_chunk->end_check=(char*)new_chunk+ sizeof(struct vqm_frag)+demanded_size; memcpy( new_chunk->end_check, END_CHECK_PATTERN, END_CHECK_PATTERN_LEN ); new_chunk->check=ST_CHECK_PATTERN; #endif return (char*)new_chunk+sizeof(struct vqm_frag); }