diff --git a/shared-bindings/memorymonitor/AllocationAlarm.c b/shared-bindings/memorymonitor/AllocationAlarm.c index 71a156f328..36e2cb5b23 100644 --- a/shared-bindings/memorymonitor/AllocationAlarm.c +++ b/shared-bindings/memorymonitor/AllocationAlarm.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -76,7 +76,27 @@ STATIC mp_obj_t memorymonitor_allocationalarm_make_new(const mp_obj_type_t *type return MP_OBJ_FROM_PTR(self); } -// TODO: Add .countdown(count) to skip allocations and alarm on something after the first. +//| def ignore(self, count) -> AllocationAlarm: +//| """Sets the number of applicable allocations to ignore before raising the exception. +//| Automatically set back to zero at context exit. +//| +//| Use it within a ``with`` block:: +//| +//| # Will not alarm because the bytearray allocation will be ignored. +//| with aa.ignore(2): +//| x = bytearray(20) +//| """ +//| ... +//| +STATIC mp_obj_t memorymonitor_allocationalarm_obj_ignore(mp_obj_t self_in, mp_obj_t count_obj) { + mp_int_t count = mp_obj_get_int(count_obj); + if (count < 0) { + mp_raise_ValueError_varg(translate("%q must be >= 0"), MP_QSTR_count); + } + common_hal_memorymonitor_allocationalarm_set_ignore(self_in, count); + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_2(memorymonitor_allocationalarm_ignore_obj, memorymonitor_allocationalarm_obj_ignore); //| def __enter__(self) -> memorymonitor.AllocationAlarm: //| """Enables the alarm.""" @@ -95,6 +115,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(memorymonitor_allocationalarm___enter___obj, memorymon //| STATIC mp_obj_t memorymonitor_allocationalarm_obj___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; + common_hal_memorymonitor_allocationalarm_set_ignore(args[0], 0); common_hal_memorymonitor_allocationalarm_pause(args[0]); return mp_const_none; } @@ -102,6 +123,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(memorymonitor_allocationalarm___exit_ STATIC const mp_rom_map_elem_t memorymonitor_allocationalarm_locals_dict_table[] = { // Methods + { MP_ROM_QSTR(MP_QSTR_ignore), MP_ROM_PTR(&memorymonitor_allocationalarm_ignore_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&memorymonitor_allocationalarm___enter___obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&memorymonitor_allocationalarm___exit___obj) }, }; diff --git a/shared-bindings/memorymonitor/AllocationAlarm.h b/shared-bindings/memorymonitor/AllocationAlarm.h index 40f5a48c5b..304b9c5a72 100644 --- a/shared-bindings/memorymonitor/AllocationAlarm.h +++ b/shared-bindings/memorymonitor/AllocationAlarm.h @@ -34,5 +34,6 @@ extern const mp_obj_type_t memorymonitor_allocationalarm_type; void common_hal_memorymonitor_allocationalarm_construct(memorymonitor_allocationalarm_obj_t* self, size_t minimum_block_count); void common_hal_memorymonitor_allocationalarm_pause(memorymonitor_allocationalarm_obj_t* self); void common_hal_memorymonitor_allocationalarm_resume(memorymonitor_allocationalarm_obj_t* self); +void common_hal_memorymonitor_allocationalarm_set_ignore(memorymonitor_allocationalarm_obj_t* self, mp_int_t count); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_MEMORYMONITOR_ALLOCATIONALARM_H diff --git a/shared-bindings/memorymonitor/AllocationSize.c b/shared-bindings/memorymonitor/AllocationSize.c index 25ecae97b8..3e0e31336f 100644 --- a/shared-bindings/memorymonitor/AllocationSize.c +++ b/shared-bindings/memorymonitor/AllocationSize.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,7 @@ //| def __init__(self): //| """Tracks the number of allocations in power of two buckets. //| -//| It will have 32 16bit buckets to track allocation counts. It is total allocations +//| It will have 16 16bit buckets to track allocation counts. It is total allocations //| meaning frees are ignored. Reallocated memory is counted twice, at allocation and when //| reallocated with the larger size. //| @@ -47,25 +47,20 @@ //| per block, typically 16. Bucket 2 will be less than or equal to 4 blocks. See //| `bytes_per_block` to convert blocks to bytes. //| -//| Multiple AllocationSizes can be used to track different boundaries. -//| -//| Active AllocationSizes will not be freed so make sure and pause before deleting. +//| Multiple AllocationSizes can be used to track different code boundaries. //| //| Track allocations:: //| //| import memorymonitor //| -//| mm = memorymonitor.AllocationSizes() -//| print("hello world" * 3) -//| mm.pause() -//| for bucket in mm: -//| print("<", 2 ** bucket, mm[bucket]) +//| mm = memorymonitor.AllocationSize() +//| with mm: +//| print("hello world" * 3) //| -//| # Clear the buckets -//| mm.clear() +//| for bucket, count in enumerate(mm): +//| print("<", 2 ** bucket, count) //| -//| # Resume allocation tracking -//| mm.resume()""" +//| """ //| ... //| STATIC mp_obj_t memorymonitor_allocationsize_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -78,7 +73,7 @@ STATIC mp_obj_t memorymonitor_allocationsize_make_new(const mp_obj_type_t *type, } //| def __enter__(self, ) -> Any: -//| """No-op used by Context Managers.""" +//| """Clears counts and resumes tracking.""" //| ... //| STATIC mp_obj_t memorymonitor_allocationsize_obj___enter__(mp_obj_t self_in) { @@ -118,12 +113,12 @@ const mp_obj_property_t memorymonitor_allocationsize_bytes_per_block_obj = { }; //| def __len__(self, ) -> Any: -//| """Returns the current pulse length +//| """Returns the number of allocation buckets. //| //| This allows you to:: //| -//| pulses = pulseio.PulseIn(pin) -//| print(len(pulses))""" +//| mm = memorymonitor.AllocationSize() +//| print(len(mm))""" //| ... //| STATIC mp_obj_t memorymonitor_allocationsize_unary_op(mp_unary_op_t op, mp_obj_t self_in) { @@ -137,12 +132,12 @@ STATIC mp_obj_t memorymonitor_allocationsize_unary_op(mp_unary_op_t op, mp_obj_t } //| def __getitem__(self, index: Any) -> Any: -//| """Returns the value at the given index or values in slice. +//| """Returns the allocation count for the given bucket. //| //| This allows you to:: //| -//| pulses = pulseio.PulseIn(pin) -//| print(pulses[0])""" +//| mm = memorymonitor.AllocationSize() +//| print(mm[0])""" //| ... //| STATIC mp_obj_t memorymonitor_allocationsize_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value) { diff --git a/shared-module/memorymonitor/AllocationAlarm.c b/shared-module/memorymonitor/AllocationAlarm.c index ed7ab75ab2..35f4e4c636 100644 --- a/shared-module/memorymonitor/AllocationAlarm.c +++ b/shared-module/memorymonitor/AllocationAlarm.c @@ -37,6 +37,10 @@ void common_hal_memorymonitor_allocationalarm_construct(memorymonitor_allocation self->previous = NULL; } +void common_hal_memorymonitor_allocationalarm_set_ignore(memorymonitor_allocationalarm_obj_t* self, mp_int_t count) { + self->count = count; +} + void common_hal_memorymonitor_allocationalarm_pause(memorymonitor_allocationalarm_obj_t* self) { // Check to make sure we aren't already paused. We can be if we're exiting from an exception we // caused. @@ -67,12 +71,16 @@ void memorymonitor_allocationalarms_allocation(size_t block_count) { // Hold onto next in case we remove the alarm from the list. memorymonitor_allocationalarm_obj_t* next = alarm->next; if (block_count >= alarm->minimum_block_count) { - // Uncomment the breakpoint below if you want to use a C debugger to figure out the C - // call stack for an allocation. - // asm("bkpt"); - // Pause now because we may alert when throwing the exception too. - common_hal_memorymonitor_allocationalarm_pause(alarm); - alert_count++; + if (alarm->count > 0) { + alarm->count--; + } else { + // Uncomment the breakpoint below if you want to use a C debugger to figure out the C + // call stack for an allocation. + // asm("bkpt"); + // Pause now because we may alert when throwing the exception too. + common_hal_memorymonitor_allocationalarm_pause(alarm); + alert_count++; + } } alarm = next; } diff --git a/shared-module/memorymonitor/AllocationAlarm.h b/shared-module/memorymonitor/AllocationAlarm.h index 95381c6609..172c24f6c8 100644 --- a/shared-module/memorymonitor/AllocationAlarm.h +++ b/shared-module/memorymonitor/AllocationAlarm.h @@ -39,6 +39,7 @@ typedef struct _memorymonitor_allocationalarm_obj_t memorymonitor_allocationalar typedef struct _memorymonitor_allocationalarm_obj_t { mp_obj_base_t base; size_t minimum_block_count; + mp_int_t count; // Store the location that points to us so we can remove ourselves. memorymonitor_allocationalarm_obj_t** previous; memorymonitor_allocationalarm_obj_t* next;