/*
 * |-----------------------------------------------------------|
 * | Copyright (c) 1991, 1990 MIPS Computer Systems, Inc.      |
 * | All Rights Reserved                                       |
 * |-----------------------------------------------------------|
 * |          Restricted Rights Legend                         |
 * | Use, duplication, or disclosure by the Government is      |
 * | subject to restrictions as set forth in                   |
 * | subparagraph (c)(1)(ii) of the Rights in Technical        |
 * | Data and Computer Software Clause of DFARS 252.227-7013.  |
 * |         MIPS Computer Systems, Inc.                       |
 * |         950 DeGuigne Avenue                               |
 * |         Sunnyvale, California 94088-3650, USA             |
 * |-----------------------------------------------------------|
 */
#ident	"$Header: prot_alloc.c,v 1.6.2.1 92/06/24 13:50:38 marker Exp $"


#include <stdio.h>
#include "prot_lock.h"

#ifdef RISCOS_DEBUG
int node_inuse = 0;
int node_null = 0;
int node_notfound = 0;
char *xmalloc_debug(), *malloc();
void xfree_debug();
#else
char *xmalloc(), *malloc();
#endif

extern int res_len, lock_len, debug;

/* # of entries used */
int used_reclock = 0;
int used_res = 0;
int used_fh = 0;
int used_me = 0;

#ifdef RISCOS_DEBUG

#define TABLESIZE 1024

typedef struct table_entry {
  unsigned int inuse, len, alloc_linen, free_linen;
  char *alloc_filen, *free_filen, *node;
} table_entry_t;

typedef struct table {
  table_entry_t entry[TABLESIZE];
} table_t;

static table_t heap_table;

int
xcheck_debug()
{
int inuse, i;
	inuse = 0;
	printf ("xcheck_debug: Remaining nodes:\n");

	for (i=0; i < TABLESIZE; i++) {
	  if (heap_table.entry[i].inuse) {
	    inuse++;
	    printf ("alloc'ed @= %s: %d; nodeaddr= %x; nodelen= %d\n",
		  heap_table.entry[i].alloc_filen,
		  heap_table.entry[i].alloc_linen,
		  heap_table.entry[i].node, heap_table.entry[i].len);
	  }
	}
return inuse;
}

void
xfree_debug(a, filen, linen)
	char **a;
        char *filen;
        unsigned int linen;
{
char *node_addr;
int i;
	if (*a == NULL) {
		node_null++;
		return;
	}
        node_addr = *a;

	for (i=0; i < TABLESIZE; i++) {
	  if (heap_table.entry[i].inuse) {
	    if (heap_table.entry[i].node == node_addr) {
	      heap_table.entry[i].inuse = 0;
	      heap_table.entry[i].free_filen = filen;
	      heap_table.entry[i].free_linen = linen;
	      free(node_addr);
	      *a = NULL;
	      node_inuse--;
	      return;
	    }
	  }
	}
	node_notfound++;
	if (debug)
	  printf("xfree_debug: Node addr= %x; NOT found in heap table\n",
	      node_addr);
	free(node_addr);
	return;
}

char *
xinit()
{
int i;
	for (i=0; i < TABLESIZE; i++) {
	heap_table.entry[i].inuse = heap_table.entry[i].len = 0;
	heap_table.entry[i].alloc_linen = heap_table.entry[i].free_linen = 0;
	heap_table.entry[i].alloc_filen = heap_table.entry[i].node =
	  heap_table.entry[i].free_filen = (char *)NULL;
	}
}

#endif

void
xfree(a)
	char **a;
{
	if (*a != NULL) {
		free(*a);
		*a = NULL;
	}
}

release_res(resp)
	remote_result *resp;
{
	used_res--;
#ifdef RISCOS_DEBUG
	xfree_debug(&resp->cookie_bytes, __FILE__, __LINE__);
	if ((char *)resp != NULL)
	  xfree_debug(&resp, __FILE__, __LINE__);
#else
	xfree(&resp->cookie_bytes);
	if ((char *)resp != NULL) free((char *)resp);
#endif
}

