blob: 8e90849e93dd07eb7d75284c763a0ff53d264d83 [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
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
Paul Sokolovskyef181022014-01-03 03:06:25 +020031#include "mpconfig.h"
Paul Sokolovsky59c675a2014-06-21 22:43:22 +030032#include "misc.h"
Damien429d7192013-10-04 19:53:11 +010033
Damien George2d15c122014-01-29 20:33:20 +000034#if 0 // print debugging info
Paul Sokolovsky44739e22014-02-16 18:11:42 +020035#define DEBUG_printf DEBUG_printf
Damien George2d15c122014-01-29 20:33:20 +000036#else // don't print debugging info
Damien George1dc76af2014-02-26 16:57:08 +000037#define DEBUG_printf(...) (void)0
Damien George2d15c122014-01-29 20:33:20 +000038#endif
39
Paul Sokolovskyef181022014-01-03 03:06:25 +020040#if MICROPY_MEM_STATS
Paul Sokolovsky520e2f52014-02-12 18:31:30 +020041STATIC int total_bytes_allocated = 0;
42STATIC int current_bytes_allocated = 0;
43STATIC int peak_bytes_allocated = 0;
Paul Sokolovsky780f5552014-01-01 23:42:21 +020044
45#define UPDATE_PEAK() { if (current_bytes_allocated > peak_bytes_allocated) peak_bytes_allocated = 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
49#include "gc.h"
50
51// We redirect standard alloc functions to GC heap - just for the rest of
52// this module. In the rest of micropython source, system malloc can be
53// 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
62#define realloc gc_realloc
63#endif // MICROPY_ENABLE_GC
64
Damien429d7192013-10-04 19:53:11 +010065void *m_malloc(int num_bytes) {
66 if (num_bytes == 0) {
67 return NULL;
68 }
69 void *ptr = malloc(num_bytes);
70 if (ptr == NULL) {
Damien George6902eed2014-04-04 10:52:59 +000071 return m_malloc_fail(num_bytes);
Damien429d7192013-10-04 19:53:11 +010072 }
Paul Sokolovskyef181022014-01-03 03:06:25 +020073#if MICROPY_MEM_STATS
Damien429d7192013-10-04 19:53:11 +010074 total_bytes_allocated += num_bytes;
Paul Sokolovsky02de0c52014-01-01 23:15:47 +020075 current_bytes_allocated += num_bytes;
Paul Sokolovsky780f5552014-01-01 23:42:21 +020076 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +020077#endif
Damien George2d15c122014-01-29 20:33:20 +000078 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
Damien429d7192013-10-04 19:53:11 +010079 return ptr;
80}
81
Damien Georgef0954e32014-04-10 14:38:25 +010082void *m_malloc_maybe(int num_bytes) {
83 void *ptr = malloc(num_bytes);
84 if (ptr == NULL) {
85 return NULL;
86 }
87#if MICROPY_MEM_STATS
88 total_bytes_allocated += num_bytes;
89 current_bytes_allocated += num_bytes;
90 UPDATE_PEAK();
91#endif
92 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
93 return ptr;
94}
95
Damien George12bab722014-04-05 20:35:48 +010096#if MICROPY_ENABLE_FINALISER
97void *m_malloc_with_finaliser(int num_bytes) {
mux4f7e9f52014-04-03 23:55:12 +020098 if (num_bytes == 0) {
99 return NULL;
100 }
Damien George12bab722014-04-05 20:35:48 +0100101 void *ptr = malloc_with_finaliser(num_bytes);
mux4f7e9f52014-04-03 23:55:12 +0200102 if (ptr == NULL) {
Damien George12bab722014-04-05 20:35:48 +0100103 return m_malloc_fail(num_bytes);
mux4f7e9f52014-04-03 23:55:12 +0200104 }
105#if MICROPY_MEM_STATS
106 total_bytes_allocated += num_bytes;
107 current_bytes_allocated += num_bytes;
108 UPDATE_PEAK();
109#endif
110 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
111 return ptr;
112}
Damien George12bab722014-04-05 20:35:48 +0100113#endif
mux4f7e9f52014-04-03 23:55:12 +0200114
Damien429d7192013-10-04 19:53:11 +0100115void *m_malloc0(int num_bytes) {
Paul Sokolovsky58ff93b2014-02-10 18:37:11 +0200116 void *ptr = m_malloc(num_bytes);
117 if (ptr != NULL) {
118 memset(ptr, 0, num_bytes);
Damien429d7192013-10-04 19:53:11 +0100119 }
Damien429d7192013-10-04 19:53:11 +0100120 return ptr;
121}
122
Damien732407f2013-12-29 19:33:23 +0000123void *m_realloc(void *ptr, int old_num_bytes, int new_num_bytes) {
124 if (new_num_bytes == 0) {
Damien429d7192013-10-04 19:53:11 +0100125 free(ptr);
126 return NULL;
127 }
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200128 void *new_ptr = realloc(ptr, new_num_bytes);
129 if (new_ptr == NULL) {
Damien George6902eed2014-04-04 10:52:59 +0000130 return m_malloc_fail(new_num_bytes);
Damien429d7192013-10-04 19:53:11 +0100131 }
Paul Sokolovskyef181022014-01-03 03:06:25 +0200132#if MICROPY_MEM_STATS
Paul Sokolovsky43f1c802014-01-01 23:04:25 +0200133 // At first thought, "Total bytes allocated" should only grow,
134 // after all, it's *total*. But consider for example 2K block
135 // shrunk to 1K and then grown to 2K again. It's still 2K
136 // allocated total. If we process only positive increments,
137 // we'll count 3K.
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200138 int diff = new_num_bytes - old_num_bytes;
139 total_bytes_allocated += diff;
140 current_bytes_allocated += diff;
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200141 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +0200142#endif
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200143 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
144 return new_ptr;
Damien429d7192013-10-04 19:53:11 +0100145}
146
Damien George58ba4c32014-04-10 14:27:31 +0000147void *m_realloc_maybe(void *ptr, int old_num_bytes, int new_num_bytes) {
148 void *new_ptr = realloc(ptr, new_num_bytes);
149 if (new_ptr == NULL) {
150 return NULL;
151 }
152#if MICROPY_MEM_STATS
153 // At first thought, "Total bytes allocated" should only grow,
154 // after all, it's *total*. But consider for example 2K block
155 // shrunk to 1K and then grown to 2K again. It's still 2K
156 // allocated total. If we process only positive increments,
157 // we'll count 3K.
158 int diff = new_num_bytes - old_num_bytes;
159 total_bytes_allocated += diff;
160 current_bytes_allocated += diff;
161 UPDATE_PEAK();
162#endif
163 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
164 return new_ptr;
165}
166
Damien732407f2013-12-29 19:33:23 +0000167void m_free(void *ptr, int num_bytes) {
168 if (ptr != NULL) {
169 free(ptr);
170 }
Paul Sokolovskyef181022014-01-03 03:06:25 +0200171#if MICROPY_MEM_STATS
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200172 current_bytes_allocated -= num_bytes;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200173#endif
Damien George2d15c122014-01-29 20:33:20 +0000174 DEBUG_printf("free %p, %d\n", ptr, num_bytes);
Damien732407f2013-12-29 19:33:23 +0000175}
176
Damien8b3a7c22013-10-23 20:20:17 +0100177int m_get_total_bytes_allocated(void) {
Paul Sokolovskyef181022014-01-03 03:06:25 +0200178#if MICROPY_MEM_STATS
Damien429d7192013-10-04 19:53:11 +0100179 return total_bytes_allocated;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200180#else
181 return -1;
182#endif
Damien429d7192013-10-04 19:53:11 +0100183}
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200184
185int m_get_current_bytes_allocated(void) {
Paul Sokolovskyef181022014-01-03 03:06:25 +0200186#if MICROPY_MEM_STATS
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200187 return current_bytes_allocated;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200188#else
189 return -1;
190#endif
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200191}
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200192
193int m_get_peak_bytes_allocated(void) {
Paul Sokolovskyef181022014-01-03 03:06:25 +0200194#if MICROPY_MEM_STATS
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200195 return peak_bytes_allocated;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200196#else
197 return -1;
198#endif
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200199}