1
/************************************************************************
4
(c) 1994, 1995 Innobase Oy
6
Created 5/11/1994 Heikki Tuuri
7
*************************************************************************/
17
#include "os0thread.h"
19
/* This struct is placed first in every allocated memory block */
20
typedef struct ut_mem_block_struct ut_mem_block_t;
22
/* The total amount of memory currently allocated from the OS with malloc */
23
ulint ut_total_allocated_memory = 0;
25
struct ut_mem_block_struct{
26
UT_LIST_NODE_T(ut_mem_block_t) mem_block_list;
27
/* mem block list node */
28
ulint size; /* size of allocated memory */
32
#define UT_MEM_MAGIC_N 1601650166
34
/* List of all memory blocks allocated from the operating system
36
UT_LIST_BASE_NODE_T(ut_mem_block_t) ut_mem_block_list;
38
os_fast_mutex_t ut_list_mutex; /* this protects the list */
40
ibool ut_mem_block_list_inited = FALSE;
42
ulint* ut_mem_null_ptr = NULL;
44
/**************************************************************************
45
Initializes the mem block list at database startup. */
48
ut_mem_block_list_init(void)
49
/*========================*/
51
os_fast_mutex_init(&ut_list_mutex);
52
UT_LIST_INIT(ut_mem_block_list);
53
ut_mem_block_list_inited = TRUE;
56
/**************************************************************************
57
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
58
defined and set_to_zero is TRUE. */
63
/* out, own: allocated memory */
64
ulint n, /* in: number of bytes to allocate */
65
ibool set_to_zero, /* in: TRUE if allocated memory should be
66
set to zero if UNIV_SET_MEM_TO_ZERO is
68
ibool assert_on_error)/* in: if TRUE, we crash mysqld if the
69
memory cannot be allocated */
71
ulint retry_count = 0;
74
ut_ad((sizeof(ut_mem_block_t) % 8) == 0); /* check alignment ok */
76
if (!ut_mem_block_list_inited) {
77
ut_mem_block_list_init();
80
os_fast_mutex_lock(&ut_list_mutex);
82
ret = malloc(n + sizeof(ut_mem_block_t));
84
if (ret == NULL && retry_count < 60) {
85
if (retry_count == 0) {
86
ut_print_timestamp(stderr);
89
" InnoDB: Error: cannot allocate"
91
"InnoDB: memory with malloc!"
92
" Total allocated memory\n"
93
"InnoDB: by InnoDB %lu bytes."
94
" Operating system errno: %lu\n"
95
"InnoDB: Check if you should"
96
" increase the swap file or\n"
97
"InnoDB: ulimits of your operating system.\n"
98
"InnoDB: On FreeBSD check you"
99
" have compiled the OS with\n"
100
"InnoDB: a big enough maximum process size.\n"
101
"InnoDB: Note that in most 32-bit"
102
" computers the process\n"
103
"InnoDB: memory space is limited"
104
" to 2 GB or 4 GB.\n"
105
"InnoDB: We keep retrying"
106
" the allocation for 60 seconds...\n",
107
(ulong) n, (ulong) ut_total_allocated_memory,
109
(ulong) GetLastError()
116
os_fast_mutex_unlock(&ut_list_mutex);
118
/* Sleep for a second and retry the allocation; maybe this is
119
just a temporary shortage of memory */
121
os_thread_sleep(1000000);
129
/* Flush stderr to make more probable that the error
130
message gets in the error file before we generate a seg
135
os_fast_mutex_unlock(&ut_list_mutex);
137
/* Make an intentional seg fault so that we get a stack
139
/* Intentional segfault on NetWare causes an abend. Avoid this
140
by graceful exit handling in ut_a(). */
141
#if (!defined __NETWARE__)
142
if (assert_on_error) {
143
ut_print_timestamp(stderr);
146
" InnoDB: We now intentionally"
147
" generate a seg fault so that\n"
148
"InnoDB: on Linux we get a stack trace.\n");
150
if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
160
#ifdef UNIV_SET_MEM_TO_ZERO
161
memset(ret, '\0', n + sizeof(ut_mem_block_t));
165
UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t));
167
((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t);
168
((ut_mem_block_t*)ret)->magic_n = UT_MEM_MAGIC_N;
170
ut_total_allocated_memory += n + sizeof(ut_mem_block_t);
172
UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list,
173
((ut_mem_block_t*)ret));
174
os_fast_mutex_unlock(&ut_list_mutex);
176
return((void*)((byte*)ret + sizeof(ut_mem_block_t)));
179
/**************************************************************************
180
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
186
/* out, own: allocated memory */
187
ulint n) /* in: number of bytes to allocate */
189
return(ut_malloc_low(n, TRUE, TRUE));
192
/**************************************************************************
193
Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
194
out. It cannot be used if we want to return an error message. Prints to
195
stderr a message if fails. */
200
/* out: TRUE if succeeded */
201
ulint n) /* in: try to allocate this many bytes */
208
ut_print_timestamp(stderr);
210
" InnoDB: Error: cannot allocate"
211
" %lu bytes of memory for\n"
212
"InnoDB: a BLOB with malloc! Total allocated memory\n"
213
"InnoDB: by InnoDB %lu bytes."
214
" Operating system errno: %d\n"
215
"InnoDB: Check if you should increase"
216
" the swap file or\n"
217
"InnoDB: ulimits of your operating system.\n"
218
"InnoDB: On FreeBSD check you have"
219
" compiled the OS with\n"
220
"InnoDB: a big enough maximum process size.\n",
222
(ulong) ut_total_allocated_memory,
232
/**************************************************************************
233
Frees a memory block allocated with ut_malloc. */
238
void* ptr) /* in, own: memory block */
240
ut_mem_block_t* block;
242
block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
244
os_fast_mutex_lock(&ut_list_mutex);
246
ut_a(block->magic_n == UT_MEM_MAGIC_N);
247
ut_a(ut_total_allocated_memory >= block->size);
249
ut_total_allocated_memory -= block->size;
251
UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
254
os_fast_mutex_unlock(&ut_list_mutex);
257
/**************************************************************************
258
Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not
259
use this function because the allocation functions in mem0mem.h are the
260
recommended ones in InnoDB.
262
man realloc in Linux, 2004:
264
realloc() changes the size of the memory block pointed to
265
by ptr to size bytes. The contents will be unchanged to
266
the minimum of the old and new sizes; newly allocated memďż˝
267
ory will be uninitialized. If ptr is NULL, the call is
268
equivalent to malloc(size); if size is equal to zero, the
269
call is equivalent to free(ptr). Unless ptr is NULL, it
270
must have been returned by an earlier call to malloc(),
271
calloc() or realloc().
274
realloc() returns a pointer to the newly allocated memory,
275
which is suitably aligned for any kind of variable and may
276
be different from ptr, or NULL if the request fails. If
277
size was equal to 0, either NULL or a pointer suitable to
278
be passed to free() is returned. If realloc() fails the
279
original block is left untouched - it is not freed or
285
/* out, own: pointer to new mem block or NULL */
286
void* ptr, /* in: pointer to old block or NULL */
287
ulint size) /* in: desired size */
289
ut_mem_block_t* block;
296
return(ut_malloc(size));
305
block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
307
ut_a(block->magic_n == UT_MEM_MAGIC_N);
309
old_size = block->size - sizeof(ut_mem_block_t);
311
if (size < old_size) {
317
new_ptr = ut_malloc(size);
319
if (new_ptr == NULL) {
324
/* Copy the old data from ptr */
325
ut_memcpy(new_ptr, ptr, min_size);
332
/**************************************************************************
333
Frees in shutdown all allocated memory not freed yet. */
336
ut_free_all_mem(void)
337
/*=================*/
339
ut_mem_block_t* block;
341
os_fast_mutex_free(&ut_list_mutex);
343
while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) {
345
ut_a(block->magic_n == UT_MEM_MAGIC_N);
346
ut_a(ut_total_allocated_memory >= block->size);
348
ut_total_allocated_memory -= block->size;
350
UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
354
if (ut_total_allocated_memory != 0) {
356
"InnoDB: Warning: after shutdown"
357
" total allocated memory is %lu\n",
358
(ulong) ut_total_allocated_memory);
362
/**************************************************************************
363
Copies up to size - 1 characters from the NUL-terminated string src to
364
dst, NUL-terminating the result. Returns strlen(src), so truncation
365
occurred if the return value >= size. */
370
/* out: strlen(src) */
371
char* dst, /* in: destination buffer */
372
const char* src, /* in: source buffer */
373
ulint size) /* in: size of destination buffer */
375
ulint src_size = strlen(src);
378
ulint n = ut_min(src_size, size - 1);
387
/**************************************************************************
388
Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last
389
(size - 1) bytes of src, not the first. */
394
/* out: strlen(src) */
395
char* dst, /* in: destination buffer */
396
const char* src, /* in: source buffer */
397
ulint size) /* in: size of destination buffer */
399
ulint src_size = strlen(src);
402
ulint n = ut_min(src_size, size - 1);
404
memcpy(dst, src + src_size - n, n + 1);
410
/**************************************************************************
411
Make a quoted copy of a NUL-terminated string. Leading and trailing
412
quotes will not be included; only embedded quotes will be escaped.
413
See also ut_strlenq() and ut_memcpyq(). */
418
/* out: pointer to end of dest */
419
char* dest, /* in: output buffer */
420
char q, /* in: the quote character */
421
const char* src) /* in: null-terminated string */
424
if ((*dest++ = *src++) == q) {
432
/**************************************************************************
433
Make a quoted copy of a fixed-length string. Leading and trailing
434
quotes will not be included; only embedded quotes will be escaped.
435
See also ut_strlenq() and ut_strcpyq(). */
440
/* out: pointer to end of dest */
441
char* dest, /* in: output buffer */
442
char q, /* in: the quote character */
443
const char* src, /* in: string to be quoted */
444
ulint len) /* in: length of src */
446
const char* srcend = src + len;
448
while (src < srcend) {
449
if ((*dest++ = *src++) == q) {
457
/**************************************************************************
458
Return the number of times s2 occurs in s1. Overlapping instances of s2
459
are only counted once. */
464
/* out: the number of times s2 occurs in s1 */
465
const char* s1, /* in: string to search in */
466
const char* s2) /* in: string to search for */
469
ulint len = strlen(s2);
491
/**************************************************************************
492
Replace every occurrence of s1 in str with s2. Overlapping instances of s1
493
are only replaced once. */
498
/* out, own: modified string, must be
499
freed with mem_free() */
500
const char* str, /* in: string to operate on */
501
const char* s1, /* in: string to replace */
502
const char* s2) /* in: string to replace s1 with */
507
ulint str_len = strlen(str);
508
ulint s1_len = strlen(s1);
509
ulint s2_len = strlen(s2);
511
int len_delta = (int)s2_len - (int)s1_len;
513
str_end = str + str_len;
515
if (len_delta <= 0) {
518
count = ut_strcount(str, s1);
521
new_str = mem_alloc(str_len + count * len_delta + 1);
525
const char* next = strstr(str, s1);
531
memcpy(ptr, str, next - str);
534
if (next == str_end) {
539
memcpy(ptr, s2, s2_len);