release_filock(fl)
        struct filock *fl;
{       
#ifdef RISCOS_DEBUG
	(void) memset((char *) fl, 0, sizeof (*fl));
        if ((char *) fl != NULL) xfree_debug(&fl, __FILE__, __LINE__); 
#else
	(void) memset((char *) fl, 0, sizeof (*fl));
        if ((char *) fl != NULL) free((char *) fl);
#endif
}

release_fh(a)
	lm_vnode *a;
{
	if (debug)
		printf("enter release_fh...\n");
	if (a->rel) {
		used_fh--;
#ifdef RISCOS_DEBUG
		xfree_debug(&a->server_name, __FILE__, __LINE__);
		obj_free(&a->fh);
		(void) memset((char *) a, 0, sizeof (*a));
		if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
		xfree(&a->server_name);
		obj_free(&a->fh);
		(void) memset((char *) a, 0, sizeof (*a));
		if ((char *)a != NULL) free((char *) a);
#endif
	}
}

free_reclock(a)
	reclock *a;
{
	used_reclock--;
	/*
	 * Make sure that this lock is not queued on msg_q.
	 * This addresses bugs 1012630 and 1011992, though
	 * the cause remains unknown.
	 */
	dequeue_lock(a);
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->lck.svr, __FILE__, __LINE__);
	xfree_debug(&a->lck.fh_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.caller_name, __FILE__, __LINE__);
	xfree_debug(&a->lck.oh_bytes, __FILE__, __LINE__);
	xfree_debug(&a->cookie_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.clnt_name, __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->lck.svr);
	xfree(&a->lck.fh_bytes);
	xfree(&a->lck.caller_name);
	xfree(&a->lck.oh_bytes);
	xfree(&a->cookie_bytes);
	xfree(&a->lck.clnt_name);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_reclock(a)
	reclock *a;
{
#ifdef RISCOS_DEBUG
	if (a->rel)
	  free_reclock(a);
	else
	  printf("release_reclock: Not freeing reclock= %x\n", a);
#else
	if (a->rel) {
		free_reclock(a);
	}
#endif
}

release_nlm_lockargs(a)
	nlm_lockargs *a;
{
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->cookie_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.caller_name, __FILE__, __LINE__);
	xfree_debug(&a->lck.fh_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.oh_bytes, __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->cookie_bytes);
	xfree(&a->lck.caller_name);
	xfree(&a->lck.fh_bytes);
	xfree(&a->lck.oh_bytes);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_nlm_unlockargs(a)
	nlm_unlockargs *a;
{
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->cookie_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.caller_name, __FILE__, __LINE__);
	xfree_debug(&a->lck.fh_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.oh_bytes, __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->cookie_bytes);
	xfree(&a->lck.caller_name);
	xfree(&a->lck.fh_bytes);
	xfree(&a->lck.oh_bytes);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_nlm_testargs(a)
	nlm_testargs *a;
{
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->cookie_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.caller_name, __FILE__, __LINE__);
	xfree_debug(&a->lck.fh_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.oh_bytes, __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->cookie_bytes);
	xfree(&a->lck.caller_name);
	xfree(&a->lck.fh_bytes);
	xfree(&a->lck.oh_bytes);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_nlm_cancargs(a)
	nlm_cancargs *a;
{
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->cookie_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.caller_name, __FILE__, __LINE__);
	xfree_debug(&a->lck.fh_bytes, __FILE__, __LINE__);
	xfree_debug(&a->lck.oh_bytes, __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->cookie_bytes);
	xfree(&a->lck.caller_name);
	xfree(&a->lck.fh_bytes);
	xfree(&a->lck.oh_bytes);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_nlm_testres(a)
	nlm_testres *a;
{
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->cookie_bytes, __FILE__, __LINE__);
	xfree_debug(&a->stat.nlm_testrply_u.holder.oh_bytes,
		    __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->cookie_bytes);
	xfree(&a->stat.nlm_testrply_u.holder.oh_bytes);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_nlm_res(a)
	nlm_res *a;
{
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->cookie_bytes, __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->cookie_bytes);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_klm_lockargs(a)
	klm_lockargs *a;
{
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->lck.svr, __FILE__, __LINE__);
	xfree_debug(&a->lck.fh_bytes, __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->lck.svr);
	xfree(&a->lck.fh_bytes);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_klm_unlockargs(a)
	klm_unlockargs *a;
{
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->lck.svr, __FILE__, __LINE__);
	xfree_debug(&a->lck.fh_bytes, __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->lck.svr);
	xfree(&a->lck.fh_bytes);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_klm_testargs(a)
	klm_testargs *a;
{
#ifdef RISCOS_DEBUG
	/* free up all space allocated through malloc */
	xfree_debug(&a->lck.svr, __FILE__, __LINE__);
	xfree_debug(&a->lck.fh_bytes, __FILE__, __LINE__);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) xfree_debug(&a, __FILE__, __LINE__);
