Skip to content

Commit 518d909

Browse files
committed
Add memorymonitor module
1 parent 9cdf5e1 commit 518d909

File tree

16 files changed

+905
-0
lines changed

16 files changed

+905
-0
lines changed

py/circuitpy_defns.mk

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ endif
174174
ifeq ($(CIRCUITPY__EVE),1)
175175
SRC_PATTERNS += _eve/%
176176
endif
177+
ifeq ($(CIRCUITPY_MEMORYMONITOR),1)
178+
SRC_PATTERNS += memorymonitor/%
179+
endif
177180
ifeq ($(CIRCUITPY_MICROCONTROLLER),1)
178181
SRC_PATTERNS += microcontroller/%
179182
endif
@@ -398,6 +401,9 @@ SRC_SHARED_MODULE_ALL = \
398401
gamepad/__init__.c \
399402
gamepadshift/GamePadShift.c \
400403
gamepadshift/__init__.c \
404+
memorymonitor/__init__.c \
405+
memorymonitor/AllocationAlarm.c \
406+
memorymonitor/AllocationSize.c \
401407
network/__init__.c \
402408
os/__init__.c \
403409
random/__init__.c \

py/circuitpy_mpconfig.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,16 @@ extern const struct _mp_obj_module_t _eve_module;
429429
#define _EVE_MODULE
430430
#endif
431431

432+
#if CIRCUITPY_MEMORYMONITOR
433+
extern const struct _mp_obj_module_t memorymonitor_module;
434+
#define MEMORYMONITOR_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_memorymonitor), (mp_obj_t)&memorymonitor_module },
435+
#define MEMORYMONITOR_ROOT_POINTERS mp_obj_t active_allocationsizes; \
436+
mp_obj_t active_allocationalarms;
437+
#else
438+
#define MEMORYMONITOR_MODULE
439+
#define MEMORYMONITOR_ROOT_POINTERS
440+
#endif
441+
432442
#if CIRCUITPY_MICROCONTROLLER
433443
extern const struct _mp_obj_module_t microcontroller_module;
434444
#define MICROCONTROLLER_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)&microcontroller_module },
@@ -708,6 +718,7 @@ extern const struct _mp_obj_module_t watchdog_module;
708718
JSON_MODULE \
709719
MATH_MODULE \
710720
_EVE_MODULE \
721+
MEMORYMONITOR_MODULE \
711722
MICROCONTROLLER_MODULE \
712723
NEOPIXEL_WRITE_MODULE \
713724
NETWORK_MODULE \
@@ -765,6 +776,7 @@ extern const struct _mp_obj_module_t watchdog_module;
765776
mp_obj_t terminal_tilegrid_tiles; \
766777
BOARD_UART_ROOT_POINTER \
767778
FLASH_ROOT_POINTERS \
779+
MEMORYMONITOR_ROOT_POINTERS \
768780
NETWORK_ROOT_POINTERS \
769781

770782
void supervisor_run_background_tasks_if_tick(void);

py/circuitpy_mpconfig.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ CFLAGS += -DCIRCUITPY_MATH=$(CIRCUITPY_MATH)
118118
CIRCUITPY__EVE ?= 0
119119
CFLAGS += -DCIRCUITPY__EVE=$(CIRCUITPY__EVE)
120120

121+
CIRCUITPY_MEMORYMONITOR ?= 0
122+
CFLAGS += -DCIRCUITPY_MEMORYMONITOR=$(CIRCUITPY_MEMORYMONITOR)
123+
121124
CIRCUITPY_MICROCONTROLLER ?= 1
122125
CFLAGS += -DCIRCUITPY_MICROCONTROLLER=$(CIRCUITPY_MICROCONTROLLER)
123126

py/gc.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333

3434
#include "supervisor/shared/safe_mode.h"
3535

36+
#if CIRCUITPY_MEMORYMONITOR
37+
#include "shared-module/memorymonitor/AllocationSize.h"
38+
#endif
39+
3640
#if MICROPY_ENABLE_GC
3741

3842
#if MICROPY_DEBUG_VERBOSE // print debugging info
@@ -653,6 +657,10 @@ void *gc_alloc(size_t n_bytes, bool has_finaliser, bool long_lived) {
653657
gc_dump_alloc_table();
654658
#endif
655659

660+
#if CIRCUITPY_MEMORYMONITOR
661+
memorymonitor_allocationsizes_track_allocation(end_block - start_block + 1);
662+
#endif
663+
656664
return ret_ptr;
657665
}
658666

@@ -906,6 +914,10 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
906914
gc_log_change(block, new_blocks);
907915
#endif
908916

917+
#if CIRCUITPY_MEMORYMONITOR
918+
memorymonitor_allocationsizes_track_allocation(new_blocks);
919+
#endif
920+
909921
return ptr_in;
910922
}
911923

@@ -935,6 +947,10 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
935947
gc_log_change(block, new_blocks);
936948
#endif
937949

