⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 su_alloc.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
/**Create a new su_home_t object. * * Create a home object used to collect multiple memory allocations under * one handle. The memory allocations made using this home object is freed * either when this home is destroyed. * * @param size    size of home object * * The memory home object allocated with su_home_new() can be reclaimed with * su_home_unref(). * * @return * This function returns a pointer to an su_home_t object, or NULL upon * an error. */void *su_home_new(int size){  su_home_t *home;  assert(size >= sizeof (*home));  if (size < sizeof (*home))    return NULL;  home = calloc(1, size);  if (home) {    home->suh_size = size;    home->suh_blocks = su_hash_alloc(SUB_N);    if (home->suh_blocks)      home->suh_blocks->sub_ref = 1;    else      free(home), home = NULL;  }  return home;}/** Create a new reference to a home object. */void *su_home_ref(su_home_t const *home){  if (home) {    su_block_t *sub = MEMLOCK(home);    if (sub == NULL || sub->sub_ref == 0) {      assert(sub && sub->sub_ref != 0);      UNLOCK(home);      return NULL;    }        if (sub->sub_ref != UINT_MAX)      sub->sub_ref++;    UNLOCK(home);  }  else    su_seterrno(EFAULT);  return (void *)home;}/** Set destructor function */SU_DLL int su_home_desctructor(su_home_t *home, void (*destructor)(void *)){  int retval = -1;  if (home) {    su_block_t *sub = MEMLOCK(home);    if (sub && sub->sub_destructor == NULL) {      sub->sub_destructor = destructor;      retval = 0;    }    UNLOCK(home);  }  else    su_seterrno(EFAULT);  return retval;}/**Unreference a su_home_t object. * * The function su_home_unref() decrements the reference count on a home * object and destroys and frees it and the memory allocations using it. * * @param home memory pool object to be unreferences * * The function return values is  * * @retval 1 if object was freed * @retval 0 if object is still alive */int su_home_unref(su_home_t *home){  su_block_t *sub;  if (home == NULL)    return 0;  sub = MEMLOCK(home);  if (sub == NULL) {    /* Xyzzy */    return 0;  }  else if (sub->sub_ref == UINT_MAX) {    UNLOCK(home);    return 0;  }  else if (--sub->sub_ref > 0) {    UNLOCK(home);    return 0;  }  else if (sub->sub_parent) {    su_home_t *parent = sub->sub_parent;    UNLOCK(home);    su_free(parent, home);    return 1;  }  else {    _su_home_deinit(home);    free(home);    /* UNLOCK(home); */    return 1;  }}/**Clone a su_home_t object. * * Clone a secondary home object used to collect multiple memoryf * allocations under one handle. The memory is freed either when the cloned * home is destroyed or when the parent home is destroyed. * * An independent * home object is created if NULL is passed as @a parent argument. * * @param parent  a parent object (may be NULL) * @param size    size of home object * * The memory home object allocated with su_home_clone() can be freed with * su_home_unref(). * * @return * This function returns a pointer to an su_home_t object, or NULL upon * an error. */void *su_home_clone(su_home_t *parent, int size){  su_home_t *home;  assert(size >= sizeof (*home));  if (size < sizeof (*home))    return NULL;  if (parent) {    su_block_t *sub = MEMLOCK(parent);    home = sub_alloc(parent, sub, size, 2);    UNLOCK(parent);  }  else {    home = su_home_new(size);  }  return home;}/** Return true if home is a clone. */int su_home_has_parent(su_home_t const *home){  return home && !home->suh_lock &&     home->suh_blocks && home->suh_blocks->sub_parent;}/** Allocate a memory block. * * The function su_alloc() allocates a memory block of a given @a size. * * If @a home is NULL, this function behaves exactly like malloc(). * * @param home  pointer to home object * @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_alloc(su_home_t *home, int size){  void *data;  if (home) {    data = sub_alloc(home, MEMLOCK(home), size, 0);    UNLOCK(home);  }  else    data = malloc(size);  return data;}/**Free a memory block. * * The function su_free() frees a single memory block. The @a home must be * the owner of the memory block (usually the memory home used to allocate * the memory block, or NULL if no home was used). * * @param home  pointer to home object * @param data  pointer to the memory block to be freed */void su_free(su_home_t *home, void *data){  if (home && data) {    su_alloc_t *allocation;    su_block_t *sub = MEMLOCK(home);    assert(sub);    allocation = su_block_find(sub, data);    assert(allocation);    if (su_alloc_check(sub, allocation)) {      void *preloaded = NULL;      /* Is this preloaded data? */      if (su_is_preloaded(sub, data))	preloaded = data;      if (sub->sub_stats)	su_home_stats_free(sub, data, preloaded, allocation->sua_size);      if (allocation->sua_home) {	su_home_t *subhome = data;	su_block_t *sub = MEMLOCK(subhome);	assert(sub->sub_ref != UINT_MAX);	/* assert(sub->sub_ref > 0); */	sub->sub_ref = 0;	/* Zap all references */	_su_home_deinit(subhome);      }#if MEMCHECK != 0      memset(data, 0xaa, allocation->sua_size);#endif      memset(allocation, 0, sizeof (*allocation));      sub->sub_used--;      if (preloaded)	data = NULL;    }    UNLOCK(home);  }  free(data);}/** Check home consistency. * * The function su_home_check() ensures that the home structure and all * memory blocks allocated through it are consistent.  It can be used to * catch memory allocation and usage errors. * * @param home Pointer to a memory home. */void su_home_check(su_home_t const *home){#if MEMCHECK != 0  su_block_t const *b = MEMLOCK(home);  su_home_check_blocks(b);  UNLOCK(home);#endif}/** Check home blocks. */staticvoid su_home_check_blocks(su_block_t const *b){#if MEMCHECK != 0  if (b) {    unsigned i, used;    assert(b->sub_used <= b->sub_n);    for (i = 0, used = 0; i < b->sub_n; i++)      if (b->sub_nodes[i].sua_data) {	su_alloc_check(b, &b->sub_nodes[i]), used++;	if (b->sub_nodes[i].sua_home)	  su_home_check((su_home_t *)b->sub_nodes[i].sua_data);      }    assert(used == b->sub_used);  }#endif}/** * Create an su_home_t object. * * The function su_home_create() creates a home object.  A home object is * used to collect multiple memory allocations, so that they all can be * freed by calling su_home_destroy(). * * @return This function returns a pointer to an @c su_home_t object, or @c * NULL upon an error.  * * @deprecated * Use su_home_clone() instead of su_home_create(). */su_home_t *su_home_create(void){  su_home_t *home = su_salloc(NULL, sizeof (*home));  if (home) {    su_home_init(home);  }  return home;}/** Deinitialize a home object * *   The function su_home_destroy() frees a home object, and all memory *   blocks associated with it. * *   @param home pointer to a home object * * @deprecated * Use su_home_deinit() instead of su_home_destroy(). */void su_home_destroy(su_home_t *home){  su_home_deinit(home);  /* free(home); - what if this is cloned one? */}/** Initialize an su_home_t object. * * The function su_home_init() initializes an object derived from su_home_t. * * @param home pointer to home object * * @return *    The function su_home_init() returns 0 when successful, *    or -1 upon an error. */int su_home_init(su_home_t *home){  if (home == NULL)    return -1;  home->suh_blocks = su_hash_alloc(SUB_N);  return 0;}/** Internal deinitialization */staticvoid _su_home_deinit(su_home_t *home){  if (home->suh_blocks) {    unsigned i;    su_block_t *b;     if (home->suh_blocks->sub_destructor) {      void (*destructor)(void *) = home->suh_blocks->sub_destructor;      home->suh_blocks->sub_destructor = NULL;      destructor(home);    }    b = home->suh_blocks;    su_home_check_blocks(b);    for (i = 0; i < b->sub_n; i++) {      if (b->sub_nodes[i].sua_data) {	if (b->sub_nodes[i].sua_home) {	  su_home_t *subhome = b->sub_nodes[i].sua_data;	  su_block_t *subb = MEMLOCK(subhome);	  assert(subb); assert(subb->sub_ref >= 1);#if 0	  if (subb->sub_ref > 0)	    SU_DEBUG_7(("su_home_unref: subhome %p with destructor %p has still %u refs\n",			subhome, subb->sub_destructor, subb->sub_ref));#endif	  subb->sub_ref = 0;	/* zap them all */	  _su_home_deinit(subhome);	}	else if (su_is_preloaded(b, b->sub_nodes[i].sua_data))	  continue;	free(b->sub_nodes[i].sua_data);      }    }    if (b->sub_preload && !b->sub_preauto)      free(b->sub_preload);    if (b->sub_stats)      free(b->sub_stats);    if (!b->sub_auto)      free(b);    home->suh_blocks = NULL;  }  home->suh_lock = NULL;}/** Free memory blocks allocated through home. * * The function @c su_home_deinit() frees the memory blocks associated with * the home object. * * @param home pointer to home object */void su_home_deinit(su_home_t *home){  if (MEMLOCK(home)) {    assert(home->suh_blocks && home->suh_blocks->sub_ref == 0);    _su_home_deinit(home);    /* UNLOCK(home); */  }}/**Move allocations from a su_home_t object to another. * * The function su_home_move() moves allocations made through the @a src * home object under the @a dst home object. It is handy, for example, if an * operation allocates some number of blocks that should be freed upon an * error. It uses a temporary home and moves the blocks from temporary to a * proper home when successful, but frees the temporary home upon an error. * * If @a src has destructor, it is called before starting to move. * * @param dst destination home * @param src source home * * @retval 0 if succesful * @retval -1 upon an error */int su_home_move(su_home_t *dst, su_home_t *src){  unsigned i, n, n2, used;  su_block_t *s, *d, *d2;  if (src == NULL || dst == src)    return 0;  if (dst) {    s = MEMLOCK(src); d = MEMLOCK(dst);    if (s && s->sub_n) {      if (s->sub_destructor) {	void (*destructor)(void *) = s->sub_destructor;	s->sub_destructor = NULL;	destructor(src);      }      if (d) 	used = s->sub_used + d->sub_used;      else	used = s->sub_used;      if ((used && d == NULL) || 3 * used > 2 * d->sub_n) {	if (d)	  for (n = n2 = d->sub_n; 3 * used > 2 * n2; n2 = 4 * n2 + 3)	    ;	else	  n = 0, n2 = s->sub_n;	if (!(d2 = su_hash_alloc(n2))) {	  UNLOCK(dst); UNLOCK(src);	  return -1;	}	dst->suh_blocks = d2;      	for (i = 0; i < n; i++)	  if (d->sub_nodes[i].sua_data) 	    su_block_add(d2, d->sub_nodes[i].sua_data)[0] = d->sub_nodes[i];	if (d) {	  d2->sub_parent = d->sub_parent;	  d2->sub_ref = d->sub_ref;	  d2->sub_preload = d->sub_preload;	  d2->sub_prsize = d->sub_prsize;	  d2->sub_prused = d->sub_prused;	  d2->sub_preauto = d->sub_preauto;	  d2->sub_stats = d->sub_stats;	}	if (d && !d->sub_auto)	  free(d);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -