From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id C9BC35A51 for ; Thu, 16 Jul 2015 09:37:15 +0200 (CEST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP; 16 Jul 2015 00:37:14 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,486,1432623600"; d="scan'208";a="748381871" Received: from irvmail001.ir.intel.com ([163.33.26.43]) by fmsmga001.fm.intel.com with ESMTP; 16 Jul 2015 00:37:13 -0700 Received: from sivswdev02.ir.intel.com (sivswdev02.ir.intel.com [10.237.217.46]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id t6G7bBvx015348 for ; Thu, 16 Jul 2015 08:37:11 +0100 Received: from sivswdev02.ir.intel.com (localhost [127.0.0.1]) by sivswdev02.ir.intel.com with ESMTP id t6G7bBkx005166 for ; Thu, 16 Jul 2015 08:37:11 +0100 Received: (from smonroy@localhost) by sivswdev02.ir.intel.com with id t6G7bB97005162 for dev@dpdk.org; Thu, 16 Jul 2015 08:37:11 +0100 From: Sergio Gonzalez Monroy To: dev@dpdk.org Date: Thu, 16 Jul 2015 08:37:11 +0100 Message-Id: <1437032231-5127-1-git-send-email-sergio.gonzalez.monroy@intel.com> X-Mailer: git-send-email 1.8.5.4 In-Reply-To: <1436977948-589-10-git-send-email-sergio.gonzalez.monroy@intel.com> References: <1436977948-589-10-git-send-email-sergio.gonzalez.monroy@intel.com> Subject: [dpdk-dev] [PATCH v11] doc: update malloc documentation X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 16 Jul 2015 07:37:17 -0000 Update malloc documentation to reflect new implementation details. Signed-off-by: Sergio Gonzalez Monroy --- v11: - Add copyright and licence to SVG file doc/guides/prog_guide/env_abstraction_layer.rst | 220 ++++- doc/guides/prog_guide/img/malloc_heap.png | Bin 81329 -> 0 bytes doc/guides/prog_guide/img/malloc_heap.svg | 1052 +++++++++++++++++++++++ doc/guides/prog_guide/index.rst | 1 - doc/guides/prog_guide/malloc_lib.rst | 233 ----- doc/guides/prog_guide/overview.rst | 11 +- 6 files changed, 1273 insertions(+), 244 deletions(-) delete mode 100644 doc/guides/prog_guide/img/malloc_heap.png create mode 100755 doc/guides/prog_guide/img/malloc_heap.svg delete mode 100644 doc/guides/prog_guide/malloc_lib.rst diff --git a/doc/guides/prog_guide/env_abstraction_layer.rst b/doc/guides/prog_guide/env_abstraction_layer.rst index 25eb281..cd4d666 100644 --- a/doc/guides/prog_guide/env_abstraction_layer.rst +++ b/doc/guides/prog_guide/env_abstraction_layer.rst @@ -116,7 +116,6 @@ The physical address of the reserved memory for that memory zone is also returne .. note:: Memory reservations done using the APIs provided by the rte_malloc library are also backed by pages from the hugetlbfs filesystem. - However, physical address information is not available for the blocks of memory allocated in this way. Xen Dom0 support without hugetbls ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -366,3 +365,222 @@ We expect only 50% of CPU spend on packet IO. echo 50000 > pkt_io/cpu.cfs_quota_us +Malloc +------ + +The EAL provides a malloc API to allocate any-sized memory. + +The objective of this API is to provide malloc-like functions to allow +allocation from hugepage memory and to facilitate application porting. +The *DPDK API Reference* manual describes the available functions. + +Typically, these kinds of allocations should not be done in data plane +processing because they are slower than pool-based allocation and make +use of locks within the allocation and free paths. +However, they can be used in configuration code. + +Refer to the rte_malloc() function description in the *DPDK API Reference* +manual for more information. + +Cookies +~~~~~~~ + +When CONFIG_RTE_MALLOC_DEBUG is enabled, the allocated memory contains +overwrite protection fields to help identify buffer overflows. + +Alignment and NUMA Constraints +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The rte_malloc() takes an align argument that can be used to request a memory +area that is aligned on a multiple of this value (which must be a power of two). + +On systems with NUMA support, a call to the rte_malloc() function will return +memory that has been allocated on the NUMA socket of the core which made the call. +A set of APIs is also provided, to allow memory to be explicitly allocated on a +NUMA socket directly, or by allocated on the NUMA socket where another core is +located, in the case where the memory is to be used by a logical core other than +on the one doing the memory allocation. + +Use Cases +~~~~~~~~~ + +This API is meant to be used by an application that requires malloc-like +functions at initialization time. + +For allocating/freeing data at runtime, in the fast-path of an application, +the memory pool library should be used instead. + +Internal Implementation +~~~~~~~~~~~~~~~~~~~~~~~ + +Data Structures +^^^^^^^^^^^^^^^ + +There are two data structure types used internally in the malloc library: + +* struct malloc_heap - used to track free space on a per-socket basis + +* struct malloc_elem - the basic element of allocation and free-space + tracking inside the library. + +Structure: malloc_heap +"""""""""""""""""""""" + +The malloc_heap structure is used to manage free space on a per-socket basis. +Internally, there is one heap structure per NUMA node, which allows us to +allocate memory to a thread based on the NUMA node on which this thread runs. +While this does not guarantee that the memory will be used on that NUMA node, +it is no worse than a scheme where the memory is always allocated on a fixed +or random node. + +The key fields of the heap structure and their function are described below +(see also diagram above): + +* lock - the lock field is needed to synchronize access to the heap. + Given that the free space in the heap is tracked using a linked list, + we need a lock to prevent two threads manipulating the list at the same time. + +* free_head - this points to the first element in the list of free nodes for + this malloc heap. + +.. note:: + + The malloc_heap structure does not keep track of in-use blocks of memory, + since these are never touched except when they are to be freed again - + at which point the pointer to the block is an input to the free() function. + +.. _figure_malloc_heap: + +.. figure:: img/malloc_heap.* + + Example of a malloc heap and malloc elements within the malloc library + + +.. _malloc_elem: + +Structure: malloc_elem +"""""""""""""""""""""" + +The malloc_elem structure is used as a generic header structure for various +blocks of memory. +It is used in three different ways - all shown in the diagram above: + +#. As a header on a block of free or allocated memory - normal case + +#. As a padding header inside a block of memory + +#. As an end-of-memseg marker + +The most important fields in the structure and how they are used are described below. + +.. note:: + + If the usage of a particular field in one of the above three usages is not + described, the field can be assumed to have an undefined value in that + situation, for example, for padding headers only the "state" and "pad" + fields have valid values. + +* heap - this pointer is a reference back to the heap structure from which + this block was allocated. + It is used for normal memory blocks when they are being freed, to add the + newly-freed block to the heap's free-list. + +* prev - this pointer points to the header element/block in the memseg + immediately behind the current one. When freeing a block, this pointer is + used to reference the previous block to check if that block is also free. + If so, then the two free blocks are merged to form a single larger block. + +* next_free - this pointer is used to chain the free-list of unallocated + memory blocks together. + It is only used in normal memory blocks; on ``malloc()`` to find a suitable + free block to allocate and on ``free()`` to add the newly freed element to + the free-list. + +* state - This field can have one of three values: ``FREE``, ``BUSY`` or + ``PAD``. + The former two are to indicate the allocation state of a normal memory block + and the latter is to indicate that the element structure is a dummy structure + at the end of the start-of-block padding, i.e. where the start of the data + within a block is not at the start of the block itself, due to alignment + constraints. + In that case, the pad header is used to locate the actual malloc element + header for the block. + For the end-of-memseg structure, this is always a ``BUSY`` value, which + ensures that no element, on being freed, searches beyond the end of the + memseg for other blocks to merge with into a larger free area. + +* pad - this holds the length of the padding present at the start of the block. + In the case of a normal block header, it is added to the address of the end + of the header to give the address of the start of the data area, i.e. the + value passed back to the application on a malloc. + Within a dummy header inside the padding, this same value is stored, and is + subtracted from the address of the dummy header to yield the address of the + actual block header. + +* size - the size of the data block, including the header itself. + For end-of-memseg structures, this size is given as zero, though it is never + actually checked. + For normal blocks which are being freed, this size value is used in place of + a "next" pointer to identify the location of the next block of memory that + in the case of being ``FREE``, the two free blocks can be merged into one. + +Memory Allocation +^^^^^^^^^^^^^^^^^ + +On EAL initialisation, all memsegs are setup as part of the malloc heap. +This setup involves placing a dummy structure at the end with ``BUSY`` state, +which may contain a sentinel value if ``CONFIG_RTE_MALLOC_DEBUG`` is enabled, +and a proper :ref:`element header` with ``FREE`` at the start +for each memseg. +The ``FREE`` element is then added to the ``free_list`` for the malloc heap. + +When an application makes a call to a malloc-like function, the malloc function +will first index the ``lcore_config`` structure for the calling thread, and +determine the NUMA node of that thread. +The NUMA node is used to index the array of ``malloc_heap`` structures which is +passed as a parameter to the ``heap_alloc()`` function, along with the +requested size, type, alignment and boundary parameters. + +The ``heap_alloc()`` function will scan the free_list of the heap, and attempt +to find a free block suitable for storing data of the requested size, with the +requested alignment and boundary constraints. + +When a suitable free element has been identified, the pointer to be returned +to the user is calculated. +The cache-line of memory immediately preceding this pointer is filled with a +struct malloc_elem header. +Because of alignment and boundary constraints, there could be free space at +the start and/or end of the element, resulting in the following behavior: + +#. Check for trailing space. + If the trailing space is big enough, i.e. > 128 bytes, then the free element + is split. + If it is not, then we just ignore it (wasted space). + +#. Check for space at the start of the element. + If the space at the start is small, i.e. <=128 bytes, then a pad header is + used, and the remaining space is wasted. + If, however, the remaining space is greater, then the free element is split. + +The advantage of allocating the memory from the end of the existing element is +that no adjustment of the free list needs to take place - the existing element +on the free list just has its size pointer adjusted, and the following element +has its "prev" pointer redirected to the newly created element. + +Freeing Memory +^^^^^^^^^^^^^^ + +To free an area of memory, the pointer to the start of the data area is passed +to the free function. +The size of the ``malloc_elem`` structure is subtracted from this pointer to get +the element header for the block. +If this header is of type ``PAD`` then the pad length is further subtracted from +the pointer to get the proper element header for the entire block. + +From this element header, we get pointers to the heap from which the block was +allocated and to where it must be freed, as well as the pointer to the previous +element, and via the size field, we can calculate the pointer to the next element. +These next and previous elements are then checked to see if they are also +``FREE``, and if so, they are merged with the current element. +This means that we can never have two ``FREE`` memory blocks adjacent to one +another, as they are always merged into a single block. diff --git a/doc/guides/prog_guide/img/malloc_heap.png b/doc/guides/prog_guide/img/malloc_heap.png deleted file mode 100644 index 4449fda0dd0b7688b32854e8e32f8c45c505f5f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81329 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 diff --git a/doc/guides/prog_guide/img/malloc_heap.svg b/doc/guides/prog_guide/img/malloc_heap.svg new file mode 100755 index 0000000..d6bcc84 --- /dev/null +++ b/doc/guides/prog_guide/img/malloc_heap.svg @@ -0,0 +1,1052 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + struct malloc_heap + prev + prev + prev + prev + prev + prev + Free element header(struct malloc_elem, state = FREE) + Used element header(struct malloc_elem, state = BUSY) + size + Memseg 0 + Memseg 1 + prev + prev + next_free + next_free + free_head + prev + Dummy Elements:Size = 0State = BUSY + pad + Pad element header(struct malloc_elem, state = PAD) + Generic element pointers + Malloc element header:state = BUSYsize = <size>pad = <padsize> + size + Free / Unallocated data space + Pad element header:state = PADpad = padsize + Used / allocated data space + Padding / unavailable space + + diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index 036640c..176f2c2 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -43,7 +43,6 @@ Programmer's Guide intro overview env_abstraction_layer - malloc_lib ring_lib mempool_lib mbuf_lib diff --git a/doc/guides/prog_guide/malloc_lib.rst b/doc/guides/prog_guide/malloc_lib.rst deleted file mode 100644 index 6418fab..0000000 --- a/doc/guides/prog_guide/malloc_lib.rst +++ /dev/null @@ -1,233 +0,0 @@ -.. BSD LICENSE - Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -.. _Malloc_Library: - -Malloc Library -============== - -The librte_malloc library provides an API to allocate any-sized memory. - -The objective of this library is to provide malloc-like functions to allow allocation from hugepage memory -and to facilitate application porting. -The *DPDK API Reference* manual describes the available functions. - -Typically, these kinds of allocations should not be done in data plane processing -because they are slower than pool-based allocation and make use of locks within the allocation -and free paths. -However, they can be used in configuration code. - -Refer to the rte_malloc() function description in the *DPDK API Reference* manual for more information. - -Cookies -------- - -When CONFIG_RTE_MALLOC_DEBUG is enabled, the allocated memory contains overwrite protection fields -to help identify buffer overflows. - -Alignment and NUMA Constraints ------------------------------- - -The rte_malloc() takes an align argument that can be used to request a memory area -that is aligned on a multiple of this value (which must be a power of two). - -On systems with NUMA support, a call to the rte_malloc() function will return memory -that has been allocated on the NUMA socket of the core which made the call. -A set of APIs is also provided, to allow memory to be explicitly allocated on a NUMA socket directly, -or by allocated on the NUMA socket where another core is located, -in the case where the memory is to be used by a logical core other than on the one doing the memory allocation. - -Use Cases ---------- - -This library is needed by an application that requires malloc-like functions at initialization time, -and does not require the physical address information for the individual memory blocks. - -For allocating/freeing data at runtime, in the fast-path of an application, -the memory pool library should be used instead. - -If a block of memory with a known physical address is needed, -e.g. for use by a hardware device, a memory zone should be used. - -Internal Implementation ------------------------ - -Data Structures -~~~~~~~~~~~~~~~ - -There are two data structure types used internally in the malloc library: - -* struct malloc_heap - used to track free space on a per-socket basis - -* struct malloc_elem - the basic element of allocation and free-space tracking inside the library. - -Structure: malloc_heap -^^^^^^^^^^^^^^^^^^^^^^ - -The malloc_heap structure is used in the library to manage free space on a per-socket basis. -Internally in the library, there is one heap structure per NUMA node, -which allows us to allocate memory to a thread based on the NUMA node on which this thread runs. -While this does not guarantee that the memory will be used on that NUMA node, -it is no worse than a scheme where the memory is always allocated on a fixed or random node. - -The key fields of the heap structure and their function are described below (see also diagram above): - -* mz_count - field to count the number of memory zones which have been allocated for heap memory on this NUMA node. - The sole use of this value is, in combination with the numa_socket value, - to generate a suitable, unique name for each memory zone. - -* lock - the lock field is needed to synchronize access to the heap. - Given that the free space in the heap is tracked using a linked list, - we need a lock to prevent two threads manipulating the list at the same time. - -* free_head - this points to the first element in the list of free nodes for this malloc heap. - -.. note:: - - The malloc_heap structure does not keep track of either the memzones allocated, - since there is little point as they cannot be freed. - Neither does it track the in-use blocks of memory, - since these are never touched except when they are to be freed again - - at which point the pointer to the block is an input to the free() function. - -.. _figure_malloc_heap: - -.. figure:: img/malloc_heap.* - - Example of a malloc heap and malloc elements within the malloc library - - -Structure: malloc_elem -^^^^^^^^^^^^^^^^^^^^^^ -The malloc_elem structure is used as a generic header structure for various blocks of memory in a memzone. -It is used in three different ways - all shown in the diagram above: - -#. As a header on a block of free or allocated memory - normal case - -#. As a padding header inside a block of memory - -#. As an end-of-memzone marker - -The most important fields in the structure and how they are used are described below. - -.. note:: - - If the usage of a particular field in one of the above three usages is not described, - the field can be assumed to have an undefined value in that situation, for example, - for padding headers only the "state" and "pad" fields have valid values. - -* heap - this pointer is a reference back to the heap structure from which this block was allocated. - It is used for normal memory blocks when they are being freed, - to add the newly-freed block to the heap's free-list. - -* prev - this pointer points to the header element/block in the memzone immediately behind the current one. - When freeing a block, this pointer is used to reference the previous block to check if that block is also free. - If so, then the two free blocks are merged to form a single larger block. - -* next_free - this pointer is used to chain the free-list of unallocated memory blocks together. - Again, it is only used in normal memory blocks - on malloc() to find a suitable free block to allocate, - and on free() to add the newly freed element to the free-list. - -* state - This field can have one of three values: "Free", "Busy" or "Pad". - The former two, are to indicate the allocation state of a normal memory block, - and the latter is to indicate that the element structure is a dummy structure at the end of the start-of-block padding - (i.e. where the start of the data within a block is not at the start of the block itself, due to alignment constraints). - In this case, the pad header is used to locate the actual malloc element header for the block. - For the end-of-memzone structure, this is always a "busy" value, which ensures that no element, - on being freed, searches beyond the end of the memzone for other blocks to merge with into a larger free area. - -* pad - this holds the length of the padding present at the start of the block. - In the case of a normal block header, it is added to the address of the end of the header - to give the address of the start of the data area i.e. - the value passed back to the application on a malloc. - Within a dummy header inside the padding, this same value is stored, - and is subtracted from the address of the dummy header to yield the address of the actual block header. - -* size - the size of the data block, including the header itself. - For end-of-memzone structures, this size is given as zero, though it is never actually checked. - For normal blocks which are being freed, - this size value is used in place of a "next" pointer to identify the location of the next block of memory - (so that if it too is free, the two free blocks can be merged into one). - -Memory Allocation -~~~~~~~~~~~~~~~~~ - -When an application makes a call to a malloc-like function, -the malloc function will first index the lcore_config structure for the calling thread, -and determine the NUMA node idea of that thread. -That is used to index the array of malloc_heap structures, -and the heap_alloc () function is called with that heap as parameter, -along with the requested size, type and alignment parameters. - -The heap_alloc() function will scan the free_list for the heap, -and attempt to find a free block suitable for storing data of the requested size, -with the requested alignment constraints. -If no suitable block is found - for example, the first time malloc is called for a node, -and the free-list is NULL - a new memzone is reserved and set up as heap elements. -The setup involves placing a dummy structure at the end of the memzone -to act as a sentinel to prevent accesses beyond the end -(as the sentinel is marked as BUSY, the malloc library code will never attempt to reference it further), -and a proper element header at the start of the memzone. -This latter header identifies all space in the memzone, bar the sentinel value at the end, -as a single free heap element, and it is then added to the free_list for the heap. - -Once the new memzone has been set up, the scan of the free-list for the heap is redone, -and on this occasion should find the newly created, -suitable element as the size of memory reserved in the memzone is set to be -at least the size of the requested data block plus the alignment - -subject to a minimum size specified in the DPDK compile-time configuration. - -When a suitable, free element has been identified, the pointer to be returned to the user is calculated, -with the space to be provided to the user being at the end of the free block. -The cache-line of memory immediately preceding this space is filled with a struct malloc_elem header: -if the remaining space within the block is small e.g. <=128 bytes, -then a pad header is used, and the remaining space is wasted. -If, however, the remaining space is greater than this, then the single free element block is split into two, -and a new, proper, malloc_elem header is put before the returned data space. -[The advantage of allocating the memory from the end of the existing element is that -in this case no adjustment of the free list needs to take place - -the existing element on the free list just has its size pointer adjusted, -and the following element has its "prev" pointer redirected to the newly created element]. - -Freeing Memory -~~~~~~~~~~~~~~ - -To free an area of memory, the pointer to the start of the data area is passed to the free function. -The size of the malloc_elem structure is subtracted from this pointer to get the element header for the block. -If this header is of type "PAD" then the pad length is further subtracted from the pointer -to get the proper element header for the entire block. - -From this element header, we get pointers to the heap from which the block came -- and to where it must be freed, -as well as the pointer to the previous element, and, via the size field, -we can calculate the pointer to the next element. -These next and previous elements are then checked to see if they too are free, -and if so, they are merged with the current elements. -This means that we can never have two free memory blocks adjacent to one another, -they are always merged into a single block. diff --git a/doc/guides/prog_guide/overview.rst b/doc/guides/prog_guide/overview.rst index cef6ca7..5d378e5 100644 --- a/doc/guides/prog_guide/overview.rst +++ b/doc/guides/prog_guide/overview.rst @@ -112,6 +112,8 @@ The services provided by the EAL are: * Alarm operations +* Memory managenent (malloc) + The EAL is fully described in :ref:`Environment Abstraction Layer `. Core Components @@ -127,15 +129,6 @@ for high-performance packet processing applications. Core Components Architecture -Memory Manager (librte_malloc) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The librte_malloc library provides an API to allocate memory from the memzones created from the hugepages instead of the heap. -This helps when allocating large numbers of items that may become susceptible to TLB misses -when using typical 4k heap pages in the Linux user space environment. - -This memory allocator is fully described in :ref:`Malloc Library `. - Ring Manager (librte_ring) ~~~~~~~~~~~~~~~~~~~~~~~~~~ -- 1.9.3