#else
	/* free up all space allocated through malloc */
	xfree(&a->lck.svr);
	xfree(&a->lck.fh_bytes);
	(void) memset((char *) a, 0, sizeof (*a));
	if ((char *) a != NULL) free((char *) a);
#endif
}

release_klm_stat(statp)
klm_stat *statp;
{
#ifdef RISCOS_DEBUG
	xfree_debug(&statp, __FILE__, __LINE__);
#else
	xfree(&statp);
#endif
	return;
}

#ifdef RISCOS_DEBUG
/*
 * allocate space and zero it;
 * in case of malloc error, print console msg and return NULL;
 */
char *
xmalloc_debug(len, filen, linen)
unsigned int len;
char *filen;
unsigned int linen;
{
char *new;
int i;

	for (i=0; i < TABLESIZE; i++) {
	  if (heap_table.entry[i].inuse == 0) {

	    if ((new = malloc(len)) == 0) {
	      /* out of heap space */
	      printf("malloc_debug: malloc returned NULL\n");
	    }
	    else {
	      (void) memset(new, 0, len);
	      heap_table.entry[i].inuse = 1;
	      heap_table.entry[i].alloc_filen = filen;
	      heap_table.entry[i].alloc_linen = linen;
	      heap_table.entry[i].len = len;
	      heap_table.entry[i].node = new;
	      node_inuse++;
	    }
	    return new;
	   }
	  }
	  /*
	   * Exhausted table space; Halt and see what's happening
	   */
	  printf("malloc_debug: Exhausted heap_table\n");
          return (NULL);
}
#endif

char *
xmalloc(len)
	unsigned len;
{
	char *new;

	if ((new = malloc(len)) == 0) {
		perror("malloc");
		return (NULL);
	}
	else {
		(void) memset(new, 0, len);
		return (new);
	}
}

/*
 * these routines are here in case we try to optimize calling to malloc
 */
struct lm_vnode *
get_me()
{
	used_me++;
#ifdef RISCOS_DEBUG
	return ((struct lm_vnode *) xmalloc_debug(sizeof(struct lm_vnode),
						   __FILE__, __LINE__));
#else
	return ( (struct lm_vnode *) xmalloc(sizeof (struct lm_vnode)) );
#endif
}

remote_result *
get_res()
{
	used_res++;
#ifdef RISCOS_DEBUG
	return ((remote_result *) xmalloc_debug(res_len, __FILE__, __LINE__));
#else
	return ((remote_result *) xmalloc(res_len));
#endif
}

lm_vnode *
get_fh()
{
	if (debug)
		printf("enter get_fh...\n");
	used_fh++;
#ifdef RISCOS_DEBUG
	return ( (lm_vnode *) xmalloc_debug(sizeof(struct lm_vnode),
				      __FILE__, __LINE__));
#else
	return ( (lm_vnode *) xmalloc(sizeof (struct lm_vnode)) );
#endif
}

