2013-11-24

2013-11-24 Doom Progress

Continuing my work on porting Doom ... actually, that isn't really fair.  I'm not making Doom work with my OS, I'm writing my OS to work for Doom, semantics.

Continuing my work on my OS, Doom is locating and opening the wad file now.  It uses the effectively finished path of Program -> C Library -> Kernel API -> DOS Layer -> File-system -> Block Device to locate the file and open it.  Still happy with that set-up.

Doom is, however, complaining that the wad file doesn't have the correct signature.  That may have something to do with not having connected the read() function into the DOS layer ... there, fixed.

The kernel is now exploding (technical term), screen gibberish and inconsistent results.  After an hour or so of debugging, I've tracked down the two causes:

  1. Doom was allocating 36k of memory on the stack ... the stack is only 16k in size.  The rest of the space was overwriting the kernel ... d'oh!  (Makes stack bigger ... shhhh!)
  2. It appears as if all the remaining memory in the memory allocator is being used suddenly, causing an out-of-memory situation.
Another hour of debugging later and I've found the problem.  Every allocation of memory has a header and a footer.  They both include information such as the length of the block, a magic number (to help detect overflows), and a flag which indicates if the block is currently used or free.


When freeing a block, the memory allocator looks to see if the block being freed and the preceding block can be combined to make a bigger free block, then does the same for the following block.  It examines the footer of the preceding block (which is immediately before the header of the block being freed, obviously) to see if that block is free.  If so, it uses the length stored in the tail of the preceding block to find the header of the preceding block, then updates everything to combine them.  The bug was that in one circumstance, the tail pointer free flag was not being set which created a block where one flag said it was free and the other said it wasn't.  :(

The allocator looked at the previous tail flag and it said the block was free, so it dutifully added the length of the block being freed onto the previous block.  Seeing that the following block was also free (the following block being all the remaining free memory on the system), it added that in as well to make one big contiguous free block ... except that the previous block wasn't free.  The tail flag said it was free, the head flag said it was in use.  In a flash, freeing a block of memory had consumed every available byte of memory  :(

Easy to fix, I'm glad that it happened now, and I'm glad that my memory allocator has one fewer bug in it.

Doom approves of my fix:

Loading Operating System ...
Kernel Initialised
Loading ELF library

                            DOOM Registered Startup v1.10

V_Init: allocate screens.
M_LoadDefaults: Load system defaults.
dos_openFile: Opening "devdatadefault.cfg".
Could not find the device.
Z_Init: Init zone memory allocation daemon.
W_Init: Init WADfiles.
dos_openFile: Opening "DH1:Doom/base/doom.wad".
 adding DH1:Doom/base/doom.wad
===========================================================================
                 Commercial product - do not distribute!
         Please report software piracy to the SPA: 1-800-388-PIR8
===========================================================================
M_Init: Init miscellaneous info.
R_Init: Init DOOM refresh daemon - Error: W_GetNumForName: PNAMES not found!
Exited!

Next time:  Investigating what PNAMES is and why it wasn't found.

1 comment:

  1. Your quote: "Doom was allocating 36k of memory on the stack ... the stack is only 16k in size. The rest of the space was overwriting the kernel ... d'oh! (Makes stack bigger ... shhhh!)" was great :) Do you intend to implement stack cookies?

    ReplyDelete