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 (assert_on_error) {
142
ut_print_timestamp(stderr);
145
" InnoDB: We now intentionally"
146
" generate a seg fault so that\n"
147
"InnoDB: on Linux we get a stack trace.\n");
149
if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
156
#ifdef UNIV_SET_MEM_TO_ZERO
157
memset(ret, '\0', n + sizeof(ut_mem_block_t));
161
UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t));
163
((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t);
164
((ut_mem_block_t*)ret)->magic_n = UT_MEM_MAGIC_N;
166
ut_total_allocated_memory += n + sizeof(ut_mem_block_t);
168
UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list,
169
((ut_mem_block_t*)ret));
170
os_fast_mutex_unlock(&ut_list_mutex);
172
return((void*)((byte*)ret + sizeof(ut_mem_block_t)));
175
/**************************************************************************
176
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
182
/* out, own: allocated memory */
183
ulint n) /* in: number of bytes to allocate */
185
return(ut_malloc_low(n, TRUE, TRUE));
188
/**************************************************************************
189
Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
190
out. It cannot be used if we want to return an error message. Prints to
191
stderr a message if fails. */
196
/* out: TRUE if succeeded */
197
ulint n) /* in: try to allocate this many bytes */
204
ut_print_timestamp(stderr);
206
" InnoDB: Error: cannot allocate"
207
" %lu bytes of memory for\n"
208
"InnoDB: a BLOB with malloc! Total allocated memory\n"
209
"InnoDB: by InnoDB %lu bytes."
210
" Operating system errno: %d\n"
211
"InnoDB: Check if you should increase"
212
" the swap file or\n"
213
"InnoDB: ulimits of your operating system.\n"
214
"InnoDB: On FreeBSD check you have"
215
" compiled the OS with\n"
216
"InnoDB: a big enough maximum process size.\n",
218
(ulong) ut_total_allocated_memory,
228
/**************************************************************************
229
Frees a memory block allocated with ut_malloc. */
234
void* ptr) /* in, own: memory block */
236
ut_mem_block_t* block;
238
block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
240
os_fast_mutex_lock(&ut_list_mutex);
242
ut_a(block->magic_n == UT_MEM_MAGIC_N);
243
ut_a(ut_total_allocated_memory >= block->size);
245
ut_total_allocated_memory -= block->size;
247
UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
250
os_fast_mutex_unlock(&ut_list_mutex);
253
/**************************************************************************
254
Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not
255
use this function because the allocation functions in mem0mem.h are the
256
recommended ones in InnoDB.
258
man realloc in Linux, 2004:
260
realloc() changes the size of the memory block pointed to
261
by ptr to size bytes. The contents will be unchanged to
262
the minimum of the old and new sizes; newly allocated mem�
263
ory will be uninitialized. If ptr is NULL, the call is
264
equivalent to malloc(size); if size is equal to zero, the
265
call is equivalent to free(ptr). Unless ptr is NULL, it
266
must have been returned by an earlier call to malloc(),
267
calloc() or realloc().
270
realloc() returns a pointer to the newly allocated memory,
271
which is suitably aligned for any kind of variable and may
272
be different from ptr, or NULL if the request fails. If
273
size was equal to 0, either NULL or a pointer suitable to
274
be passed to free() is returned. If realloc() fails the
275
original block is left untouched - it is not freed or
281
/* out, own: pointer to new mem block or NULL */
282
void* ptr, /* in: pointer to old block or NULL */
283
ulint size) /* in: desired size */
285
ut_mem_block_t* block;
292
return(ut_malloc(size));
301
block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));
303
ut_a(block->magic_n == UT_MEM_MAGIC_N);
305
old_size = block->size - sizeof(ut_mem_block_t);
307
if (size < old_size) {
313
new_ptr = ut_malloc(size);
315
if (new_ptr == NULL) {
320
/* Copy the old data from ptr */
321
ut_memcpy(new_ptr, ptr, min_size);
328
/**************************************************************************
329
Frees in shutdown all allocated memory not freed yet. */
332
ut_free_all_mem(void)
333
/*=================*/
335
ut_mem_block_t* block;
337
os_fast_mutex_free(&ut_list_mutex);
339
while ((block = UT_LIST_GET_FIRST(ut_mem_block_list))) {
341
ut_a(block->magic_n == UT_MEM_MAGIC_N);
342
ut_a(ut_total_allocated_memory >= block->size);
344
ut_total_allocated_memory -= block->size;
346
UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
350
if (ut_total_allocated_memory != 0) {
352
"InnoDB: Warning: after shutdown"
353
" total allocated memory is %lu\n",
354
(ulong) ut_total_allocated_memory);
358
/**************************************************************************
359
Copies up to size - 1 characters from the NUL-terminated string src to
360
dst, NUL-terminating the result. Returns strlen(src), so truncation
361
occurred if the return value >= size. */
366
/* out: strlen(src) */
367
char* dst, /* in: destination buffer */
368
const char* src, /* in: source buffer */
369
ulint size) /* in: size of destination buffer */
371
ulint src_size = strlen(src);
374
ulint n = ut_min(src_size, size - 1);
383
/**************************************************************************
384
Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last
385
(size - 1) bytes of src, not the first. */
390
/* out: strlen(src) */
391
char* dst, /* in: destination buffer */
392
const char* src, /* in: source buffer */
393
ulint size) /* in: size of destination buffer */
395
ulint src_size = strlen(src);
398
ulint n = ut_min(src_size, size - 1);
400
memcpy(dst, src + src_size - n, n + 1);
406
/**************************************************************************
407
Make a quoted copy of a NUL-terminated string. Leading and trailing
408
quotes will not be included; only embedded quotes will be escaped.
409
See also ut_strlenq() and ut_memcpyq(). */
414
/* out: pointer to end of dest */
415
char* dest, /* in: output buffer */
416
char q, /* in: the quote character */
417
const char* src) /* in: null-terminated string */
420
if ((*dest++ = *src++) == q) {
428
/**************************************************************************
429
Make a quoted copy of a fixed-length string. Leading and trailing
430
quotes will not be included; only embedded quotes will be escaped.
431
See also ut_strlenq() and ut_strcpyq(). */
436
/* out: pointer to end of dest */
437
char* dest, /* in: output buffer */
438
char q, /* in: the quote character */
439
const char* src, /* in: string to be quoted */
440
ulint len) /* in: length of src */
442
const char* srcend = src + len;
444
while (src < srcend) {
445
if ((*dest++ = *src++) == q) {
453
/**************************************************************************
454
Return the number of times s2 occurs in s1. Overlapping instances of s2
455
are only counted once. */
460
/* out: the number of times s2 occurs in s1 */
461
const char* s1, /* in: string to search in */
462
const char* s2) /* in: string to search for */
465
ulint len = strlen(s2);
487
/**************************************************************************
488
Replace every occurrence of s1 in str with s2. Overlapping instances of s1
489
are only replaced once. */
494
/* out, own: modified string, must be
495
freed with mem_free() */
496
const char* str, /* in: string to operate on */
497
const char* s1, /* in: string to replace */
498
const char* s2) /* in: string to replace s1 with */
503
ulint str_len = strlen(str);
504
ulint s1_len = strlen(s1);
505
ulint s2_len = strlen(s2);
507
int len_delta = (int)s2_len - (int)s1_len;
509
str_end = str + str_len;
511
if (len_delta <= 0) {
514
count = ut_strcount(str, s1);
517
new_str = mem_alloc(str_len + count * len_delta + 1);
521
const char* next = strstr(str, s1);
527
memcpy(ptr, str, next - str);
530
if (next == str_end) {
535
memcpy(ptr, s2, s2_len);