/****************************************************************************/
/* Copyright 1990 - 2002 MBARI											    */
/****************************************************************************/
/* Summary  : C malloc utility                                              */
/* Filename : malloc.c													    */
/* Author   : Bob Herlien													*/
/* Project  : OASIS Mooring Replacement (OASIS5)							*/
/* Revision: 1.0															*/
/* Created  : 28jun2016														*/
/*																		    */
/* MBARI provides this documentation and code "as is", with no warranty,    */
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium  */
/* Research Institute to assist in its use, correction, modification, or    */
/* enhancement. This information should not be published or distributed to  */
/* third parties without specific written permission from MBARI.            */
/*																		    */
/****************************************************************************/
/* Modification History:                                                    */
/* 28june2016, rah, adapted from malloc.c for OASIS3/4					    */
/* $Log: malloc.c,v $
 */
/****************************************************************************/

#include <mbariTypes.h>						/* MBARI type definitions	    */
#include <mbariConst.h>						/* MBARI constants				*/
#include <malloc.h>							/* OASIS malloc routines	    */
#include <utils.h>							/* OASIS Utility routines	    */
#include <istdio.h>							/* integer-only version of stdio.h*/
#include <FreeRTOS.h>						/* FreeRTOS definitions			*/
#include <task.h>							/* FreeRTOS Task definitions	*/
#include <otask.h>							/* Oasis Task definitions		*/


/****************************************************************************/
/* Function    : malloc														*/
/* Purpose     : Replacement for library's malloc							*/
/* Inputs      : size to malloc												*/
/* Outputs     : Ptr to malloc'd memory, or NULL							*/
/* Comments    : Saves up to two malloc'd ptrs in ThreadLocalStorage, to	*/
/*               allow us to free them at mallocTaskExit					*/
/****************************************************************************/
void *malloc(size_t size)
{
	void	*p;

	if ((p = pvPortMalloc(size)) == NULL)
		return(NULL);

	if (pvTaskGetThreadLocalStoragePointer(NULL, Malloc1) == NULL)
		vTaskSetThreadLocalStoragePointer(NULL, Malloc1, p);
	else
		vTaskSetThreadLocalStoragePointer(NULL, Malloc2, p);
	
	return(p);
}
	

/****************************************************************************/
/* Function    : free														*/
/* Purpose     : Replacement for library's free								*/
/* Inputs      : ptr to free												*/
/* Outputs     : None														*/
/****************************************************************************/
void free(void *p)
{
	if (pvTaskGetThreadLocalStoragePointer(NULL, Malloc1) == p)
		vTaskSetThreadLocalStoragePointer(NULL, Malloc1, NULL);
	else if (pvTaskGetThreadLocalStoragePointer(NULL, Malloc2) == p)
		vTaskSetThreadLocalStoragePointer(NULL, Malloc2, NULL);
	
	vPortFree(p);
}


/****************************************************************************/
/* Function    : pmalloc													*/
/* Purpose     : Malloc with error message on failure						*/
/* Inputs      : size to malloc												*/
/* Outputs     : Ptr to malloc'd memory, or NULL							*/
/****************************************************************************/
void	*pmalloc(size_t n)
{
	void	*p;

	if ((p = malloc(n)) == NULL)
		iprintf("Cannot malloc %d bytes\n", n);

	return(p);

} /* pmalloc() */


/****************************************************************************/
/* Function    : mallocTaskExit												*/
/* Purpose     : Free any allocated memory owned by exiting task			*/
/* Inputs      : TaskHandle													*/
/* Outputs     : None														*/
/****************************************************************************/
void	mallocTaskExit(TaskHandle_t td)
{
	void	*p;

	if ((p = pvTaskGetThreadLocalStoragePointer(td, Malloc1)) != NULL)
	{
		vPortFree(p);
		vTaskSetThreadLocalStoragePointer(td, Malloc1, NULL);
	}

	if ((p = pvTaskGetThreadLocalStoragePointer(td, Malloc2)) != NULL)
	{
		vPortFree(p);
		vTaskSetThreadLocalStoragePointer(td, Malloc2, NULL);
	}
}


/****************************************************************************/
/* Function    : memCheck												    */
/* Purpose     : User function to check memory integrity, show pool sizes   */
/* Inputs      : None                                                       */
/* Outputs     : None                                                       */
/****************************************************************************/
CmdRtn memCheck(void)
{
	iprintf("Heap space:  Current %d  Lowest %d\n",
		   xPortGetFreeHeapSize(), xPortGetMinimumEverFreeHeapSize());

	return(OK);

} /* memCheck() */
