MQ--Memory Quarantine SYNOPSIS: (CLI environment) MQ [statusfile] DESCRIPTION: MQ makes addresses which cause memory errors unavailable to the system. It works by removing those memory locations from the system's memory free list so they appear to be allocated to another process. MQ is intended as a temporary fix for memory failures until you can replace the defective RAM chips. MQ runs from the Command Line Interface (CLI). It reads data from standard input and writes a status message to standard output. COMMAND LINE OPTIONS: MQ does not recognize any command line options. INPUT: MQ reads a list of addresses to be quarantined from standard input. The addresses must be in ascending order and expressed as ASCII characters representing hexadecimal values. There can be a maximum of 100 addresses. MQ will ignore any addresses beyond the first 100. If necessary additional addresses can be quarantined by running MQ again with a different list. MQ's companion program, MD (a memory diagnostic), can produce a file for direct input to MQ. OUTPUT: When MQ finishes it writes a status message to standard output. The message tells the number of bytes that were quarantined. EXECUTION: MQ's execution time is usually less than the time required to load the program. The entire process takes about a second. The recommended way to use MQ is to put it in your Startup-Sequence file. It should appear in the Startup-Sequence as early as possible. MQ will fragment memory so certain applications may have to be run before you can run MQ. For example, if you want a recoverable RAM disk (RAD:) you must have 880K of contiguous memory available. If MQ doesn't leave you with that large a block you can run MQ after you create your RAD: disk. You will have defective memory in the RAD: disk but if it is in a location that isn't accessed it will be harmless. Use MD to create a file of defective memory locations. Then copy that file to your Workbench disk. Add a line to your Startup-Sequence file invoking MQ with standard input redirected from the address list file. Then each time you boot your system the defective memory locations will be quarantined. PROGRAM LOGIC: MQ searches the system's memory free list to find each chunk of free memory which contains one or more of the bad addresses it reads from standard input. It modifies the memory free list so the bad addresses will be excluded. The smallest block of memory that can be allocated is eight bytes. Thus the memory free list loses eight bytes for each bad address that is quarantined. MQ does not keep track of the quarantined memory so there is no way to recover it without rebooting the system. As MQ examines each block of memory it goes through its list of bad addresses. If the block ends before the bad address MQ goes on to the next block. If the block starts after the bad address MQ gets the next address. If the bad address falls within the block MQ resizes the block to exclude it. Each block of memory is described by a MemChunk structure which contains a pointer to the next block and the size of the current block. The structure is defined in exec/memory.h as follows: /****** MemChunk ****************************************************/ struct MemChunk { struct MemChunk *mc_Next; /* pointer to next chunk */ ULONG mc_Bytes; /* chunk byte size */ }; MQ calculates the number of bytes between the start of the block and the bad address, then rounds it down to a multiple of 8. That will be the new size of the block. Let's call it Size1. Then it adds that size plus 8 to the beginning address of the block to get the starting address of a new block. We'll call it NewChunk. To calculate the size of the new block MQ adds 8 to Size1 and subtracts the result from the original block size. We'll call it Size2. Because the original block may be as small as 8 bytes and because the bad address may be within 8 bytes of either end of the block Size1 and Size2 may be zero. If Size2 is zero MQ simply reduces the size of the original block by storing Size1 in the original block's mc_Bytes field. Otherwise it creates a new block at NewChunk. Each block of memory contains a pointer to the next block (mc_Next) and the size of the current block (mc_Bytes). So MQ takes the next block pointer from the original block and puts it at NewChunk->mc_Next. Then it puts Size2 at NewChunk->mc_Bytes. If Size1 is zero MQ copies the address from the original block's mc_Next field to the mc_Next field of the previous block. If the previous block pointer is NULL the original block is the first one in the list. In that case MQ copies the mc_Next field from the original block to the mh_First field in the MemHeader structure. Send questions, comments, or bug reports to: --Fabbian Dufoe 350 Ling-A-Mor Terrace South St. Petersburg, Florida 33705 813-823-2350 UUCP: ...uunet!pdn!jc3b21!fgd3