MEMMGR.C
资源名称:840.rar [点击查看]
上传用户:dcs7469208
上传日期:2010-01-02
资源大小:443k
文件大小:16k
源码类别:
操作系统开发
开发平台:
DOS
- /****************************************************************/
- /* */
- /* memmgr.c */
- /* */
- /* Memory Manager for Core Allocation */
- /* */
- /* Copyright (c) 1995 */
- /* Pasquale J. Villani */
- /* All Rights Reserved */
- /* */
- /* This file is part of DOS-C. */
- /* */
- /* DOS-C 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, or (at your option) any later version. */
- /* */
- /* DOS-C 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 DOS-C; see the file COPYING. If not, */
- /* write to the Free Software Foundation, 675 Mass Ave, */
- /* Cambridge, MA 02139, USA. */
- /****************************************************************/
- #include "../../hdr/portab.h"
- #include "globals.h"
- /* $Logfile*/
- #ifdef VERSION_STRING
- static BYTE *memmgrRcsId = "$Header: C:/dos-c/src/kernel/memmgr.c_v 1.6 04 Jan 1998 23:15:18 patv $";
- #endif
- /* $Log: C:/dos-c/src/kernel/memmgr.c_v $
- *
- * Rev 1.6 04 Jan 1998 23:15:18 patv
- * Changed Log for strip utility
- *
- * Rev 1.5 16 Jan 1997 12:47:00 patv
- * pre-Release 0.92 feature additions
- *
- * Rev 1.4 29 May 1996 21:03:34 patv
- * bug fixes for v0.91a
- *
- * Rev 1.3 19 Feb 1996 3:21:36 patv
- * Added NLS, int2f and config.sys processing
- *
- * Rev 1.2 01 Sep 1995 17:54:20 patv
- * First GPL release.
- *
- * Rev 1.1 30 Jul 1995 20:51:58 patv
- * Eliminated version strings in ipl
- *
- * Rev 1.0 02 Jul 1995 8:33:08 patv
- * Initial revision.
- */
- /* $EndLog$ */
- VOID mcb_init();
- VOID mcb_print();
- VOID show_chain();
- /* The following code is 8086 dependant */
- #ifdef KERNEL
- VOID
- mcb_init (mcb FAR *mcbp, UWORD size)
- {
- COUNT i;
- mcbp -> m_type = MCB_LAST;
- mcbp -> m_psp = FREE_PSP;
- mcbp -> m_size = size;
- for(i = 0; i < 8; i++)
- mcbp -> m_name[i] = ' ';
- mem_access_mode = FIRST_FIT;
- }
- #endif
- seg
- far2para (VOID FAR *p)
- {
- seg u1 = FP_SEG(p);
- offset u2 = FP_OFF(p);
- ULONG phy_addr;
- phy_addr = (((long)u1) << 4) + u2;
- return (phy_addr>>4);
- }
- seg
- long2para (LONG size)
- {
- return ((size + 0x0f)>>4);
- }
- VOID FAR *
- add_far (VOID FAR *fp, ULONG off)
- {
- UWORD seg_val;
- UWORD off_val;
- /* Break far pointer into components */
- seg_val = FP_SEG(fp);
- off_val = FP_OFF(fp);
- /* add the offset to the fp's offset part */
- off += off_val;
- /* make off_val equal to lower part of new value */
- off_val = off & 0xffff;
- /* and add top part into seg */
- seg_val += ((off & 0x000f0000l) / 0x10);
- /* and send back the new pointer */
- return (VOID FAR *)MK_FP(seg_val, off_val);
- }
- VOID FAR *
- adjust_far (VOID FAR *fp)
- {
- ULONG linear;
- UWORD seg_val;
- UWORD off_val;
- /* First, convert the segmented pointer to a linear address */
- linear = (((ULONG)FP_SEG(fp)) << 4) + FP_OFF(fp);
- /* Break it into segments. */
- seg_val = (UWORD)(linear >> 4);
- off_val = (UWORD)(linear & 0xf);
- /* and return an adddress adjusted to the nearest paragraph */
- /* boundary. */
- return MK_FP(seg_val, off_val);
- }
- #undef REG
- #define REG
- #ifdef KERNEL
- COUNT
- DosMemAlloc (UWORD size, COUNT mode, seg FAR *para, UWORD FAR *asize)
- {
- REG mcb FAR *p;
- mcb FAR *q;
- COUNT i;
- BOOL found;
- /* Initialize */
- p = (mcb FAR *)(MK_FP(first_mcb, 0));
- /* Search through memory blocks */
- for(q = (mcb FAR *)0, i = 0, found = FALSE; !found; )
- {
- /* check for corruption */
- if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
- return DE_MCBDESTRY;
- /* Test if free based on mode rules */
- switch(mode)
- {
- case LAST_FIT:
- default:
- /* Check for a last fit candidate */
- if(p -> m_size >= size && p -> m_psp == FREE_PSP)
- /* keep the last know fit */
- q = p;
- /* not free - bump the pointer */
- if(p -> m_type != MCB_LAST)
- p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- /* was there no room (q == 0)? */
- else if(p -> m_type == MCB_LAST && q == (mcb FAR *)0)
- return DE_NOMEM;
- /* something was found - continue */
- else
- found = TRUE;
- break;
- case FIRST_FIT:
- /* Check for a first fit candidate */
- if(p -> m_size >= size && p -> m_psp == FREE_PSP)
- {
- q = p;
- found = TRUE;
- break;
- }
- /* not free - bump the pointer */
- if(p -> m_type != MCB_LAST)
- p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- /* nothing found till end - no room */
- else
- return DE_NOMEM;
- break;
- case BEST_FIT:
- /* Check for a best fit candidate */
- if(p -> m_size >= size && p -> m_psp == FREE_PSP)
- {
- if(i == 0 || p -> m_size < i)
- {
- i = p -> m_size;
- q = p;
- }
- }
- /* not free - bump the pointer */
- if(p -> m_type != MCB_LAST)
- p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- /* was there no room (q == 0)? */
- else if(p -> m_type == MCB_LAST && q == (mcb FAR *)0)
- return DE_NOMEM;
- /* something was found - continue */
- else
- found = TRUE;
- break;
- case LARGEST:
- /* Check for a first fit candidate */
- if((p -> m_psp == FREE_PSP) && (i == 0 || p -> m_size > i))
- {
- size = *asize = i = p -> m_size;
- q = p;
- }
- /* not free - bump the pointer */
- if(p -> m_type != MCB_LAST)
- p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- /* was there no room (q == 0)? */
- else if(p -> m_type == MCB_LAST && q == (mcb FAR *)0)
- return DE_NOMEM;
- /* something was found - continue */
- else
- found = TRUE;
- break;
- }
- }
- p = q;
- /* Larger fit case */
- if(p -> m_size > size)
- {
- if(mode != LAST_FIT)
- {
- q = MK_FP(far2para((VOID FAR *)p) + size + 1, 0);
- /* Always flow m_type up */
- /* on alloc */
- q -> m_type = p -> m_type;
- p -> m_type = MCB_NORMAL;
- p -> m_psp = cu_psp;
- q -> m_psp = FREE_PSP;
- q -> m_size = p -> m_size - size - 1;
- p -> m_size = size;
- for(i = 0; i < 8; i++)
- p -> m_name[i] = q -> m_name[i] = ' ';
- }
- else
- {
- q = MK_FP(far2para((VOID FAR *)p) + (p -> m_size - size), 0);
- /* Always flow m_type up */
- /* on alloc */
- q -> m_type = p -> m_type;
- p -> m_type = MCB_NORMAL;
- q -> m_psp = cu_psp;
- p -> m_psp = FREE_PSP;
- p -> m_size = p -> m_size - size - 1;
- q -> m_size = size;
- for(i = 0; i < 8; i++)
- p -> m_name[i] = q -> m_name[i] = ' ';
- }
- /* Found - return good */
- *para = far2para((VOID FAR *)(mode == LAST_FIT ? (VOID FAR *)q : (VOID FAR *)p));
- return SUCCESS;
- }
- /* Exact fit case */
- else if(p -> m_size == size)
- {
- p -> m_psp = cu_psp;
- for(i = 0; i < 8; i++)
- p -> m_name[i] = ' ';
- /* Found - return good */
- *para = far2para((VOID FAR *)(BYTE FAR *)p);
- return SUCCESS;
- }
- else
- return DE_MCBDESTRY;
- }
- seg
- DosMemLargest (seg FAR *size)
- {
- REG mcb FAR *p;
- mcb FAR *q;
- COUNT found;
- /* Initialize */
- p = (mcb FAR *)(MK_FP(first_mcb, 0));
- /* Search through memory blocks */
- for(q = (mcb FAR *)0, *size = 0, found = FALSE; !found; )
- {
- /* check for corruption */
- if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
- return DE_MCBDESTRY;
- /* Test for largest fit/available */
- if((p -> m_psp == FREE_PSP) && (p -> m_size > *size))
- {
- *size = p -> m_size;
- q = p;
- }
- /* not free - bump the pointer */
- if(p -> m_type != MCB_LAST)
- p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- /* was there no room (q == 0)? */
- else if(p -> m_type == MCB_LAST && q == (mcb FAR *)0)
- return DE_NOMEM;
- /* something was found - continue */
- else
- found = TRUE;
- }
- if( q != 0)
- return SUCCESS;
- else
- return DE_NOMEM;
- }
- COUNT
- DosMemFree (UWORD para)
- {
- REG mcb FAR *p, FAR *q;
- COUNT i;
- /* Initialize */
- p = (mcb FAR *)(MK_FP(para, 0));
- /* check for corruption */
- if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
- return DE_INVLDMCB;
- /* Mark the mcb as free so that we can later */
- /* merge with other surrounding free mcb's */
- p -> m_psp = FREE_PSP;
- for(i = 0; i < 8; i++)
- p -> m_name[i] = ' ';
- /* Now merge free blocks */
- for(p = (mcb FAR *)(MK_FP(first_mcb, 0)); p -> m_type != MCB_LAST; p = q)
- {
- /* make q a pointer to the next block */
- q = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- /* and test for corruption */
- if(q -> m_type != MCB_NORMAL && q -> m_type != MCB_LAST)
- return DE_MCBDESTRY;
- if(p -> m_psp != FREE_PSP)
- continue;
- /* test if next is free - if so merge */
- if(q -> m_psp == FREE_PSP)
- {
- /* Always flow type down on free */
- p -> m_type = q -> m_type;
- p -> m_size += q -> m_size + 1;
- /* and make pointers the same */
- /* since the next free is now */
- /* this block */
- q = p;
- }
- }
- return SUCCESS;
- }
- COUNT
- DosMemChange (UWORD para, UWORD size, UWORD *maxSize)
- {
- REG mcb FAR *p, FAR *q;
- REG COUNT i;
- /* Initialize */
- p = (mcb FAR *)(MK_FP(--para, 0));
- /* check for corruption */
- if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
- return DE_MCBDESTRY;
- /* check for wrong allocation */
- if(size > p -> m_size)
- {
- REG UCOUNT delta;
- if (p -> m_type == MCB_LAST)
- {
- if (maxSize) *maxSize = p -> m_size + q -> m_size;
- return DE_NOMEM;
- }
- /* make q a pointer to the next block */
- q = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- /* check for corruption */
- if(q -> m_type != MCB_NORMAL && q -> m_type != MCB_LAST)
- return DE_MCBDESTRY;
- /* if next mcb is not free, error no memory */
- if(q -> m_psp != FREE_PSP)
- {
- if (maxSize) *maxSize = p -> m_size;
- return DE_NOMEM;
- }
- /* reduce the size of q and add difference to p */
- /* but check that q is big enough first */
- delta = size - p -> m_size;
- if(q -> m_size < delta)
- {
- if (maxSize) *maxSize = p -> m_size + q -> m_size;
- return DE_NOMEM;
- }
- q -> m_size -= delta;
- p -> m_size += delta;
- /* Now go back and adjust q, we'll make p new q */
- p = MK_FP(far2para((VOID FAR *)q) + delta, 0);
- p -> m_type = q -> m_type;
- p -> m_psp = q -> m_psp;
- p -> m_size = q -> m_size;
- for(i = 0; i < 8; i++)
- p -> m_name[i] = q -> m_name[i];
- /* and finished */
- return SUCCESS;
- }
- /* else, shrink it down */
- else if(size < p -> m_size)
- {
- /* make q a pointer to the new next block */
- q = MK_FP(far2para((VOID FAR *)p) + size + 1, 0);
- /* reduce the size of p and add difference to q */
- q -> m_type = p -> m_type;
- q -> m_size = p -> m_size - size - 1;
- p -> m_size = size;
- /* Make certian the old psp is not last (if it was) */
- p -> m_type = MCB_NORMAL;
- /* Mark the mcb as free so that we can later */
- /* merge with other surrounding free mcb's */
- q -> m_psp = FREE_PSP;
- for(i = 0; i < 8; i++)
- q -> m_name[i] = ' ';
- /* now free it so that we have a complete block */
- return DosMemFree(far2para((VOID FAR *)q));
- }
- /* otherwise, its a no-op */
- else
- return SUCCESS;
- }
- COUNT
- DosMemCheck (void)
- {
- REG mcb FAR *p;
- /* Initialize */
- p = (mcb FAR *)(MK_FP(first_mcb, 0));
- /* Search through memory blocks */
- for( ; ; )
- {
- /* check for corruption */
- if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
- return DE_MCBDESTRY;
- /* not corrupted - if last we're OK! */
- if(p -> m_type == MCB_LAST)
- return SUCCESS;
- /* not corrupted - but not end, bump the pointer */
- else if(p -> m_type != MCB_LAST)
- p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- /* totally lost - bad exit */
- else
- return DE_MCBDESTRY;
- }
- }
- COUNT
- FreeProcessMem (UWORD ps)
- {
- mcb FAR *p;
- /* Initialize */
- p = (mcb FAR *)(MK_FP(first_mcb, 0));
- /* Search through memory blocks */
- for( ; ; )
- {
- /* check for corruption */
- if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
- return DE_MCBDESTRY;
- if(p -> m_psp == ps)
- DosMemFree( FP_SEG(p) );
- /* not corrupted - if last we're OK! */
- if(p -> m_type == MCB_LAST) break;
- p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- }
- return SUCCESS;
- }
- COUNT
- DosGetLargestBlock(UWORD FAR *block)
- {
- UWORD sz = 0;
- mcb FAR *p;
- *block = sz;
- /* Initialize */
- p = (mcb FAR *)(MK_FP(first_mcb, 0));
- /* Search through memory blocks */
- for( ; ; )
- {
- /* check for corruption */
- if(p -> m_type != MCB_NORMAL && p -> m_type != MCB_LAST)
- return DE_MCBDESTRY;
- if (p -> m_psp == FREE_PSP && p -> m_size > sz)
- sz = p -> m_size;
- /* not corrupted - if last we're OK! */
- if(p -> m_type == MCB_LAST) break;
- p = MK_FP(far2para((VOID FAR *)p) + p -> m_size + 1, 0);
- }
- *block = sz;
- return SUCCESS;
- }
- VOID
- show_chain (void)
- {
- mcb FAR *p = (mcb FAR *)(MK_FP(first_mcb, 0));
- for(;;)
- {
- mcb_print(p);
- if(p -> m_type == MCB_LAST || p -> m_type != MCB_NORMAL)
- return;
- else
- p = (mcb FAR *)(MK_FP(far2para((VOID FAR *)p)+p -> m_size+1,0));
- }
- }
- VOID
- mcb_print (mcb FAR *mcbp)
- {
- static BYTE buff[9];
- VOID _fmemcpy();
- _fmemcpy((BYTE FAR *)buff, (BYTE FAR *)(mcbp -> m_name), 8);
- buff[8] = ' ';
- printf("%04x:%04x -> |%s| m_type = 0x%02x; m_psp = 0x%04x; m_size = 0x%04xn",
- FP_SEG(mcbp),
- FP_OFF(mcbp),
- *buff == ' ' ? "*NO-ID*" : buff,
- mcbp -> m_type,
- mcbp -> m_psp,
- mcbp -> m_size);
- }
- VOID _fmemcpy(BYTE FAR *d, BYTE FAR *s, REG COUNT n)
- {
- while(n--)
- *d++ = *s++;
- }
- #endif