8000 Update core with upstream umm_malloc by mhightower83 · Pull Request #6438 · esp8266/Arduino · GitHub
[go: up one dir, main page]

Skip to content

Update core with upstream umm_malloc #6438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 40 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
88a32c8
WIP: Initial overlay of upstream version of umm_malloc over
mhightower83 Aug 20, 2019
b508642
WIP: upstream version of umm_malloc customized for Arduino ESP8266 Core
mhightower83 Aug 20, 2019
d7363e0
Resoved Travis CI - issue
mhightower83 Aug 23, 2019
57b65ab
Corrected #ifdef's for UMM_STATS/UMM_STATS_FULL
mhightower83 Aug 27, 2019
da47a79
Merge branch 'master' into WIP-upstream-umm_malloc
d-a-v Aug 29, 2019
71b10fd
Corrected UMM_REALLOC_DEFRAG option to be more like the original umm_…
mhightower83 Sep 3, 2019
4612235
Merge branch 'WIP-upstream-umm_malloc' of github.com:mhightower83/Ard…
mhightower83 Sep 3, 2019
79fe67f
Updated UMM_POISON_CHECK_LITE - Expanded the poison check on the current
mhightower83 Sep 5, 2019
5ded134
Updated printing in heap.cpp to behave the way os_printf did.
mhightower83 Sep 8, 2019
2a1923e
Merged latest, 2019-09-07, from upstream umm_malloc
mhightower83 Sep 8, 2019
f68a64f
Resolved issue where OOM selected w/ Debug port: "Disabled" caused hang.
mhightower83 Sep 8, 2019
9fcf27b
Fixed realloc OOM bug introduced due to confusing code, added comment…
mhightower83 Sep 9, 2019
ad03e16
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Sep 11, 2019
f438e02
Updated to track PRs for various print definitions. Cleaned up comments
mhightower83 Sep 27, 2019
919b122
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Sep 28, 2019
35c6868
Added missing "#ifdef __cplusplus"
mhightower83 Sep 28, 2019
47563cd
Reorganize local enhancements
mhightower83 Sep 29, 2019
2a1b722
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Sep 30, 2019
5560f6b
Print notice message for the need of -DUMM_INFO_PRINT
mhightower83 Sep 30, 2019
c4a46bc
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Sep 30, 2019
0b89ce7
This updates the heap management library, umm_malloc, to the current …
mhightower83 Sep 30, 2019
7e859c5
This updates the heap management library, umm_malloc, to the current …
mhightower83 Sep 30, 2019
2d26ccb
Updated upstream TODO
mhightower83 Oct 1, 2019
eed4b99
Merge branch 'WIP-upstream-umm_malloc' of github.com:mhightower83/Ard…
mhightower83 Oct 1, 2019
966812a
Changes on printing to comply with new understanding of SPI bus avail…
mhightower83 Oct 1, 2019
3669bf5
Removed no longer needed files.
mhightower83 Oct 1, 2019
be66ae7
OOM build option now saves file and line number for post mortem repor…
mhightower83 Oct 2, 2019
917e723
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 2, 2019
503def2
Merge branch 'WIP-upstream-umm_malloc' of github.com:mhightower83/Ard…
mhightower83 Oct 2, 2019
3b80577
Missed change.
mhightower83 Oct 5, 2019
2507ced
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 10, 2019
46b61fb
Consolated upstream integration comments into Notes.h. This helps
mhightower83 Oct 10, 2019
e9401c7
Comment updates.
mhightower83 Oct 10, 2019
648c028
Notes update.
mhightower83 Oct 10, 2019
3475ba2
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 17, 2019
435b8a6
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 23, 2019
eb5a7ca
Changes to heap.cpp -
mhightower83 Oct 24, 2019
3c77efe
Corrected Full Poison Check's placement and documented the
mhightower83 Oct 24, 2019
9da7eb8
Merge branch 'master' into WIP-upstream-umm_malloc
mhightower83 Oct 28, 2019
0eaa613
Fixed typos
mhightower83 Oct 29, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
WIP: Initial overlay of upstream version of umm_malloc over
our current version w/o any edits.

