os_alloc.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:7k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: os_alloc.c,v 11.18 2000/11/30 00:58:42 ubell Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #endif
  16. #include "db_int.h"
  17. #include "os_jump.h"
  18. #ifdef DIAGNOSTIC
  19. static void __os_guard __P((void));
  20. #endif
  21. /*
  22.  * !!!
  23.  * Correct for systems that return NULL when you allocate 0 bytes of memory.
  24.  * There are several places in DB where we allocate the number of bytes held
  25.  * by the key/data item, and it can be 0.  Correct here so that malloc never
  26.  * returns a NULL for that reason (which behavior is permitted by ANSI).  We
  27.  * could make these calls macros on non-Alpha architectures (that's where we
  28.  * saw the problem), but it's probably not worth the autoconf complexity.
  29.  *
  30.  * !!!
  31.  * Correct for systems that don't set errno when malloc and friends fail.
  32.  *
  33.  * Out of memory.
  34.  * We wish to hold the whole sky,
  35.  * But we never will.
  36.  */
  37. /*
  38.  * __os_strdup --
  39.  * The strdup(3) function for DB.
  40.  *
  41.  * PUBLIC: int __os_strdup __P((DB_ENV *, const char *, void *));
  42.  */
  43. int
  44. __os_strdup(dbenv, str, storep)
  45. DB_ENV *dbenv;
  46. const char *str;
  47. void *storep;
  48. {
  49. size_t size;
  50. int ret;
  51. void *p;
  52. *(void **)storep = NULL;
  53. size = strlen(str) + 1;
  54. if ((ret = __os_malloc(dbenv, size, NULL, &p)) != 0)
  55. return (ret);
  56. memcpy(p, str, size);
  57. *(void **)storep = p;
  58. return (0);
  59. }
  60. /*
  61.  * __os_calloc --
  62.  * The calloc(3) function for DB.
  63.  *
  64.  * PUBLIC: int __os_calloc __P((DB_ENV *, size_t, size_t, void *));
  65.  */
  66. int
  67. __os_calloc(dbenv, num, size, storep)
  68. DB_ENV *dbenv;
  69. size_t num, size;
  70. void *storep;
  71. {
  72. void *p;
  73. int ret;
  74. size *= num;
  75. if ((ret = __os_malloc(dbenv, size, NULL, &p)) != 0)
  76. return (ret);
  77. memset(p, 0, size);
  78. *(void **)storep = p;
  79. return (0);
  80. }
  81. /*
  82.  * __os_malloc --
  83.  * The malloc(3) function for DB.
  84.  *
  85.  * PUBLIC: int __os_malloc __P((DB_ENV *, size_t, void *(*)(size_t), void *));
  86.  */
  87. int
  88. __os_malloc(dbenv, size, db_malloc, storep)
  89. DB_ENV *dbenv;
  90. size_t size;
  91. void *(*db_malloc) __P((size_t)), *storep;
  92. {
  93. int ret;
  94. void *p;
  95. *(void **)storep = NULL;
  96. /* Never allocate 0 bytes -- some C libraries don't like it. */
  97. if (size == 0)
  98. ++size;
  99. #ifdef DIAGNOSTIC
  100. else
  101. ++size; /* Add room for a guard byte. */
  102. #endif
  103. /* Some C libraries don't correctly set errno when malloc(3) fails. */
  104. __os_set_errno(0);
  105. if (db_malloc != NULL)
  106. p = db_malloc(size);
  107. else if (__db_jump.j_malloc != NULL)
  108. p = __db_jump.j_malloc(size);
  109. else
  110. p = malloc(size);
  111. if (p == NULL) {
  112. ret = __os_get_errno();
  113. if (ret == 0) {
  114. __os_set_errno(ENOMEM);
  115. ret = ENOMEM;
  116. }
  117. __db_err(dbenv,
  118.     "malloc: %s: %lu", strerror(ret), (u_long)size);
  119. return (ret);
  120. }
  121. #ifdef DIAGNOSTIC
  122. /*
  123.  * Guard bytes: if #DIAGNOSTIC is defined, we allocate an additional
  124.  * byte after the memory and set it to a special value that we check
  125.  * for when the memory is free'd.  This is fine for structures, but
  126.  * not quite so fine for strings.  There are places in DB where memory
  127.  * is allocated sufficient to hold the largest possible string that
  128.  * we'll see, and then only some subset of the memory is used.  To
  129.  * support this usage, the __os_freestr() function checks the byte
  130.  * after the string's nul, which may or may not be the last byte in
  131.  * the originally allocated memory.
  132.  */
  133. memset(p, CLEAR_BYTE, size); /* Initialize guard byte. */
  134. #endif
  135. *(void **)storep = p;
  136. return (0);
  137. }
  138. /*
  139.  * __os_realloc --
  140.  * The realloc(3) function for DB.
  141.  *
  142.  * PUBLIC: int __os_realloc __P((DB_ENV *,
  143.  * PUBLIC:     size_t, void *(*)(void *, size_t), void *));
  144.  */
  145. int
  146. __os_realloc(dbenv, size, db_realloc, storep)
  147. DB_ENV *dbenv;
  148. size_t size;
  149. void *(*db_realloc) __P((void *, size_t)), *storep;
  150. {
  151. int ret;
  152. void *p, *ptr;
  153. ptr = *(void **)storep;
  154. /* If we haven't yet allocated anything yet, simply call malloc. */
  155. if (ptr == NULL && db_realloc == NULL)
  156. return (__os_malloc(dbenv, size, NULL, storep));
  157. /* Never allocate 0 bytes -- some C libraries don't like it. */
  158. if (size == 0)
  159. ++size;
  160. #ifdef DIAGNOSTIC
  161. else
  162. ++size; /* Add room for a guard byte. */
  163. #endif
  164. /*
  165.  * Some C libraries don't correctly set errno when realloc(3) fails.
  166.  *
  167.  * Don't overwrite the original pointer, there are places in DB we
  168.  * try to continue after realloc fails.
  169.  */
  170. __os_set_errno(0);
  171. if (db_realloc != NULL)
  172. p = db_realloc(ptr, size);
  173. else if (__db_jump.j_realloc != NULL)
  174. p = __db_jump.j_realloc(ptr, size);
  175. else
  176. p = realloc(ptr, size);
  177. if (p == NULL) {
  178. if ((ret = __os_get_errno()) == 0) {
  179. ret = ENOMEM;
  180. __os_set_errno(ENOMEM);
  181. }
  182. __db_err(dbenv,
  183.     "realloc: %s: %lu", strerror(ret), (u_long)size);
  184. return (ret);
  185. }
  186. #ifdef DIAGNOSTIC
  187. ((u_int8_t *)p)[size - 1] = CLEAR_BYTE; /* Initialize guard byte. */
  188. #endif
  189. *(void **)storep = p;
  190. return (0);
  191. }
  192. /*
  193.  * __os_free --
  194.  * The free(3) function for DB.
  195.  *
  196.  * PUBLIC: void __os_free __P((void *, size_t));
  197.  */
  198. void
  199. __os_free(ptr, size)
  200. void *ptr;
  201. size_t size;
  202. {
  203. #ifdef DIAGNOSTIC
  204. if (size != 0) {
  205. /*
  206.  * Check that the guard byte (one past the end of the memory) is
  207.  * still CLEAR_BYTE.
  208.  */
  209. if (((u_int8_t *)ptr)[size] != CLEAR_BYTE)
  210.  __os_guard();
  211. /* Clear memory. */
  212. if (size != 0)
  213. memset(ptr, CLEAR_BYTE, size);
  214. }
  215. #else
  216. COMPQUIET(size, 0);
  217. #endif
  218. if (__db_jump.j_free != NULL)
  219. __db_jump.j_free(ptr);
  220. else
  221. free(ptr);
  222. }
  223. /*
  224.  * __os_freestr --
  225.  * The free(3) function for DB, freeing a string.
  226.  *
  227.  * PUBLIC: void __os_freestr __P((void *));
  228.  */
  229. void
  230. __os_freestr(ptr)
  231. void *ptr;
  232. {
  233. #ifdef DIAGNOSTIC
  234. size_t size;
  235. size = strlen(ptr) + 1;
  236. /*
  237.  * Check that the guard byte (one past the end of the memory) is
  238.  * still CLEAR_BYTE.
  239.  */
  240. if (((u_int8_t *)ptr)[size] != CLEAR_BYTE)
  241.  __os_guard();
  242. /* Clear memory. */
  243. memset(ptr, CLEAR_BYTE, size);
  244. #endif
  245. if (__db_jump.j_free != NULL)
  246. __db_jump.j_free(ptr);
  247. else
  248. free(ptr);
  249. }
  250. #ifdef DIAGNOSTIC
  251. /*
  252.  * __os_guard --
  253.  * Complain and abort.
  254.  */
  255. static void
  256. __os_guard()
  257. {
  258. /*
  259.  * Eventually, once we push a DB_ENV handle down to these
  260.  * routines, we should use the standard output channels.
  261.  */
  262. fprintf(stderr, "Guard byte incorrect during free.n");
  263. abort();
  264. /* NOTREACHED */
  265. }
  266. #endif
  267. /*
  268.  * __ua_memcpy --
  269.  * Copy memory to memory without relying on any kind of alignment.
  270.  *
  271.  * There are places in DB that we have unaligned data, for example,
  272.  * when we've stored a structure in a log record as a DBT, and now
  273.  * we want to look at it.  Unfortunately, if you have code like:
  274.  *
  275.  * struct a {
  276.  * int x;
  277.  * } *p;
  278.  *
  279.  * void *func_argument;
  280.  * int local;
  281.  *
  282.  * p = (struct a *)func_argument;
  283.  * memcpy(&local, p->x, sizeof(local));
  284.  *
  285.  * compilers optimize to use inline instructions requiring alignment,
  286.  * and records in the log don't have any particular alignment.  (This
  287.  * isn't a compiler bug, because it's a structure they're allowed to
  288.  * assume alignment.)
  289.  *
  290.  * Casting the memcpy arguments to (u_int8_t *) appears to work most
  291.  * of the time, but we've seen examples where it wasn't sufficient
  292.  * and there's nothing in ANSI C that requires that work.
  293.  *
  294.  * PUBLIC: void *__ua_memcpy __P((void *, const void *, size_t));
  295.  */
  296. void *
  297. __ua_memcpy(dst, src, len)
  298. void *dst;
  299. const void *src;
  300. size_t len;
  301. {
  302. return ((void *)memcpy(dst, src, len));
  303. }