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