📄 su_alloc.c
字号:
d = d2; } if ((n = s->sub_n)) { for (i = 0; i < n; i++) if (s->sub_nodes[i].sua_data) { su_block_add(d, s->sub_nodes[i].sua_data)[0] = s->sub_nodes[i]; } s->sub_used = 0; memset(s->sub_nodes, 0, n * sizeof (s->sub_nodes[0])); } if (s->sub_stats) { } } UNLOCK(dst); UNLOCK(src); } else { s = MEMLOCK(src); if (s && s->sub_used) { s->sub_used = 0; memset(s->sub_nodes, 0, s->sub_n * sizeof (s->sub_nodes[0])); } UNLOCK(src); } return 0;}/** Preload a memory home. * * The function su_home_preload() preloads a memory home. */void su_home_preload(su_home_t *home, int n, int isize){ su_block_t *sub; if (home == NULL) return; if (home->suh_blocks == NULL) su_home_init(home); sub = MEMLOCK(home); if (!sub->sub_preload) { int size; void *preload; size = n * ALIGN(isize); if (size > USHRT_MAX) size = USHRT_MAX & (ALIGNMENT - 1); preload = malloc(size); home->suh_blocks->sub_preload = preload; home->suh_blocks->sub_prsize = size; } UNLOCK(home);}/** Preload a memory home from stack. * * The function su_home_auto() initalizes a memory home using an area * allocated from stack. Poor mans alloca(). */su_home_t *su_home_auto(void *area, int size){ su_home_t *home; su_block_t *sub; size_t homesize = ALIGN(sizeof *home); size_t subsize = ALIGN(offsetof(su_block_t, sub_nodes[SUB_N_AUTO])); size_t prepsize; char *p = area; prepsize = homesize + subsize + (ALIGN((intptr_t)p) - (intptr_t)p); if (area == NULL || size < prepsize) return NULL; home = memset(p, 0, homesize); home->suh_size = size; sub = memset(p + homesize, 0, subsize); home->suh_blocks = sub; sub->sub_n = SUB_N_AUTO; sub->sub_preload = p + prepsize; sub->sub_prsize = size - prepsize; sub->sub_preauto = 1; sub->sub_auto = 1; sub->sub_auto_all = 1; return home;}/** Reallocate a memory block. * * The function su_realloc() allocates a memory block of @a size bytes. * It copies the old block contents to the new block and frees the old * block. * * If @a home is NULL, this function behaves exactly like realloc(). * * @param home pointer to memory pool object * @param data pointer to old memory block * @param size size of the memory block to be allocated * * @return * This function returns a pointer to the allocated memory block or * NULL if an error occurred. */void *su_realloc(su_home_t *home, void *data, int size){ void *ndata; su_alloc_t *sua; su_block_t *sub; int p; int term = -size; if (!home) return realloc(data, size); if (size == 0) { if (data) su_free(home, data); return NULL; } sub = MEMLOCK(home); if (!data) { data = sub_alloc(home, sub, size, 0); UNLOCK(home); return data; } sua = su_block_find(sub, data); if (!su_alloc_check(sub, sua)) return UNLOCK(home); assert(!sua->sua_home); if (sua->sua_home) return UNLOCK(home); if (!su_is_preloaded(sub, data)) { ndata = realloc(data, size + MEMCHECK_EXTRA); if (ndata) { if (sub->sub_stats) { su_home_stats_free(sub, data, 0, sua->sua_size); su_home_stats_alloc(sub, data, 0, size, 1); }#if MEMCHECK_EXTRA memcpy((char *)ndata + size, &term, sizeof (term));#else (void)term;#endif memset(sua, 0, sizeof *sua); sub->sub_used--; su_block_add(sub, ndata)->sua_size = size; } UNLOCK(home); return ndata; } p = (char *)data - home->suh_blocks->sub_preload; p += sua->sua_size + MEMCHECK_EXTRA; p = ALIGN(p); if (p == sub->sub_prused) { int p2 = (char *)data - sub->sub_preload + size + MEMCHECK_EXTRA; p2 = ALIGN(p2); if (p2 <= sub->sub_prsize) { /* Extend/reduce existing preload */ if (sub->sub_stats) { su_home_stats_free(sub, data, data, sua->sua_size); su_home_stats_alloc(sub, data, data, size, 0); } sub->sub_prused = p2; sua->sua_size = size;#if MEMCHECK_EXTRA memcpy((char *)data + size, &term, sizeof (term));#endif UNLOCK(home); return data; } } else if (size < sua->sua_size) { /* Reduce existing preload */ if (sub->sub_stats) { su_home_stats_free(sub, data, data, sua->sua_size); su_home_stats_alloc(sub, data, data, size, 0); }#if MEMCHECK_EXTRA memcpy((char *)data + size, &term, sizeof (term));#endif sua->sua_size = size; UNLOCK(home); return data; } ndata = malloc(size + MEMCHECK_EXTRA); if (ndata) { if (p == sub->sub_prused) { /* Free preload */ sub->sub_prused = (char *)data - home->suh_blocks->sub_preload; if (sub->sub_stats) su_home_stats_free(sub, data, data, sua->sua_size); } memcpy(ndata, data, sua->sua_size < size ? sua->sua_size : size);#if MEMCHECK_EXTRA memcpy((char *)ndata + size, &term, sizeof (term));#endif if (sub->sub_stats) su_home_stats_alloc(sub, data, 0, size, 1); memset(sua, 0, sizeof *sua); sub->sub_used--; su_block_add(sub, ndata)->sua_size = size; } UNLOCK(home); return ndata;}/**Allocate and zero a memory block. * * The function su_zalloc() allocates a memory block with a given size from * given memory home @a home and zeroes the allocated block. * * @param home pointer to memory pool object * @param size size of the memory block * * @note The memory home pointer @a home may be @c NULL. In that case, the * allocated memory block is not associated with any memory home, and it * must be freed by calling su_free() or free(). * * @return * The function su_zalloc() returns a pointer to the allocated memory block, * or NULL upon an error. */void *su_zalloc(su_home_t *home, int size){ void *data; assert (size >= 0); if (home) { data = sub_alloc(home, MEMLOCK(home), size, 1); UNLOCK(home); } else data = calloc(1, size); return data;}/** Allocate a structure * * The function su_salloc() allocates a structure with a given size, zeros * it, and initializes the size field to the given size. The size field * is the first in the structure. * * @param home pointer to memory pool object * @param size size of the structure * * @par Example * The structure is defined and allocated as follows: * @code * struct test { * int tst_size; * char *tst_name; * void *tst_ptr[3]; * }; * * struct test *t; * ... * t = su_salloc(home, sizeof (*t)); * assert(t && t->t_size == sizeof (*t)); * t->name * @endcode * After calling su_salloc() we get a pointer t to a struct test, * initialized to zero except the * * * @return This function returns a pointer to the allocated structure, or * NULL upon an error. */void *su_salloc(su_home_t *home, int size){ struct { int size; } *retval; if (size < sizeof (*retval)) size = sizeof (*retval); assert (size >= 0); if (home) { retval = sub_alloc(home, MEMLOCK(home), size, 1); UNLOCK(home); } else retval = calloc(1, size); if (retval) retval->size = size; return retval;}/** Check if a memory home is threadsafe */int su_home_is_threadsafe(su_home_t const *home){ return home && home->suh_lock;}/** Obtain exclusive lock on home (if home is threadsafe). */int su_home_mutex_lock(su_home_t *home){ if (home == NULL) return su_seterrno(EFAULT); if (home->suh_lock) { su_home_ref(home); su_home_mutex_locker(home->suh_lock); } else if (home->suh_blocks) { if (!su_home_ref(home)) return -1; } return 0;}/** Release exclusive lock on home (if home is threadsafe) */int su_home_mutex_unlock(su_home_t *home){ if (home == NULL) return su_seterrno(EFAULT); if (home->suh_lock) { su_home_mutex_unlocker(home->suh_lock); su_home_unref(home); } else if (home->suh_blocks) { su_home_unref(home); } return 0;}/** Initialize statistics structure */void su_home_init_stats(su_home_t *home){ su_block_t *sub; int size; if (home == NULL) return; sub = home->suh_blocks; if (!sub) sub = home->suh_blocks = su_hash_alloc(SUB_N); if (!sub) return; if (!sub->sub_stats) { size = sizeof (*sub->sub_stats); sub->sub_stats = malloc(size); if (!sub->sub_stats) return; } else size = sub->sub_stats->hs_size; memset(sub->sub_stats, 0, size); sub->sub_stats->hs_size = size; sub->sub_stats->hs_blocksize = sub->sub_n;}/** Retrieve statistics from memory home. */void su_home_get_stats(su_home_t *home, int include_clones, su_home_stat_t hs[1], int size){ su_block_t *sub; if (hs == NULL || size < (sizeof hs->hs_size)) return; memset(hs, 0, size); sub = MEMLOCK(home); if (sub && sub->sub_stats) { int sub_size = sub->sub_stats->hs_size; if (sub_size > size) sub_size = size; sub->sub_stats->hs_preload.hsp_size = sub->sub_prsize; sub->sub_stats->hs_preload.hsp_used = sub->sub_prused; memcpy(hs, sub->sub_stats, sub_size); hs->hs_size = size; } UNLOCK(home);}static void su_home_stats_alloc(su_block_t *sub, void *p, void *preload, unsigned size, int zero){ su_home_stat_t *hs = sub->sub_stats; unsigned rsize = ALIGN(size); hs->hs_rehash += (sub->sub_n != hs->hs_blocksize); hs->hs_blocksize = sub->sub_n; hs->hs_clones += zero > 1; if (preload) { hs->hs_allocs.hsa_preload++; return; } hs->hs_allocs.hsa_number++; hs->hs_allocs.hsa_bytes += size; hs->hs_allocs.hsa_rbytes += rsize; if (hs->hs_allocs.hsa_rbytes > hs->hs_allocs.hsa_maxrbytes) hs->hs_allocs.hsa_maxrbytes = hs->hs_allocs.hsa_rbytes; hs->hs_blocks.hsb_number++; hs->hs_blocks.hsb_bytes += size; hs->hs_blocks.hsb_rbytes += rsize;}static void su_home_stats_free(su_block_t *sub, void *p, void *preload, unsigned size){ su_home_stat_t *hs = sub->sub_stats; unsigned rsize = ALIGN(size); if (preload) { hs->hs_frees.hsf_preload++; return; } hs->hs_frees.hsf_number++; hs->hs_frees.hsf_bytes += size; hs->hs_frees.hsf_rbytes += rsize; hs->hs_blocks.hsb_number--; hs->hs_blocks.hsb_bytes -= size; hs->hs_blocks.hsb_rbytes -= rsize;}void su_home_stat_add(su_home_stat_t total[1], su_home_stat_t const hs[1]){ total->hs_clones += hs->hs_clones; total->hs_rehash += hs->hs_rehash; if (total->hs_blocksize < hs->hs_blocksize) total->hs_blocksize = hs->hs_blocksize; total->hs_allocs.hsa_number += hs->hs_allocs.hsa_number; total->hs_allocs.hsa_bytes += hs->hs_allocs.hsa_bytes; total->hs_allocs.hsa_rbytes += hs->hs_allocs.hsa_rbytes; total->hs_allocs.hsa_maxrbytes += hs->hs_allocs.hsa_maxrbytes; total->hs_frees.hsf_number += hs->hs_frees.hsf_number; total->hs_frees.hsf_bytes += hs->hs_frees.hsf_bytes; total->hs_frees.hsf_rbytes += hs->hs_frees.hsf_rbytes; total->hs_blocks.hsb_number += hs->hs_blocks.hsb_number; total->hs_blocks.hsb_bytes += hs->hs_blocks.hsb_bytes; total->hs_blocks.hsb_rbytes += hs->hs_blocks.hsb_rbytes;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -