/* size should already be rounded-up */ void __shm_frag_split(struct hp_block *hpb, struct hp_frag *frag, unsigned long size, unsigned int old_hash) { unsigned long rest, hash; struct hp_frag *n; #ifdef HP_MALLOC_FAST_STATS hpb->free_hash[PEEK_HASH_RR(hpb, frag->size)].total_no--; hpb->free_hash[PEEK_HASH_RR(hpb, size)].total_no++; #endif rest = frag->size - size; frag->size = size; /* split the fragment */ n = FRAG_NEXT(frag); n->size = rest - FRAG_OVERHEAD; /* insert the newly obtained hp_frag in its free list */ hash = PEEK_HASH_RR(hpb, n->size); if (hash != old_hash) SHM_LOCK(hash); hp_frag_attach(hpb, n); #ifdef HP_MALLOC_FAST_STATS hpb->free_hash[hash].total_no++; #endif if (hash != old_hash) SHM_UNLOCK(hash); }
void __shm_frag_split_unsafe(struct hp_block *hpb, struct hp_frag *frag, unsigned long size) { unsigned long rest; struct hp_frag *n; #ifdef HP_MALLOC_FAST_STATS hpb->free_hash[PEEK_HASH_RR(hpb, frag->size)].total_no--; hpb->free_hash[PEEK_HASH_RR(hpb, size)].total_no++; #endif rest = frag->size - size; frag->size = size; /* split the fragment */ n = FRAG_NEXT(frag); n->size = rest - FRAG_OVERHEAD; #ifdef HP_MALLOC_FAST_STATS hpb->free_hash[PEEK_HASH_RR(hpb, n->size)].total_no++; #endif hp_frag_attach(hpb, n); if (stats_are_ready()) update_stats_shm_frag_attach(n); else { hpb->used -= n->size; hpb->real_used -= n->size; } }
struct hp_block *hp_shm_malloc_init(char *address, unsigned long size, char *name) { struct hp_block *hpb; hpb = hp_malloc_init(address, size, name); if (!hpb) { LM_ERR("failed to initialize shm block\n"); return NULL; } #ifdef HP_MALLOC_FAST_STATS hpb->free_hash[PEEK_HASH_RR(hpb, hpb->first_frag->size)].total_no++; #endif hp_frag_attach(hpb, hpb->first_frag); /* first fragment attach is the equivalent of a split */ if (stats_are_ready()) { #if defined(STATISTICS) && !defined(HP_MALLOC_FAST_STATS) update_stat(shm_rused, FRAG_OVERHEAD); update_stat(shm_frags, 1); #endif #if defined(DBG_MALLOC) || defined(STATISTICS) hpb->real_used += FRAG_OVERHEAD; hpb->total_fragments++; #endif } else { hpb->real_used += FRAG_OVERHEAD; hpb->total_fragments++; } #ifdef HP_MALLOC_FAST_STATS #ifdef DBG_MALLOC hp_stats_lock = hp_shm_malloc_unsafe(hpb, sizeof *hp_stats_lock, __FILE__, __FUNCTION__, __LINE__); #else hp_stats_lock = hp_shm_malloc_unsafe(hpb, sizeof *hp_stats_lock); #endif if (!hp_stats_lock) { LM_ERR("failed to alloc hp statistics lock\n"); return NULL; } if (!lock_init(hp_stats_lock)) { LM_CRIT("could not initialize hp statistics lock\n"); return NULL; } #endif return hpb; }
struct hp_block *hp_shm_malloc_init(char *address, unsigned long size) { struct hp_block *hpb; hpb = hp_malloc_init(address, size); if (!hpb) { LM_ERR("failed to initialize shm block\n"); return NULL; } #ifdef HP_MALLOC_FAST_STATS hpb->free_hash[PEEK_HASH_RR(hpb, hpb->first_frag->size)].total_no++; #endif hp_frag_attach(hpb, hpb->first_frag); /* first fragment attach is the equivalent of a split */ if (stats_are_ready()) update_stats_shm_frag_split(hpb, hpb->first_frag); else { hpb->real_used += FRAG_OVERHEAD; hpb->total_fragments++; } /* if memory warming is on, pre-populate the hash with free fragments */ if (mem_warming_enabled) { if (!mem_warming_pattern_file) mem_warming_pattern_file = MEM_WARMING_DEFAULT_PATTERN_FILE; if (mem_warming_percentage == -1) mem_warming_percentage = MEM_WARMING_DEFAULT_PERCENTAGE; if (hp_mem_warming(hpb) != 0) LM_INFO("skipped memory warming\n"); } hp_stats_lock = hp_shm_malloc_unsafe(hpb, sizeof *hp_stats_lock); if (!hp_stats_lock) { LM_ERR("failed to alloc hp statistics lock\n"); return NULL; } if (!lock_init(hp_stats_lock)) { LM_CRIT("could not initialize hp statistics lock\n"); return NULL; } return hpb; }
void *hp_shm_realloc(struct hp_block *hpb, void *p, unsigned long size) { struct hp_frag *f; unsigned long orig_size; unsigned int hash; void *ptr; if (size == 0) { if (p) hp_shm_free(hpb, p); return NULL; } if (!p) return hp_shm_malloc(hpb, size); f = FRAG_OF(p); size = ROUNDUP(size); hash = PEEK_HASH_RR(hpb, f->size); SHM_LOCK(hash); orig_size = f->size; if (orig_size > size) { /* shrink */ shm_frag_split_unsafe(hpb, f, size); } else if (orig_size < size) { SHM_UNLOCK(hash); ptr = hp_shm_malloc(hpb, size); if (ptr) { /* copy, need by libssl */ memcpy(ptr, p, orig_size); hp_shm_free(hpb, p); } return ptr; } SHM_UNLOCK(hash); return p; }
void hp_shm_free(struct hp_block *hpb, void *p) { struct hp_frag *f; unsigned int hash; if (!p) { LM_WARN("free(0) called\n"); return; } f = FRAG_OF(p); hash = PEEK_HASH_RR(hpb, f->size); SHM_LOCK(hash); hp_frag_attach(hpb, f); SHM_UNLOCK(hash); update_stats_shm_frag_attach(f); }