/*
 * Marko Kiiskila carnil@cs.tut.fi 
 * 
 * Copyright (c) 1996
 * Tampere University of Technology - Telecommunications Laboratory
 * All rights reserved.
 *
 * Permission to use, copy, modify and distribute this
 * software and its documentation is hereby granted,
 * provided that both the copyright notice and this
 * permission notice appear in all copies of the software,
 * derivative works or modified versions, and any portions
 * thereof, that both notices appear in supporting
 * documentation, and that the use of this software is
 * acknowledged in any publications resulting from using
 * the software.
 * 
 * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
 * SOFTWARE.
 * 
 */
/*
 *
 * Utility functions which are used, but not defined in DIGITAL's 
 * code are defined here.
 *
 * $Id: utils.c,v 1.7 1996/08/06 14:14:11 carnil Exp carnil $
 *
 */

/* Global includes */
#include <string.h>
#include <stdio.h>

/* Digital includes */
#include "utl.h"
#include "utl_os.h"
#include "codes.h"
#include "g_event.h"

#define EMOD MOD_UTL_OS
#define EINST "utils.c"
#include "emask.h"

/* List of allocated memory blocks */
typedef struct _MemList_t {
  void *mem;
  size_t memsize;
  char *unit;
  struct _MemList_t *next;
} MemList_t;

static MemList_t *memlist = NULL;

void*
os_mem_alloc(UINT32 size)
{
  return(mem_alloc("utils.c",size));
}

void 
os_mem_dealloc(void *p_mem)
{
  mem_free("utils.c", p_mem);
}

void*
mem_alloc(const char *unit, unsigned long nbytes)
{
  MemList_t *tmp;

  tmp = (MemList_t *)malloc(sizeof(MemList_t));
  memset (tmp, 0, sizeof(*tmp));

  tmp->mem = malloc(nbytes);
  memset (tmp->mem, 0, nbytes);

  tmp->memsize = nbytes;
  tmp->unit = (char*)malloc(strlen(unit)+1);
  sprintf(tmp->unit,"%s",unit);
  tmp->unit[strlen(unit)] = '\0';
  tmp->next = memlist;
  memlist = tmp;
  EVENT(EM_MEM,("Unit %s allocates %ld bytes of memory from 0x%lx\n",
		unit, nbytes, (unsigned long)tmp->mem));
  return tmp->mem;

}

void
mem_free(const char *unit, const void *mem)
{
  MemList_t *tmp, *prev = NULL;
 
  EVENT(EM_MEM, ("Unit %s frees ptr 0x%lx\n", unit, (unsigned long)mem));

  for (tmp = memlist; tmp != NULL; prev = tmp, tmp = tmp->next) {
    if (tmp->mem == mem) {
      break;
    }
  }
  /* Found a match? */
  if (tmp) {
    if (strcmp(tmp->unit, unit) != 0) {
      EVENT(EM_MEM,
	    ("Unit %s frees ptr 0x%lx size %d allocated by unit %s\n",
	     unit, (unsigned long)tmp->mem, tmp->memsize, 
	     tmp->unit));
    }
    if (memlist == tmp) {
      memlist = tmp->next;
    }
    if (prev != NULL) {
      prev->next = tmp->next;
    }
    free(tmp->unit);
    free(tmp->mem);
    free(tmp);
  }
  else {
    EVENT(EM_MEM, ("could not find block 0x%lx for freeing\n", 
		   (unsigned long)mem));
  }
}

void
mem_usage(void)
{
  MemList_t *tmp;

  tmp = memlist;
  
  printf("Memory usage:\n");
  for(tmp=memlist;tmp;tmp=tmp->next) {
    printf("\t%20s\t:%p %6d bytes\n",tmp->unit, tmp->mem, tmp->memsize);
  }
}
/*
 *
 * $Log: utils.c,v $
 * Revision 1.7  1996/08/06 14:14:11  carnil
 * Malloc changed to mem_alloc
 *
 * Revision 1.6  1996/07/07 11:51:47  carnil
 * Global_msgmask
 *
 * Revision 1.5  1996/04/25 19:42:13  carnil
 * Copyright notice
 *
 * Revision 1.4  1996/02/16 06:16:20  carnil
 * oshandle,cmhandle removed
 *
 * Revision 1.3  1996/01/29  09:30:43  carnil
 * mem_alloc, mem_free
 *
 * Revision 1.2  1996/01/22  12:59:50  carnil
 * os_buff_hdr_copy
 *
 * Revision 1.1  1996/01/17  08:48:41  carnil
 * Initial revision
 *
 *
 */
