/* vim: set filetype=c:
 *
 * memory.c86  -  MGL memory management routines
 *
 * Copyright (C) 2004-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  This program 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; either version 2 of the License, or
 *  any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: memory.c86,v 1.5 2007/01/06 18:31:38 gkminix Exp $
 */

#include "rtcommon.h86"
#include <i386/memory.h86>



/*
 *****************************************************************************
 *
 * Memory allocation
 */
#ifdef malloc
# undef malloc	/* Undefine any gcc preprocessor defines */
#endif

__INTERNAL(malloc, __nptr, short nsize)
{
  size_t allocsize;
  char *retptr;
  __nptr retval;

  /* Round (allocation size + 2) to nearest 16 bytes */
  allocsize = ((unsigned short)nsize + sizeof(__nptr) + 15) & 0x0000FFF0;

  /* Allocate memory block. If not enough memory, raise an exception */
  retptr = (char *)malloc(allocsize);
  if (retptr == NULL)
	rtint_raise(ENOMEMORY);

  /*
   * We write the pointer value into the first 2 bytes of the memory block
   * in order to check for a valid pointer when freeing the block lateron.
   */
  retval = ((__nptr)((int)retptr));
  *((__nptr *)retptr) = retval;

  /* Return the pointer to caller */
  return(retval + sizeof(__nptr));
}


/* Function wrapper */
__PUBLIC(malloc, 1, __A(short, 0));


/* Export info */
__EXPORT_PROC(malloc, POINTER, 1, __ARGS(__D(NUM, NONE)));



/*
 *****************************************************************************
 *
 * Free a previously allocated memory block
 */
#ifdef free
# undef free	/* Undefine any gcc preprocessor defines */
#endif

__INTERNAL(free, short, __nptr memblock)
{
  char *ptr;

  /* Check if the pointer is valid */
  if ((unsigned short)memblock < sizeof(__nptr))
	rtint_raise(EINVPOINTER);
  memblock -= sizeof(__nptr);
  ptr = (char *)((int)memblock);
  if (*((__nptr *)ptr) != memblock)
	rtint_raise(EINVPOINTER);

  /* Finally free the memory block */
  free(ptr);
  return(TRUE);
}


/* Function wrapper */
__PUBLIC(free, 1, __A(__nptr, 0));


/* Export info */
__EXPORT_PROC(free, NONE, 1, __ARGS(__D(POINTER, NONE)));


