blob: f8728c596488dc175883ce4a7e72c01aba1d3a95 [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
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
Damien George2d15c122014-01-29 20:33:20 +000035#if 0 // 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
Damien Georgeb4b10fd2015-01-01 23:30:53 +000042#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 +020043#endif
Damien429d7192013-10-04 19:53:11 +010044
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020045#if MICROPY_ENABLE_GC
Damien George51dfcb42015-01-01 20:27:54 +000046#include "py/gc.h"
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020047
48// We redirect standard alloc functions to GC heap - just for the rest of
49// this module. In the rest of micropython source, system malloc can be
50// freely accessed - for interfacing with system and 3rd-party libs for
51// example. On the other hand, some (e.g. bare-metal) ports may use GC
52// heap as system heap, so, to avoid warnings, we do undef's first.
53#undef malloc
54#undef free
55#undef realloc
Damien George12bab722014-04-05 20:35:48 +010056#define malloc(b) gc_alloc((b), false)
57#define malloc_with_finaliser(b) gc_alloc((b), true)
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020058#define free gc_free
59#define realloc gc_realloc
60#endif // MICROPY_ENABLE_GC
61
Damien Georgeb0261342014-09-23 18:10:17 +010062void *m_malloc(size_t num_bytes) {
Damien429d7192013-10-04 19:53:11 +010063 void *ptr = malloc(num_bytes);
Damien George37378f82014-10-23 12:02:00 +010064 if (ptr == NULL && num_bytes != 0) {
Damien George6902eed2014-04-04 10:52:59 +000065 return m_malloc_fail(num_bytes);
Damien429d7192013-10-04 19:53:11 +010066 }
Paul Sokolovskyef181022014-01-03 03:06:25 +020067#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +000068 MP_STATE_MEM(total_bytes_allocated) += num_bytes;
69 MP_STATE_MEM(current_bytes_allocated) += num_bytes;
Paul Sokolovsky780f5552014-01-01 23:42:21 +020070 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +020071#endif
Damien George2d15c122014-01-29 20:33:20 +000072 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
Damien429d7192013-10-04 19:53:11 +010073 return ptr;
74}
75
Damien Georgeb0261342014-09-23 18:10:17 +010076void *m_malloc_maybe(size_t num_bytes) {
Damien Georgef0954e32014-04-10 14:38:25 +010077 void *ptr = malloc(num_bytes);
Damien Georgef0954e32014-04-10 14:38:25 +010078#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +000079 MP_STATE_MEM(total_bytes_allocated) += num_bytes;
80 MP_STATE_MEM(current_bytes_allocated) += num_bytes;
Damien Georgef0954e32014-04-10 14:38:25 +010081 UPDATE_PEAK();
82#endif
83 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
84 return ptr;
85}
86
Damien George12bab722014-04-05 20:35:48 +010087#if MICROPY_ENABLE_FINALISER
Damien Georgeb0261342014-09-23 18:10:17 +010088void *m_malloc_with_finaliser(size_t num_bytes) {
Damien George12bab722014-04-05 20:35:48 +010089 void *ptr = malloc_with_finaliser(num_bytes);
Damien George37378f82014-10-23 12:02:00 +010090 if (ptr == NULL && num_bytes != 0) {
Damien George12bab722014-04-05 20:35:48 +010091 return m_malloc_fail(num_bytes);
mux4f7e9f52014-04-03 23:55:12 +020092 }
93#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +000094 MP_STATE_MEM(total_bytes_allocated) += num_bytes;
95 MP_STATE_MEM(current_bytes_allocated) += num_bytes;
mux4f7e9f52014-04-03 23:55:12 +020096 UPDATE_PEAK();
97#endif
98 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
99 return ptr;
100}
Damien George12bab722014-04-05 20:35:48 +0100101#endif
mux4f7e9f52014-04-03 23:55:12 +0200102
Damien Georgeb0261342014-09-23 18:10:17 +0100103void *m_malloc0(size_t num_bytes) {
Paul Sokolovsky58ff93b2014-02-10 18:37:11 +0200104 void *ptr = m_malloc(num_bytes);
Damien George37378f82014-10-23 12:02:00 +0100105 if (ptr == NULL && num_bytes != 0) {
106 return m_malloc_fail(num_bytes);
Damien429d7192013-10-04 19:53:11 +0100107 }
Damien George37378f82014-10-23 12:02:00 +0100108 memset(ptr, 0, num_bytes);
Damien429d7192013-10-04 19:53:11 +0100109 return ptr;
110}
111
Damien Georged8914522015-02-27 09:54:12 +0000112#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien Georgeb0261342014-09-23 18:10:17 +0100113void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
Damien Georged8914522015-02-27 09:54:12 +0000114#else
115void *m_realloc(void *ptr, size_t new_num_bytes) {
116#endif
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200117 void *new_ptr = realloc(ptr, new_num_bytes);
Damien George37378f82014-10-23 12:02:00 +0100118 if (new_ptr == NULL && new_num_bytes != 0) {
Damien George6902eed2014-04-04 10:52:59 +0000119 return m_malloc_fail(new_num_bytes);
Damien429d7192013-10-04 19:53:11 +0100120 }
Paul Sokolovskyef181022014-01-03 03:06:25 +0200121#if MICROPY_MEM_STATS
Paul Sokolovsky43f1c802014-01-01 23:04:25 +0200122 // At first thought, "Total bytes allocated" should only grow,
123 // after all, it's *total*. But consider for example 2K block
124 // shrunk to 1K and then grown to 2K again. It's still 2K
125 // allocated total. If we process only positive increments,
126 // we'll count 3K.
Damien Georgeb0261342014-09-23 18:10:17 +0100127 size_t diff = new_num_bytes - old_num_bytes;
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000128 MP_STATE_MEM(total_bytes_allocated) += diff;
129 MP_STATE_MEM(current_bytes_allocated) += diff;
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200130 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +0200131#endif
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200132 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
133 return new_ptr;
Damien429d7192013-10-04 19:53:11 +0100134}
135
Damien Georged8914522015-02-27 09:54:12 +0000136#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien Georgeb0261342014-09-23 18:10:17 +0100137void *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
Damien Georged8914522015-02-27 09:54:12 +0000138#else
139void *m_realloc_maybe(void *ptr, size_t new_num_bytes) {
140#endif
Damien George58ba4c32014-04-10 14:27:31 +0000141 void *new_ptr = realloc(ptr, new_num_bytes);
Damien George58ba4c32014-04-10 14:27:31 +0000142#if MICROPY_MEM_STATS
143 // At first thought, "Total bytes allocated" should only grow,
144 // after all, it's *total*. But consider for example 2K block
145 // shrunk to 1K and then grown to 2K again. It's still 2K
146 // allocated total. If we process only positive increments,
147 // we'll count 3K.
Damien George37378f82014-10-23 12:02:00 +0100148 // Also, don't count failed reallocs.
149 if (!(new_ptr == NULL && new_num_bytes != 0)) {
150 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;
Damien George37378f82014-10-23 12:02:00 +0100153 UPDATE_PEAK();
154 }
Damien George58ba4c32014-04-10 14:27:31 +0000155#endif
156 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
157 return new_ptr;
158}
159
Damien Georged8914522015-02-27 09:54:12 +0000160#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien Georgeb0261342014-09-23 18:10:17 +0100161void m_free(void *ptr, size_t num_bytes) {
Damien Georged8914522015-02-27 09:54:12 +0000162#else
163void m_free(void *ptr) {
164#endif
Damien George37378f82014-10-23 12:02:00 +0100165 free(ptr);
Paul Sokolovskyef181022014-01-03 03:06:25 +0200166#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000167 MP_STATE_MEM(current_bytes_allocated) -= num_bytes;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200168#endif
Damien George2d15c122014-01-29 20:33:20 +0000169 DEBUG_printf("free %p, %d\n", ptr, num_bytes);
Damien732407f2013-12-29 19:33:23 +0000170}
171
Paul Sokolovskyef181022014-01-03 03:06:25 +0200172#if MICROPY_MEM_STATS
Damien Georgeb0261342014-09-23 18:10:17 +0100173size_t m_get_total_bytes_allocated(void) {
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000174 return MP_STATE_MEM(total_bytes_allocated);
Damien429d7192013-10-04 19:53:11 +0100175}
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200176
Damien Georgeb0261342014-09-23 18:10:17 +0100177size_t m_get_current_bytes_allocated(void) {
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000178 return MP_STATE_MEM(current_bytes_allocated);
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200179}
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200180
Damien Georgeb0261342014-09-23 18:10:17 +0100181size_t m_get_peak_bytes_allocated(void) {
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000182 return MP_STATE_MEM(peak_bytes_allocated);
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200183}
Damien Georgeb0261342014-09-23 18:10:17 +0100184#endif