blob: f8ed1487a5b8c6d6a2740162fdbd35e96f5182aa [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
Alexander Steffen55f33242017-06-30 09:22:17 +02002 * This file is part of the MicroPython project, http://micropython.org/
Damien George04b91472014-05-03 23:27:38 +01003 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
Damien429d7192013-10-04 19:53:11 +010027#include <stdio.h>
28#include <stdlib.h>
Paul Sokolovsky58ff93b2014-02-10 18:37:11 +020029#include <string.h>
Damien429d7192013-10-04 19:53:11 +010030
Damien George51dfcb42015-01-01 20:27:54 +000031#include "py/mpconfig.h"
32#include "py/misc.h"
Damien Georgeb4b10fd2015-01-01 23:30:53 +000033#include "py/mpstate.h"
Damien429d7192013-10-04 19:53:11 +010034
Stefan Naumannace9fb52017-07-24 18:55:14 +020035#if MICROPY_DEBUG_VERBOSE // print debugging info
Paul Sokolovsky44739e22014-02-16 18:11:42 +020036#define DEBUG_printf DEBUG_printf
Damien George2d15c122014-01-29 20:33:20 +000037#else // don't print debugging info
Damien George1dc76af2014-02-26 16:57:08 +000038#define DEBUG_printf(...) (void)0
Damien George2d15c122014-01-29 20:33:20 +000039#endif
40
Paul Sokolovskyef181022014-01-03 03:06:25 +020041#if MICROPY_MEM_STATS
Paul Sokolovsky88a80432017-12-07 10:52:40 +020042#if !MICROPY_MALLOC_USES_ALLOCATED_SIZE
43#error MICROPY_MEM_STATS requires MICROPY_MALLOC_USES_ALLOCATED_SIZE
44#endif
Damien Georgeb4b10fd2015-01-01 23:30:53 +000045#define UPDATE_PEAK() { if (MP_STATE_MEM(current_bytes_allocated) > MP_STATE_MEM(peak_bytes_allocated)) MP_STATE_MEM(peak_bytes_allocated) = MP_STATE_MEM(current_bytes_allocated); }
Paul Sokolovskyef181022014-01-03 03:06:25 +020046#endif
Damien429d7192013-10-04 19:53:11 +010047
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020048#if MICROPY_ENABLE_GC
Damien George51dfcb42015-01-01 20:27:54 +000049#include "py/gc.h"
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020050
51// We redirect standard alloc functions to GC heap - just for the rest of
Alexander Steffen55f33242017-06-30 09:22:17 +020052// this module. In the rest of MicroPython source, system malloc can be
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020053// freely accessed - for interfacing with system and 3rd-party libs for
54// example. On the other hand, some (e.g. bare-metal) ports may use GC
55// heap as system heap, so, to avoid warnings, we do undef's first.
56#undef malloc
57#undef free
58#undef realloc
Damien George12bab722014-04-05 20:35:48 +010059#define malloc(b) gc_alloc((b), false)
60#define malloc_with_finaliser(b) gc_alloc((b), true)
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020061#define free gc_free
Damien Georgeade9a052015-06-13 21:53:22 +010062#define realloc(ptr, n) gc_realloc(ptr, n, true)
63#define realloc_ext(ptr, n, mv) gc_realloc(ptr, n, mv)
64#else
Damien Georgefcf621b2018-07-09 14:40:02 +100065
66// GC is disabled. Use system malloc/realloc/free.
67
68#if MICROPY_ENABLE_FINALISER
69#error MICROPY_ENABLE_FINALISER requires MICROPY_ENABLE_GC
70#endif
71
Damien Georgee9d1a942016-02-23 13:53:38 +000072STATIC void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) {
73 if (allow_move) {
74 return realloc(ptr, n_bytes);
75 } else {
76 // We are asked to resize, but without moving the memory region pointed to
77 // by ptr. Unless the underlying memory manager has special provision for
78 // this behaviour there is nothing we can do except fail to resize.
79 return NULL;
80 }
81}
Damien Georgefcf621b2018-07-09 14:40:02 +100082
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020083#endif // MICROPY_ENABLE_GC
84
Damien Georgeb0261342014-09-23 18:10:17 +010085void *m_malloc(size_t num_bytes) {
Damien429d7192013-10-04 19:53:11 +010086 void *ptr = malloc(num_bytes);
Damien George37378f82014-10-23 12:02:00 +010087 if (ptr == NULL && num_bytes != 0) {
Damien Georgeca21aed2017-08-31 17:00:14 +100088 m_malloc_fail(num_bytes);
Damien429d7192013-10-04 19:53:11 +010089 }
Paul Sokolovskyef181022014-01-03 03:06:25 +020090#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +000091 MP_STATE_MEM(total_bytes_allocated) += num_bytes;
92 MP_STATE_MEM(current_bytes_allocated) += num_bytes;
Paul Sokolovsky780f5552014-01-01 23:42:21 +020093 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +020094#endif
Damien George2d15c122014-01-29 20:33:20 +000095 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
Damien429d7192013-10-04 19:53:11 +010096 return ptr;
97}
98
Damien Georgeb0261342014-09-23 18:10:17 +010099void *m_malloc_maybe(size_t num_bytes) {
Damien Georgef0954e32014-04-10 14:38:25 +0100100 void *ptr = malloc(num_bytes);
Damien Georgef0954e32014-04-10 14:38:25 +0100101#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000102 MP_STATE_MEM(total_bytes_allocated) += num_bytes;
103 MP_STATE_MEM(current_bytes_allocated) += num_bytes;
Damien Georgef0954e32014-04-10 14:38:25 +0100104 UPDATE_PEAK();
105#endif
106 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
107 return ptr;
108}
109
Damien George12bab722014-04-05 20:35:48 +0100110#if MICROPY_ENABLE_FINALISER
Damien Georgeb0261342014-09-23 18:10:17 +0100111void *m_malloc_with_finaliser(size_t num_bytes) {
Damien George12bab722014-04-05 20:35:48 +0100112 void *ptr = malloc_with_finaliser(num_bytes);
Damien George37378f82014-10-23 12:02:00 +0100113 if (ptr == NULL && num_bytes != 0) {
Damien Georgeca21aed2017-08-31 17:00:14 +1000114 m_malloc_fail(num_bytes);
mux4f7e9f52014-04-03 23:55:12 +0200115 }
116#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000117 MP_STATE_MEM(total_bytes_allocated) += num_bytes;
118 MP_STATE_MEM(current_bytes_allocated) += num_bytes;
mux4f7e9f52014-04-03 23:55:12 +0200119 UPDATE_PEAK();
120#endif
121 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
122 return ptr;
123}
Damien George12bab722014-04-05 20:35:48 +0100124#endif
mux4f7e9f52014-04-03 23:55:12 +0200125
Damien Georgeb0261342014-09-23 18:10:17 +0100126void *m_malloc0(size_t num_bytes) {
Paul Sokolovsky58ff93b2014-02-10 18:37:11 +0200127 void *ptr = m_malloc(num_bytes);
Damien George5ffe1d82016-08-26 15:35:26 +1000128 // If this config is set then the GC clears all memory, so we don't need to.
129 #if !MICROPY_GC_CONSERVATIVE_CLEAR
Damien George37378f82014-10-23 12:02:00 +0100130 memset(ptr, 0, num_bytes);
Damien George5ffe1d82016-08-26 15:35:26 +1000131 #endif
Damien429d7192013-10-04 19:53:11 +0100132 return ptr;
133}
134
Damien Georged8914522015-02-27 09:54:12 +0000135#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien Georgeb0261342014-09-23 18:10:17 +0100136void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
Damien Georged8914522015-02-27 09:54:12 +0000137#else
138void *m_realloc(void *ptr, size_t new_num_bytes) {
139#endif
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200140 void *new_ptr = realloc(ptr, new_num_bytes);
Damien George37378f82014-10-23 12:02:00 +0100141 if (new_ptr == NULL && new_num_bytes != 0) {
Damien Georgeca21aed2017-08-31 17:00:14 +1000142 m_malloc_fail(new_num_bytes);
Damien429d7192013-10-04 19:53:11 +0100143 }
Paul Sokolovskyef181022014-01-03 03:06:25 +0200144#if MICROPY_MEM_STATS
Paul Sokolovsky43f1c802014-01-01 23:04:25 +0200145 // At first thought, "Total bytes allocated" should only grow,
146 // after all, it's *total*. But consider for example 2K block
147 // shrunk to 1K and then grown to 2K again. It's still 2K
148 // allocated total. If we process only positive increments,
149 // we'll count 3K.
Damien Georgeb0261342014-09-23 18:10:17 +0100150 size_t diff = new_num_bytes - old_num_bytes;
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000151 MP_STATE_MEM(total_bytes_allocated) += diff;
152 MP_STATE_MEM(current_bytes_allocated) += diff;
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200153 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +0200154#endif
Paul Sokolovsky9ebc0372017-12-07 17:57:33 +0200155 #if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200156 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
Paul Sokolovsky9ebc0372017-12-07 17:57:33 +0200157 #else
158 DEBUG_printf("realloc %p, %d : %p\n", ptr, new_num_bytes, new_ptr);
159 #endif
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200160 return new_ptr;
Damien429d7192013-10-04 19:53:11 +0100161}
162
Damien Georged8914522015-02-27 09:54:12 +0000163#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien Georgeade9a052015-06-13 21:53:22 +0100164void *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes, bool allow_move) {
Damien Georged8914522015-02-27 09:54:12 +0000165#else
Damien Georgeade9a052015-06-13 21:53:22 +0100166void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move) {
Damien Georged8914522015-02-27 09:54:12 +0000167#endif
Damien Georgeade9a052015-06-13 21:53:22 +0100168 void *new_ptr = realloc_ext(ptr, new_num_bytes, allow_move);
Damien George58ba4c32014-04-10 14:27:31 +0000169#if MICROPY_MEM_STATS
170 // At first thought, "Total bytes allocated" should only grow,
171 // after all, it's *total*. But consider for example 2K block
172 // shrunk to 1K and then grown to 2K again. It's still 2K
173 // allocated total. If we process only positive increments,
174 // we'll count 3K.
Damien George37378f82014-10-23 12:02:00 +0100175 // Also, don't count failed reallocs.
176 if (!(new_ptr == NULL && new_num_bytes != 0)) {
177 size_t diff = new_num_bytes - old_num_bytes;
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000178 MP_STATE_MEM(total_bytes_allocated) += diff;
179 MP_STATE_MEM(current_bytes_allocated) += diff;
Damien George37378f82014-10-23 12:02:00 +0100180 UPDATE_PEAK();
181 }
Damien George58ba4c32014-04-10 14:27:31 +0000182#endif
Paul Sokolovsky9ebc0372017-12-07 17:57:33 +0200183 #if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien George58ba4c32014-04-10 14:27:31 +0000184 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
Paul Sokolovsky9ebc0372017-12-07 17:57:33 +0200185 #else
186 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, new_num_bytes, new_ptr);
187 #endif
Damien George58ba4c32014-04-10 14:27:31 +0000188 return new_ptr;
189}
190
Damien Georged8914522015-02-27 09:54:12 +0000191#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien Georgeb0261342014-09-23 18:10:17 +0100192void m_free(void *ptr, size_t num_bytes) {
Damien Georged8914522015-02-27 09:54:12 +0000193#else
194void m_free(void *ptr) {
195#endif
Damien George37378f82014-10-23 12:02:00 +0100196 free(ptr);
Paul Sokolovskyef181022014-01-03 03:06:25 +0200197#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000198 MP_STATE_MEM(current_bytes_allocated) -= num_bytes;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200199#endif
Paul Sokolovsky9ebc0372017-12-07 17:57:33 +0200200 #if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien George2d15c122014-01-29 20:33:20 +0000201 DEBUG_printf("free %p, %d\n", ptr, num_bytes);
Paul Sokolovsky9ebc0372017-12-07 17:57:33 +0200202 #else
203 DEBUG_printf("free %p\n", ptr);
204 #endif
Damien732407f2013-12-29 19:33:23 +0000205}
206
Paul Sokolovskyef181022014-01-03 03:06:25 +0200207#if MICROPY_MEM_STATS
Damien Georgeb0261342014-09-23 18:10:17 +0100208size_t m_get_total_bytes_allocated(void) {
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000209 return MP_STATE_MEM(total_bytes_allocated);
Damien429d7192013-10-04 19:53:11 +0100210}
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200211
Damien Georgeb0261342014-09-23 18:10:17 +0100212size_t m_get_current_bytes_allocated(void) {
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000213 return MP_STATE_MEM(current_bytes_allocated);
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200214}
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200215
Damien Georgeb0261342014-09-23 18:10:17 +0100216size_t m_get_peak_bytes_allocated(void) {
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000217 return MP_STATE_MEM(peak_bytes_allocated);
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200218}
Damien Georgeb0261342014-09-23 18:10:17 +0100219#endif