<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9"> <TITLE>RVM: Recoverable Virtual Memory, Release 1.3: RDS, A Dynamic Heap Allocator for RVM </TITLE> <LINK HREF="rvm_manual-7.html" REL=next> <LINK HREF="rvm_manual-5.html" REL=previous> <LINK HREF="rvm_manual.html#toc6" REL=contents> </HEAD> <BODY> <A HREF="rvm_manual-7.html">Next</A> <A HREF="rvm_manual-5.html">Previous</A> <A HREF="rvm_manual.html#toc6">Contents</A> <HR> <H2><A NAME="RDS"></A> <A NAME="s6">6. RDS, A Dynamic Heap Allocator for RVM </A></H2> <P><EM>Designed and programmed by David C. Steere</EM> <P> <H2><A NAME="ss6.1">6.1 Introduction to RDS</A> </H2> <P> <P> <P>The Recoverable Dynamic Storage (RDS) library provides a heap similar to that of the C library, although with persistence, for RVM segments. Additional provisions for convenient initialization and reloading of the heap after shutdown or crash are included. <P>RDS uses the Quick Fit method </I>] for allocation. In this method, separate free lists are maintained for a specified number of sizes. Most programs tend to repeatedly allocate a small number of distinct sized blocks. Quick Fit avoids overhead by retaining those block sizes as long as possible in the expectation that they will be re-allocated when freed. Coalescing of adjacent free blocks is deferred until a request cannot be satisfied. <P>The free list sizes are integer multiples of the <EM>chunk size</EM>, which is specified when the recoverable heap is created and cannot be modified thereafter except by re-initializing the heap. The chunk size must be an integral multiple of <CODE>sizeof (char *)</CODE>, and be at least <CODE>RDS_MIN_CHUNK_SIZE</CODE>. The free lists are maintained in sizes of one chunk to <EM>n</EM> chunks, where <EM>n</EM> is the maximum number of free lists. The number of lists is also specified at heap creation and cannot be modified thereafter. <P>When an allocation request is made, the requested size is rounded up to an integral multiple of the chunk size. The free list for that size is checked first, and if not empty, the first block is returned. Otherwise, the next larger free list is checked, and if not empty, the first block is selected, the requested size split off, and the remainder placed on the appropriate free list. If the free list is empty, the next is searched. If no specific-sized free list can allocate the block, the request is taken from the single list of larger blocks by splitting the first block on the list. The remainder is returned to the appropriate free list. Sizes larger than <EM>n</EM> times the chunksize are also allocated from the large blocks list on a first-fit basis. This list is always created in addition to the fixed size lists. <P>When a block is freed, it is simply placed on the appropriate free list with no attempt coalesce it with adjacent free blocks. Coalescing is deferred until an allocation request can not be satisfied. <P>The allocation and deallocation functions, rds_malloc and rds_free, resemble malloc and free, although they are modified for transactions. To help prevent fragmentation, RDS also provides for pre-allocation of pools of block sizes that the application will repeatedly allocate with the function rds_prealloc. <P>The function rds_load_heap provides a convenient way to use the RVM segment loader to load the persistent heap and a statically allocated region. rds_load_heap will make the necessary RVM mapping calls and initialize RDS. When it completes, the allocations persistent data is ready for use. <P>Initialization of an RDS heap is done with the function rds_init_heap. A second function, rds_zap_heap, which calls rds_init_heap and rvm_create_segment, can be used to prepare a segment for loading via rds_load_heap. However, heap initialization is usually done with the utility rdsinit, which will prompt for the necessary parameters to call rds_zap_heap. <P>To assist in detecting buffer overruns and other memory clobbers, RDS puts special <EM>guard</EM> constants at the beginning and end of each block. These are not within the space allocated to satisfy an allocation request and will never be addressed by a correctly operating application. The rounding up of allocation request sizes to integral multiples of the chunk size automatically includes space for the guard constants. <P>If memory damage is detected by the corruption of one of the guards when a block is deallocated, or when damage to a free list is detected during allocation, the error code ECORRUPT is returned. If this error is detected during deallocation, the block is not put on a free list, but is left unmodified for analysis of how the overwrite occurred. <P>RDS generally returns error indications in a parameter whose address must be specified in the call. However, a few functions return the error code as their value. RDS error codes are all defined as negative integers in rds.h. Because RDS must perform its actions via transactions, the RVM error codes can also be returned in the error code parameter or as function values. These are defined in <CODE>rvm.h</CODE>, and are all positive values. Success is always indicated by the code SUCCESS, which is defined to be zero. <P>The header file giving all necessary definitions for RDS is included in Appendix <A HREF="rvm_manual-10.html#RVMheaders">of C declarations</A>. <P> <H2><A NAME="ss6.2">6.2 Transactions and RDS</A> </H2> <P> <P>All functions in RDS use RVM transactions. Some, particularly rds_malloc and rds_free, must interact with the applications transactions, requiring some care from the caller. RDS does not hold its lock until after commit so that greater concurrency can possibly be achieved in Coda. This is not generally recommended because it permits uncommitted state to be used by other than the calling transaction. See the notes on good programming practice with RVM, Section <A HREF="rvm_manual-2.html#GoodLocking">of Transactions in Critical Sections</A>. <P>Since the lock is not held until commit, some additional complexity must be introduced to insure that allocation and deallocation actions are independent. There are two cases that must be recognized: if the caller guarantees that no context swaps among application threads will occur before transaction commit, and if such swaps must be allowed. <P>If context swapsare avoided, the application can supply the transaction to be used by RDS in the allocation/deallocation calls and be sure that if the transaction must later be aborted, all will be restored correctly. The transaction must be started in restore mode, which is required for all RDS calls. The transaction will not be committed or aborted by RDS. <P>If context swaps must be allowed (frequently the case), a null transaction parameter must be specified. This will force an internal transaction to be created by RDS. This transaction will be committed by RDS before the function returns. In this case, if <CODE>rds_malloc</CODE> is called and the application transaction requesting the allocation must abort, the block must be explicitly deallocated by a call to rds_free. Otherwise, recoverable heap space will be lost. <P>When the application deallocates blocks in a transaction that could later abort and context swaps are possible, two special functions are provided, rds_fake_free and rds_do_free. These functions manage an <EM>intention list</EM> that records the intended deallocations, but defers the actual deallocation until the application transaction is ready to commit. If the transaction aborts, the intention list is discarded. The application must call rds_fake_free at the point where the block would logically be freed, and then call rds_do_free immediately before committing the application transaction. The application must provide the intention list header, of type <CODE>intentionList_t</CODE>; RDS will manage the actual list. <P>Note that these methods are safe <EM>only</EM> in a coroutine thread environment. If pre-emptive threads, or a multiprocessor, are required, RDS cannot safely be used. <P><HR> <P> <P> NAME <H3><A HREF="rvm_manual-2.html#GoodLocking">of Transactions in Critical Sections</A></H3> <P>rds_malloc - allocate from recoverable heap <P> SYNOPSIS <H3></H3> <P> <PRE> #include "rds.h" int rds_malloc (size, tid, err); unsigned long size; /* length of allocation request */ rvm_tid_t *tid; /* optional pointer to transaction identifier */ int *err; /* pointer to error return location */ </PRE> <P> DESCRIPTION <H3></H3> <P><CODE>rds_malloc</CODE> allocates from the recoverable heap a block large enough to hold the request, specified in bytes by the <CODE>size</CODE> parameter. The address of the allocated block is returned as type <CODE>int</CODE> and must be cast to the desired type. If the request cannot be satisfied, zero is returned, and the <CODE>err</CODE> parameter is set to the appropriate error code. <P>Because allocation actions in the recoverable heap must be done via transactions, <CODE>rds_malloc</CODE> offers two choices for the transaction. In the first case, <CODE>rds_malloc</CODE> can be instructed to use an existing transaction begun in <CODE>restore</CODE> mode, by passing the address of a valid <CODE>rvm_tid_t</CODE> record in the <CODE>tid</CODE> parameter. This avoids extra transaction start and commit overhead and provides automatic deallocation if the transaction must later abort. However, no context swap can be permitted between allocation and transaction commit or abort since the modified, but uncommitted, free lists are visible to other RDS actions. <P>If context swaps cannot be prohibited, or the available transaction was started in <CODE>no_restore</CODE> mode, the <CODE>tid</CODE> parameter should be set to null, instructing <CODE>rds_malloc</CODE> to start an internal transaction. This transaction will be committed in <CODE>no_flush</CODE> mode if the allocation is made, and aborted otherwise. In this case, an explicit <CODE>rds_free</CODE> must be done if the allocating transaction later aborts. <P> <P> DIAGNOSTICS <H3></H3> <P> <DL> <DT><B>SUCCESS</B><DD><P>success <DT><B>ENO_ROOM</B><DD><P>RDS heap exhausted <DT><B>ECORRUPT</B><DD><P>RDS heap damaged <DT><B>EHEAP_INIT</B><DD><P>RDS not initialized <DT><B>positive values</B><DD><P>RVM return codes </DL> <P> <P> SEE ALSO <H3></H3> <P><CODE>rds_free (3)</CODE> <P> <P> AUTHOR <H3></H3> <P>David C. Steere <P> <P> BUGS <H3></H3> <P>The internal synchronization is not valid with pre-emptive threads. <P> <P> <HR>NAME <H3></H3> <P>rds_free - return a block to the recoverable heap <P> SYNOPSIS <H3></H3> <P> <PRE> #include "rds.h" int rds_free (addr, tid, err) char *addr; /* address of block to be freed */ rvm_tid_t *tid; /* optional pointer to transaction identifier */ int *err; /* pointer to error return location */ </PRE> <P> DESCRIPTION <H3></H3> <P><CODE>rds_free</CODE> deallocates recoverable storage allocated by <CODE>rds_malloc</CODE>. The block to be deallocated is passed in the <CODE>addr</CODE> parameter. This block must not already be free, or the <CODE>EFREED_TWICE</CODE> error code will be returned in <CODE>err</CODE>. <P>Because deallocation actions in the recoverable heap must be done via transactions, <CODE>rds_free</CODE> offers two choices for the transaction. In the first case, <CODE>rds_free</CODE> can be instructed to use an existing transaction by passing the address of a valid <CODE>rvm_tid_t</CODE> record in the <CODE>tid</CODE> parameter. This avoids extra transaction start and commit overhead and provides automatic reallocation if the transaction must later abort. <P>If the available transaction was started in <CODE>no_restore</CODE> mode, the <CODE>tid</CODE> parameter should be set to null, instructing <CODE>rds_free</CODE> to start an internal transaction. This transaction will be committed in <CODE>no_flush</CODE> mode if the allocation is made, and aborted otherwise. <P>In neither case can context swaps be permitted between deallocation and transaction commit or abort since the modified, but uncommitted, free lists are visible to other RDS actions. If this condition cannot be met, or if there is a possibility that the transaction will abort, the functions <CODE>rds_fake_free</CODE> and <CODE>rds_do_free</CODE> must be used. <P> <P> DIAGNOSTICS <H3></H3> <P> <DL> <DT><B>SUCCESS</B><DD><P>success <DT><B>EFREED_TWICE</B><DD><P>block is already free <DT><B>ECORRUPT</B><DD><P>RDS heap damaged <DT><B>EBAD_ARGS</B><DD><P>block is not on 4 byte boundary <DT><B>EHEAP_INIT</B><DD><P>RDS not initialized <DT><B>positive values</B><DD><P>RVM return codes </DL> <P> <P> SEE ALSO <H3></H3> <P><CODE>rds_malloc (3)</CODE>, <CODE>rds_fake_free (3)</CODE>, <CODE>rds_do_free (3)</CODE> <P> <P> AUTHOR <H3></H3> <P>David C. Steere <P> <P> BUGS <H3></H3> <P>The internal synchronization is not valid with pre-emptive threads. <P> <P> <HR>NAME <H3></H3> <P>rds_fake_free - deferred return of blocks to the recoverable heap <P> SYNOPSIS <H3></H3> <P> <PRE> #include "rds.h" typedef struct intlist { unsigned long size; unsigned long count; char **table; } intentionList_t; int rds_fake_free(addr, list); char *addr; /* address of block to be freed */ intentionList_t *list; /* pointer to intention list */ int rds_do_free(addr, list); intentionList_t *list; /* pointer to intention list */ rvm_mode_t mode; /* transaction commit mode */ </PRE> <P> DESCRIPTION <H3></H3> <P>In cases where the application must free recoverable storage without knowing whether the transaction will later abort, <CODE>rds_free</CODE> should not be used since the internal free list lock is not held until commit or abort. To handle these cases, RDS allows the creation of an <EM>intention list</EM> for the blocks to be freed. At the point where the block would logically be freed, <CODE>rds_fake_free</CODE> is called to place the block on the intention list. To actually free the blocks on the intention list, <CODE>rds_do_free</CODE> is called. This must be done immediately before calling <CODE>rvm_end_transaction</CODE> for the deallocating transaction, and must not be done if <CODE>rvm_abort_transaction</CODE> is called. Also, no context swaps can be allowed between the calls on <CODE>rds_do_free</CODE> and <CODE>rvm_end_transaction</CODE>. <P>The intention list header (type <CODE>intentionList_t</CODE>) must be provided by the application. The <CODE>table</CODE> field must be null on the first call to <CODE>rds_fake_free</CODE>. RDS will allocate space as necessary for the blocks to be freed. <CODE>rds_do_free</CODE> will deallocate the <CODE>table</CODE> vector. The application is responsible for deallocation of <CODE>table</CODE> if the transaction is aborted. Deallocation of the <CODE>intentionList_t</CODE> itself is always the responsibility of the application. RDS does not internally synchronize access to the intention list. If more than one thread is involved in the transaction, synchronization of access to the intention list is the responsibility of the application. <P>The block to be deallocated is passed in the <CODE>addr</CODE> parameter to <CODE>rds_fake_free</CODE> . This block must not already be free, or the <CODE>EFREED_TWICE</CODE> error code will be returned. The <CODE>ECORRUPT</CODE> error return is given by <CODE>rds_fake_free</CODE> if the block guards are damaged. <CODE>rds_do_free</CODE> returns this code if internal damage to the free lists is found. <P>These functions return error codes as the value of the function rather than in a parameter. <P> <P> DIAGNOSTICS <H3></H3> <P> <DL> <DT><B>SUCCESS</B><DD><P>success <DT><B>EFREED_TWICE</B><DD><P>block is already free <DT><B>ECORRUPT</B><DD><P>block or heap damaged <DT><B>EBAD_ARGS</B><DD><P>block is not on 4 byte boundary <DT><B>EHEAP_INIT</B><DD><P>RDS not initialized <DT><B>positive values</B><DD><P>RVM return codes </DL> <P> <P> SEE ALSO <H3></H3> <P><CODE>rds_free (3)</CODE>, <CODE>rds_malloc (3)</CODE> <P> <P> AUTHOR <H3></H3> <P>David C. Steere <P> <P> <HR>NAME <H3></H3> <P>rds_init_heap - initialize a recoverable heap <P> SYNOPSIS <H3></H3> <P> <PRE> #include "rds.h" int rds_init_heap (base, length, chunkSize, nlists, tid, err) char *base; /* base address of heap */ unsigned long length; /* length of heap */ unsigned long chunkSize; /* size of allocation unit */ unsigned long nlists; /* number of allocation lists */ rvm_tid_t *tid; /* pointer to transaction identifier */ int *err; /* pointer to error return location */ </PRE> <P> DESCRIPTION <H3></H3> <P><CODE>rds_init_heap</CODE> initializes a recoverable heap in the previously mapped memory region specified by the address <CODE>base</CODE> and <CODE>length</CODE> parameters. Allocation requests will be rounded up to an integral number of allocation units <CODE>chunkSize</CODE>, which is specified in bytes, and must be an integral multiple of <CODE>sizeof (char *)</CODE>, and be at least <CODE>RDS_MIN_CHUNK_SIZE</CODE>. <P>For rapid allocation, RDS maintains separate allocation lists for blocks of different sizes. The sizes are integrals of <CODE>chunkSize</CODE>, beginning with 1 and extending to the number of lists specified by <CODE>nlists</CODE>, which must be at least <CODE>RDS_MIN_FREE_LISTS</CODE>. These lists are initially empty and the entire heap is placed on the large block list as a single block. <CODE>rds_malloc</CODE> will split this block as required. <P>If a number of blocks of specific sizes are required by the application, the function <CODE>rds_prealloc</CODE> is provided for efficient pre-allocation. It should be called immediately after initializing the heap. <P>An active transaction must be specified in the <CODE>tid</CODE> parameter; RDS will not create an internal transaction for this function. This transaction must be committed by the application for the initialization to be permanent. <P>Since this function is called only to initialize the heap, RDS assumes there is no concurrent access and does no internal locking. <P> <P> DIAGNOSTICS <H3></H3> <P> <DL> <DT><B>SUCCESS</B><DD><P>success <DT><B>ENO_ROOM</B><DD><P>heap length not long enough for heap structures <DT><B>EBAD_CHUNK_SIZE</B><DD><P>the chunk size is not large enough or is not a multiple of sizeof(char *) <DT><B>EBAD_LIST_LENGTH</B><DD><P>the number of free lists is not at least RDS_MIN_FREE_LISTS <DT><B>positive values</B><DD><P>RVM return codes </DL> <P> <P> SEE ALSO <H3></H3> <P><CODE>rds_zap_heap (3)</CODE>, <CODE>rds_prealloc (3)</CODE> <P> <P> AUTHOR <H3></H3> <P>David C. Steere <P> <P> <HR>NAME <H3></H3> <P>rds_load_heap, rds_start_heap - map recoverable storage <P> SYNOPSIS <H3></H3> <P> <PRE> #include "rds.h" int rds_load_heap (DevName, DevLength, staticAddr, err); char *DevName; /* name of heap segment */ rvm_length_t DevLength; /* length of heap raw partition */ char **staticAddr; /* address of static region (out)*/ int *err; /* pointer to error return location */ int rds_start_heap (staticAddr, err); char **staticAddr; /* address of static region (out)*/ int *err; /* pointer to error return location */ </PRE> <P> DESCRIPTION <H3></H3> <P><CODE>rds_load_heap</CODE> provides a convenient method of mapping the heap segment and initializing RDS. The name of the file or partition containing the recoverable heap is specified by <CODE>DevName</CODE>, and the length of the partition is specified in <CODE>DevLength</CODE>. If the heap is in a file, <CODE>DevLength</CODE> should be zero. <P><CODE>rds_load_heap</CODE> calls <CODE>rvm_load_segment</CODE> to map the heap. This requires that the heap file or partition be created with <CODE>rds_zap_heap</CODE> or <CODE>rvm_create_segment</CODE>, which is most conveniently done with the <CODE>rdsinit</CODE> utility. After the heap is mapped, the address of the static region is returned in <CODE>staticAddr</CODE>. <CODE>rds_start_heap</CODE> is automatically called to initialize RDS. <P>If the actual mapping of the heap and static regions is done by the application, <CODE>rds_start_heap</CODE> should be used to initialize RDS. In this case, the address of the static region must be specified to RDS in the <CODE>staticAddr</CODE> parameter. <P>With either function, the version of RDS that the heap was built with is compared with the version of the currently linked RDS library. If there is a mismatch, the error code <CODE>EHEAP_VERSION_SKEW</CODE> is returned. <P>Since these functions are called only to initialize the application, RDS assumes there is no concurrent access and does no internal locking. <P> <P> DIAGNOSTICS <H3></H3> <P> <DL> <DT><B>SUCCESS</B><DD><P>success <DT><B>EHEAP_VERSION_SKEW</B><DD><P>RDS heap and library have different versions <DT><B>positive values</B><DD><P>RVM return codes </DL> <P> <P> SEE ALSO <H3></H3> <P><CODE>rvm_load_segment (3)</CODE>, <CODE>rvm_map (3)</CODE>, <CODE>rdsinit (1)</CODE> <P> <P> AUTHOR <H3></H3> <P>David C. Steere <P> <P> <HR>NAME <H3></H3> <P>rds_zap_heap - initialize an RVM segment as an RDS heap <P> SYNOPSIS <H3></H3> <P> <PRE> #include "rds.h" int rds_zap_heap (DevName, DevLength, startAddr, staticLength, heapLength, nlists, chunkSize, err) char *DevName; /* name of heap segment */ rvm_length_t DevLength; /* length of heap raw partition */ char *startAddr;/* base address of heap */ rvm_length_t staticLength; /* length of static region */ rvm_length_t heapLength;/* length of heap region */ unsigned long nlist; /* number of allocation lists */ unsigned long chunkSize; /* size of allocation unit */ int *err; /* pointer to error return location */ </PRE> <P> DESCRIPTION <H3></H3> <P><CODE>rds_zap_heap</CODE> prepares a recoverable heap for loading by <CODE>rds_load_heap</CODE>. Two regions are created in the heap segment named by <CODE>DevName</CODE>, one for the applications statically allocated region and one for the recoverable heap. The lengths of the regions, specified by <CODE>staticLength</CODE> and <CODE>heapLength</CODE>, must be integrals of the system page size. The heap region is allocated at <CODE>*startAddr</CODE> in virtual memory, which must be on a page boundary. This address is the permanent address of the heap. The static region starts at <CODE>*startAddr</CODE> + <CODE>heapLength</CODE> and is also permanent. One additional region is created at the beginning of the segment for the segment header, and is one page long. This region is only temporarily mapped by <CODE>rds_load_heap</CODE>. The heap region follows the header in the segment, and the static region follows the heap. <P>If the segment is represented by a raw partition, the maximum usable length of the partition must be specified in <CODE>DevLength</CODE>. For files, this length should be zero. <P>The region of virtual memory for the heap and static regions should not be allocated by the application. <CODE>rds_zap_heap</CODE> uses the RVM segment utilities to build the segment header and map the regions. When <CODE>rds_zap_heap</CODE> is complete, the memory will be mapped. <P><CODE>rds_zap_heap</CODE> uses <CODE>rvm_create_segment</CODE> to build the segment, and then calls <CODE>rds_init_heap</CODE> to initialize the free lists as specified by the <CODE>nlists</CODE> and <CODE>chunkSize</CODE> parameters. <CODE>chunkSize</CODE> is specified in bytes, and must be an integral multiple of <CODE>sizeof (char *)</CODE>, and be at least <CODE>RDS_MIN_CHUNK_SIZE</CODE>. The number of free lists must be at least <CODE>RDS_MIN_FREE_LISTS</CODE>. The transaction required by <CODE>rds_init_heap</CODE> is created and terminated internally. <P>If a number of blocks of specific sizes are required by the application, the function <CODE>rds_prealloc</CODE> is provided for efficient pre-allocation. It should be called immediately after initializing the heap. <P>The utility <CODE>rdsinit</CODE> is usually used to create recoverable heap segments. It prompts for the parameters and calls <CODE>rds_zap_heap</CODE>. <P>Since this function is called only to initialize the heap, RDS assumes there is no concurrent access and does no internal locking. <P> <P> DIAGNOSTICS <H3></H3> <P> <DL> <DT><B>SUCCESS</B><DD><P>success <DT><B>ENO_ROOM</B><DD><P>heap length not long enough for header <DT><B>EBAD_CHUNK_SIZE</B><DD><P>the chunk size is not large enough or is not a muliple of <CODE>sizeof(char *)</CODE> <DT><B>EBAD_LIST_LENGTH</B><DD><P>the number of free lists is not at least <CODE>RDS_MIN_FREE_LISTS</CODE> <DT><B>positive values</B><DD><P>RVM return codes </DL> <P> SEE ALSO <H3></H3> <P><CODE>rds_init_heap (3)</CODE>, <CODE>rds_load_heap (3)</CODE>, <CODE>rvm_create_segment (3)</CODE>, <CODE>rvm_load_segment (3)</CODE>, <CODE>rdsinit (1)</CODE>, <CODE>rds_prealloc (3)</CODE> <P> <P> AUTHOR <H3></H3> <P>David C. Steere <P> <P> <HR>NAME <H3></H3> <P>rds_prealloc - initialize allocation pools <P> SYNOPSIS <H3></H3> <P> <PRE> #include "rds.h" int rds_prealloc (size, nblocks, tid, err) unsigned long size; /* size of allocation request */ unsigned long nblocks; /* length of allocation request */ rvm_tid_t *tid; /* pointer to transaction identifer */ int *err; /* pointer to error return location */ </PRE> <P> DESCRIPTION <H3></H3> <P><CODE>rds_prealloc</CODE> assists applications in minimizing heap fragmentation by pre-allocating pools of blocks in sizes that the application is known to use in relatively large numbers. <CODE>rds_prealloc</CODE> is best called immediately after the heap is initialized, although it can be called anytime. When pools of several block sizes are pre-allocated, they should be allocated in increasing block size order so that the larger blocks are not split to make the smaller. <P>The <CODE>size</CODE> parameter specifies the size, in bytes, of the blocks to be pre-allocated, and <CODE>nblocks</CODE> controls the number of blocks pre-allocated. <P>Because allocation actions in the recoverable heap must be done via transactions, <CODE>rds_prealloc</CODE> offers two choices for the transaction. In the first case, <CODE>rds_prealloc</CODE> can be instructed to use an existing transaction begun in <CODE>restore</CODE> mode, by passing the address of a valid <CODE>rvm_tid_t</CODE> record in the <CODE>tid</CODE> parameter. This avoids extra transaction start and commit overhead and provides automatic deallocation if the transaction must later abort. However, no context swap can be permitted between allocation and transaction commit or abort since the uncommitted state is visible to other allocations. <P>If context swaps cannot be prohibited, or the available transaction was started in <CODE>no_restore</CODE> mode, the <CODE>tid</CODE> parameter should be set to null, instructing <CODE>rds_prealloc</CODE> to start an internal transaction. This transaction will be committed in <CODE>no_flush</CODE> mode if the allocation is made, and aborted otherwise. In this case, if the allocating transaction later aborts, the pre-allocated blocks remain allocated. <P> <P> DIAGNOSTICS <H3></H3> <P> <DL> <DT><B>SUCCESS</B><DD><P>success <DT><B>ENO_ROOM</B><DD><P>RDS heap exhausted <DT><B>ECORRUPT</B><DD><P>RDS heap damaged <DT><B>EHEAP_INIT</B><DD><P>RDS not initialized <DT><B>positive values</B><DD><P>RVM return codes </DL> <P> <P> SEE ALSO <H3></H3> <P><CODE>rds_malloc(3)</CODE>, <CODE>rds_init_heap(3)</CODE>, <CODE>rds_zap_heap(3)</CODE> <P> <P> AUTHOR <H3></H3> <P>David C. Steere <P> <P> BUGS <H3></H3> <P>The internal synchronization is not valid with pre-emptive threads. <P> <P> <HR>NAME <H3></H3> <P>rds_get_stats, rds_clear_stats, rds_print_stats - RDS statistics functions <P> SYNOPSIS <H3></H3> <P> <PRE> #include "rds.h" int rds_get_stats (stats); rds_stats_t *stats; /* pointer to RDS statistics record */ int rds_clear_stats (err); int *err; /* pointer to error return location */ int rds_print_stats(); </PRE> <P> DESCRIPTION <H3></H3> <P>RDS maintains simple statistics about the recoverable heap and the allocations performed. The statistics area is kept in the recoverable heap region and is initialized when the heap is initialized. <P>The statistics can be read by <CODE>rds_get_stats</CODE> into an <CODE>rds_stats_t</CODE> record for analysis by the application, or printed on <CODE>stdout</CODE> by <CODE>rds_print_stats</CODE>. <CODE>rds_get_stats (stats)</CODE> and <CODE>rds_print_stats ()</CODE> return error codes as the value of the function rather than in a parameter. <P>After heap initialization, the statistics area can be cleared by calling <CODE>rds_clear_stats</CODE>. <CODE>rds_clear_stats</CODE> simply zeroes the statistics area via an internal transaction. The space allocated and free counts will not be accurate if it is called after initializing the RDS heap. Note that <CODE>rds_clear_stats</CODE> requires an error return code as a parameter, while the others return the error status as the function value. <P>RDS performs no internal synchronization for these calls, so if there is a possibility of concurrent access to the statistics, the accesses must be serialized by the application. <P> <P> DIAGNOSTICS <H3></H3> <P> <DL> <DT><B>SUCCESS</B><DD><P>success <DT><B>EHEAP_INIT</B><DD><P>RDS not initialized <DT><B>EBAD_ARGS</B><DD><P>null RDS statistics record pointer </DL> <P> <P> AUTHOR <H3></H3> <P>David C. Steere <P> <P> <HR>NAME <H3></H3> <P>rdsinit - RDS heap initialization utility <P> SYNOPSIS <H3></H3> <P> <P><B>rdsinit</B> <EM>log</EM> <EM>data_seg</EM> <P><B>rdsinit</B> <EM>log</EM> <EM>data_seg</EM> <EM>datalen</EM> <EM>saddr</EM> <EM>hlen</EM> <EM>slen</EM> <EM>nl</EM> <EM>chunk</EM> <P><B>rdsinit</B> <EM>-f</EM> <EM>log</EM> <EM>data_seg</EM> <EM>datalen</EM> <EM>saddr</EM> <EM>hlen</EM> <EM>slen</EM> <EM>nl</EM> <EM>chunk</EM> <P> <P> DESCRIPTION <H3></H3> <P><CODE>rdsinit</CODE> is a utility that constructs an initialized RDS heap in an RVM segment. It is intended to create a structure that can be loaded by <CODE>rds_load_heap</CODE>. <P>There are three different ways of using rdsinit. General users are expected to use first two interactive modes, where users may supply parameters for the rds heap interactively or on command line arguments. However, in both cases, users will be asked interactively to confirm their choice of parameters before rdsinit goes ahead to make any permanent change. These are the preferred modes of using rdsinit. Script writers, however, may prefer to supply all the parameters on the command line and <EM>no</EM> confirmation required for those parameters. This is accomodate in the third mode where an additional switch of -f (firm) is supplied on the command line. <P>In any case, two command-line parameters are always required: <CODE>log</CODE> and <CODE>data_seg</CODE>. The former is the name of the RVM log, which must have previously been initialized by <CODE>rvmutl</CODE>; the latter is the name of the data segment that will be initialized with an RDS heap. If either is missing, a command line error is printed. If the log has not been initialized, an RVM error will result. A short message indicating RVM initialization succeeded is then printed. Both the log and data segment can be regular files or raw partitions. <P>After the name of log and data segment, there are six other numeric parameters required. They are summarized here and will be explained one by one in the following paragraphs: <P> <DL> <DT><B>datalen</B><DD><P>Length of data segment <DT><B>saddr</B><DD><P>Starting address of rvm <DT><B>hlen</B><DD><P>Heap region length <DT><B>slen</B><DD><P>Static region length <DT><B>nl</B><DD><P>Number of lists of free block <DT><B>chunk</B><DD><P>Chunk size </DL> <P>While entering these six numeric parameters, either on command line on via the interactive prompt, users may use numeric number in hexadecimal, decimal or even octal notation. Hexadecimal numbers are preceeded by <CODE>Ox</CODE>, decimal numbers are preceeded by nothing and octal numbers are preceded by <CODE>0</CODE>. <P>Special note for long time rdsinit user: the old rdsinit automatically assumed <CODE>saddr</CODE>, <CODE>hlen</CODE> and <CODE>slen</CODE> parameters supplied on command lines are in hexidecimal and <EM>did not</EM> require the prefix <CODE>0x</CODE>. <EM>This is no longer true with this version of rdsinit.</EM> <P>Users specify the length of the data segment with the parameter <EM>datalen</EM>. Again, old version of rdsinit did not require this parameter if the data segment was a regular file and it existed already at the time of running rdsinit. This special case is eliminated: <EM>length of data segment must to be supplied in all circumstances.</EM> <P>Starting address of rvm, or <EM>saddr</EM>, is where heap and static region will be mapped into virtual memory. Heap region is located right at the starting address, while static region is located at starting address plus heap region length. Users may need to have some knowledges of the overall layout of the virtual memory use by the system before they can make the right choice of starting address. For example, the starting address of rvm must be much larger than the largest possible break point of your application, and it should not be in conflict other uses of virtual memory (such as use by shared libraries). It must also be on a page boundary. In CMU, we use 0x20000000 (536870912) with Linux and BSD44, or 0x70000000 (1879048192) with Mach. It is possible to choose other values, but you have to choose them carefully. <P>Length of regions of heap and static are specified by the parameter <EM>hlen</EM> and <EM>slen</EM> respectively. They both must be integral multiple of pagesize of the system. Also, the combined length of the two regions must be smaller than the length of data segment minus one extra page. <P>Note that the above three parameters: saddr, hlen, slen, are permanent. They can't be changed without re-initizing (and brain-wiping) the data segment. <P>The next two parameters: <EM>nl</EM> and <EM>chunk</EM> are related to underlying structure of management of the heap. RDS uses the Quick Fit method for heap allocation. In this method, free blocks are maintained by a number of free lists, each list for one particular size of free blocks. Specifically, there will be <CODE>nl</CODE> free lists, and each of them will have free blocks of size <CODE>1..nl</CODE> chunk respectively. <P>Chunk size must be integral multiple of <CODE>sizeof(char *)</CODE>, and be at least <CODE>RDS_MIN_CHUNK_SIZE</CODE>. Number of lists must be at least <CODE>RDS_MIN_FREE_LISTS</CODE>. For example, a reasonable choice is to have 100 free list with chunk size 32 bytes. <P>Once all the parameters are chosen, rdsinit will ask user for confirmation before it goes ahead and make permanent change on the log and data segment. Note in the following example that those numerical arguments are presented in both hexidecimal and decimal (in bracket). It is safe to quit at this point and no permanent changes will be made. <PRE> The following parameters are chosen: length of data segment: 0xf5000 ( 1003520) starting address of rvm: 0x20000000 ( 536870912) heap len: 0xf0000 ( 983040) static len: 0x4000 ( 16384) nlists: 0x64 ( 100) chunk size: 0x20 ( 32) Do you agree with these parameters ? (y|n|q) y </PRE> <P>If user supplied the -f (firm) switch on command line, this last confirmation will not show up. <P> <P> SEE ALSO <H3></H3> <P><CODE>rds_init_heap (3)</CODE>, <CODE>rds_load_heap (3)</CODE>, <CODE>rds_zap_heap (3)</CODE>, <CODE>rvm_create_segment (3)</CODE>, <CODE>rvm_load_segment (3)</CODE>, <CODE>rvmutl (1)</CODE> <P> <P> AUTHOR <H3></H3> <P>David C. Steere, created man page <P>Yui W. Lee, modified (Sept 1997) <P> <P> <HR> <HR> <A HREF="rvm_manual-7.html">Next</A> <A HREF="rvm_manual-5.html">Previous</A> <A HREF="rvm_manual.html#toc6">Contents</A> </BODY> </HTML>