blob: 0aecbd71d47928d1a34d93c880e5660c4db65b05 [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
Damien Georgeade9a052015-06-13 21:53:22 +010059#define realloc(ptr, n) gc_realloc(ptr, n, true)
60#define realloc_ext(ptr, n, mv) gc_realloc(ptr, n, mv)
61#else
62#define realloc_ext(ptr, n, mv) realloc(ptr, n)
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020063#endif // MICROPY_ENABLE_GC
64
Damien Georgeb0261342014-09-23 18:10:17 +010065void *m_malloc(size_t num_bytes) {
Damien429d7192013-10-04 19:53:11 +010066 void *ptr = malloc(num_bytes);
Damien George37378f82014-10-23 12:02:00 +010067 if (ptr == NULL && num_bytes != 0) {
Damien George6902eed2014-04-04 10:52:59 +000068 return m_malloc_fail(num_bytes);
Damien429d7192013-10-04 19:53:11 +010069 }
Paul Sokolovskyef181022014-01-03 03:06:25 +020070#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +000071 MP_STATE_MEM(total_bytes_allocated) += num_bytes;
72 MP_STATE_MEM(current_bytes_allocated) += num_bytes;
Paul Sokolovsky780f5552014-01-01 23:42:21 +020073 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +020074#endif
Damien George2d15c122014-01-29 20:33:20 +000075 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
Damien429d7192013-10-04 19:53:11 +010076 return ptr;
77}
78
Damien Georgeb0261342014-09-23 18:10:17 +010079void *m_malloc_maybe(size_t num_bytes) {
Damien Georgef0954e32014-04-10 14:38:25 +010080 void *ptr = malloc(num_bytes);
Damien Georgef0954e32014-04-10 14:38:25 +010081#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +000082 MP_STATE_MEM(total_bytes_allocated) += num_bytes;
83 MP_STATE_MEM(current_bytes_allocated) += num_bytes;
Damien Georgef0954e32014-04-10 14:38:25 +010084 UPDATE_PEAK();
85#endif
86 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
87 return ptr;
88}
89
Damien George12bab722014-04-05 20:35:48 +010090#if MICROPY_ENABLE_FINALISER
Damien Georgeb0261342014-09-23 18:10:17 +010091void *m_malloc_with_finaliser(size_t num_bytes) {
Damien George12bab722014-04-05 20:35:48 +010092 void *ptr = malloc_with_finaliser(num_bytes);
Damien George37378f82014-10-23 12:02:00 +010093 if (ptr == NULL && num_bytes != 0) {
Damien George12bab722014-04-05 20:35:48 +010094 return m_malloc_fail(num_bytes);
mux4f7e9f52014-04-03 23:55:12 +020095 }
96#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +000097 MP_STATE_MEM(total_bytes_allocated) += num_bytes;
98 MP_STATE_MEM(current_bytes_allocated) += num_bytes;
mux4f7e9f52014-04-03 23:55:12 +020099 UPDATE_PEAK();
100#endif
101 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
102 return ptr;
103}
Damien George12bab722014-04-05 20:35:48 +0100104#endif
mux4f7e9f52014-04-03 23:55:12 +0200105
Damien Georgeb0261342014-09-23 18:10:17 +0100106void *m_malloc0(size_t num_bytes) {
Paul Sokolovsky58ff93b2014-02-10 18:37:11 +0200107 void *ptr = m_malloc(num_bytes);
Damien George37378f82014-10-23 12:02:00 +0100108 if (ptr == NULL && num_bytes != 0) {
109 return m_malloc_fail(num_bytes);
Damien429d7192013-10-04 19:53:11 +0100110 }
Damien George37378f82014-10-23 12:02:00 +0100111 memset(ptr, 0, num_bytes);
Damien429d7192013-10-04 19:53:11 +0100112 return ptr;
113}
114
Damien Georged8914522015-02-27 09:54:12 +0000115#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien Georgeb0261342014-09-23 18:10:17 +0100116void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
Damien Georged8914522015-02-27 09:54:12 +0000117#else
118void *m_realloc(void *ptr, size_t new_num_bytes) {
119#endif
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200120 void *new_ptr = realloc(ptr, new_num_bytes);
Damien George37378f82014-10-23 12:02:00 +0100121 if (new_ptr == NULL && new_num_bytes != 0) {
Damien George6902eed2014-04-04 10:52:59 +0000122 return m_malloc_fail(new_num_bytes);
Damien429d7192013-10-04 19:53:11 +0100123 }
Paul Sokolovskyef181022014-01-03 03:06:25 +0200124#if MICROPY_MEM_STATS
Paul Sokolovsky43f1c802014-01-01 23:04:25 +0200125 // At first thought, "Total bytes allocated" should only grow,
126 // after all, it's *total*. But consider for example 2K block
127 // shrunk to 1K and then grown to 2K again. It's still 2K
128 // allocated total. If we process only positive increments,
129 // we'll count 3K.
Damien Georgeb0261342014-09-23 18:10:17 +0100130 size_t diff = new_num_bytes - old_num_bytes;
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000131 MP_STATE_MEM(total_bytes_allocated) += diff;
132 MP_STATE_MEM(current_bytes_allocated) += diff;
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200133 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +0200134#endif
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200135 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
136 return new_ptr;
Damien429d7192013-10-04 19:53:11 +0100137}
138
Damien Georged8914522015-02-27 09:54:12 +0000139#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien Georgeade9a052015-06-13 21:53:22 +0100140void *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 +0000141#else
Damien Georgeade9a052015-06-13 21:53:22 +0100142void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move) {
Damien Georged8914522015-02-27 09:54:12 +0000143#endif
Damien Georgeade9a052015-06-13 21:53:22 +0100144 void *new_ptr = realloc_ext(ptr, new_num_bytes, allow_move);
Damien George58ba4c32014-04-10 14:27:31 +0000145#if MICROPY_MEM_STATS
146 // At first thought, "Total bytes allocated" should only grow,
147 // after all, it's *total*. But consider for example 2K block
148 // shrunk to 1K and then grown to 2K again. It's still 2K
149 // allocated total. If we process only positive increments,
150 // we'll count 3K.
Damien George37378f82014-10-23 12:02:00 +0100151 // Also, don't count failed reallocs.
152 if (!(new_ptr == NULL && new_num_bytes != 0)) {
153 size_t diff = new_num_bytes - old_num_bytes;
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000154 MP_STATE_MEM(total_bytes_allocated) += diff;
155 MP_STATE_MEM(current_bytes_allocated) += diff;
Damien George37378f82014-10-23 12:02:00 +0100156 UPDATE_PEAK();
157 }
Damien George58ba4c32014-04-10 14:27:31 +0000158#endif
159 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
160 return new_ptr;
161}
162
Damien Georged8914522015-02-27 09:54:12 +0000163#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
Damien Georgeb0261342014-09-23 18:10:17 +0100164void m_free(void *ptr, size_t num_bytes) {
Damien Georged8914522015-02-27 09:54:12 +0000165#else
166void m_free(void *ptr) {
167#endif
Damien George37378f82014-10-23 12:02:00 +0100168 free(ptr);
Paul Sokolovskyef181022014-01-03 03:06:25 +0200169#if MICROPY_MEM_STATS
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000170 MP_STATE_MEM(current_bytes_allocated) -= num_bytes;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200171#endif
Damien George2d15c122014-01-29 20:33:20 +0000172 DEBUG_printf("free %p, %d\n", ptr, num_bytes);
Damien732407f2013-12-29 19:33:23 +0000173}
174
Paul Sokolovskyef181022014-01-03 03:06:25 +0200175#if MICROPY_MEM_STATS
Damien Georgeb0261342014-09-23 18:10:17 +0100176size_t m_get_total_bytes_allocated(void) {
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000177 return MP_STATE_MEM(total_bytes_allocated);
Damien429d7192013-10-04 19:53:11 +0100178}
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200179
Damien Georgeb0261342014-09-23 18:10:17 +0100180size_t m_get_current_bytes_allocated(void) {
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000181 return MP_STATE_MEM(current_bytes_allocated);
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200182}
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200183
Damien Georgeb0261342014-09-23 18:10:17 +0100184size_t m_get_peak_bytes_allocated(void) {
Damien Georgeb4b10fd2015-01-01 23:30:53 +0000185 return MP_STATE_MEM(peak_bytes_allocated);
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200186}
Damien Georgeb0261342014-09-23 18:10:17 +0100187#endif