/*
 * khm.h - kernel heap manager used for variable size memory allocation.
 *
 * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
 *          Mohamed Lamine Karaoui (2015)
 *          Alain Greiner (2016)
 *
 * Copyright (c) UPMC Sorbonne Universites
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _HEAP_MANAGER_H_
#define _HEAP_MANAGER_H_

#include <kernel_config.h>
#include <hal_kernel_types.h>
#include <spinlock.h>

/*******************************************************************************************
 * This structure defines a Kernel Heap Manager (KHM) in a given cluster.
 * It is used to allocate memory objects, that are not
 * enough replicated to justify a dedicated KCM allocator.
 ******************************************************************************************/

typedef struct khm_s
{
	spinlock_t lock;           /*! lock protecting exclusive access to heap               */
	intptr_t   base;           /*! heap base address                                      */
	uint32_t   size;           /*! heap size (bytes)                                      */
	intptr_t   next;           /*! next free block address                                */
}
khm_t;

/*******************************************************************************************
 * This structure defines an allocated block descriptor for the KHM.
 * This block descriptor is stored at the beginning of the allocated block.
 * The returned pointer is the allocated memory block base + block descriptor size.
 ******************************************************************************************/

typedef struct khm_block_s
{
	uint32_t   busy:1;         /*! free block if zero                                     */
	uint32_t   size:31;        /*! size coded on 31 bits                                  */
}
khm_block_t;


/*******************************************************************************************
 * This function initializes a KHM heap manager in a given cluster.
 * It is used to allocate variable size memory objects, that are not
 * enough replicated to justify a dedicated KCM allocator.
 *******************************************************************************************
 * @ khm        : pointer on KHM to initialize.
 * @ heap_base  : heap base address.
 * @ heap_size  : heap size in bytes.
 ******************************************************************************************/
void khm_init( khm_t    * khm );

/*******************************************************************************************
 * This function allocates a memory block from the local KHM.
 * The actual size of the allocated block is the requested size, plus the block descriptor
 * size, rounded to a cache line size.
 *******************************************************************************************
 * @ khm    : pointer on local kernel heap manager.
 * @ size   : number of requested bytes (must be smaller than 2G bytes).
 * @ returns a pointer on memory block if success / returns NULL if failure.
 ******************************************************************************************/
void * khm_alloc( khm_t    * khm,
                  uint32_t   size );

/*******************************************************************************************
 * This function releases a previoully allocated memory block to the local KHM.
 *******************************************************************************************
 * @ ptr    : pointer on released block.
 ******************************************************************************************/
void  khm_free( void * ptr );

#endif	/* _HEAP_MANAGER_H_ */