Using files from:
  https://github.com/rhempel/umm_malloc/tree/master/src
  https://github.com/rhempel/c-helper-macros/tree/develop

The following file remanents from our old version were removed:
  umm_malloc.cpp, umm_performance.h, umm_performance.cpp, and umm_stats.h

This is intended to be a "compare to" for changes made to
upstream version.
  • Loading branch information
mhightower83 committed Aug 20, 2019
commit 88a32c8d9f326ee33568bf04d3d1c5d84a3b4b8b
109 changes: 86 additions & 23 deletions cores/esp8266/umm_malloc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ might get expensive.

## Acknowledgements

Joerg Wunsch and the avr-libc provided the first malloc() implementation
Joerg Wunsch and the avr-libc provided the first `malloc()` implementation
that I examined in detail.

http://www.nongnu.org/avr-libc
`http://www.nongnu.org/avr-libc`

Doug Lea's paper on malloc() was another excellent reference and provides
a lot of detail on advanced memory management techniques such as binning.

http://g.oswego.edu/dl/html/malloc.html
`http://g.oswego.edu/dl/html/malloc.html`

Bill Dittman provided excellent suggestions, including macros to support
using these functions in critical sections, and for optimizing realloc()
using these functions in critical sections, and for optimizing `realloc()`
further by checking to see if the previous block was free and could be
used for the new block size. This can help to reduce heap fragmentation
significantly.
Expand All @@ -30,11 +30,73 @@ Yaniv Ankin suggested that a way to dump the current heap condition
might be useful. I combined this with an idea from plarroy to also
allow checking a free pointer to make sure it's valid.

Dimitry Frank contributed many helpful additions to make things more
robust including a user specified config file and a method of testing
the integrity of the data structures.

## Usage

Copy the `umm_malloc_cfg_example.h` file to `umm_malloc_cfg.h` and
make the changes required to support your application.

The following `#define`s must be set to something useful for the
library to work at all

- `UMM_MALLOC_CFG_HEAP_ADDR` must be set to the symbol representing
the starting address of the heap. The heap must be
aligned on the natural boundary size of the processor.
- `UMM_MALLOC_CFG_HEAP_SIZE` must be set to the size of the heap.
The heap size must be a multiple of the natural boundary size of
the processor.

The fit algorithm is defined as either:

- `UMM_BEST_FIT` which scans the entire free list and looks
for either an exact fit or the smallest block that will
satisfy the request. This is the default fit method.
- `UMM_FIRST_FIT` which scans the entire free list and looks
for the first block that satisfies the request.

The following `#define`s are disabled by default and should
remain disabled for production use. They are helpful when
testing allocation errors (which are normally due to bugs in
the application code) or for running the test suite when
making changes to the code.

You can define them in your compiler command line or uncomment
the corresponding entries is `umm_malloc_cfg.h`:

