ReactOS 0.4.16-dev-336-gb667d82
memory.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _DOS_MCB
 

Macros

#define SEGMENT_TO_MCB(seg)   ((PDOS_MCB)SEG_OFF_TO_PTR((seg), 0))
 
#define DOS_ALLOC_HIGH   0x40
 
#define DOS_ALLOC_HIGH_LOW   0x80
 

Typedefs

typedef struct _DOS_MCB DOS_MCB
 
typedef struct _DOS_MCBPDOS_MCB
 

Enumerations

enum  DOS_ALLOC_STRATEGY { DOS_ALLOC_FIRST_FIT , DOS_ALLOC_BEST_FIT , DOS_ALLOC_LAST_FIT }
 

Functions

 C_ASSERT (sizeof(DOS_MCB)==0x10)
 
WORD DosAllocateMemory (WORD Size, WORD *MaxAvailable)
 
BOOLEAN DosResizeMemory (WORD BlockData, WORD NewSize, WORD *MaxAvailable)
 
BOOLEAN DosFreeMemory (WORD BlockData)
 
BOOLEAN DosLinkUmb (VOID)
 
BOOLEAN DosUnlinkUmb (VOID)
 
VOID DosChangeMemoryOwner (WORD Segment, WORD NewOwner)
 
VOID DosInitializeUmb (VOID)
 
VOID DosInitializeMemory (VOID)
 

Macro Definition Documentation

◆ DOS_ALLOC_HIGH

#define DOS_ALLOC_HIGH   0x40

Definition at line 17 of file memory.h.

◆ DOS_ALLOC_HIGH_LOW

#define DOS_ALLOC_HIGH_LOW   0x80

Definition at line 18 of file memory.h.

◆ SEGMENT_TO_MCB

#define SEGMENT_TO_MCB (   seg)    ((PDOS_MCB)SEG_OFF_TO_PTR((seg), 0))

Definition at line 15 of file memory.h.

Typedef Documentation

◆ DOS_MCB

◆ PDOS_MCB

Enumeration Type Documentation

◆ DOS_ALLOC_STRATEGY

Enumerator
DOS_ALLOC_FIRST_FIT 
DOS_ALLOC_BEST_FIT 
DOS_ALLOC_LAST_FIT 

Definition at line 20 of file memory.h.

21{
25};
@ DOS_ALLOC_LAST_FIT
Definition: memory.h:24
@ DOS_ALLOC_BEST_FIT
Definition: memory.h:23
@ DOS_ALLOC_FIRST_FIT
Definition: memory.h:22

Function Documentation

◆ C_ASSERT()

