update copyright date to 2013
[dpdk.git] / lib / librte_malloc / malloc_heap.c
index 4f2e6d9..b6d83a4 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  * 
- *   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
  *   All rights reserved.
  * 
  *   Redistribution and use in source and binary forms, with or without 
 #include <rte_memzone.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
+#include <rte_eal_memconfig.h>
 #include <rte_launch.h>
 #include <rte_per_lcore.h>
 #include <rte_lcore.h>
 #include <rte_common.h>
 #include <rte_string_fns.h>
 #include <rte_spinlock.h>
+#include <rte_memcpy.h>
+#include <rte_atomic.h>
 
 #include "malloc_elem.h"
 #include "malloc_heap.h"
 
-#define QUOTE_(x) #x
-#define QUOTE(x) QUOTE_(x)
 /* since the memzone size starts with a digit, it will appear unquoted in
  * rte_config.h, so quote it so it can be passed to rte_str_to_size */
-#define MALLOC_MEMZONE_SIZE QUOTE(RTE_MALLOC_MEMZONE_SIZE)
+#define MALLOC_MEMZONE_SIZE RTE_STR(RTE_MALLOC_MEMZONE_SIZE)
 
 /*
  * returns the configuration setting for the memzone size as a size_t value
@@ -96,7 +97,7 @@ malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align)
        struct malloc_elem *start_elem = (struct malloc_elem *)mz->addr;
        struct malloc_elem *end_elem = RTE_PTR_ADD(mz->addr,
                        mz_size - MALLOC_ELEM_OVERHEAD);
-       end_elem = RTE_ALIGN_FLOOR(end_elem, CACHE_LINE_SIZE);
+       end_elem = RTE_PTR_ALIGN_FLOOR(end_elem, CACHE_LINE_SIZE);
 
        const unsigned elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
        malloc_elem_init(start_elem, heap, elem_size);
@@ -104,6 +105,8 @@ malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align)
 
        start_elem->next_free = heap->free_head;
        heap->free_head = start_elem;
+       /* increase heap total size by size of new memzone */
+       heap->total_size+=mz_size - MALLOC_ELEM_OVERHEAD;
        return 0;
 }
 
@@ -116,16 +119,27 @@ malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align)
 static void
 malloc_heap_init(struct malloc_heap *heap)
 {
-       static rte_spinlock_t init_lock = RTE_SPINLOCK_INITIALIZER;
-       rte_spinlock_lock(&init_lock);
-       if (!heap->initialised) {
-               heap->free_head = NULL;
-               heap->mz_count = 0;
-               heap->numa_socket = malloc_get_numa_socket();
-               rte_spinlock_init(&heap->lock);
-               heap->initialised = INITIALISED;
+       struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
+
+       rte_eal_mcfg_wait_complete(mcfg);
+       while (heap->initialised != INITIALISED) {
+               if (rte_atomic32_cmpset(
+                               (volatile uint32_t*)&heap->initialised,
+                               NOT_INITIALISED, INITIALISING)) {
+
+                       heap->free_head = NULL;
+                       heap->mz_count = 0;
+                       heap->alloc_count = 0;
+                       heap->total_size = 0;
+                       /*
+                        * Find NUMA socket of heap that is being initialised, so that
+                        * malloc_heaps[n].numa_socket == n
+                        */
+                       heap->numa_socket = heap - mcfg->malloc_heaps;
+                       rte_spinlock_init(&heap->lock);
+                       heap->initialised = INITIALISED;
+               }
        }
-       rte_spinlock_unlock(&init_lock);
 }
 
 /*
@@ -166,15 +180,54 @@ malloc_heap_alloc(struct malloc_heap *heap,
        size = CACHE_LINE_ROUNDUP(size);
        align = CACHE_LINE_ROUNDUP(align);
        rte_spinlock_lock(&heap->lock);
-
        struct malloc_elem *prev, *elem = find_suitable_element(heap,
                        size, align, &prev);
        if (elem == NULL){
-               malloc_heap_add_memzone(heap, size, align);
-               elem = find_suitable_element(heap, size, align, &prev);
+               if ((malloc_heap_add_memzone(heap, size, align)) == 0)
+                       elem = find_suitable_element(heap, size, align, &prev);
        }
-       if (elem != NULL)
+
+       if (elem != NULL){
                elem = malloc_elem_alloc(elem, size, align, prev);
+               /* increase heap's count of allocated elements */
+               heap->alloc_count++;
+       }
        rte_spinlock_unlock(&heap->lock);
        return elem == NULL ? NULL : (void *)(&elem[1]);
+
+}
+
+/*
+ * Function to retrieve data for heap on given socket
+ */
+int
+malloc_heap_get_stats(struct malloc_heap *heap,
+               struct rte_malloc_socket_stats *socket_stats)
+{
+       if (!heap->initialised)
+               return -1;
+
+       struct malloc_elem *elem = heap->free_head;
+
+       /* Initialise variables for heap */
+       socket_stats->free_count = 0;
+       socket_stats->heap_freesz_bytes = 0;
+       socket_stats->greatest_free_size = 0;
+
+       /* Iterate through free list */
+       while(elem) {
+               socket_stats->free_count++;
+               socket_stats->heap_freesz_bytes += elem->size;
+               if (elem->size > socket_stats->greatest_free_size)
+                       socket_stats->greatest_free_size = elem->size;
+
+               elem = elem->next_free;
+       }
+       /* Get stats on overall heap and allocated memory on this heap */
+       socket_stats->heap_totalsz_bytes = heap->total_size;
+       socket_stats->heap_allocsz_bytes = (socket_stats->heap_totalsz_bytes -
+                       socket_stats->heap_freesz_bytes);
+       socket_stats->alloc_count = heap->alloc_count;
+       return 0;
 }
+