- `UMM_INFO` is used to include code that allows dumping
the entire heap structure (helpful when there's a problem).

- `UMM_INTEGRITY_CHECK` is used to include code that
performs an integrity check on the heap structure. It's
up to you to call the `umm_integrity_check()` function.

- `UMM_POISON_CHECK` is used to include code that
adds some bytes around the memory being allocated that
are filled with known data. If the data is not intact
when the block is checked, then somone has written outside
of the memory block they have been allocated. It is up
to you to call the `umm_poison_check()` function.

## API

The following functions are available for your application:

- `void *umm_malloc( size_t size );`
- `void *umm_calloc( size_t num, size_t size );`
- `void *umm_realloc( void *ptr, size_t size );`
- `void umm_free( void *ptr );`

They have exactly the same semantics as the corresponding standard library
functions.

## Background

The memory manager assumes the following things:

1. The standard POSIX compliant malloc/realloc/free semantics are used
1. The standard POSIX compliant malloc/calloc/realloc/free semantics are used
1. All memory used by the manager is allocated at link time, it is aligned
on a 32 bit boundary, it is contiguous, and its extent (start and end
address) is filled in by the linker.
Expand All @@ -45,17 +107,17 @@ The fastest linked list implementations use doubly linked lists so that
its possible to insert and delete blocks in constant time. This memory
manager keeps track of both free and used blocks in a doubly linked list.

Most memory managers use some kind of list structure made up of pointers
Most memory managers use a list structure made up of pointers
to keep track of used - and sometimes free - blocks of memory. In an
embedded system, this can get pretty expensive as each pointer can use
up to 32 bits.

In most embedded systems there is no need for managing large blocks
of memory dynamically, so a full 32 bit pointer based data structure
In most embedded systems there is no need for managing a large quantity
of memory block dynamically, so a full 32 bit pointer based data structure
for the free and used block lists is wasteful. A block of memory on
the free list would use 16 bytes just for the pointers!

This memory management library sees the malloc heap as an array of blocks,
This memory management library sees the heap as an array of blocks,
and uses block numbers to keep track of locations. The block numbers are
15 bits - which allows for up to 32767 blocks of memory. The high order
bit marks a block as being either free or in use, which will be explained
Expand All @@ -75,7 +137,7 @@ can always add more data bytes to the body of the memory block
at the expense of free block size overhead.

There are a lot of little features and optimizations in this memory
management system that makes it especially suited to small embedded, but
management system that makes it especially suited to small systems, and
the best way to appreciate them is to review the data structures and
algorithms used, so let's get started.

Expand Down Expand Up @@ -124,10 +186,9 @@ Where:
- n is the index of the next block in the heap
- p is the index of the previous block in the heap

Note that the free list information is gone, because it's now being used to
store actual data for the application. It would have been nice to store
the next and previous free list indexes as well, but that would be a waste
of space. If we had even 500 items in use, that would be 2,000 bytes for
Note that the free list information is gone because it's now
being used to store actual data for the application. If we had
even 500 items in use, that would be 2,000 bytes for
free list information. We simply can't afford to waste that much.

The address of the `...` area is what is returned to the application
Expand All @@ -143,7 +204,7 @@ described.
`...` between memory blocks indicates zero or more additional blocks are
allocated for use by the upper block.

And while we're talking about "upper" and "lower" blocks, we should make
While we're talking about "upper" and "lower" blocks, we should make
a comment about adresses. In the diagrams, a block higher up in the
picture is at a lower address. And the blocks grow downwards their
block index increases as does their physical address.
Expand All @@ -166,24 +227,27 @@ we're at the end of the list!

At this point, the malloc has a special test that checks if the current
block index is 0, which it is. This special case initializes the free
list to point at block index 1.
list to point at block index 1 and then points block 1 to the
last block (lf) on the heap.

```
BEFORE AFTER

+----+----+----+----+ +----+----+----+----+
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
+----+----+----+----+ +----+----+----+----+
+----+----+----+----+
1 | 0 | 0 | 0 | 0 |
1 |*lf | 0 | 0 | 0 |
+----+----+----+----+
...
+----+----+----+----+
lf | 0 | 1 | 0 | 0 |
+----+----+----+----+
```

The heap is now ready to complete the first malloc operation.


### Operation of malloc when we have reached the end of the free list and
there is no block large enough to accommodate the request.
### Operation of malloc when we have reached the end of the free list and there is no block large enough to accommodate the request.

This happens at the very first malloc operation, or any time the free
list is traversed and no free block large enough for the request is
Expand Down Expand Up @@ -306,8 +370,7 @@ else
```

Step 1 of the free operation checks if the next block is free, and if it
is then insert this block into the free list and assimilate the next block
with this one.
is assimilate the next block with this one.

Note that c is the block we are freeing up, cf is the free block that
follows it.
Expand Down
21 changes: 21 additions & 0 deletions cores/esp8266/umm_malloc/dbglog/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2016 Ralph Hempel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
1 change: 1 addition & 0 deletions cores/esp8266/umm_malloc/dbglog/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Downloaded from: https://github.com/rhempel/c-helper-macros/tree/develop
98 changes: 98 additions & 0 deletions cores/esp8266/umm_malloc/dbglog/dbglog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/* ----------------------------------------------------------------------------
* dbglog.h - A set of macros that cleans up code that needs to produce debug
* or log information.
*
* Many embedded systems still put a premium on code space and therefore need
* a way to conditionally compile in debug code. Yes, it can lead to code that
* runs differently depending on whether the debug code is cmpiled in or not
* but you need to be able to evaluate the tradeoff.
*
* See copyright notice in LICENSE.TXT
* ----------------------------------------------------------------------------
* NOTE WELL that this file may be included multiple times - this allows you
* to set the trace level #define DBGLOG_LEVEL x
*
* To update which of the DBGLOG macros are compiled in, you must redefine the
* DBGLOG_LEVEL macro and the inlcude the dbglog.h file again, like this:
*
* #undef DBGLOG_LEVEL
* #define DBGLOG_LEVEL 6
* #include "dbglog/dbglog.txt"
*
* To handle multiple inclusion, we need to first undefine any macros we define
* so that the compiler does not warn us that we are changing a macro.
* ----------------------------------------------------------------------------
* The DBGLOG_LEVEL and DBGLOG_FUNCTION should be defined BEFORE this
* file is included or else the following defaults are used:
*
* #define DBGLOG_LEVEL 0
* #define DBGLOG_FUNCTION printf
* ----------------------------------------------------------------------------
* There are macros to handle the following decreasing levels of detail:
*
* 6 = TRACE
* 5 = DEBUG
* 4 = CRITICAL
* 3 = ERROR
* 2 = WARNING
* 1 = INFO
* 0 = FORCE - The DBGLOG_FUNCTION is always compiled in and is called only when
* the first parameter to the macro is non-0
* ----------------------------------------------------------------------------
*/

#undef DBGLOG_TRACE
#undef DBGLOG_DEBUG
#undef DBGLOG_CRITICAL
#undef DBGLOG_ERROR
#undef DBGLOG_WARNING
#undef DBGLOG_INFO
#undef DBGLOG_FORCE

#ifndef DBGLOG_LEVEL
# define DBGLOG_LEVEL 0
#endif

#ifndef DBGLOG_FUNCTION
# define DBGLOG_FUNCTION printf
#endif

/* ------------------------------------------------------------------------- */

#if DBGLOG_LEVEL >= 6
# define DBGLOG_TRACE(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__)
#else
# define DBGLOG_TRACE(format, ...)
#endif

#if DBGLOG_LEVEL >= 5
# define DBGLOG_DEBUG(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__)
#else
# define DBGLOG_DEBUG(format, ...)
#endif

#if DBGLOG_LEVEL >= 4
# define DBGLOG_CRITICAL(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__)
#else
# define DBGLOG_CRITICAL(format, ...)
#endif

#if DBGLOG_LEVEL >= 3
# define DBGLOG_ERROR(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__)
#else
# define DBGLOG_ERROR(format, ...)
#endif

#if DBGLOG_LEVEL >= 2
# define DBGLOG_WARNING(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__)
#else
# define DBGLOG_WARNING(format, ...)
#endif

#if DBGLOG_LEVEL >= 1
# define DBGLOG_INFO(format, ...) DBGLOG_FUNCTION(format, ## __VA_ARGS__)
#else
# define DBGLOG_INFO(format, ...)
#endif

#define DBGLOG_FORCE(force, format, ...) {if(force) {DBGLOG_FUNCTION(format, ## __VA_ARGS__);}}
Loading
0