reclock *
get_reclock()
{
	used_reclock++;
#ifdef RISCOS_DEBUG
	return ( (reclock *) xmalloc_debug(lock_len, __FILE__, __LINE__));
#else
	return ( (reclock *) xmalloc(lock_len) );
#endif
}


klm_lockargs *
get_klm_lockargs()
{
#ifdef RISCOS_DEBUG
	return ((struct klm_lockargs *) xmalloc_debug(
			sizeof (struct klm_lockargs), __FILE__, __LINE__));
#else
	return ((struct klm_lockargs *) xmalloc(sizeof (struct klm_lockargs)));
#endif
}

klm_unlockargs *
get_klm_unlockargs()
{
#ifdef RISCOS_DEBUG
	return ((struct klm_unlockargs *)xmalloc_debug(
			sizeof(struct klm_unlockargs), __FILE__, __LINE__));
#else
	return ((struct klm_unlockargs *)xmalloc(
			sizeof (struct klm_unlockargs)));
#endif
}

klm_testargs *
get_klm_testargs()
{
#ifdef RISCOS_DEBUG
	return ((struct klm_testargs *) xmalloc_debug(
			sizeof (struct klm_testargs), __FILE__, __LINE__));
#else
	return ((struct klm_testargs *) xmalloc(sizeof (struct klm_testargs)));
#endif
}

klm_testrply *
get_klm_testrply()
{
#ifdef RISCOS_DEBUG
	return ((struct klm_testrply *) xmalloc_debug(
			sizeof (struct klm_testrply), __FILE__, __LINE__));
#else
	return ((struct klm_testrply *) xmalloc(sizeof (struct klm_testrply)));
#endif
}

klm_stat *
get_klm_stat()
{
#ifdef RISCOS_DEBUG
	return ((struct klm_stat *) xmalloc_debug(
		sizeof (struct klm_stat), __FILE__, __LINE__));
#else
	return ((struct klm_stat *) xmalloc(sizeof (struct klm_stat)));
#endif
}

nlm_lockargs *
get_nlm_lockargs()
{
#ifdef RISCOS_DEBUG
	return ((struct nlm_lockargs *) xmalloc_debug(
		sizeof (struct nlm_lockargs), __FILE__, __LINE__));
#else
	return ((struct nlm_lockargs *) xmalloc(sizeof (struct nlm_lockargs)));
#endif
}

nlm_unlockargs *
get_nlm_unlockargs()
{
#ifdef RISCOS_DEBUG
	return ((struct nlm_unlockargs *)xmalloc_debug(
		sizeof(struct nlm_unlockargs), __FILE__, __LINE__));
#else
	return ((struct nlm_unlockargs *)xmalloc(sizeof (struct nlm_unlockargs)));
#endif
}

nlm_cancargs *
get_nlm_cancargs()
{
#ifdef RISCOS_DEBUG
	return ((struct nlm_cancargs *) xmalloc_debug(
		sizeof (struct nlm_cancargs), __FILE__, __LINE__));
#else
	return ((struct nlm_cancargs *) xmalloc(sizeof (struct nlm_cancargs)));
#endif
}

nlm_testargs *
get_nlm_testargs()
{
#ifdef RISCOS_DEBUG
	return ((struct nlm_testargs *) xmalloc_debug(
			sizeof (struct nlm_testargs), __FILE__, __LINE__));
#else
	return ((struct nlm_testargs *) xmalloc(sizeof (struct nlm_testargs)));
#endif
}

nlm_testres *
get_nlm_testres()
{
#ifdef RISCOS_DEBUG
	return ((struct nlm_testres *) xmalloc_debug(
			sizeof(struct nlm_testres), __FILE__, __LINE__));
#else
	return ((struct nlm_testres *) xmalloc(sizeof (struct nlm_testres)));
#endif
}

nlm_res *
get_nlm_res()
{
#ifdef RISCOS_DEBUG
	return ((struct nlm_res *) xmalloc_debug(sizeof (struct nlm_res),
					  __FILE__, __LINE__));
#else
	return ((struct nlm_res *) xmalloc(sizeof (struct nlm_res)));
#endif
}
