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

📄 su_alloc.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
  if (home->suh_blocks == NULL)     su_home_init(home);  sub = MEMLOCK(home);  if (!sub->sub_preload) {    size_t size;    void *preload;    size = n * ALIGN(isize);    if (size > 65535)		/* We have 16 bits... */      size = 65535 & (ALIGNMENT - 1);    preload = malloc(size);    home->suh_blocks->sub_preload = preload;    home->suh_blocks->sub_prsize = (unsigned)size;  }  UNLOCK(home);}/** Preload a memory home from stack. * * Initializes a memory home using an area allocated from stack. Poor man's * alloca(). */su_home_t *su_home_auto(void *area, isize_t 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;  if (size > INT_MAX)    size = INT_MAX;  home = memset(p, 0, homesize);  home->suh_size = (int)size;  sub = memset(p + homesize, 0, subsize);  home->suh_blocks = sub;  if (size > prepsize + 65535)    size = prepsize + 65535;  sub->sub_n = SUB_N_AUTO;  sub->sub_ref = 1;  sub->sub_preload = p + prepsize;  sub->sub_prsize = (unsigned)(size - prepsize);  sub->sub_hauto = 1;  sub->sub_auto = 1;  sub->sub_preauto = 1;  sub->sub_auto_all = 1;  return home;}/** Reallocate a memory block. * *   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 *   A pointer to the allocated memory block or *   NULL if an error occurred. */void *su_realloc(su_home_t *home, void *data, isize_t size){  void *ndata;  su_alloc_t *sua;  su_block_t *sub;  size_t p;  size_t term = 0 - 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 = (unsigned)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) {    size_t 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 = (unsigned)p2;      sua->sua_size = (unsigned)size;#if MEMCHECK_EXTRA      memcpy((char *)data + size, &term, sizeof (term));#endif      UNLOCK(home);      return data;    }  }  else if (size < (size_t)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 = (unsigned)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,	   (size_t)sua->sua_size < size	   ? (size_t)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 = (unsigned)size;  }  UNLOCK(home);  return ndata;}/**Check if a memory block has been allocated from the @a home. * * Check if the given memory block has been allocated from the home. * * @param home pointer to memory pool object * @param memory ponter to memory block * * @retval 1 if @a memory has been allocated from @a home. * @retval 0 otherwise * * @since New in @VERSION_1_12_4. */int su_in_home(su_home_t *home, void const *memory){  su_alloc_t *sua;  su_block_t *sub;  int retval = 0;  if (!home || !memory)    return 0;  sub = MEMLOCK(home);  if (sub) {    sua = su_block_find(sub, memory);    retval = su_alloc_check(sub, sua);    UNLOCK(home);  }    return retval;}/**Allocate and zero a memory block. * * 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, isize_t 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 * * Allocates a structure with a given size, zeros * it, and initializes the size field to the given size.  The size field * is an int at the beginning of the structure. Note that it has type of int.  * * @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)); *    * @endcode * After calling su_salloc() we get a pointer t to a struct test, * initialized to zero except the tst_size field, which is initialized to * sizeof (*t). * * @return A pointer to the allocated structure, or NULL upon an error. */void *su_salloc(su_home_t *home, isize_t size){  struct { int size; } *retval;  if (size < sizeof (*retval))    size = sizeof (*retval);  if (size > INT_MAX)    return (void)(errno = ENOMEM), NULL;  if (home) {    retval = sub_alloc(home, MEMLOCK(home), size, 1);    UNLOCK(home);  }  else    retval = calloc(1, size);  if (retval)    retval->size = (int)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;}/** Increase refcount and obtain exclusive lock on home.  * * @note The #su_home_t structure must be created with su_home_new() or * su_home_clone(), or initialized with su_home_init() before using this * function.  * * In order to enable actual locking, use su_home_threadsafe(), too.  * Otherwise the su_home_mutex_lock() will just increase the reference * count. */int su_home_mutex_lock(su_home_t *home){  int error;  if (home == NULL)    return su_seterrno(EFAULT);  if (home->suh_blocks == NULL || !su_home_ref(home))    return su_seterrno(EINVAL);  /* Uninitialized home */  if (!home->suh_lock)    return 0;			/* No-op */  error = _su_home_mutex_locker(home->suh_lock);  if (error)    return su_seterrno(error);  return 0;}/** Release exclusive lock on home and decrease refcount (if home is threadsafe). * * @sa su_home_unlock(). */int su_home_mutex_unlock(su_home_t *home){  if (home == NULL)    return su_seterrno(EFAULT);  if (home->suh_lock) {    int error = _su_home_mutex_unlocker(home->suh_lock);    if (error)      return su_seterrno(error);  }  if (home->suh_blocks == NULL)    return su_seterrno(EINVAL), -1; /* Uninitialized home */  su_home_unref(home);  return 0;}/** Obtain exclusive lock on home without increasing refcount.  * * Unless su_home_threadsafe() has been used to intialize locking on home * object the function just returns -1. * * @return 0 if successful, -1 if not threadsafe, error code otherwise. * * @sa su_home_mutex_lock(), su_home_unlock(), su_home_trylock(). * * @NEW_1_12_8 */int su_home_lock(su_home_t *home){  if (home == NULL)    return EFAULT;  if (home->suh_lock == NULL)    return -1;			/* No-op */  return _su_home_mutex_locker(home->suh_lock);}/** Try to obtain exclusive lock on home without increasing refcount.  * * @return 0 if successful, -1 if not threadsafe,  * EBUSY if already locked, error code otherwise. * * @sa su_home_lock(), su_home_unlock(). * * @NEW_1_12_8 */int su_home_trylock(su_home_t *home){  if (home == NULL)    return EFAULT;  if (home->suh_lock == NULL)    return -1;			/* No-op */  return _su_home_mutex_trylocker(home->suh_lock);}/** Release exclusive lock on home. * * Release lock without decreasing refcount. * * @return 0 if successful, -1 if not threadsafe, error code otherwise. * * @sa su_home_lock(), su_home_trylock(), su_home_mutex_unlock(). * * @NEW_1_12_8 */int su_home_unlock(su_home_t *home){  if (home == NULL)    return EFAULT;  if (home->suh_lock == NULL)    return -1;			/* No-op */  return _su_home_mutex_unlocker(home->suh_lock);}/** Initialize statistics structure */void su_home_init_stats(su_home_t *home){  su_block_t *sub;  size_t 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 = (int)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,		       isize_t size){  su_block_t *sub;  if (hs == NULL || size < (sizeof hs->hs_size))    return;  memset((void *)hs, 0, size);  sub = MEMLOCK(home);  if (sub && sub->sub_stats) {    int sub_size = sub->sub_stats->hs_size;    if (sub_size > (int)size)      sub_size = (int)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 = sub_size;  }  UNLOCK(home);}static void su_home_stats_alloc(su_block_t *sub, void *p, void *preload,			 size_t size, int zero){  su_home_stat_t *hs = sub->sub_stats;  size_t 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;  size_t 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 + -