blob: db2578d9ad68dada018cae0300b5175a2692981c [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <stdio.h>
2#include <stdlib.h>
Paul Sokolovsky58ff93b2014-02-10 18:37:11 +02003#include <string.h>
Damien429d7192013-10-04 19:53:11 +01004
5#include "misc.h"
Paul Sokolovskyef181022014-01-03 03:06:25 +02006#include "mpconfig.h"
Damien429d7192013-10-04 19:53:11 +01007
Damien George2d15c122014-01-29 20:33:20 +00008#if 0 // print debugging info
Paul Sokolovsky44739e22014-02-16 18:11:42 +02009#define DEBUG_printf DEBUG_printf
Damien George2d15c122014-01-29 20:33:20 +000010#else // don't print debugging info
Damien George1dc76af2014-02-26 16:57:08 +000011#define DEBUG_printf(...) (void)0
Damien George2d15c122014-01-29 20:33:20 +000012#endif
13
Paul Sokolovskyef181022014-01-03 03:06:25 +020014#if MICROPY_MEM_STATS
Paul Sokolovsky520e2f52014-02-12 18:31:30 +020015STATIC int total_bytes_allocated = 0;
16STATIC int current_bytes_allocated = 0;
17STATIC int peak_bytes_allocated = 0;
Paul Sokolovsky780f5552014-01-01 23:42:21 +020018
19#define UPDATE_PEAK() { if (current_bytes_allocated > peak_bytes_allocated) peak_bytes_allocated = current_bytes_allocated; }
Paul Sokolovskyef181022014-01-03 03:06:25 +020020#endif
Damien429d7192013-10-04 19:53:11 +010021
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020022#if MICROPY_ENABLE_GC
23#include "gc.h"
24
25// We redirect standard alloc functions to GC heap - just for the rest of
26// this module. In the rest of micropython source, system malloc can be
27// freely accessed - for interfacing with system and 3rd-party libs for
28// example. On the other hand, some (e.g. bare-metal) ports may use GC
29// heap as system heap, so, to avoid warnings, we do undef's first.
30#undef malloc
31#undef free
32#undef realloc
Damien George12bab722014-04-05 20:35:48 +010033#define malloc(b) gc_alloc((b), false)
34#define malloc_with_finaliser(b) gc_alloc((b), true)
Paul Sokolovskyb62c30b2014-02-10 22:37:09 +020035#define free gc_free
36#define realloc gc_realloc
37#endif // MICROPY_ENABLE_GC
38
Damien429d7192013-10-04 19:53:11 +010039void *m_malloc(int num_bytes) {
40 if (num_bytes == 0) {
41 return NULL;
42 }
43 void *ptr = malloc(num_bytes);
44 if (ptr == NULL) {
Damien George6902eed2014-04-04 10:52:59 +000045 return m_malloc_fail(num_bytes);
Damien429d7192013-10-04 19:53:11 +010046 }
Paul Sokolovskyef181022014-01-03 03:06:25 +020047#if MICROPY_MEM_STATS
Damien429d7192013-10-04 19:53:11 +010048 total_bytes_allocated += num_bytes;
Paul Sokolovsky02de0c52014-01-01 23:15:47 +020049 current_bytes_allocated += num_bytes;
Paul Sokolovsky780f5552014-01-01 23:42:21 +020050 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +020051#endif
Damien George2d15c122014-01-29 20:33:20 +000052 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
Damien429d7192013-10-04 19:53:11 +010053 return ptr;
54}
55
Damien Georgef0954e32014-04-10 14:38:25 +010056void *m_malloc_maybe(int num_bytes) {
57 void *ptr = malloc(num_bytes);
58 if (ptr == NULL) {
59 return NULL;
60 }
61#if MICROPY_MEM_STATS
62 total_bytes_allocated += num_bytes;
63 current_bytes_allocated += num_bytes;
64 UPDATE_PEAK();
65#endif
66 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
67 return ptr;
68}
69
Damien George12bab722014-04-05 20:35:48 +010070#if MICROPY_ENABLE_FINALISER
71void *m_malloc_with_finaliser(int num_bytes) {
mux4f7e9f52014-04-03 23:55:12 +020072 if (num_bytes == 0) {
73 return NULL;
74 }
Damien George12bab722014-04-05 20:35:48 +010075 void *ptr = malloc_with_finaliser(num_bytes);
mux4f7e9f52014-04-03 23:55:12 +020076 if (ptr == NULL) {
Damien George12bab722014-04-05 20:35:48 +010077 return m_malloc_fail(num_bytes);
mux4f7e9f52014-04-03 23:55:12 +020078 }
79#if MICROPY_MEM_STATS
80 total_bytes_allocated += num_bytes;
81 current_bytes_allocated += num_bytes;
82 UPDATE_PEAK();
83#endif
84 DEBUG_printf("malloc %d : %p\n", num_bytes, ptr);
85 return ptr;
86}
Damien George12bab722014-04-05 20:35:48 +010087#endif
mux4f7e9f52014-04-03 23:55:12 +020088
Damien429d7192013-10-04 19:53:11 +010089void *m_malloc0(int num_bytes) {
Paul Sokolovsky58ff93b2014-02-10 18:37:11 +020090 void *ptr = m_malloc(num_bytes);
91 if (ptr != NULL) {
92 memset(ptr, 0, num_bytes);
Damien429d7192013-10-04 19:53:11 +010093 }
Damien429d7192013-10-04 19:53:11 +010094 return ptr;
95}
96
Damien732407f2013-12-29 19:33:23 +000097void *m_realloc(void *ptr, int old_num_bytes, int new_num_bytes) {
98 if (new_num_bytes == 0) {
Damien429d7192013-10-04 19:53:11 +010099 free(ptr);
100 return NULL;
101 }
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200102 void *new_ptr = realloc(ptr, new_num_bytes);
103 if (new_ptr == NULL) {
Damien George6902eed2014-04-04 10:52:59 +0000104 return m_malloc_fail(new_num_bytes);
Damien429d7192013-10-04 19:53:11 +0100105 }
Paul Sokolovskyef181022014-01-03 03:06:25 +0200106#if MICROPY_MEM_STATS
Paul Sokolovsky43f1c802014-01-01 23:04:25 +0200107 // At first thought, "Total bytes allocated" should only grow,
108 // after all, it's *total*. But consider for example 2K block
109 // shrunk to 1K and then grown to 2K again. It's still 2K
110 // allocated total. If we process only positive increments,
111 // we'll count 3K.
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200112 int diff = new_num_bytes - old_num_bytes;
113 total_bytes_allocated += diff;
114 current_bytes_allocated += diff;
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200115 UPDATE_PEAK();
Paul Sokolovskyef181022014-01-03 03:06:25 +0200116#endif
Paul Sokolovskycdd2c622014-01-30 03:58:17 +0200117 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
118 return new_ptr;
Damien429d7192013-10-04 19:53:11 +0100119}
120
Damien George58ba4c32014-04-10 14:27:31 +0000121void *m_realloc_maybe(void *ptr, int old_num_bytes, int new_num_bytes) {
122 void *new_ptr = realloc(ptr, new_num_bytes);
123 if (new_ptr == NULL) {
124 return NULL;
125 }
126#if MICROPY_MEM_STATS
127 // At first thought, "Total bytes allocated" should only grow,
128 // after all, it's *total*. But consider for example 2K block
129 // shrunk to 1K and then grown to 2K again. It's still 2K
130 // allocated total. If we process only positive increments,
131 // we'll count 3K.
132 int diff = new_num_bytes - old_num_bytes;
133 total_bytes_allocated += diff;
134 current_bytes_allocated += diff;
135 UPDATE_PEAK();
136#endif
137 DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
138 return new_ptr;
139}
140
Damien732407f2013-12-29 19:33:23 +0000141void m_free(void *ptr, int num_bytes) {
142 if (ptr != NULL) {
143 free(ptr);
144 }
Paul Sokolovskyef181022014-01-03 03:06:25 +0200145#if MICROPY_MEM_STATS
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200146 current_bytes_allocated -= num_bytes;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200147#endif
Damien George2d15c122014-01-29 20:33:20 +0000148 DEBUG_printf("free %p, %d\n", ptr, num_bytes);
Damien732407f2013-12-29 19:33:23 +0000149}
150
Damien8b3a7c22013-10-23 20:20:17 +0100151int m_get_total_bytes_allocated(void) {
Paul Sokolovskyef181022014-01-03 03:06:25 +0200152#if MICROPY_MEM_STATS
Damien429d7192013-10-04 19:53:11 +0100153 return total_bytes_allocated;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200154#else
155 return -1;
156#endif
Damien429d7192013-10-04 19:53:11 +0100157}
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200158
159int m_get_current_bytes_allocated(void) {
Paul Sokolovskyef181022014-01-03 03:06:25 +0200160#if MICROPY_MEM_STATS
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200161 return current_bytes_allocated;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200162#else
163 return -1;
164#endif
Paul Sokolovsky02de0c52014-01-01 23:15:47 +0200165}
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200166
167int m_get_peak_bytes_allocated(void) {
Paul Sokolovskyef181022014-01-03 03:06:25 +0200168#if MICROPY_MEM_STATS
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200169 return peak_bytes_allocated;
Paul Sokolovskyef181022014-01-03 03:06:25 +0200170#else
171 return -1;
172#endif
Paul Sokolovsky780f5552014-01-01 23:42:21 +0200173}