C_ASSERT ( sizeof(DOS_MCB = =0x10)

◆ DosAllocateMemory()

WORD DosAllocateMemory ( WORD  Size,
WORD MaxAvailable 
)

Definition at line 136 of file memory.c.

137{
138 WORD Result = 0, Segment = SysVars->FirstMcb, MaxSize = 0;
139 PDOS_MCB CurrentMcb;
140 BOOLEAN SearchUmb = FALSE;
141
142 DPRINT("DosAllocateMemory: Size 0x%04X\n", Size);
143
145
146 if (SysVars->UmbLinked && SysVars->UmbChainStart != 0xFFFF &&
148 {
149 /* Search UMB first */
151 SearchUmb = TRUE;
152 }
153
154 while (TRUE)
155 {
156 /* Get a pointer to the MCB */
157 CurrentMcb = SEGMENT_TO_MCB(Segment);
158
159 /* Make sure it's valid */
160 if (!ValidateMcb(CurrentMcb))
161 {
162 DPRINT1("The DOS memory arena is corrupted!\n");
164 return 0;
165 }
166
167 /* Only check free blocks */
168 if (CurrentMcb->OwnerPsp != 0) goto Next;
169
170 /* Combine this free block with adjoining free blocks */
172
173 /* Update the maximum block size */
174 if (CurrentMcb->Size > MaxSize) MaxSize = CurrentMcb->Size;
175
176 /* Check if this block is big enough */
177 if (CurrentMcb->Size < Size) goto Next;
178
180 {
182 {
183 /* For first fit, stop immediately */
184 Result = Segment;
185 goto Done;
186 }
187
189 {
190 /* For best fit, update the smallest block found so far */
191 if ((Result == 0) || (CurrentMcb->Size < SEGMENT_TO_MCB(Result)->Size))
192 {
193 Result = Segment;
194 }
195
196 break;
197 }
198
200 {
201 /* For last fit, make the current block the result, but keep searching */
202 Result = Segment;
203 break;
204 }
205 }
206
207Next:
208 /* If this was the last MCB in the chain, quit */
209 if (CurrentMcb->BlockType == 'Z')
210 {
211 /* Check if nothing was found while searching through UMBs */
212 if ((Result == 0) && SearchUmb && (Sda->AllocStrategy & DOS_ALLOC_HIGH_LOW))
213 {
214 /* Search low memory */
216 SearchUmb = FALSE;
217 continue;
218 }
219
220 break;
221 }
222
223 /* Otherwise, update the segment and continue */
224 Segment += CurrentMcb->Size + 1;
225 }
226
227Done:
229
230 /* If we didn't find a free block, bail out */
231 if (Result == 0)
232 {
233 DPRINT("DosAllocateMemory FAILED. Maximum available: 0x%04X\n", MaxSize);
235 if (MaxAvailable) *MaxAvailable = MaxSize;
236 return 0;
237 }
238
239 /* Get a pointer to the MCB */
240 CurrentMcb = SEGMENT_TO_MCB(Result);
241
242 /* Check if the block is larger than requested */
243 if (CurrentMcb->Size > Size)
244 {
245 /* It is, split it into two blocks */
247 {
248 PDOS_MCB NextMcb = SEGMENT_TO_MCB(Result + Size + 1);
249
250 /* Initialize the new MCB structure */
251 NextMcb->BlockType = CurrentMcb->BlockType;
252 NextMcb->Size = CurrentMcb->Size - Size - 1;
253 NextMcb->OwnerPsp = 0;
254
255 /* Update the current block */
256 CurrentMcb->BlockType = 'M';
257 CurrentMcb->Size = Size;
258 }
259 else
260 {
261 /* Save the location of the current MCB */
262 PDOS_MCB PreviousMcb = CurrentMcb;
263
264 /* Move the current MCB higher */
265 Result += CurrentMcb->Size - Size;
266 CurrentMcb = SEGMENT_TO_MCB(Result);
267
268 /* Initialize the new MCB structure */
269 CurrentMcb->BlockType = PreviousMcb->BlockType;
270 CurrentMcb->Size = Size;
271 CurrentMcb->OwnerPsp = 0;
272
273 /* Update the previous block */
274 PreviousMcb->BlockType = 'M';
275 PreviousMcb->Size -= Size + 1;
276 }
277 }
278
279 /* Take ownership of the block */
280 CurrentMcb->OwnerPsp = Sda->CurrentPsp;
281 RtlCopyMemory(CurrentMcb->Name, SEGMENT_TO_MCB(Sda->CurrentPsp - 1)->Name, sizeof(CurrentMcb->Name));
282
284
285 /* Return the segment of the data portion of the block */
286 return Result + 1;
287}
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
PDOS_SYSVARS SysVars
Definition: dos.c:47
PDOS_SDA Sda
Definition: dos.c:48
unsigned short WORD
Definition: ntddk_ex.h:93
#define DPRINT
Definition: sndvol32.h:73
CHAR BlockType
Definition: memory.h:30
WORD Size
Definition: memory.h:32
CHAR Name[8]
Definition: memory.h:34
WORD OwnerPsp
Definition: memory.h:31
WORD LastErrorCode
Definition: dos.h:160
WORD CurrentPsp
Definition: dos.h:165
BYTE AllocStrategy
Definition: dos.h:152
WORD FirstMcb
Definition: dos.h:77
WORD UmbChainStart
Definition: dos.h:102
BYTE UmbLinked
Definition: dos.h:100
static VOID DosCombineFreeBlocks(WORD StartBlock)
Definition: memory.c:85
#define DosMemValidate()
Definition: memory.c:82
static BOOLEAN ValidateMcb(PDOS_MCB Mcb)
Definition: memory.c:44
#define DOS_ALLOC_HIGH_LOW
Definition: memory.h:18
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15
#define DOS_ALLOC_HIGH
Definition: memory.h:17
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
#define ERROR_ARENA_TRASHED
Definition: winerror.h:110
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Inout_ PVOID Segment
Definition: exfuncs.h:1101

Referenced by DosCopyEnvironmentBlock(), DosCountryInitialize(), DosCreateDeviceEx(), DosInt21h(), DosLoadDriver(), DosLoadExecutableInternal(), DosMouseInitialize(), and DosResizeHandleTable().

◆ DosChangeMemoryOwner()

VOID DosChangeMemoryOwner ( WORD  Segment,
WORD  NewOwner 
)

Definition at line 532 of file memory.c.

533{
535 Mcb->OwnerPsp = NewOwner;
536}
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:349

Referenced by DosLoadExecutableInternal().

◆ DosFreeMemory()

BOOLEAN DosFreeMemory ( WORD  BlockData)

Definition at line 418 of file memory.c.

419{
420 PDOS_MCB Mcb = SEGMENT_TO_MCB(BlockData - 1);
421
422 DPRINT("DosFreeMemory: BlockData 0x%04X\n", BlockData);
423
424 if (BlockData == 0)
425 {
427 return FALSE;
428 }
429
431
432 /* Make sure the MCB is valid */
433 if (!ValidateMcb(Mcb))
434 {
435 DPRINT("MCB block type '%c' not valid!\n", Mcb->BlockType);
437 return FALSE;
438 }
439
440 /* Mark the block as free */
441 Mcb->OwnerPsp = 0;
442
443 return TRUE;
444}
#define ERROR_INVALID_BLOCK
Definition: winerror.h:112

Referenced by DosCreateDeviceEx(), DosDeleteDevice(), DosInt21h(), DosLoadDriver(), DosLoadExecutableInternal(), DosMouseCleanup(), DosResizeHandleTable(), and DosTerminateProcess().

◆ DosInitializeMemory()

VOID DosInitializeMemory ( VOID  )

Definition at line 665 of file memory.c.

666{
668
669 /* Set the initial allocation strategy to "best fit" */
671
672 /* Initialize conventional memory; we don't have UMBs yet */
673 SysVars->FirstMcb = FIRST_MCB_SEGMENT; // The Arena Head
675 SysVars->UmbChainStart = 0xFFFF;
676
678
679 /* Initialize the MCB */
680 Mcb->BlockType = 'Z';
681 Mcb->Size = USER_MEMORY_SIZE;
682 Mcb->OwnerPsp = 0;
683}
#define USER_MEMORY_SIZE
Definition: memory.c:29
#define FIRST_MCB_SEGMENT
Definition: memory.c:28

Referenced by DosKRNLInitialize().

◆ DosInitializeUmb()

VOID DosInitializeUmb ( VOID  )

Definition at line 582 of file memory.c.

583{
585 USHORT UmbSegment = 0x0000, PrevSegment;
586 USHORT Size;
587 PDOS_MCB Mcb, PrevMcb;
588
589 ASSERT(SysVars->UmbChainStart == 0xFFFF);
590
591 // SysVars->UmbLinked = FALSE;
592
593 /* Try to allocate all the UMBs */
594 while (TRUE)
595 {
596 /* Find the maximum amount of memory that can be allocated */
597 Size = 0xFFFF;
598 Result = UmaDescReserve(&UmbSegment, &Size);
599
600 /* If we are out of UMBs, bail out */
601 if (!Result && Size == 0) // XMS_STATUS_OUT_OF_UMBS
602 break;
603
604 /* We should not have succeeded! */
605 ASSERT(!Result);
606
607 /* 'Size' now contains the size of the biggest UMB block. Request it. */
608 Result = UmaDescReserve(&UmbSegment, &Size);
609 ASSERT(Result); // XMS_STATUS_SUCCESS
610
611 /* If this is our first UMB block, initialize the UMB chain */
612 if (SysVars->UmbChainStart == 0xFFFF)
613 {
614 /* Initialize the link MCB to the UMB area */
615 // NOTE: We use the fact that UmbChainStart is still == 0xFFFF
616 // so that we initialize this block from 9FFF:0000 up to FFFF:000F.
617 // It will be splitted as needed just below.
618 Mcb = SEGMENT_TO_MCB(SysVars->FirstMcb + USER_MEMORY_SIZE + 1); // '+1': Readjust the fact that USER_MEMORY_SIZE is based using 0x9FFE instead of 0x9FFF
619 Mcb->BlockType = 'Z'; // At the moment it is really the last block
620 Mcb->Size = (SysVars->UmbChainStart /* UmbSegment */ - SysVars->FirstMcb - USER_MEMORY_SIZE - 2) + 1;
621 Mcb->OwnerPsp = SYSTEM_PSP;
622 RtlCopyMemory(Mcb->Name, "SC ", sizeof("SC ")-1);
623
624#if 0 // Keep here for reference; this will be deleted as soon as it becomes unneeded.
625 /* Initialize the UMB area */
627 Mcb->Size = UMB_END_SEGMENT - SysVars->UmbChainStart;
628#endif
629
630 // FIXME: We should adjust the size of the previous block!!
631
632 /* Initialize the start of the UMB chain */
634 }
635
636 /* Split the block */
637
638 /* Get the previous block */
639 PrevSegment = DosGetPreviousUmb(UmbSegment);
640 PrevMcb = SEGMENT_TO_MCB(PrevSegment);
641
642 /* Initialize the next block */
643 Mcb = SEGMENT_TO_MCB(UmbSegment + /*Mcb->Size*/(Size - 1) + 0);
644 // Mcb->BlockType = 'Z'; // FIXME: What if this block happens to be the last one??
645 Mcb->BlockType = PrevMcb->BlockType;
646 Mcb->Size = PrevMcb->Size - (UmbSegment + Size - PrevSegment) + 1;
647 Mcb->OwnerPsp = PrevMcb->OwnerPsp;
648 RtlCopyMemory(Mcb->Name, PrevMcb->Name, sizeof(PrevMcb->Name));
649
650 /* The previous block is not the latest one anymore */
651 PrevMcb->BlockType = 'M';
652 PrevMcb->Size = UmbSegment - PrevSegment - 1;
653
654 /* Initialize the new UMB block */
655 Mcb = SEGMENT_TO_MCB(UmbSegment);
656 Mcb->BlockType = 'M'; // 'Z' // FIXME: What if this block happens to be the last one??
657 Mcb->Size = Size - 1 - 1; // minus 2 because we need to have one arena at the beginning and one at the end.
658 Mcb->OwnerPsp = 0;
659 // FIXME: Which MCB name should we use? I need to explore more the docs!
660 RtlCopyMemory(Mcb->Name, "UMB ", sizeof("UMB ")-1);
661 // RtlCopyMemory(Mcb->Name, "SM ", sizeof("SM ")-1);
662 }
663}
#define ASSERT(a)
Definition: mode.c:44
unsigned short USHORT
Definition: pedump.c:61
#define SYSTEM_PSP
Definition: dos.h:39
WORD DosGetPreviousUmb(WORD UmbSegment)
Definition: memory.c:544
BOOLEAN UmaDescReserve(IN OUT PUSHORT Segment, IN OUT PUSHORT Size)
Definition: umamgr.c:84

Referenced by DosKRNLInitialize().

◆ DosLinkUmb()

BOOLEAN DosLinkUmb ( VOID  )

Definition at line 446 of file memory.c.

447{
450
451 DPRINT("Linking UMB\n");
452
453 /* Check if UMBs are initialized and already linked */
454 if (SysVars->UmbChainStart == 0xFFFF) return FALSE;
455 if (SysVars->UmbLinked) return TRUE;
456
458
459 /* Find the last block before the start of the UMB chain */
460 while (Segment < SysVars->UmbChainStart)
461 {
462 /* Get a pointer to the MCB */
464
465 /* Make sure it's valid */
466 if (!ValidateMcb(Mcb))
467 {
468 DPRINT1("The DOS memory arena is corrupted!\n");
470 return FALSE;
471 }
472
473 /* If this was the last MCB in the chain, quit */
474 if (Mcb->BlockType == 'Z') break;
475
476 /* Otherwise, update the segment and continue */
477 Segment += Mcb->Size + 1;
478 }
479
480 /* Make sure it's valid */
481 if (Mcb->BlockType != 'Z') return FALSE;
482
483 /* Connect the MCB with the UMB chain */
484 Mcb->BlockType = 'M';
485
487
489 return TRUE;
490}
unsigned long DWORD
Definition: ntddk_ex.h:95

Referenced by DosInt21h().

◆ DosResizeMemory()

BOOLEAN DosResizeMemory ( WORD  BlockData,
WORD  NewSize,
WORD MaxAvailable 
)

Definition at line 289 of file memory.c.

290{
292 WORD Segment = BlockData - 1, ReturnSize = 0, NextSegment;
294
295 DPRINT("DosResizeMemory: BlockData 0x%04X, NewSize 0x%04X\n",
296 BlockData, NewSize);
297
299
300 /* Make sure this is a valid and allocated block */
301 if (BlockData == 0 || !ValidateMcb(Mcb) || Mcb->OwnerPsp == 0)
302 {
304 Success = FALSE;
305 goto Done;
306 }
307
308 ReturnSize = Mcb->Size;
309
310 /* Check if we need to expand or contract the block */
311 if (NewSize > Mcb->Size)
312 {
313 /* We can't expand the last block */
314 if (Mcb->BlockType == 'Z')
315 {
316 DPRINT("Cannot expand memory block 0x%04X: this is the last block (size 0x%04X)!\n", Segment, Mcb->Size);
318 Success = FALSE;
319 goto Done;
320 }
321
322 /* Get the pointer and segment of the next MCB */
323 NextSegment = Segment + Mcb->Size + 1;
324 NextMcb = SEGMENT_TO_MCB(NextSegment);
325
326 /* Make sure it's valid */
327 if (!ValidateMcb(NextMcb))
328 {
329 DPRINT1("The DOS memory arena is corrupted!\n");
331 return FALSE;
332 }
333
334 /* Make sure the next segment is free */
335 if (NextMcb->OwnerPsp != 0)
336 {
337 DPRINT("Cannot expand memory block 0x%04X: next segment is not free!\n", Segment);
339 Success = FALSE;
340 goto Done;
341 }
342
343 /* Combine this free block with adjoining free blocks */
344 DosCombineFreeBlocks(NextSegment);
345
346 /* Set the maximum possible size of the block */
347 ReturnSize += NextMcb->Size + 1;
348
349 if (ReturnSize < NewSize)
350 {
351 DPRINT("Cannot expand memory block 0x%04X: insufficient free segments available!\n", Segment);
353 Success = FALSE;
354 goto Done;
355 }
356
357 /* Maximize the current block */
358 Mcb->Size = ReturnSize;
359 Mcb->BlockType = NextMcb->BlockType;
360
361 /* Invalidate the next block */
362 NextMcb->BlockType = 'I';
363
364 /* Check if the block is larger than requested */
365 if (Mcb->Size > NewSize)
366 {
367 DPRINT("Block too large, reducing size from 0x%04X to 0x%04X\n",
368 Mcb->Size, NewSize);
369
370 /* It is, split it into two blocks */
371 NextMcb = SEGMENT_TO_MCB(Segment + NewSize + 1);
372
373 /* Initialize the new MCB structure */
374 NextMcb->BlockType = Mcb->BlockType;
375 NextMcb->Size = Mcb->Size - NewSize - 1;
376 NextMcb->OwnerPsp = 0;
377
378 /* Update the current block */
379 Mcb->BlockType = 'M';
380 Mcb->Size = NewSize;
381 }
382 }
383 else if (NewSize < Mcb->Size)
384 {
385 DPRINT("Shrinking block from 0x%04X to 0x%04X\n",
386 Mcb->Size, NewSize);
387
388 /* Just split the block */
389 NextSegment = Segment + NewSize + 1;
390 NextMcb = SEGMENT_TO_MCB(NextSegment);
391 NextMcb->BlockType = Mcb->BlockType;
392 NextMcb->Size = Mcb->Size - NewSize - 1;
393 NextMcb->OwnerPsp = 0;
394
395 /* Update the MCB */
396 Mcb->BlockType = 'M';
397 Mcb->Size = NewSize;
398
399 /* Combine this free block with adjoining free blocks */
400 DosCombineFreeBlocks(NextSegment);
401 }
402
403Done:
404 /* Check if the operation failed */
405 if (!Success)
406 {
407 DPRINT("DosResizeMemory FAILED. Maximum available: 0x%04X\n", ReturnSize);
408
409 /* Return the maximum possible size */
410 if (MaxAvailable) *MaxAvailable = ReturnSize;
411 }
412
414
415 return Success;
416}
@ Success
Definition: eventcreate.c:712
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975

Referenced by DosInt21h(), DosResizeHandleTable(), and DosTerminateProcess().

◆ DosUnlinkUmb()

BOOLEAN DosUnlinkUmb ( VOID  )

Definition at line 492 of file memory.c.

493{
496
497 DPRINT("Unlinking UMB\n");
498
499 /* Check if UMBs are initialized and already unlinked */
500 if (SysVars->UmbChainStart == 0xFFFF) return FALSE;
501 if (!SysVars->UmbLinked) return TRUE;
502
504
505 /* Find the last block before the start of the UMB chain */
506 while (Segment < SysVars->UmbChainStart)
507 {
508 /* Get a pointer to the MCB */
510
511 /* Make sure it's valid */
512 if (!ValidateMcb(Mcb))
513 {
514 DPRINT1("The DOS memory arena is corrupted!\n");
516 return FALSE;
517 }
518
519 /* Advance to the next MCB */
520 Segment += Mcb->Size + 1;
521 }
522
523 /* Mark the MCB as the last MCB */
524 Mcb->BlockType = 'Z';
525
527
529 return TRUE;
530}

Referenced by DosInt21h().