950+
#if CIRCUITPY_MEMORYMONITOR
951+
memorymonitor_allocationsizes_track_allocation(new_blocks);
952+
#endif
953+
938954
return ptr_in;
939955
}
940956

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
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+
27+
#include <stdint.h>
28+
29+
#include "py/objproperty.h"
30+
#include "py/runtime.h"
31+
#include "py/runtime0.h"
32+
#include "shared-bindings/memorymonitor/AllocationAlarm.h"
33+
#include "shared-bindings/util.h"
34+
#include "supervisor/shared/translate.h"
35+
36+
//| class AllocationAlarm:
37+
//|
38+
//| def __init__(self, *, minimum_block_count=1):
39+
//| """Throw an exception when an allocation of ``minimum_block_count`` or more blocks
40+
//| occurs while active.
41+
//|
42+
//| Track allocations::
43+
//|
44+
//| import memorymonitor
45+
//|
46+
//| aa = memorymonitor.AllocationAlarm(minimum_block_count=2)
47+
//| x = 2
48+
//| # Should not allocate any blocks.
49+
//| with aa:
50+
//| x = 5
51+
//|
52+
//| # Should throw an exception when allocating storage for the 20 bytes.
53+
//| with aa:
54+
//| x = bytearray(20)
55+
//|
56+
//| """
57+
//| ...
58+
//|
59+
STATIC mp_obj_t memorymonitor_allocationalarm_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
60+
enum { ARG_minimum_block_count };
61+
static const mp_arg_t allowed_args[] = {
62+
{ MP_QSTR_minimum_block_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
63+
};
64+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
65+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
66+
mp_int_t minimum_block_count = args[ARG_minimum_block_count].u_int;
67+
if (minimum_block_count < 1) {
68+
mp_raise_ValueError_varg(translate("%q must be >= 1"), MP_QSTR_minimum_block_count);
69+
}
70+
71+
memorymonitor_allocationalarm_obj_t *self = m_new_obj(memorymonitor_allocationalarm_obj_t);
72+
self->base.type = &memorymonitor_allocationalarm_type;
73+
74+
common_hal_memorymonitor_allocationalarm_construct(self, minimum_block_count);
75+
76+
return MP_OBJ_FROM_PTR(self);
77+
}
78+
79+
//| def __enter__(self) -> memorymonitor.AllocationAlarm:
80+
//| """Enables the alarm."""
81+
//| ...
82+
//|
83+
STATIC mp_obj_t memorymonitor_allocationalarm_obj___enter__(mp_obj_t self_in) {
84+
common_hal_memorymonitor_allocationalarm_resume(self_in);
85+
return self_in;
86+
}
87+
MP_DEFINE_CONST_FUN_OBJ_1(memorymonitor_allocationalarm___enter___obj, memorymonitor_allocationalarm_obj___enter__);
88+
89+
//| def __exit__(self) -> None:
90+
//| """Automatically disables the allocation alarm when exiting a context. See
91+
//| :ref:`lifetime-and-contextmanagers` for more info."""
92+
//| ...
93+
//|
94+
STATIC mp_obj_t memorymonitor_allocationalarm_obj___exit__(size_t n_args, const mp_obj_t *args) {
95+
(void)n_args;
96+
common_hal_memorymonitor_allocationalarm_pause(args[0]);
97+
return mp_const_none;
98+
}
99+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(memorymonitor_allocationalarm___exit___obj, 4, 4, memorymonitor_allocationalarm_obj___exit__);
100+
101+
STATIC const mp_rom_map_elem_t memorymonitor_allocationalarm_locals_dict_table[] = {
102+
// Methods
103+
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&memorymonitor_allocationalarm___enter___obj) },
104+
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&memorymonitor_allocationalarm___exit___obj) },
105+
};
106+
STATIC MP_DEFINE_CONST_DICT(memorymonitor_allocationalarm_locals_dict, memorymonitor_allocationalarm_locals_dict_table);
107+
108+
const mp_obj_type_t memorymonitor_allocationalarm_type = {
109+
{ &mp_type_type },
110+
.name = MP_QSTR_AllocationAlarm,
111+
.make_new = memorymonitor_allocationalarm_make_new,
112+
.locals_dict = (mp_obj_dict_t*)&memorymonitor_allocationalarm_locals_dict,
113+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
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+
27+
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_MEMORYMONITOR_ALLOCATIONALARM_H
28+
#define MICROPY_INCLUDED_SHARED_BINDINGS_MEMORYMONITOR_ALLOCATIONALARM_H
29+
30+
#include "shared-module/memorymonitor/AllocationAlarm.h"
31+
32+
extern const mp_obj_type_t memorymonitor_allocationalarm_type;
33+
34+
void common_hal_memorymonitor_allocationalarm_construct(memorymonitor_allocationalarm_obj_t* self, size_t minimum_block_count);
35+
void common_hal_memorymonitor_allocationalarm_pause(memorymonitor_allocationalarm_obj_t* self);
36+
void common_hal_memorymonitor_allocationalarm_resume(memorymonitor_allocationalarm_obj_t* self);
37+
38+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MEMORYMONITOR_ALLOCATIONALARM_H

0 commit comments

Comments
 (0)