os_alloc.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:10k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1997-2002
  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.32 2002/08/06 04:57:07 bostic 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. #ifdef DIAGNOSTIC
  18. static void __os_guard __P((DB_ENV *));
  19. union __db_alloc {
  20. size_t size;
  21. double align;
  22. };
  23. #endif
  24. /*
  25.  * !!!
  26.  * Correct for systems that return NULL when you allocate 0 bytes of memory.
  27.  * There are several places in DB where we allocate the number of bytes held
  28.  * by the key/data item, and it can be 0.  Correct here so that malloc never
  29.  * returns a NULL for that reason (which behavior is permitted by ANSI).  We
  30.  * could make these calls macros on non-Alpha architectures (that's where we
  31.  * saw the problem), but it's probably not worth the autoconf complexity.
  32.  *
  33.  * !!!
  34.  * Correct for systems that don't set errno when malloc and friends fail.
  35.  *
  36.  * !!!
  37.  * There is no circumstance in which we can call __os_umalloc, __os_urealloc
  38.  * or __os_ufree without an environment handle, as we need one to determine
  39.  * whether or not to use an application-specified malloc function.  If we
  40.  * don't have an environment handle, we should be calling __os_XXX instead.
  41.  * Make DIAGNOSTIC blow up if we get this wrong.
  42.  *
  43.  * Out of memory.
  44.  * We wish to hold the whole sky,
  45.  * But we never will.
  46.  */
  47. /*
  48.  * __os_umalloc --
  49.  * A malloc(3) function that will use, in order of preference,
  50.  * the allocation function specified to the DB handle, the DB_ENV
  51.  * handle, or __os_malloc.
  52.  *
  53.  * PUBLIC: int __os_umalloc __P((DB_ENV *, size_t, void *));
  54.  */
  55. int
  56. __os_umalloc(dbenv, size, storep)
  57. DB_ENV *dbenv;
  58. size_t size;
  59. void *storep;
  60. {
  61. int ret;
  62. /* Require an environment handle. */
  63. DB_ASSERT(dbenv != NULL);
  64. /* Never allocate 0 bytes -- some C libraries don't like it. */
  65. if (size == 0)
  66. ++size;
  67. if (dbenv == NULL || dbenv->db_malloc == NULL) {
  68. if (DB_GLOBAL(j_malloc) != NULL)
  69. *(void **)storep = DB_GLOBAL(j_malloc)(size);
  70. else
  71. *(void **)storep = malloc(size);
  72. if (*(void **)storep == NULL) {
  73. /*
  74.  *  Correct error return, see __os_malloc.
  75.  */
  76. if ((ret = __os_get_errno()) == 0) {
  77. ret = ENOMEM;
  78. __os_set_errno(ENOMEM);
  79. }
  80. __db_err(dbenv,
  81.     "malloc: %s: %lu", strerror(ret), (u_long)size);
  82. return (ret);
  83. }
  84. return (0);
  85. }
  86. if ((*(void **)storep = dbenv->db_malloc(size)) == NULL) {
  87. __db_err(dbenv, "User-specified malloc function returned NULL");
  88. return (ENOMEM);
  89. }
  90. return (0);
  91. }
  92. /*
  93.  * __os_urealloc --
  94.  * realloc(3) counterpart to __os_umalloc.
  95.  *
  96.  * PUBLIC: int __os_urealloc __P((DB_ENV *, size_t, void *));
  97.  */
  98. int
  99. __os_urealloc(dbenv, size, storep)
  100. DB_ENV *dbenv;
  101. size_t size;
  102. void *storep;
  103. {
  104. int ret;
  105. void *ptr;
  106. ptr = *(void **)storep;
  107. /* Require an environment handle. */
  108. DB_ASSERT(dbenv != NULL);
  109. /* Never allocate 0 bytes -- some C libraries don't like it. */
  110. if (size == 0)
  111. ++size;
  112. if (dbenv == NULL || dbenv->db_realloc == NULL) {
  113. if (ptr == NULL)
  114. return (__os_umalloc(dbenv, size, storep));
  115. if (DB_GLOBAL(j_realloc) != NULL)
  116. *(void **)storep = DB_GLOBAL(j_realloc)(ptr, size);
  117. else
  118. *(void **)storep = realloc(ptr, size);
  119. if (*(void **)storep == NULL) {
  120. /*
  121.  * Correct errno, see __os_realloc.
  122.  */
  123. if ((ret = __os_get_errno()) == 0) {
  124. ret = ENOMEM;
  125. __os_set_errno(ENOMEM);
  126. }
  127. __db_err(dbenv,
  128.     "realloc: %s: %lu", strerror(ret), (u_long)size);
  129. return (ret);
  130. }
  131. return (0);
  132. }
  133. if ((*(void **)storep = dbenv->db_realloc(ptr, size)) == NULL) {
  134. __db_err(dbenv,
  135.     "User-specified realloc function returned NULL");
  136. return (ENOMEM);
  137. }
  138. return (0);
  139. }
  140. /*
  141.  * __os_ufree --
  142.  * free(3) counterpart to __os_umalloc.
  143.  *
  144.  * PUBLIC: int __os_ufree __P((DB_ENV *, void *));
  145.  */
  146. int
  147. __os_ufree(dbenv, ptr)
  148. DB_ENV *dbenv;
  149. void *ptr;
  150. {
  151. /* Require an environment handle. */
  152. DB_ASSERT(dbenv != NULL);
  153. if (dbenv != NULL && dbenv->db_free != NULL)
  154. dbenv->db_free(ptr);
  155. else if (DB_GLOBAL(j_free) != NULL)
  156. DB_GLOBAL(j_free)(ptr);
  157. else
  158. free(ptr);
  159. return (0);
  160. }
  161. /*
  162.  * __os_strdup --
  163.  * The strdup(3) function for DB.
  164.  *
  165.  * PUBLIC: int __os_strdup __P((DB_ENV *, const char *, void *));
  166.  */
  167. int
  168. __os_strdup(dbenv, str, storep)
  169. DB_ENV *dbenv;
  170. const char *str;
  171. void *storep;
  172. {
  173. size_t size;
  174. int ret;
  175. void *p;
  176. *(void **)storep = NULL;
  177. size = strlen(str) + 1;
  178. if ((ret = __os_malloc(dbenv, size, &p)) != 0)
  179. return (ret);
  180. memcpy(p, str, size);
  181. *(void **)storep = p;
  182. return (0);
  183. }
  184. /*
  185.  * __os_calloc --
  186.  * The calloc(3) function for DB.
  187.  *
  188.  * PUBLIC: int __os_calloc __P((DB_ENV *, size_t, size_t, void *));
  189.  */
  190. int
  191. __os_calloc(dbenv, num, size, storep)
  192. DB_ENV *dbenv;
  193. size_t num, size;
  194. void *storep;
  195. {
  196. void *p;
  197. int ret;
  198. size *= num;
  199. if ((ret = __os_malloc(dbenv, size, &p)) != 0)
  200. return (ret);
  201. memset(p, 0, size);
  202. *(void **)storep = p;
  203. return (0);
  204. }
  205. /*
  206.  * __os_malloc --
  207.  * The malloc(3) function for DB.
  208.  *
  209.  * PUBLIC: int __os_malloc __P((DB_ENV *, size_t, void *));
  210.  */
  211. int
  212. __os_malloc(dbenv, size, storep)
  213. DB_ENV *dbenv;
  214. size_t size;
  215. void *storep;
  216. {
  217. int ret;
  218. void *p;
  219. *(void **)storep = NULL;
  220. /* Never allocate 0 bytes -- some C libraries don't like it. */
  221. if (size == 0)
  222. ++size;
  223. #ifdef DIAGNOSTIC
  224. /* Add room for size and a guard byte. */
  225. size += sizeof(union __db_alloc) + 1;
  226. #endif
  227. if (DB_GLOBAL(j_malloc) != NULL)
  228. p = DB_GLOBAL(j_malloc)(size);
  229. else
  230. p = malloc(size);
  231. if (p == NULL) {
  232. /*
  233.  * Some C libraries don't correctly set errno when malloc(3)
  234.  * fails.  We'd like to 0 out errno before calling malloc,
  235.  * but it turns out that setting errno is quite expensive on
  236.  * Windows/NT in an MT environment.
  237.  */
  238. if ((ret = __os_get_errno()) == 0) {
  239. ret = ENOMEM;
  240. __os_set_errno(ENOMEM);
  241. }
  242. __db_err(dbenv,
  243.     "malloc: %s: %lu", strerror(ret), (u_long)size);
  244. return (ret);
  245. }
  246. #ifdef DIAGNOSTIC
  247. /*
  248.  * Guard bytes: if #DIAGNOSTIC is defined, we allocate an additional
  249.  * byte after the memory and set it to a special value that we check
  250.  * for when the memory is free'd.
  251.  */
  252. ((u_int8_t *)p)[size - 1] = CLEAR_BYTE;
  253. ((union __db_alloc *)p)->size = size;
  254. p = &((union __db_alloc *)p)[1];
  255. #endif
  256. *(void **)storep = p;
  257. return (0);
  258. }
  259. /*
  260.  * __os_realloc --
  261.  * The realloc(3) function for DB.
  262.  *
  263.  * PUBLIC: int __os_realloc __P((DB_ENV *, size_t, void *));
  264.  */
  265. int
  266. __os_realloc(dbenv, size, storep)
  267. DB_ENV *dbenv;
  268. size_t size;
  269. void *storep;
  270. {
  271. int ret;
  272. void *p, *ptr;
  273. ptr = *(void **)storep;
  274. /* Never allocate 0 bytes -- some C libraries don't like it. */
  275. if (size == 0)
  276. ++size;
  277. /* If we haven't yet allocated anything yet, simply call malloc. */
  278. if (ptr == NULL)
  279. return (__os_malloc(dbenv, size, storep));
  280. #ifdef DIAGNOSTIC
  281. /* Add room for size and a guard byte. */
  282. size += sizeof(union __db_alloc) + 1;
  283. /* Back up to the real begining */
  284. ptr = &((union __db_alloc *)ptr)[-1];
  285. #endif
  286. /*
  287.  * Don't overwrite the original pointer, there are places in DB we
  288.  * try to continue after realloc fails.
  289.  */
  290. if (DB_GLOBAL(j_realloc) != NULL)
  291. p = DB_GLOBAL(j_realloc)(ptr, size);
  292. else
  293. p = realloc(ptr, size);
  294. if (p == NULL) {
  295. /*
  296.  * Some C libraries don't correctly set errno when malloc(3)
  297.  * fails.  We'd like to 0 out errno before calling malloc,
  298.  * but it turns out that setting errno is quite expensive on
  299.  * Windows/NT in an MT environment.
  300.  */
  301. if ((ret = __os_get_errno()) == 0) {
  302. ret = ENOMEM;
  303. __os_set_errno(ENOMEM);
  304. }
  305. __db_err(dbenv,
  306.     "realloc: %s: %lu", strerror(ret), (u_long)size);
  307. return (ret);
  308. }
  309. #ifdef DIAGNOSTIC
  310. ((u_int8_t *)p)[size - 1] = CLEAR_BYTE; /* Initialize guard byte. */
  311. ((union __db_alloc *)p)->size = size;
  312. p = &((union __db_alloc *)p)[1];
  313. #endif
  314. *(void **)storep = p;
  315. return (0);
  316. }
  317. /*
  318.  * __os_free --
  319.  * The free(3) function for DB.
  320.  *
  321.  * PUBLIC: void __os_free __P((DB_ENV *, void *));
  322.  */
  323. void
  324. __os_free(dbenv, ptr)
  325. DB_ENV *dbenv;
  326. void *ptr;
  327. {
  328. #ifdef DIAGNOSTIC
  329. int size;
  330. /*
  331.  * Check that the guard byte (one past the end of the memory) is
  332.  * still CLEAR_BYTE.
  333.  */
  334. if (ptr == NULL)
  335. return;
  336. ptr = &((union __db_alloc *)ptr)[-1];
  337. size = ((union __db_alloc *)ptr)->size;
  338. if (((u_int8_t *)ptr)[size - 1] != CLEAR_BYTE)
  339.  __os_guard(dbenv);
  340. /* Clear memory. */
  341. if (size != 0)
  342. memset(ptr, CLEAR_BYTE, size);
  343. #endif
  344. COMPQUIET(dbenv, NULL);
  345. if (DB_GLOBAL(j_free) != NULL)
  346. DB_GLOBAL(j_free)(ptr);
  347. else
  348. free(ptr);
  349. }
  350. #ifdef DIAGNOSTIC
  351. /*
  352.  * __os_guard --
  353.  * Complain and abort.
  354.  */
  355. static void
  356. __os_guard(dbenv)
  357. DB_ENV *dbenv;
  358. {
  359. __db_err(dbenv, "Guard byte incorrect during free");
  360. abort();
  361. /* NOTREACHED */
  362. }
  363. #endif
  364. /*
  365.  * __ua_memcpy --
  366.  * Copy memory to memory without relying on any kind of alignment.
  367.  *
  368.  * There are places in DB that we have unaligned data, for example,
  369.  * when we've stored a structure in a log record as a DBT, and now
  370.  * we want to look at it.  Unfortunately, if you have code like:
  371.  *
  372.  * struct a {
  373.  * int x;
  374.  * } *p;
  375.  *
  376.  * void *func_argument;
  377.  * int local;
  378.  *
  379.  * p = (struct a *)func_argument;
  380.  * memcpy(&local, p->x, sizeof(local));
  381.  *
  382.  * compilers optimize to use inline instructions requiring alignment,
  383.  * and records in the log don't have any particular alignment.  (This
  384.  * isn't a compiler bug, because it's a structure they're allowed to
  385.  * assume alignment.)
  386.  *
  387.  * Casting the memcpy arguments to (u_int8_t *) appears to work most
  388.  * of the time, but we've seen examples where it wasn't sufficient
  389.  * and there's nothing in ANSI C that requires that work.
  390.  *
  391.  * PUBLIC: void *__ua_memcpy __P((void *, const void *, size_t));
  392.  */
  393. void *
  394. __ua_memcpy(dst, src, len)
  395. void *dst;
  396. const void *src;
  397. size_t len;
  398. {
  399. return ((void *)memcpy(dst, src, len));
  400. }