home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
salomo.zip
/
SALOMON.TXT
Wrap
Text File
|
1993-05-17
|
38KB
|
1,141 lines
#--------------------------------------------------------------------------
# Program name: MAKEFILE Title: Memory toolbox make file
# OS/2 Developer Magazine Issue: Spring '93, page 127
#
# Article: "Writing Memory Allocation Functions With DosSubAllocMem"
# Author: Larry Salomon, Jr.
# Phone: n/a Fax: n/a
#
# Description: The following is a component of the complete source to the
# above article in the specified issue of OS/2 Developer Magazine. This
# source is provided AS-IS without any implied or expressed warranty. The
# author can be contacted via the Internet at the email address
# "os2man@panix.com".
#
# This component contains the make file needed to build the memory
# toolbox. Before building, the following macro definitions need to be
# changed to reflect the directory structure on your machine:
#
# MYLIB - specifies the directory to copy the library into for
# linking by other programs and to copy the programming
# reference into.
#
# To build the 32-bit version, type "nmake 32bit" on any OS/2 command line.
# To build the 16-bit version, type "nmake 16bit" on any OS/2 command line.
#
# Program requirements: IBM C-Set/2 for 32-bit compilation, Microsoft
# C 6.0 (or better) for 16-bit compilation.
#--------------------------------------------------------------------------
MYLIB=D:\MYLIB
32BIT:
@NMAKE SUFFIX=32 TBMEM32.LIB
16BIT:
@NMAKE SUFFIX=16 TBMEM16.LIB
!IF "$(SUFFIX)"=="32"
CLOPTS=-C+ -Kb+ -Ss+ -W3 -D_32BIT
!IFDEF DEBUG
CLOPTS=$(CLOPTS) -Ti+
!ENDIF
CLEXE=ICC
LIBEXE=LIB
!ELSE
CLOPTS=-c -AL -W4 -G2 -D_16BIT
!IFDEF DEBUG
CLOPTS=$(CLOPTS) -Zipde -Od
!ELSE
CLOPTS=$(CLOPTS) -Zpe -Ol
!ENDIF
CLEXE=CL
LIBEXE=LIB
!ENDIF
TBMEM$(SUFFIX).LIB: TBMEM$(SUFFIX).OBJ
IF EXIST TBMEM$(SUFFIX).LIB DEL TBMEM$(SUFFIX).LIB
$(LIBEXE) @<<
TBMEM$(SUFFIX).LIB
Y
+ TBMEM$(SUFFIX).OBJ;
<<
COPY TBMEM$(SUFFIX).LIB $(MYLIB)
TBMEM$(SUFFIX).OBJ: TBMEM.C \
TBMEM.H
$(CLEXE) $(CLOPTS) -FoTBMEM$(SUFFIX).OBJ TBMEM.C
TBMEM.INF: TBMEM.IPF
IPFC /INF TBMEM.IPF
COPY TBMEM.INF $(MYLIB)
---------------------------------------------------------
//-------------------------------------------------------------------------
// Program name: TBMEM.C Title: Memory toolbox
// OS/2 Developer Magazine Issue: Spring '93, page 127
//
// Article: "Writing Memory Allocation Functions With DosSubAllocMem"
// Author: Larry Salomon, Jr.
// Phone: n/a Fax: n/a
//
// Description: The following is a component of the complete source to the
// above article in the specified issue of OS/2 Developer Magazine. This
// source is provided AS-IS without any implied or expressed warranty. The
// author can be contacted via the Internet at the email address
// "os2man@panix.com".
//
// This component contains the implementation source for the routines
// as described by the article.
//
// Program requirements: IBM C-Set/2 for 32-bit compilation, Microsoft
// C 6.0 (or better) for 16-bit compilation.
//-------------------------------------------------------------------------
#define INCL_DOSMEMMGR
#define INCL_DOSSEMAPHORES
#include <os2.h>
#include <stdlib.h>
#include <string.h>
#include <tbheader.h>
#include "tbmem.h"
#define TBSIG_HTBMEM MAKEULONG(TBSIG_TBMEM,0x0000)
#define SZACTUAL(ulSzBuf)
(ULONG)((ulSzBuf+sizeof(TBHEAPINFO))+8-((ulSzBuf+sizeof(TBHEAPINFO))%8))
static PVOID myMalloc(ULONG ulSzBuf)
//-------------------------------------------------------------------------
// This function allocates a block of memory using the appropriate
// system call.
//
// Input: ulSzBuf - specifies the requested size of the buffer in bytes
// Returns: pointer to the buffer if successful, NULL otherwise
//-------------------------------------------------------------------------
{
PVOID pvBuf;
#ifdef _32BIT
if (DosAllocMem(&pvBuf,ulSzBuf,PAG_READ|PAG_WRITE|PAG_COMMIT|OBJ_TILE)) {
return NULL;
} /* endif */
memset(pvBuf,0,ulSzBuf);
#else
if (DosAllocSeg((USHORT)ulSzBuf,&SELECTOROF(pvBuf),SEG_NONSHARED)) {
return NULL;
} /* endif */
OFFSETOF(pvBuf)=0;
memset(pvBuf,0,(USHORT)ulSzBuf);
#endif
return pvBuf;
}
static BOOL myFree(PVOID pvBuf)
//-------------------------------------------------------------------------
// This function frees the buffer. It assumes that the buffer was
// allocated with myMalloc().
//
// Input: pvBuf - points to the buffer to free
// Returns: TRUE if successful, FALSE otherwise
//-------------------------------------------------------------------------
{
#ifdef _32BIT
if (pvBuf==NULL) {
return FALSE;
} else
if (DosFreeMem(pvBuf)) {
return FALSE;
} else {
return TRUE;
} /* endif */
#else
if (pvBuf==NULL) {
return FALSE;
} else
if (DosFreeSeg(SELECTOROF(pvBuf))) {
return FALSE;
} else {
return TRUE;
} /* endif */
#endif
}
static USHORT semAccess(PTBHEADER ptbhHeader,USHORT usAction)
//-------------------------------------------------------------------------
// This function provides access to the specified handle via the
// appropriate system semaphore function.
//
// Input: ptbhHeader - pointer to the toolbox handle header
// usAction - specifies the action to take as a TBSEM_* constant
// Returns: TBSEM_ERROR if an error occurs, value for usAction to for
// next call to function otherwise
//-------------------------------------------------------------------------
{
switch (usAction) {
case TBSEM_SET:
if ((ptbhHeader->ulStatus & TBSTS_INTOOLBOX)!=0) {
return TBSEM_ALREADYSET;
} /* endif */
#ifdef _32BIT
DosRequestMutexSem(ptbhHeader->hsmAccess,SEM_INDEFINITE_WAIT);
#else
DosSemRequest(&ptbhHeader->hsmAccess,SEM_INDEFINITE_WAIT);
DosSemSet(&ptbhHeader->hsmAccess);
#endif
ptbhHeader->ulStatus|=TBSTS_INTOOLBOX;
return TBSEM_CLEAR;
case TBSEM_CLEAR:
if ((ptbhHeader->ulStatus & TBSTS_INTOOLBOX)==0) {
return TBSEM_NOTSET;
} /* endif */
#ifdef _32BIT
DosReleaseMutexSem(ptbhHeader->hsmAccess);
#else
DosSemClear(&ptbhHeader->hsmAccess);
#endif
ptbhHeader->ulStatus&=~TBSTS_INTOOLBOX;
return TBSEM_SET;
case TBSEM_ALREADYSET:
return TBSEM_NOTSET;
case TBSEM_NOTSET:
return TBSEM_ALREADYSET;
default:
return TBSEM_ERROR;
} /* endswitch */
}
TBERROR MemInitialize(PTBMEMINFO ptbmiInfo,PHTBMEM phtbmMem)
//-------------------------------------------------------------------------
// This function initializes an instance to the memory manager and
// returns a handle to the instance.
//
// Input: ptbmiInfo - pointer to the TBMEMINFO structure specifying
// the desired attributes of the instance. If this
// is NULL, the defaults are used
// phtbmMem - pointer to the variable which receives the result.
// On return, this variable contains a memory handle
// Returns: TBMEM_EC_* constant
//-------------------------------------------------------------------------
{
TBMEMINFO tbmiInfo;
ULONG ulSzBuf;
*phtbmMem=NULL;
if (ptbmiInfo!=NULL) {
tbmiInfo=*ptbmiInfo;
} else {
tbmiInfo.usNumHeaps=256;
tbmiInfo.ulSzHeap=61440;
} /* endif */
ulSzBuf=sizeof(TBMEM)+sizeof(TBHEAP)*(tbmiInfo.usNumHeaps-1);
*phtbmMem=myMalloc(ulSzBuf);
if (*phtbmMem==NULL) {
return TBMEM_EC_NOMEMORY;
} /* endif */
(*phtbmMem)->ulSig=TBSIG_HTBMEM;
(*phtbmMem)->ulStatus=0L;
#ifdef _32BIT
if (DosCreateMutexSem(NULL,&(*phtbmMem)->hsmAccess,0,FALSE)) {
free(*phtbmMem);
return TBMEM_EC_INITFAILED;
} /* endif */
#else
(*phtbmMem)->hsmAccess=0L;
#endif
(*phtbmMem)->tbmiInfo=tbmiInfo;
return TBMEM_EC_NOERROR;
}
TBERROR MemTerminate(HTBMEM htbmMem)
//-------------------------------------------------------------------------
// This function destroys the memory handle specified and returns all
// used memory to the system (via a call to MemReset()).
//
// Input: htbmMem - specifies the handle to destroy
// Returns: TBMEM_EC_* constant
//-------------------------------------------------------------------------
{
USHORT usSemAction;
if (MemQueryHandle(htbmMem)!=TBMEM_QH_HTBMEM) {
return TBMEM_EC_BADHANDLE;
} /* endif */
usSemAction=semAccess((PTBHEADER)htbmMem,TBSEM_SET);
if (MemReset(htbmMem)!=TBMEM_EC_NOERROR) {
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_ERROR;
} /* endif */
semAccess((PTBHEADER)htbmMem,usSemAction);
#ifdef _32BIT
DosCloseMutexSem(htbmMem->hsmAccess);
#endif // #ifdef _32BIT
myFree(htbmMem);
return TBMEM_EC_NOERROR;
}
TBERROR MemReset(HTBMEM htbmMem)
//-------------------------------------------------------------------------
// This function "resets" the memory handle specified. That is, all
// memory currently consumed is returned to the system.
//
// Input: htbmMem - specifies the handle to reset
// Returns: TBMEM_EC_* constant
//-------------------------------------------------------------------------
{
USHORT usSemAction;
USHORT usIndex;
if (MemQueryHandle(htbmMem)!=TBMEM_QH_HTBMEM) {
return TBMEM_EC_BADHANDLE;
} /* endif */
usSemAction=semAccess((PTBHEADER)htbmMem,TBSEM_SET);
for (usIndex=0; usIndex<htbmMem->tbmiInfo.usNumHeaps; usIndex++) {
if (htbmMem->atbhHeaps[usIndex].pvHeap!=NULL) {
myFree(htbmMem->atbhHeaps[usIndex].pvHeap);
htbmMem->atbhHeaps[usIndex].ulRef=0;
htbmMem->atbhHeaps[usIndex].pvHeap=NULL;
} /* endif */
} /* endfor */
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_NOERROR;
}
TBERROR MemAllocMem(HTBMEM htbmMem,ULONG ulSzBuf,PVOID *ppvBuf)
//-------------------------------------------------------------------------
// This function allocates a buffer of the size requested from the
// specified memory handle.
//
// Input: htbmMem - specifies the memory handle to allocate from
// ulSzBuf - specifies the size of the buffer
// ppvBuf - pointer to the variable which receives the result. On
// return, this contains a pointer to the allocated
// memory
// Returns: TBMEM_EC_* constant
//-------------------------------------------------------------------------
{
USHORT usSemAction;
ULONG ulSzActual;
USHORT usFirstNull;
USHORT usIndex;
PTBHEAPINFO ptbhiInfo;
PTBHEAP ptbhHeap;
if (MemQueryHandle(htbmMem)!=TBMEM_QH_HTBMEM) {
return TBMEM_EC_BADHANDLE;
} /* endif */
usSemAction=semAccess((PTBHEADER)htbmMem,TBSEM_SET);
*ppvBuf=NULL;
ulSzActual=SZACTUAL(ulSzBuf);
if (ulSzActual>htbmMem->tbmiInfo.ulSzHeap-64) {
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_SIZETOOLARGE;
} /* endif */
usFirstNull=htbmMem->tbmiInfo.usNumHeaps;
for (usIndex=0; usIndex<htbmMem->tbmiInfo.usNumHeaps; usIndex++) {
if (htbmMem->atbhHeaps[usIndex].pvHeap!=NULL) {
#ifdef _32BIT
if (!DosSubAllocMem(htbmMem->atbhHeaps[usIndex].pvHeap,
(PVOID)&ptbhiInfo,
ulSzActual)) {
#else
if (!DosSubAlloc(SELECTOROF(htbmMem->atbhHeaps[usIndex].pvHeap),
&OFFSETOF(ptbhiInfo),
(USHORT)ulSzActual)) {
SELECTOROF(ptbhiInfo)=SELECTOROF(htbmMem->atbhHeaps[usIndex].pvHeap);
#endif
htbmMem->atbhHeaps[usIndex].ulRef++;
ptbhiInfo->ulSzRequested=ulSzBuf;
*ppvBuf=(PVOID)(ptbhiInfo+1);
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_NOERROR;
} /* endif */
} else
if (usFirstNull==htbmMem->tbmiInfo.usNumHeaps) {
usFirstNull=usIndex;
} /* endif */
} /* endfor */
if (usFirstNull==htbmMem->tbmiInfo.usNumHeaps) {
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_NOMEMORY;
} /* endif */
ptbhHeap=&htbmMem->atbhHeaps[usFirstNull];
ptbhHeap->ulRef=0;
ptbhHeap->pvHeap=myMalloc(htbmMem->tbmiInfo.ulSzHeap);
if (ptbhHeap->pvHeap==NULL) {
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_NOMEMORY;
} /* endif */
#ifdef _32BIT
if (DosSubSetMem(ptbhHeap->pvHeap,
DOSSUB_INIT,
htbmMem->tbmiInfo.ulSzHeap)) {
myFree(ptbhHeap->pvHeap);
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_NOMEMORY;
} /* endif */
if (!DosSubAllocMem(ptbhHeap->pvHeap,
(PVOID)&ptbhiInfo,
ulSzActual)) {
#else
if (DosSubSet(SELECTOROF(ptbhHeap->pvHeap),
TRUE,
(USHORT)htbmMem->tbmiInfo.ulSzHeap)) {
myFree(ptbhHeap->pvHeap);
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_NOMEMORY;
} /* endif */
if (!DosSubAlloc(SELECTOROF(ptbhHeap->pvHeap),
&OFFSETOF(ptbhiInfo),
(USHORT)ulSzActual)) {
SELECTOROF(ptbhiInfo)=SELECTOROF(ptbhHeap->pvHeap);
#endif
ptbhHeap->ulRef++;
ptbhiInfo->ulSzRequested=ulSzBuf;
*ppvBuf=(PVOID)(ptbhiInfo+1);
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_NOERROR;
} else {
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_NOMEMORY;
} /* endif */
}
TBERROR MemFreeMem(HTBMEM htbmMem,PVOID pvBuf)
//-------------------------------------------------------------------------
// This function returns the memory to the specified memory handle. It
// assumes the memory was allocated using MemAllocMem().
//
// Input: htbmMem - specifies the memory handle to return the memory
// to
// pvBuf - pointer to the memory to free
// Returns: TBMEM_EC_* constant
//-------------------------------------------------------------------------
{
USHORT usSemAction;
USHORT usIndex;
PTBHEAPINFO ptbhiInfo;
if (MemQueryHandle(htbmMem)!=TBMEM_QH_HTBMEM) {
return TBMEM_EC_BADHANDLE;
} /* endif */
usSemAction=semAccess((PTBHEADER)htbmMem,TBSEM_SET);
for (usIndex=0; usIndex<htbmMem->tbmiInfo.usNumHeaps; usIndex++) {
if (SELECTOROF(htbmMem->atbhHeaps[usIndex].pvHeap)==SELECTOROF(pvBuf)) {
ptbhiInfo=((PTBHEAPINFO)pvBuf)-1;
#ifdef _32BIT
if (DosSubFreeMem(htbmMem->atbhHeaps[usIndex].pvHeap,
ptbhiInfo,
SZACTUAL(ptbhiInfo->ulSzRequested))) {
#else
if (DosSubFree(SELECTOROF(ptbhiInfo),
OFFSETOF(ptbhiInfo),
(USHORT)SZACTUAL(ptbhiInfo->ulSzRequested))) {
#endif
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_ERROR;
} /* endif */
htbmMem->atbhHeaps[usIndex].ulRef--;
if (htbmMem->atbhHeaps[usIndex].ulRef==0) {
myFree(htbmMem->atbhHeaps[usIndex].pvHeap);
htbmMem->atbhHeaps[usIndex].pvHeap=NULL;
} /* endif */
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_NOERROR;
} /* endif */
} /* endfor */
semAccess((PTBHEADER)htbmMem,usSemAction);
return TBMEM_EC_BADPOINTER;
}
ULONG MemQueryMemSize(PVOID pvBuf)
//-------------------------------------------------------------------------
// This function returns the size of the specified buffer.
//
// Input: pvBuf - pointer to the buffer to query
// Returns: the size of the buffer
//-------------------------------------------------------------------------
{
PTBHEAPINFO ptbhiInfo;
ptbhiInfo=((PTBHEAPINFO)pvBuf)-1;
return ptbhiInfo->ulSzRequested;
}
USHORT MemQueryHandle(PVOID pvHandle)
//-------------------------------------------------------------------------
// This function returns the type of the specified handle, if known.
//
// Input: pvHandle - pointer to the handle to query
// Returns: TBMEM_QH_* constant
//-------------------------------------------------------------------------
{
ULONG ulSig;
if (pvHandle==NULL) {
return TBMEM_QH_ERROR;
} /* endif */
ulSig=*((PULONG)pvHandle);
if (ulSig==TBSIG_HTBMEM) {
return TBMEM_QH_HTBMEM;
} else {
return TBMEM_QH_ERROR;
} /* endif */
}
TBERROR MemQueryHandleInfo(PVOID pvHandle,PVOID pvInfo)
//-------------------------------------------------------------------------
// This function returns information about the specified memory handle.
//
// Input: pvHandle - specifies the memory handle to query
// pvInfo - pointer to a TBMEMINFO structure. On return, this
// contains the attributes of the memory handle
// Returns: TBMEM_EC_* constant
//-------------------------------------------------------------------------
{
switch (MemQueryHandle(pvHandle)) {
case TBMEM_QH_HTBMEM:
*((PTBMEMINFO)pvInfo)=((HTBMEM)pvHandle)->tbmiInfo;
break;
default:
return TBMEM_EC_BADHANDLE;
} /* endif */
return TBMEM_EC_NOERROR;
}
---------------------------------------------------------
//-------------------------------------------------------------------------
// Program name: TBDEFS.H Title: Common toolbox header file
// OS/2 Developer Magazine Issue: Spring '93, page 127
//
// Article: "Writing Memory Allocation Functions With DosSubAllocMem"
// Author: Larry Salomon, Jr.
// Phone: n/a Fax: n/a
//
// Description: The following is a component of the complete source to the
// above article in the specified issue of OS/2 Developer Magazine. This
// source is provided AS-IS without any implied or expressed warranty. The
// author can be contacted via the Internet at the email address
// "os2man@panix.com".
//
// This component contains common definitions needed by the toolbox
// described in this article and any toolboxes described in future
// articles.
//
// Program requirements: IBM C-Set/2 for 32-bit compilation, Microsoft
// C 6.0 (or better) for 16-bit compilation.
//-------------------------------------------------------------------------
#ifndef TBDEFS_INCLUDED
#define TBDEFS_INCLUDED
#ifndef OS2_INCLUDED
#ifdef _32BIT
#define PASCAL
#define FAR
#else
#define PASCAL pascal
#define FAR far
#endif /* #ifdef _32BIT */
#define APIENTRY PASCAL FAR
#define EXPENTRY PASCAL FAR _loadds
#define NULL 0L
typedef unsigned short BOOL;
typedef unsigned char BYTE;
typedef char CHAR;
typedef short int SHORT;
typedef long int LONG;
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned long ULONG;
typedef BOOL FAR *PBOOL;
typedef BYTE FAR *PBYTE;
typedef CHAR FAR *PCHAR;
typedef SHORT FAR *PSHORT;
typedef LONG FAR *PLONG;
typedef UCHAR FAR *PUCHAR;
typedef USHORT FAR *PUSHORT;
typedef ULONG FAR *PULONG;
#define VOID void
typedef VOID FAR *PVOID;
typedef VOID FAR *LHANDLE;
#endif /* #ifndef APIENTRY */
typedef ULONG TBERROR;
#endif /* #ifndef TBDEFS_INCLUDED */
---------------------------------------------------------
//-------------------------------------------------------------------------
// Program name: TBMEM.H Title: Memory toolbox header file
// OS/2 Developer Magazine Issue: Spring '93, page 127
//
// Article: "Writing Memory Allocation Functions With DosSubAllocMem"
// Author: Larry Salomon, Jr.
// Phone: n/a Fax: n/a
//
// Description: The following is a component of the complete source to the
// above article in the specified issue of OS/2 Developer Magazine. This
// source is provided AS-IS without any implied or expressed warranty. The
// author can be contacted via the Internet at the email address
// "os2man@panix.com".
//
// This component contains definitions needed by the toolbox described
// described in this article. All data definitions are exposed, so a
// separate, non-exposing header file should be used for applications
// linking with the toolbox.
//
// Program requirements: IBM C-Set/2 for 32-bit compilation, Microsoft
// C 6.0 (or better) for 16-bit compilation.
//-------------------------------------------------------------------------
#include <tbdefs.h>
#define TBMEM_EC_NOERROR (TBERROR)0
#define TBMEM_EC_ERROR (TBERROR)1
#define TBMEM_EC_BADHANDLE (TBERROR)2
#define TBMEM_EC_NOMEMORY (TBERROR)3
#define TBMEM_EC_SIZETOOLARGE (TBERROR)4
#define TBMEM_EC_BADPOINTER (TBERROR)5
#define TBMEM_EC_INITFAILED (TBERROR)6
typedef struct _TBMEMINFO {
USHORT usNumHeaps;
ULONG ulSzHeap;
} TBMEMINFO, FAR *PTBMEMINFO;
typedef struct _TBHEAPINFO {
ULONG ulSzRequested;
} TBHEAPINFO, FAR *PTBHEAPINFO;
typedef struct _TBHEAP {
ULONG ulRef;
PVOID pvHeap;
} TBHEAP, FAR *PTBHEAP;
typedef struct _TBMEM {
ULONG ulSig;
ULONG ulStatus;
ULONG hsmAccess;
TBMEMINFO tbmiInfo;
TBHEAP atbhHeaps[1];
} TBMEM, FAR *HTBMEM;
typedef HTBMEM FAR *PHTBMEM;
TBERROR MemInitialize(PTBMEMINFO ptbmiInfo,PHTBMEM phtbmMem);
TBERROR MemTerminate(HTBMEM htbmMem);
TBERROR MemReset(HTBMEM htbmMem);
TBERROR MemAllocMem(HTBMEM htbmMem,ULONG ulSzBuf,PVOID *ppvBuf);
TBERROR MemFreeMem(HTBMEM htbmMem,PVOID pvBuf);
ULONG MemQueryMemSize(PVOID pvBuf);
#define TBMEM_QH_ERROR (USHORT)0
#define TBMEM_QH_HTBMEM (USHORT)1
USHORT MemQueryHandle(PVOID pvHandle);
TBERROR MemQueryHandleInfo(PVOID pvHandle,PVOID pvInfo);
---------------------------------------------------------
.*-------------------------------------------------------------------------
.* Program name: TBMEM.IPF Title: Memory toolbox programming
.* reference source
.* OS/2 Developer Magazine Issue: Spring '93, page 127
.*
.* Article: "Writing Memory Allocation Functions With DosSubAllocMem"
.* Author: Larry Salomon, Jr.
.* Phone: n/a Fax: n/a
.*
.* Description: The following is a component of the complete source to the
.* above article in the specified issue of OS/2 Developer Magazine. This
.* source is provided AS-IS without any implied or expressed warranty. The
.* author can be contacted via the Internet at the email address
.* "os2man@panix.com".
.*
.* This component contains the source - in .IPF format - for the programming
.* reference.
.*
.* Program requirements: IPFC from either the 1.3 or 2.0 toolkit
.*-------------------------------------------------------------------------
:userdoc.
:title.Memory Toolbox Programming Reference
:body.
:h1.Introduction
:p.The :hp2.Memory Toolbox:ehp2. (referred to as :hp2.TBMEM:ehp2.) is a
collection of routines that provide memory-related functions for an OS/2
application. In addition to the standard allocation and free functions, other
API are included which perform other tasks. Although the API set is not
&odq.standardized&cdq. or as complete as the C run-time library, there are a
few reasons that you should consider when deciding which to use&colon.
:ul compact.
:li.It is completely thread reentrant. No longer do you have to fumble with
two sets of include files and libraries.
:li.It is as fast as, or faster than, the C run-time library.
:li.It reads better that the C run-time calls, which makes for easier program
maintenance.
:eul.
:p.Granted, these are not convincing arguments that compel you to switch to
the toolbox, but I believe they are sufficient to warrant further
investigation.
:p.:hp2.Using the Toolbox:ehp2.
:p.To enable your application to use the toolbox, include the
:hp2.TBMEM.H:ehp2. header file in the appropriate source file(s) and link with
the :hp2.TBMEM16.LIB:ehp2. library that is also provided.
:h1.API Reference
:p.The following sections describe each of the following API in detail. To
view a particular section, double click on the corresponding API listed
below.
:ul compact.
:li.:link reftype=hd refid=MAM.MemAllocMem:elink.
:li.:link reftype=hd refid=MFM.MemFreeMem:elink.
:li.:link reftype=hd refid=MI.MemInitialize:elink.
:li.:link reftype=hd refid=MQH.MemQueryHandle:elink.
:li.:link reftype=hd refid=MQHI.MemQueryHandleInfo:elink.
:li.:link reftype=hd refid=MQMS.MemQueryMemSize:elink.
:li.:link reftype=hd refid=MR.MemReset:elink.
:li.:link reftype=hd refid=MT.MemTerminate:elink.
:eul.
:h2 id=MAM.MemAllocMem
:p.Allocates a block of memory of a specified size.
:xmp.
(TBERROR)MemAllocMem(HTBMEM htbmMem,ULONG ulSzBuf,PVOID *ppvBuf);
:exmp.
:dl tsize=30 compact.
:dt.htbmMem (Input)
:dd.TBMEM instance handle
:dt.ulSzBuf (Input)
:dd.Size of the memory block requested
:dt.ppvBuf (Output)
:dd.Points to the resulting memory block that was allocated
:edl.
:p.:hp2.MemAllocMem:ehp2. returns one of the following values&colon.
:sl compact.
:li.TBMEM_EC_NOERROR
:li.TBMEM_EC_BADHANDLE
:li.TBMEM_EC_NOMEMORY
:li.TBMEM_EC_SIZETOOLARGE
:esl.
:p.:hp2.Notes:ehp2.
:p.The algorithm used by the toolbox is to attempt to allocate the specified
amount of memory from those heaps which already are associated with a memory
selector. If the request cannot be satisfied :hp2.and:ehp2. there is at
least one heap that is not in use, then a new selector is allocated by the
toolbox and the memory requested is allocated from that.
:h2 id=MFM.MemFreeMem
:p.Frees a block of memory previously allocated with MemAllocMem.
:xmp.
(TBERROR)MemFreeMem(HTBMEM htbmMem,PVOID pvBuf);
:exmp.
:dl tsize=30 compact.
:dt.htbmMem (Input)
:dd.TBMEM instance handle
:dt.pvBuf (Output)
:dd.Pointer to the memory block to return to the system
:edl.
:p.:hp2.MemFreeMem:ehp2. returns one of the following values&colon.
:sl compact.
:li.TBMEM_EC_NOERROR
:li.TBMEM_EC_BADHANDLE
:li.TBMEM_EC_BADPOINTER
:li.TBMEM_EC_ERROR
:esl.
:p.:hp2.Notes:ehp2.
:p.Because of the toolbox&apos.s dynamic committal strategy, a reference count
is maintained for each heap that is in use and it is updated whenever either
:hp2.MemAllocMem:ehp2. or :hp2.MemFreeMem:ehp2. is called. When this function
determines that the reference count is zero, it returns the memory back to the
system.
:h2 id=MI.MemInitialize
:p.Initializes an instance of the Memory Toolbox.
:xmp.
(TBERROR)MemInitialize(PTBMEMINFO ptbmiInfo,PHTBMEM phtbmMem);
:exmp.
:dl tsize=30 compact.
:dt.ptbmiInfo (Input)
:dd.Pointer to a :hp2.TBMEMINFO:ehp2. structure which describes the
desired characteristics of the instance to be created. If :hp2.NULL:ehp2.,
the defaults are used.
:dt.phtbmMem (Output)
:dd.Points to the resulting instance that was created.
:edl.
:p.:hp2.MemInitialize:ehp2. returns one of the following values&colon.
:sl compact.
:li.TBMEM_EC_NOERROR
:li.TBMEM_EC_NOMEMORY
:esl.
:p.:hp2.Notes:ehp2.
:p.The :hp2.TBMEMINFO:ehp2. structure is described below&colon.
:xmp.
typedef struct _TBMEMINFO &lbrc.
USHORT usNumHeaps;
ULONG ulSzHeap;
&rbrc. TBMEMINFO, FAR *PTBMEMINFO;
:exmp.
:dl tsize=20 compact.
:dt.usNumHeaps
:dd.Contains the number of internal heaps to be used by the toolkit. The
default for the 16-bit version of the toolbox is 256.
:dt.ulSzHeaps
:dd.Contains the size of each heap. The default for the 16-bit version of the
toolbox is 61440.
:edl.
:p.The heaps are subdivided (via calls to :hp2.MemAllocMem:ehp2. and
:hp2.MemFreeMem:ehp2.) using the :hp2.DosSubAlloc:ehp2. and
:hp2.DosSubFree:ehp2. API. Allowing for housekeeping data kept by both the
system and the toolbox, the amount of allocatable memory will be less than the
value of :hp1.ulSzHeaps:ehp1. (how much less depends on the number of
allocations have been made from a particular heap).
:h2 id=MQH.MemQueryHandle
:p.Returns the type of the specified handle.
:xmp.
(USHORT)MemQueryHandle(LHANDLE lhHandle);
:exmp.
:dl tsize=30 compact.
:dt.lhHandle (Input)
:dd.Specifies the handle to check
:edl.
:p.:hp2.MemQueryHandle:ehp2. returns one of the following values&colon.
:sl compact.
:li.TBMEM_QH_HTBMEM
:li.TBMEM_QH_ERROR
:esl.
:p.:hp2.Notes:ehp2.
:p.This function does not validate the accessability of the memory pointed to
by :hp1.lhHandle:ehp1.. Thus, a value that contains an invalid selector will
cause the application to trap.
:h2 id=MQHI.MemQueryHandleInfo
:p.Returns information about the specified handle.
:xmp.
(TBERROR)MemQueryHandleInfo(LHANDLE lhHandle,PVOID pvInfo);
:exmp.
:dl tsize=30 compact.
:dt.lhHandle (Input)
:dd.Specifies the handle to check
:dt.pvInfo (Input/Output)
:dd.On entry, points to a handle-specific structure to be initialized. On
exit, points to the initialized structure.
:edl.
:p.:hp2.MemQueryHandleInfo:ehp2. returns one of the following values&colon.
:sl compact.
:li.TBMEM_EC_NOERROR
:li.TBMEM_EC_BADHANDLE
:esl.
:p.:hp2.Notes:ehp2.
:p.What :hp1.pvInfo:ehp1. points to depends on the type of the handle
specified. Although in this toolbox there is only one handle type, there
might be other toolboxes which contain several handle types; thus, this
convention for obtaining handle information is established now to avoid
problems in the future.
:dl tsize=30 compact.
:dthd.Handle type
:ddhd.Info buffer type
:dt.HTBMEM
:dd.pvInfo should point to a TBMEMINFO structure
:edl.
:h2 id=MQMS.MemQueryMemSize
:p.Returns the size of the specified memory block
:xmp.
(ULONG)MemQueryMemSize(PVOID pvBuf);
:exmp.
:dl tsize=30 compact.
:dt.pvBuf (Input)
:dd.Points to a memory block previously allocated by :hp2.MemAllocMem:ehp2.
:edl.
:p.:hp2.MemQueryMemSize:ehp2. returns the size of the memory block specified.
:p.:hp2.Notes:ehp2.
:p.This function does no validity checks to insure that :hp1.pvBuf:ehp1. was
indeed allocated with :hp2.MemAllocMem:ehp2..
:h2 id=MR.MemReset
:p.Resets the specified instance of the Memory Toolbox to its starting state.
:xmp.
(TBERROR)MemReset(HTBMEM htbmMem);
:exmp.
:dl tsize=30 compact.
:dt.htbmMem (Input)
:dd.TBMEM instance handle
:edl.
:p.:hp2.MemReset:ehp2. returns one of the following values&colon.
:sl compact.
:li.TBMEM_EC_NOERROR
:li.TBMEM_EC_BADHANDLE
:esl.
:p.:hp2.Notes:ehp2.
:p.This function returns :hp2.all:ehp2. memory to the system and reinitializes
all of the internal heaps to their stating state.
:h2 id=MT.MemTerminate
:p.Terminates the specified instance of the Memory Toolbox.
:xmp.
(TBERROR)MemTerminate(HTBMEM htbmMem);
:exmp.
:dl tsize=30 compact.
:dt.htbmMem (Input)
:dd.TBMEM instance handle
:edl.
:p.:hp2.MemTerminate:ehp2. returns one of the following values&colon.
:sl compact.
:li.TBMEM_EC_NOERROR
:li.TBMEM_EC_BADHANDLE
:li.TBMEM_EC_ERROR
:esl.
:p.:hp2.Notes:ehp2.
:p.This function first calls :hp2.MemReset:ehp2. to return all allocated
memory to the system.
:euserdoc.
---------------------------------------------------------
#--------------------------------------------------------------------------
# Program name: TEST.MAK Title: Memory toolbox make file
# OS/2 Developer Magazine Issue: Spring '93, page 127
#
# Article: "Writing Memory Allocation Functions With DosSubAllocMem"
# Author: Larry Salomon, Jr.
# Phone: n/a Fax: n/a
#
# Description: The following is a component of the complete source to the
# above article in the specified issue of OS/2 Developer Magazine. This
# source is provided AS-IS without any implied or expressed warranty. The
# author can be contacted via the Internet at the email address
# "os2man@panix.com".
#
# This component contains the make file needed to build the memory
# toolbox test file. To build the 32-bit version, type "nmake 32bit TEST=MEM"
# on any OS/2 command line. To build the 16-bit version, type
# "nmake 16bit TEST=MEM" on any OS/2 command line.
#
# Program requirements: IBM C-Set/2 for 32-bit compilation, Microsoft
# C 6.0 (or better) for 16-bit compilation.
#--------------------------------------------------------------------------
!IFNDEF TEST
!ERROR You must define TEST!
!ENDIF
32BIT:
NMAKE SUFFIX=32 $(TEST)32.EXE
16BIT:
NMAKE SUFFIX=16 $(TEST)16.EXE
!IF "$(SUFFIX)"=="32"
CLOPTS=-C+ -Kb+ -Ss+ -W3 -D_32BIT
LINKOPTS=/MAP
!IFDEF DEBUG
CLOPTS=$(CLOPTS) -Ti+
LINKOPTS=$(LINKOPTS) /CO
!ENDIF
CLEXE=ICC
LINKEXE=LINK386
OS2LIB=OS2386
!ELSE
CLOPTS=-c -AL -W4 -G2 -D_16BIT
LINKOPTS=/MAP
!IFDEF DEBUG
CLOPTS=$(CLOPTS) -Zipde -Od
LINKOPTS=$(LINKOPTS) /CO
!ELSE
CLOPTS=$(CLOPTS) -Zpe -Ol
!ENDIF
CLEXE=CL
LINKEXE=LINK
OS2LIB=OS2
!ENDIF
$(TEST)$(SUFFIX).EXE: $(TEST)$(SUFFIX).OBJ
ECHO NAME $(TEST)$(SUFFIX) > TEST.DEF
TYPE TESTEND.DEF >> TEST.DEF
$(LINKEXE) $(LINKOPTS) @<<
$(TEST)$(SUFFIX)
$(TEST)$(SUFFIX)
$(TEST)$(SUFFIX)
$(OS2LIB)+TBMEM$(SUFFIX)
TEST
<<
$(TEST)$(SUFFIX).OBJ: $(TEST).C
$(CLEXE) $(CLOPTS) -Fo$(TEST)$(SUFFIX) $(TEST).C
---------------------------------------------------------
//-------------------------------------------------------------------------
// Program name: MEM.C Title: Memory toolbox test application
// OS/2 Developer Magazine Issue: Spring '93, page 127
//
// Article: "Writing Memory Allocation Functions With DosSubAllocMem"
// Author: Larry Salomon, Jr.
// Phone: n/a Fax: n/a
//
// Description: The following is a component of the complete source to the
// above article in the specified issue of OS/2 Developer Magazine. This
// source is provided AS-IS without any implied or expressed warranty. The
// author can be contacted via the Internet at the email address
// "os2man@panix.com".
//
// This component contains a program written to test the TBMEM library.
// It iterates 200 times through a loop which picks a random number and,
// if the pointer stored at that index in an array is NULL, allocates a
// 30000 byte block of memory. If the pointer stored is not NULL, it
// calls MemQueryMemSize() and compares the result with the size stored
// on the allocation call. It then calls MemFree().
//
// Program requirements: IBM C-Set/2 for 32-bit compilation, Microsoft
// C 6.0 (or better) for 16-bit compilation.
//-------------------------------------------------------------------------
#include <tbmem.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_INFO 100
typedef struct {
ULONG ulSzBuf;
PVOID pvBuf;
} MEMINFO, FAR *PMEMINFO;
MEMINFO amiInfo[MAX_INFO];
VOID main(USHORT usArgs,PCHAR apchArgs[])
{
HTBMEM htbmMem;
USHORT usSeed;
USHORT usIndex;
if (usArgs==1) {
puts("Syntax: MEM1 seed");
return;
} /* endif */
memset(amiInfo,0,sizeof(amiInfo));
srand(atoi(apchArgs[1]));
usSeed=rand()%MAX_INFO;
if (MemInitialize(NULL,&htbmMem)!=TBMEM_EC_NOERROR) {
printf("\nInitialize error.\n");
return;
} /* endif */
printf("Testing memory allocation/free. Using starting slot %d.\n\n",
usSeed);
for (usIndex=0; usIndex<200; usIndex++) {
printf("Slot=%3d, ",usSeed);
if (amiInfo[usSeed].pvBuf==NULL) {
amiInfo[usSeed].ulSzBuf=30000;
if (MemAllocMem(htbmMem,
amiInfo[usSeed].ulSzBuf,
&amiInfo[usSeed].pvBuf)!=TBMEM_EC_NOERROR) {
printf("allocation error.\n");
} else {
printf("allocation successful.\n");
} /* endif */
} else {
if (MemQueryMemSize(amiInfo[usSeed].pvBuf)!=amiInfo[usSeed].ulSzBuf) {
printf("verify error.\n");
} else
if (MemFreeMem(htbmMem,amiInfo[usSeed].pvBuf)!=TBMEM_EC_NOERROR) {
printf("free error.\n");
} else {
amiInfo[usSeed].pvBuf=NULL;
printf("verify and free successful.\n");
} /* endif */
} /* endif */
usSeed=rand()%MAX_INFO;
} /* endfor */
if (MemTerminate(htbmMem)!=TBMEM_EC_NOERROR) {
printf("\nTermination error.\n");
} /* endif */
}
---------------------------------------------------------
;--------------------------------------------------------------------------
; Program name: TESTEND.DEF Title: Memory toolbox test application
; OS/2 Developer Magazine Issue: Spring '93, page 127
;
; Article: "Writing Memory Allocation Functions With DosSubAllocMem"
; Author: Larry Salomon, Jr.
; Phone: n/a Fax: n/a
;
; Description: The following is a component of the complete source to the
; above article in the specified issue of OS/2 Developer Magazine. This
; source is provided AS-IS without any implied or expressed warranty. The
; author can be contacted via the Internet at the email address
; "os2man@panix.com".
;
; This component contains the tail of the module definition file used
; by the toolbox test programs. The NAME statement is prepended by the
; TEST.MAK makefile.
;
; Program requirements: IBM C-Set/2 for 32-bit compilation, Microsoft
; C 6.0 (or better) for 16-bit compilation.
;--------------------------------------------------------------------------
DESCRIPTION 'Test program for a toolbox component
Written by Larry Salomon, Jr.
All rights reserved.'
PROTMODE
STACKSIZE 0x8000