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 /**************************************************************************
62 /* out, own: allocated memory */
63 ulint n
, /* in: number of bytes to allocate */
64 ibool assert_on_error
)/* in: if TRUE, we crash mysqld if the
65 memory cannot be allocated */
67 ulint retry_count
= 0;
70 ut_ad((sizeof(ut_mem_block_t
) % 8) == 0); /* check alignment ok */
72 if (!ut_mem_block_list_inited
) {
73 ut_mem_block_list_init();
76 os_fast_mutex_lock(&ut_list_mutex
);
78 ret
= malloc(n
+ sizeof(ut_mem_block_t
));
80 if (ret
== NULL
&& retry_count
< 60) {
81 if (retry_count
== 0) {
82 ut_print_timestamp(stderr
);
85 " InnoDB: Error: cannot allocate"
87 "InnoDB: memory with malloc!"
88 " Total allocated memory\n"
89 "InnoDB: by InnoDB %lu bytes."
90 " Operating system errno: %lu\n"
91 "InnoDB: Check if you should"
92 " increase the swap file or\n"
93 "InnoDB: ulimits of your operating system.\n"
94 "InnoDB: On FreeBSD check you"
95 " have compiled the OS with\n"
96 "InnoDB: a big enough maximum process size.\n"
97 "InnoDB: Note that in most 32-bit"
98 " computers the process\n"
99 "InnoDB: memory space is limited"
100 " to 2 GB or 4 GB.\n"
101 "InnoDB: We keep retrying"
102 " the allocation for 60 seconds...\n",
103 (ulong
) n
, (ulong
) ut_total_allocated_memory
,
105 (ulong
) GetLastError()
112 os_fast_mutex_unlock(&ut_list_mutex
);
114 /* Sleep for a second and retry the allocation; maybe this is
115 just a temporary shortage of memory */
117 os_thread_sleep(1000000);
125 /* Flush stderr to make more probable that the error
126 message gets in the error file before we generate a seg
131 os_fast_mutex_unlock(&ut_list_mutex
);
133 /* Make an intentional seg fault so that we get a stack
135 /* Intentional segfault on NetWare causes an abend. Avoid this
136 by graceful exit handling in ut_a(). */
137 #if (!defined __NETWARE__)
138 if (assert_on_error
) {
139 ut_print_timestamp(stderr
);
142 " InnoDB: We now intentionally"
143 " generate a seg fault so that\n"
144 "InnoDB: on Linux we get a stack trace.\n");
146 if (*ut_mem_null_ptr
) ut_mem_null_ptr
= 0;
155 UNIV_MEM_ALLOC(ret
, n
+ sizeof(ut_mem_block_t
));
157 ((ut_mem_block_t
*)ret
)->size
= n
+ sizeof(ut_mem_block_t
);
158 ((ut_mem_block_t
*)ret
)->magic_n
= UT_MEM_MAGIC_N
;
160 ut_total_allocated_memory
+= n
+ sizeof(ut_mem_block_t
);
162 UT_LIST_ADD_FIRST(mem_block_list
, ut_mem_block_list
,
163 ((ut_mem_block_t
*)ret
));
164 os_fast_mutex_unlock(&ut_list_mutex
);
166 return((void*)((byte
*)ret
+ sizeof(ut_mem_block_t
)));
169 /**************************************************************************
170 Frees a memory block allocated with ut_malloc. */
175 void* ptr
) /* in, own: memory block */
177 ut_mem_block_t
* block
;
179 block
= (ut_mem_block_t
*)((byte
*)ptr
- sizeof(ut_mem_block_t
));
181 os_fast_mutex_lock(&ut_list_mutex
);
183 ut_a(block
->magic_n
== UT_MEM_MAGIC_N
);
184 ut_a(ut_total_allocated_memory
>= block
->size
);
186 ut_total_allocated_memory
-= block
->size
;
188 UT_LIST_REMOVE(mem_block_list
, ut_mem_block_list
, block
);
191 os_fast_mutex_unlock(&ut_list_mutex
);
194 /**************************************************************************
195 Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not
196 use this function because the allocation functions in mem0mem.h are the
197 recommended ones in InnoDB.
199 man realloc in Linux, 2004:
201 realloc() changes the size of the memory block pointed to
202 by ptr to size bytes. The contents will be unchanged to
203 the minimum of the old and new sizes; newly allocated memĀ
204 ory will be uninitialized. If ptr is NULL, the call is
205 equivalent to malloc(size); if size is equal to zero, the
206 call is equivalent to free(ptr). Unless ptr is NULL, it
207 must have been returned by an earlier call to malloc(),
208 calloc() or realloc().
211 realloc() returns a pointer to the newly allocated memory,
212 which is suitably aligned for any kind of variable and may
213 be different from ptr, or NULL if the request fails. If
214 size was equal to 0, either NULL or a pointer suitable to
215 be passed to free() is returned. If realloc() fails the
216 original block is left untouched - it is not freed or
222 /* out, own: pointer to new mem block or NULL */
223 void* ptr
, /* in: pointer to old block or NULL */
224 ulint size
) /* in: desired size */
226 ut_mem_block_t
* block
;
233 return(ut_malloc(size
));
242 block
= (ut_mem_block_t
*)((byte
*)ptr
- sizeof(ut_mem_block_t
));
244 ut_a(block
->magic_n
== UT_MEM_MAGIC_N
);
246 old_size
= block
->size
- sizeof(ut_mem_block_t
);
248 if (size
< old_size
) {
254 new_ptr
= ut_malloc(size
);
256 if (new_ptr
== NULL
) {
261 /* Copy the old data from ptr */
262 ut_memcpy(new_ptr
, ptr
, min_size
);
269 /**************************************************************************
270 Frees in shutdown all allocated memory not freed yet. */
273 ut_free_all_mem(void)
274 /*=================*/
276 ut_mem_block_t
* block
;
278 os_fast_mutex_free(&ut_list_mutex
);
280 while ((block
= UT_LIST_GET_FIRST(ut_mem_block_list
))) {
282 ut_a(block
->magic_n
== UT_MEM_MAGIC_N
);
283 ut_a(ut_total_allocated_memory
>= block
->size
);
285 ut_total_allocated_memory
-= block
->size
;
287 UT_LIST_REMOVE(mem_block_list
, ut_mem_block_list
, block
);
291 if (ut_total_allocated_memory
!= 0) {
293 "InnoDB: Warning: after shutdown"
294 " total allocated memory is %lu\n",
295 (ulong
) ut_total_allocated_memory
);
299 /**************************************************************************
300 Copies up to size - 1 characters from the NUL-terminated string src to
301 dst, NUL-terminating the result. Returns strlen(src), so truncation
302 occurred if the return value >= size. */
307 /* out: strlen(src) */
308 char* dst
, /* in: destination buffer */
309 const char* src
, /* in: source buffer */
310 ulint size
) /* in: size of destination buffer */
312 ulint src_size
= strlen(src
);
315 ulint n
= ut_min(src_size
, size
- 1);
324 /**************************************************************************
325 Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last
326 (size - 1) bytes of src, not the first. */
331 /* out: strlen(src) */
332 char* dst
, /* in: destination buffer */
333 const char* src
, /* in: source buffer */
334 ulint size
) /* in: size of destination buffer */
336 ulint src_size
= strlen(src
);
339 ulint n
= ut_min(src_size
, size
- 1);
341 memcpy(dst
, src
+ src_size
- n
, n
+ 1);
347 /**************************************************************************
348 Return the number of times s2 occurs in s1. Overlapping instances of s2
349 are only counted once. */
354 /* out: the number of times s2 occurs in s1 */
355 const char* s1
, /* in: string to search in */
356 const char* s2
) /* in: string to search for */
359 ulint len
= strlen(s2
);
381 /**************************************************************************
382 Replace every occurrence of s1 in str with s2. Overlapping instances of s1
383 are only replaced once. */
388 /* out, own: modified string, must be
389 freed with mem_free() */
390 const char* str
, /* in: string to operate on */
391 const char* s1
, /* in: string to replace */
392 const char* s2
) /* in: string to replace s1 with */
397 ulint str_len
= strlen(str
);
398 ulint s1_len
= strlen(s1
);
399 ulint s2_len
= strlen(s2
);
401 int len_delta
= (int)s2_len
- (int)s1_len
;
403 str_end
= str
+ str_len
;
405 if (len_delta
<= 0) {
408 count
= ut_strcount(str
, s1
);
411 new_str
= mem_alloc(str_len
+ count
* len_delta
+ 1);
415 const char* next
= strstr(str
, s1
);
421 memcpy(ptr
, str
, next
- str
);
424 if (next
== str_end
) {
429 memcpy(ptr
, s2
, s2_len
);