/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
// memory.c

#define INCL_DEV
#define INCL_DOS
#define INCL_SPL
#define INCL_DOSERRORS
#include <os2.h>

// c includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <builtin.h>

// driver includes
#include "def.h"
#include "driver.h"
#include "funcs.h"
#include "assert.h"



// --------------------------------------------------------------------------------------------------


PVOID DRVENTRY AllocSharedMem( ULONG ulSize )
{

  assert( ulSize );

  // relay this call to AllocMem and give the shared heap base pointer
  return AllocMem(  globals.pvSharedHeap,  ulSize );
}



// --------------------------------------------------------------------------------------------------


PVOID DRVENTRY AllocMem( PVOID pvHeapBase, ULONG ulSize )
{
  APIRET       rc;
  PULONG       pul = NULL;


  rc = DosRequestMutexSem( procdata.hmtxProcessSem, SEM_INDEFINITE_WAIT );
  assert( rc == 0 );

  assert( ulSize );

  // add sizeof a ULONG for storing size of alloc
  // add sizeof a ULONG for storing heap base pointer
  // add enough for size to be a multiple of 8
  ulSize = ( ulSize + (2*sizeof(ULONG)) + 7 ) & 0xFFFFFFF8 ;

  // carve it out of heap
  rc = DosSubAllocMem(  pvHeapBase, (PVOID*)&pul, ulSize );
  assert( 0 == rc );

  // fill the allocated memory with nulls
  memset( pul, 0, ulSize );

  // store size at first dword allocated
  *pul++ = ulSize;

  // store heap base pointer at second dword allocated
  *pul++ = (ULONG)pvHeapBase;

  rc = DosReleaseMutexSem( procdata.hmtxProcessSem );
  assert( rc == 0 );

  // return a pointer above where I stored the size and base of this suballoc
  return (PVOID)pul;
}


// --------------------------------------------------------------------------------------------------

BOOL DRVENTRY FreeMem( PVOID pv )
{
  APIRET rc;
  ULONG  ulSize;
  PVOID  pvHeapBase;
  PULONG pul;


  // sem request returns invalid_handle when a process terminates with open DCs;
  // in that case, driver initterm processing has already closed the sem by the time
  // GRE exitlist processing gets around to closing those open DCs;
  // since there is but one thread left on the process at exitlist time, mutex is not an issue

  rc = DosRequestMutexSem( procdata.hmtxProcessSem, SEM_INDEFINITE_WAIT );
  assert( rc == 0 || ( rc == ERROR_INVALID_HANDLE && procdata.hmtxProcessSem == HMTX_CLOSED ));

  assert( pv );

  // cast to PULONG
  pul = (PULONG)pv;

  // get stored heap base
  pvHeapBase = (PVOID)*--pul;

  // stored heap base should be a multiple of page size 4096
  assert( 0 == ((ULONG)pvHeapBase & 0x000000FFF));

  // get stored size
  ulSize = *--pul;

  // stored size should be a multiple of eight
  assert( 0 == (ulSize & 0x000000007));

  // free it
  rc = DosSubFreeMem(  pvHeapBase, (PVOID)pul, ulSize );
  assert( 0 == rc );

  rc = DosReleaseMutexSem( procdata.hmtxProcessSem );
  assert( rc == 0 || ( rc == ERROR_INVALID_HANDLE && procdata.hmtxProcessSem == HMTX_CLOSED ));


  return TRUE;
}

