From 461ceab52ae6252be3e74ac31cf59dd476f44513 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Wed, 1 Apr 2026 11:53:43 +0300 Subject: [PATCH] hmamgr: implement topdown allocations [fixes #292] --- kernel/hmamgr.c | 23 ++++++++++++++++------- kernel/inthndlr.c | 10 +++------- kernel/proto.h | 2 +- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/kernel/hmamgr.c b/kernel/hmamgr.c index c8deec41..79f5a5c7 100644 --- a/kernel/hmamgr.c +++ b/kernel/hmamgr.c @@ -34,7 +34,8 @@ static hmcb init_mcb = { .signature = HMCB_SIG, }; #define FIRST_MCB 0x10 #define nxtMCBsize(mcb,size) MK_FP(FP_SEG(mcb), FP_OFF(mcb) + (size) + 16) -#define nxtMCB(mcb) MK_FP(FP_SEG(mcb), mcb->next) +#define nxtMCBsizeTd(mcb,size) MK_FP(FP_SEG(mcb), FP_OFF(mcb) + (mcb)->size - (size)) +#define nxtMCB(mcb) MK_FP(FP_SEG(mcb), (mcb)->next) #define mcbFree(mcb) ((mcb)->owner == 0) #define mcbValid(mcb) ( ((mcb)->signature == HMCB_SIG) ) @@ -99,10 +100,10 @@ STATIC COUNT joinMCBs(UWORD off) size is the minimum size of the block to search for, even if mode == LARGEST. */ -COUNT DosHMAAlloc(UWORD size, UWORD *off) +COUNT DosHMAAlloc(UWORD size, BOOL topdown, UWORD *off) { - REG hmcb FAR *p; - REG hmcb FAR *q = NULL; + hmcb FAR *p; + hmcb FAR *q = NULL; hmcb FAR *foundSeg; hmcb FAR *biggestSeg; @@ -156,13 +157,16 @@ COUNT DosHMAAlloc(UWORD size, UWORD *off) /* foundSeg := pointer to allocated block p := pointer to MCB that will form the rest of the block */ - p = nxtMCBsize(foundSeg, size); + p = topdown ? nxtMCBsizeTd(foundSeg, size) : nxtMCBsize(foundSeg, size); fd_prot_mem(p, sizeof(*p), FD_MEM_NORMAL); /* initialize stuff because p > foundSeg */ *p = init_mcb; p->next = foundSeg->next; - p->size = foundSeg->size - size - 16; + if (topdown) + p->size = size; + else + p->size = foundSeg->size - size - 16; fd_mark_mem(p, sizeof(*p), FD_MEM_READONLY); fd_prot_mem(foundSeg, sizeof(*foundSeg), FD_MEM_NORMAL); foundSeg->next = mcb2off(p); @@ -173,8 +177,13 @@ COUNT DosHMAAlloc(UWORD size, UWORD *off) p->owner = 0; /* unused */ fd_prot_mem(p, sizeof(*p), FD_MEM_READONLY); - foundSeg->size = size; + if (topdown) + foundSeg->size -= size + 16; + else + foundSeg->size = size; fd_prot_mem(foundSeg, sizeof(*foundSeg), FD_MEM_READONLY); + if (topdown) + foundSeg = p; } /* Already initialized: diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index 7292b807..c07b5738 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -1861,7 +1861,7 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs FAR *regs) r.BX = (r.BX + 0xf) & 0xfff0; if (r.BX > avail) r.BX = avail; - rc = DosHMAAlloc(r.BX, &r.DI); + rc = DosHMAAlloc(r.BX, 0, &r.DI); break; case 3: if (!HMAclaimed) @@ -1876,14 +1876,10 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs FAR *regs) switch (r.DL) { case 0: // alloc + case 1: /* align to para */ r.BX = (r.BX + 0xf) & 0xfff0; - rc = DosHMAAlloc(r.BX, &r.DI); - break; - case 1: // resize - /* align to para */ - r.BX = (r.BX + 0xf) & 0xfff0; - rc = DosHMAChange(r.DI, r.BX); + rc = DosHMAAlloc(r.BX, r.DL, &r.DI); break; case 2: // free rc = DosHMAFree(r.DI); diff --git a/kernel/proto.h b/kernel/proto.h index 9566bdae..45633af8 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -251,7 +251,7 @@ void DosUmbLink(unsigned n); VOID mcb_print(__FAR(mcb) mcbp); COUNT DosHMAQuery(UWORD *off, UWORD *avail); -COUNT DosHMAAlloc(UWORD size, UWORD *off); +COUNT DosHMAAlloc(UWORD size, BOOL topdown, UWORD *off); COUNT DosHMAFree(UWORD off); COUNT DosHMAChange(UWORD para, UWORD size); COUNT DosHMACheck(void);