blob: 83677dcd231fc9718f07ecf5bebca4410fce9840 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CDEV_CURRENT_FUNCTION _comment_
/**
* @file
* @ingroup Port
* @brief Memory Utilities
*/
#undef CDEV_CURRENT_FUNCTION
/*
* This file contains code for the portability library memory management.
*/
#include <stdlib.h>
#include <string.h>
#include "hyport.h"
#include "portpriv.h"
#include "hyportpg.h"
#include "ut_hyprt.h"
#if defined(DEBUG_MALLOC_FREE_LEAK)
#include <stdio.h>
static UDATA DEBUG_TOTAL_ALLOCATED_MEMORY = 0;
#endif
#define CDEV_CURRENT_FUNCTION hymem_allocate_memory
/**
* Allocate memory.
*
* @param[in] portLibrary The port library
* @param[in] byteAmount Number of bytes to allocate.
*
* @return pointer to memory on success, NULL on error.
* @return Memory is not guaranteed to be zeroed as part of this call
*
* @internal @warning Do not call error handling code @ref hyerror upon error as
* the error handling code uses per thread buffers to store the last error. If memory
* can not be allocated the result would be an infinite loop.
*/
void *VMCALL
hymem_allocate_memory (struct HyPortLibrary *portLibrary, UDATA byteAmount)
{
void *pointer = NULL;
void *mem;
Trc_PRT_mem_hymem_allocate_memory_Entry (byteAmount);
#if defined(DEBUG_MALLOC_FREE_LEAK)
if (byteAmount == 0)
{ /* prevent malloc from failing causing allocate to return null */
byteAmount = 1;
}
DEBUG_TOTAL_ALLOCATED_MEMORY += byteAmount;
portLibrary->tty_printf (portLibrary,
"\nallocate of %u bytes (new total is %u bytes)\n",
byteAmount, DEBUG_TOTAL_ALLOCATED_MEMORY);
mem = (void *) malloc (byteAmount + sizeof (UDATA));
#if defined(HYS390)
mem = (void *) (((UDATA) mem) & 0x7FFFFFFF);
#endif /* HYS390 */
*((UDATA *) mem) = byteAmount;
pointer = ((UDATA) mem + sizeof (UDATA));
#else
if (byteAmount == 0)
{ /* prevent malloc from failing causing allocate to return null */
byteAmount = 1;
}
pointer = malloc (byteAmount);
#if defined(HYS390)
pointer = (void *) (((UDATA) pointer) & 0x7FFFFFFF);
#endif /* HYS390 */
#endif
Trc_PRT_mem_hymem_allocate_memory_Exit (pointer);
return pointer;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hymem_free_memory
/**
* Deallocate memory.
*
* @param[in] portLibrary The port library
* @param[in] memoryPointer Base address of memory to be deallocated.
*/
void VMCALL
hymem_free_memory (struct HyPortLibrary *portLibrary, void *memoryPointer)
{
Trc_PRT_mem_hymem_free_memory_Entry (memoryPointer);
#if defined(DEBUG_MALLOC_FREE_LEAK)
DEBUG_TOTAL_ALLOCATED_MEMORY -=
*((UDATA *) ((UDATA) memoryPointer - sizeof (UDATA)));
portLibrary->tty_printf (portLibrary,
"\nfree of %u bytes (new total is %u bytes)\n",
*((UDATA *) ((UDATA) memoryPointer -
sizeof (UDATA))),
DEBUG_TOTAL_ALLOCATED_MEMORY);
free ((void *) ((UDATA) memoryPointer - sizeof (UDATA)));
#else
free (memoryPointer);
#endif
Trc_PRT_mem_hymem_free_memory_Exit ();
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hymem_reallocate_memory
/**
* Re-allocate memory.
*
* @param[in] portLibrary The port library
* @param[in] memoryPointer Base address of memory to be re-allocated.
* @param[in] byteAmount Number of bytes to re-allocated.
*
* @return pointer to memory on success, NULL on error.
*
* @internal @warning Do not call error handling code @ref hyerror upon error as
* the error handling code uses per thread buffers to store the last error. If memory
* can not be allocated the result would be an infinite loop.
*/
void *VMCALL
hymem_reallocate_memory (struct HyPortLibrary *portLibrary,
void *memoryPointer, UDATA byteAmount)
{
void *ptr = NULL;
Trc_PRT_mem_hymem_reallocate_memory_Entry (memoryPointer, byteAmount);
ptr = realloc (memoryPointer, byteAmount);
#if defined(HYS390)
ptr = (void *) (((UDATA) ptr) & 0x7FFFFFFF);
#endif
Trc_PRT_mem_hymem_reallocate_memory_Exit (ptr);
return ptr;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hymem_shutdown
/**
* PortLibrary shutdown.
*
* This function is called during shutdown of the portLibrary. Any resources that were created by @ref hymem_startup
* should be destroyed here.
*
* @param[in] portLibrary The port library
*
* @note Must deallocate portGlobals.
* @note Most implementations will just deallocate portGlobals.
*/
void VMCALL
hymem_shutdown (struct HyPortLibrary *portLibrary)
{
portLibrary->mem_free_memory (portLibrary, portLibrary->portGlobals);
portLibrary->portGlobals = NULL;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hymem_startup
/**
* PortLibrary startup.
*
* This function is called during startup of the portLibrary. Any resources that are required for
* the memory operations may be created here. All resources created here should be destroyed
* in @ref hymem_shutdown.
*
* @param[in] portLibrary The port library
* @param[in] portGlobalSize Size of the global data structure to allocate
*
* @return 0 on success, negative error code on failure. Error code values returned are
* \arg HYPORT_ERROR_STARTUP_MEM
*.
* @note Must allocate portGlobals.
* @note Most implementations will just allocate portGlobals.
*
* @internal @note portLibrary->portGlobals must point to an aligned structure
*/
I_32 VMCALL
hymem_startup (struct HyPortLibrary *portLibrary, UDATA portGlobalSize)
{
portLibrary->portGlobals =
portLibrary->mem_allocate_memory (portLibrary, portGlobalSize);
if (!portLibrary->portGlobals)
{
return HYPORT_ERROR_STARTUP_MEM;
}
memset (portLibrary->portGlobals, 0, portGlobalSize);
return 0;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hymem_allocate_memory_callSite
/**
* Allocate memory.
*
* @param[in] portLibrary The port library
* @param[in] byteAmount Number of bytes to allocate.
* @param[in] callSite String describing callsite, usually file and line number.
*
* @return pointer to memory on success, NULL on error.
*
* @internal @warning Do not call error handling code @ref hyerror upon error as
* the error handling code uses per thread buffers to store the last error. If memory
* can not be allocated the result would be an infinite loop.
*/
void *VMCALL
hymem_allocate_memory_callSite (struct HyPortLibrary *portLibrary,
UDATA byteAmount, const char *callSite)
{
void *ptr = NULL;
Trc_PRT_mem_hymem_allocate_memory_callSite_Entry (byteAmount, callSite);
ptr = portLibrary->mem_allocate_memory (portLibrary, byteAmount);
Trc_PRT_mem_hymem_allocate_memory_callSite_Exit (ptr);
return ptr;
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hymem_allocate_portLibrary
/**
* @internal Allocate memory for a portLibrary.
*
* @param[in] byteAmount Number of bytes to allocate.
*
* @return pointer to memory on success, NULL on error.
* @note This function is called prior to the portLibrary being initialized
* @note Must be implemented for all platforms.
*/
void *VMCALL
hymem_allocate_portLibrary (UDATA byteAmount)
{
return (void *) malloc (byteAmount);
}
#undef CDEV_CURRENT_FUNCTION
#define CDEV_CURRENT_FUNCTION hymem_deallocate_portLibrary
/**
* @internal Free memory for a portLibrary.
*
* @param[in] memoryPointer Base address to be deallocated.
*
* @note Must be implemented for all platforms.
*/
void VMCALL
hymem_deallocate_portLibrary (void *memoryPointer)
{
free (memoryPointer);
}
#undef CDEV_CURRENT_FUNCTION