Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

efence.c File Reference

#include "efence.h"
#include <stdlib.h>
#include <unistd.h>
#include <memory.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <signal.h>

Go to the source code of this file.


Data Structures

struct  _Slot

Defines

#define MEMORY_CREATION_SIZE   1024 * 1024
#define NUMBER_BUFFER_SIZE   64

Typedefs

typedef enum _Mode Mode
typedef _Slot Slot

Enumerations

enum  _Mode {
  NOT_IN_USE = 0, FREE, ALLOCATED, PROTECTED,
  INTERNAL_USE
}

Functions

void internalError (void)
void initialize (void)
void allocateMoreSlots (void)
C_LINKAGE void * memalign (size_t alignment, size_t userSize)
SlotslotForUserAddress (void *address)
SlotslotForInternalAddress (void *address)
SlotslotForInternalAddressPreviousTo (void *address)
C_LINKAGE void free (void *address)
C_LINKAGE void * realloc (void *oldBuffer, size_t newSize)
C_LINKAGE void * malloc (size_t size)
C_LINKAGE void * calloc (size_t nelem, size_t elsize)
C_LINKAGE void * valloc (size_t size)
const char * stringErrorReport (void)
void * Page_Create (size_t size)
void mprotectFailed (void)
void Page_AllowAccess (void *address, size_t size)
void Page_DenyAccess (void *address, size_t size)
void Page_Delete (void *address, size_t size)
int getpagesize ()
size_t Page_Size (void)
void printNumber (unsigned int number, unsigned int base)
void vprint (const char *pattern, va_list args)
void EF_Abort (const char *pattern,...)
void EF_Exit (const char *pattern,...)
void EF_Print (const char *pattern,...)

Variables

const char version []
int EF_ALIGNMENT = -1
int EF_PROTECT_FREE = -1
int EF_PROTECT_BELOW = -1
int EF_ALLOW_MALLOC_0 = -1
SlotallocationList = 0
size_t allocationListSize = 0
size_t slotCount = 0
size_t unUsedSlots = 0
size_t slotsPerPage = 0
int internalUse = 0
int noAllocationListProtection = 0
size_t bytesPerPage = 0
caddr_t startAddr = (caddr_t) 0
int sys_nerr
char * sys_errlist []

Define Documentation

#define MEMORY_CREATION_SIZE   1024 * 1024
 

Definition at line 53 of file efence.c.

Referenced by initialize(), and memalign().

#define NUMBER_BUFFER_SIZE   64
 

Definition at line 954 of file efence.c.

Referenced by printNumber().


Typedef Documentation

typedef enum _Mode Mode
 

Definition at line 65 of file efence.c.

Referenced by main(), SUMA_CreateFileSelectionDialogStruct(), SUMA_CreatePromptDialogStruct(), and SUMA_SetCellEditMode().

typedef struct _Slot Slot
 

Definition at line 78 of file efence.c.


Enumeration Type Documentation

enum _Mode
 

Enumeration values:
NOT_IN_USE 
FREE 
ALLOCATED 
PROTECTED 
INTERNAL_USE 

Definition at line 58 of file efence.c.

00058            {
00059         NOT_IN_USE = 0, /* Available to represent a malloc buffer. */
00060         FREE,           /* A free buffer. */
00061         ALLOCATED,      /* A buffer that is in use. */
00062         PROTECTED,      /* A freed buffer that can not be allocated again. */
00063         INTERNAL_USE    /* A buffer used internally by malloc(). */
00064 };

Function Documentation

void allocateMoreSlots void    [static]
 

Definition at line 306 of file efence.c.

References allocationListSize, bytesPerPage, free, internalUse, malloc, noAllocationListProtection, Page_AllowAccess(), slotCount, slotsPerPage, and unUsedSlots.

Referenced by memalign().

00307 {
00308         size_t  newSize = allocationListSize + bytesPerPage;
00309         void *  newAllocation;
00310         void *  oldAllocation = allocationList;
00311 
00312         Page_AllowAccess(allocationList, allocationListSize);
00313         noAllocationListProtection = 1;
00314         internalUse = 1;
00315 
00316         newAllocation = malloc(newSize);
00317         memcpy(newAllocation, allocationList, allocationListSize);
00318         memset(&(((char *)newAllocation)[allocationListSize]), 0, bytesPerPage);
00319 
00320         allocationList = (Slot *)newAllocation;
00321         allocationListSize = newSize;
00322         slotCount += slotsPerPage;
00323         unUsedSlots += slotsPerPage;
00324 
00325         free(oldAllocation);
00326 
00327         /*
00328          * Keep access to the allocation list open at this point, because
00329          * I am returning to memalign(), which needs that access.
00330          */
00331         noAllocationListProtection = 0;
00332         internalUse = 0;
00333 }

C_LINKAGE void* calloc size_t    nelem,
size_t    elsize
 

Definition at line 751 of file efence.c.

References malloc.

00752 {
00753         size_t  size = nelem * elsize;
00754         void *  allocation = malloc(size);
00755 
00756         memset(allocation, 0, size);
00757         return allocation;
00758 }

void EF_Abort const char *    pattern,
...   
 

Definition at line 1045 of file efence.c.

References args, EF_Print(), getpid(), and vprint().

Referenced by free(), internalError(), memalign(), printNumber(), and realloc().

01046 {
01047         va_list args;
01048 
01049         va_start(args, pattern);
01050 
01051         EF_Print("\nElectricFence Aborting: ");
01052         vprint(pattern, args);
01053         EF_Print("\n");
01054 
01055         va_end(args);
01056 
01057         /*
01058          * I use kill(getpid(), SIGILL) instead of abort() because some
01059          * mis-guided implementations of abort() flush stdio, which can
01060          * cause malloc() or free() to be called.
01061          */
01062         kill(getpid(), SIGILL);
01063         /* Just in case something handles SIGILL and returns, exit here. */
01064         _exit(-1);
01065 }

void EF_Exit const char *    pattern,
...   
 

Definition at line 1068 of file efence.c.

References args, EF_Print(), and vprint().

Referenced by mprotectFailed(), Page_Create(), and Page_Delete().

01069 {
01070         va_list args;
01071 
01072         va_start(args, pattern);
01073 
01074         EF_Print("\nElectricFence Exiting: ");
01075         vprint(pattern, args);
01076         EF_Print("\n");
01077 
01078         va_end(args);
01079 
01080         /*
01081          * I use _exit() because the regular exit() flushes stdio,
01082          * which may cause malloc() or free() to be called.
01083          */
01084         _exit(-1);
01085 }

void EF_Print const char *    pattern,
...   
 

Definition at line 1088 of file efence.c.

References args, and vprint().

Referenced by EF_Abort(), EF_Exit(), initialize(), and vprint().

01089 {
01090         va_list args;
01091 
01092         va_start(args, pattern);
01093         vprint(pattern, args);
01094         va_end(args);
01095 }

C_LINKAGE void free void *    address
 

Definition at line 618 of file efence.c.

References ALLOCATED, allocationListSize, EF_Abort(), FREE, INTERNAL_USE, _Slot::internalAddress, _Slot::internalSize, internalUse, _Slot::mode, noAllocationListProtection, NOT_IN_USE, Page_AllowAccess(), Page_Delete(), Page_DenyAccess(), PROTECTED, slotForInternalAddress(), slotForInternalAddressPreviousTo(), slotForUserAddress(), unUsedSlots, _Slot::userAddress, and _Slot::userSize.

00619 {
00620         Slot *  slot;
00621         Slot *  previousSlot = 0;
00622         Slot *  nextSlot = 0;
00623 
00624         if ( address == 0 )
00625                 EF_Abort("free() called for address zero.");
00626 
00627         if ( allocationList == 0 )
00628                 EF_Abort("free() called before first malloc().");
00629 
00630         if ( !noAllocationListProtection )
00631                 Page_AllowAccess(allocationList, allocationListSize);
00632 
00633         slot = slotForUserAddress(address);
00634 
00635         if ( !slot )
00636                 EF_Abort("free(%x): address not from malloc().", address);
00637 
00638         if ( slot->mode != ALLOCATED ) {
00639                 if ( internalUse && slot->mode == INTERNAL_USE )
00640                         /* Do nothing. */;
00641                 else {
00642                         EF_Abort(
00643                          "free(%x): freeing free memory."
00644                         ,address);
00645                 }
00646         }
00647 
00648         if ( EF_PROTECT_FREE )
00649                 slot->mode = PROTECTED;
00650         else
00651                 slot->mode = FREE;
00652 
00653         previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress);
00654         nextSlot = slotForInternalAddress(
00655          ((char *)slot->internalAddress) + slot->internalSize);
00656 
00657         if ( previousSlot
00658          && (previousSlot->mode == FREE || previousSlot->mode == PROTECTED) ) {
00659                 /* Coalesce previous slot with this one. */
00660                 previousSlot->internalSize += slot->internalSize;
00661                 if ( EF_PROTECT_FREE )
00662                         previousSlot->mode = PROTECTED;
00663 
00664                 slot->internalAddress = slot->userAddress = 0;
00665                 slot->internalSize = slot->userSize = 0;
00666                 slot->mode = NOT_IN_USE;
00667                 slot = previousSlot;
00668                 unUsedSlots++;
00669         }
00670         if ( nextSlot
00671          && (nextSlot->mode == FREE || nextSlot->mode == PROTECTED) ) {
00672                 /* Coalesce next slot with this one. */
00673                 slot->internalSize += nextSlot->internalSize;
00674                 nextSlot->internalAddress = nextSlot->userAddress = 0;
00675                 nextSlot->internalSize = nextSlot->userSize = 0;
00676                 nextSlot->mode = NOT_IN_USE;
00677                 unUsedSlots++;
00678         }
00679 
00680         slot->userAddress = slot->internalAddress;
00681         slot->userSize = slot->internalSize;
00682 
00683         /*
00684          * Free memory is _always_ set to deny access. When EF_PROTECT_FREE
00685          * is true, free memory is never reallocated, so it remains access
00686          * denied for the life of the process. When EF_PROTECT_FREE is false, 
00687          * the memory may be re-allocated, at which time access to it will be
00688          * allowed again.
00689          *
00690          * Some operating systems allow munmap() with single-page resolution,
00691          * and allow you to un-map portions of a region, rather than the
00692          * entire region that was mapped with mmap(). On those operating
00693          * systems, we can release protected free pages with Page_Delete(),
00694          * in the hope that the swap space attached to those pages will be
00695          * released as well.
00696          */
00697         if ( EF_PROTECT_FREE )
00698             Page_Delete(slot->internalAddress, slot->internalSize);
00699         else
00700             Page_DenyAccess(slot->internalAddress, slot->internalSize);
00701 
00702         if ( !noAllocationListProtection )
00703                 Page_DenyAccess(allocationList, allocationListSize);
00704 }

int getpagesize  
 

Referenced by Page_Size(), and pagesize().

void initialize void    [static]
 

Definition at line 186 of file efence.c.

References allocationListSize, bytesPerPage, EF_ALIGNMENT, EF_ALLOW_MALLOC_0, EF_Print(), EF_PROTECT_BELOW, EF_PROTECT_FREE, FREE, getenv(), INTERNAL_USE, _Slot::internalAddress, _Slot::internalSize, MEMORY_CREATION_SIZE, _Slot::mode, Page_Create(), Page_DenyAccess(), Page_Size(), slotCount, slotsPerPage, unUsedSlots, _Slot::userAddress, _Slot::userSize, and version.

Referenced by main(), malloc(), and memalign().

00187 {
00188         size_t  size = MEMORY_CREATION_SIZE;
00189         size_t  slack;
00190         char *  string;
00191         Slot *  slot;
00192 
00193         EF_Print(version);
00194 
00195         /*
00196          * Import the user's environment specification of the default
00197          * alignment for malloc(). We want that alignment to be under
00198          * user control, since smaller alignment lets us catch more bugs,
00199          * however some software will break if malloc() returns a buffer
00200          * that is not word-aligned.
00201          *
00202          * I would like
00203          * alignment to be zero so that we could catch all one-byte
00204          * overruns, however if malloc() is asked to allocate an odd-size
00205          * buffer and returns an address that is not word-aligned, or whose
00206          * size is not a multiple of the word size, software breaks.
00207          * This was the case with the Sun string-handling routines,
00208          * which can do word fetches up to three bytes beyond the end of a
00209          * string. I handle this problem in part by providing
00210          * byte-reference-only versions of the string library functions, but
00211          * there are other functions that break, too. Some in X Windows, one
00212          * in Sam Leffler's TIFF library, and doubtless many others.
00213          */
00214         if ( EF_ALIGNMENT == -1 ) {
00215                 if ( (string = getenv("EF_ALIGNMENT")) != 0 )
00216                         EF_ALIGNMENT = (size_t)atoi(string);
00217                 else
00218                         EF_ALIGNMENT = sizeof(int);
00219         }
00220 
00221         /*
00222          * See if the user wants to protect the address space below a buffer,
00223          * rather than that above a buffer.
00224          */
00225         if ( EF_PROTECT_BELOW == -1 ) {
00226                 if ( (string = getenv("EF_PROTECT_BELOW")) != 0 )
00227                         EF_PROTECT_BELOW = (atoi(string) != 0);
00228                 else
00229                         EF_PROTECT_BELOW = 0;
00230         }
00231 
00232         /*
00233          * See if the user wants to protect memory that has been freed until
00234          * the program exits, rather than until it is re-allocated.
00235          */
00236         if ( EF_PROTECT_FREE == -1 ) {
00237                 if ( (string = getenv("EF_PROTECT_FREE")) != 0 )
00238                         EF_PROTECT_FREE = (atoi(string) != 0);
00239                 else
00240                         EF_PROTECT_FREE = 0;
00241         }
00242 
00243         /*
00244          * See if the user wants to allow malloc(0).
00245          */
00246         if ( EF_ALLOW_MALLOC_0 == -1 ) {
00247                 if ( (string = getenv("EF_ALLOW_MALLOC_0")) != 0 )
00248                         EF_ALLOW_MALLOC_0 = (atoi(string) != 0);
00249                 else
00250                         EF_ALLOW_MALLOC_0 = 0;
00251         }
00252 
00253         /*
00254          * Get the run-time configuration of the virtual memory page size.
00255          */
00256         bytesPerPage = Page_Size();
00257 
00258         /*
00259          * Figure out how many Slot structures to allocate at one time.
00260          */
00261         slotCount = slotsPerPage = bytesPerPage / sizeof(Slot);
00262         allocationListSize = bytesPerPage;
00263 
00264         if ( allocationListSize > size )
00265                 size = allocationListSize;
00266 
00267         if ( (slack = size % bytesPerPage) != 0 )
00268                 size += bytesPerPage - slack;
00269 
00270         /*
00271          * Allocate memory, and break it up into two malloc buffers. The
00272          * first buffer will be used for Slot structures, the second will
00273          * be marked free.
00274          */
00275         slot = allocationList = (Slot *)Page_Create(size);
00276         memset((char *)allocationList, 0, allocationListSize);
00277 
00278         slot[0].internalSize = slot[0].userSize = allocationListSize;
00279         slot[0].internalAddress = slot[0].userAddress = allocationList;
00280         slot[0].mode = INTERNAL_USE;
00281         if ( size > allocationListSize ) {
00282                 slot[1].internalAddress = slot[1].userAddress
00283                  = ((char *)slot[0].internalAddress) + slot[0].internalSize;
00284                 slot[1].internalSize
00285                  = slot[1].userSize = size - slot[0].internalSize;
00286                 slot[1].mode = FREE;
00287         }
00288 
00289         /*
00290          * Deny access to the free page, so that we will detect any software
00291          * that treads upon free memory.
00292          */
00293         Page_DenyAccess(slot[1].internalAddress, slot[1].internalSize);
00294 
00295         /*
00296          * Account for the two slot structures that we've used.
00297          */
00298         unUsedSlots = slotCount - 2;
00299 }

void internalError void    [static]
 

Definition at line 176 of file efence.c.

References EF_Abort().

Referenced by memalign().

00177 {
00178         EF_Abort("Internal error in allocator.");
00179 }

C_LINKAGE void* malloc size_t    size
 

Definition at line 742 of file efence.c.

References EF_ALIGNMENT, initialize(), and memalign().

00743 {
00744         if ( allocationList == 0 )
00745                 initialize();   /* This sets EF_ALIGNMENT */
00746 
00747         return memalign(EF_ALIGNMENT, size);
00748 }

C_LINKAGE void* memalign size_t    alignment,
size_t    userSize
 

Definition at line 358 of file efence.c.

References ALLOCATED, allocateMoreSlots(), allocationListSize, bytesPerPage, EF_Abort(), EF_ALLOW_MALLOC_0, EF_PROTECT_BELOW, FREE, initialize(), INTERNAL_USE, _Slot::internalAddress, internalError(), _Slot::internalSize, internalUse, MEMORY_CREATION_SIZE, _Slot::mode, noAllocationListProtection, NOT_IN_USE, Page_AllowAccess(), Page_Create(), Page_Delete(), Page_DenyAccess(), slotCount, unUsedSlots, _Slot::userAddress, and _Slot::userSize.

Referenced by malloc(), mpeg2_malloc(), and valloc().

00359 {
00360         register Slot * slot;
00361         register size_t count;
00362         Slot *          fullSlot = 0;
00363         Slot *          emptySlots[2];
00364         size_t          internalSize;
00365         size_t          slack;
00366         char *          address;
00367 
00368 
00369         if ( allocationList == 0 )
00370                 initialize();
00371 
00372         if ( userSize == 0 && !EF_ALLOW_MALLOC_0 )
00373                 EF_Abort("Allocating 0 bytes, probably a bug.");
00374 
00375         /*
00376          * If EF_PROTECT_BELOW is set, all addresses returned by malloc()
00377          * and company will be page-aligned.
00378          */
00379         if ( !EF_PROTECT_BELOW && alignment > 1 ) {
00380                 if ( (slack = userSize % alignment) != 0 )
00381                         userSize += alignment - slack;
00382         }
00383 
00384         /*
00385          * The internal size of the buffer is rounded up to the next page-size
00386          * boudary, and then we add another page's worth of memory for the
00387          * dead page.
00388          */
00389         internalSize = userSize + bytesPerPage;
00390         if ( (slack = internalSize % bytesPerPage) != 0 )
00391                 internalSize += bytesPerPage - slack;
00392 
00393         /*
00394          * These will hold the addresses of two empty Slot structures, that
00395          * can be used to hold information for any memory I create, and any
00396          * memory that I mark free.
00397          */
00398         emptySlots[0] = 0;
00399         emptySlots[1] = 0;
00400 
00401         /*
00402          * The internal memory used by the allocator is currently
00403          * inaccessable, so that errant programs won't scrawl on the
00404          * allocator's arena. I'll un-protect it here so that I can make
00405          * a new allocation. I'll re-protect it before I return.
00406          */
00407         if ( !noAllocationListProtection )
00408                 Page_AllowAccess(allocationList, allocationListSize);
00409 
00410         /*
00411          * If I'm running out of empty slots, create some more before
00412          * I don't have enough slots left to make an allocation.
00413          */
00414         if ( !internalUse && unUsedSlots < 7 ) {
00415                 allocateMoreSlots();
00416         }
00417         
00418         /*
00419          * Iterate through all of the slot structures. Attempt to find a slot
00420          * containing free memory of the exact right size. Accept a slot with
00421          * more memory than we want, if the exact right size is not available.
00422          * Find two slot structures that are not in use. We will need one if
00423          * we split a buffer into free and allocated parts, and the second if
00424          * we have to create new memory and mark it as free.
00425          *
00426          */
00427         
00428         for ( slot = allocationList, count = slotCount ; count > 0; count-- ) {
00429                 if ( slot->mode == FREE
00430                  && slot->internalSize >= internalSize ) {
00431                         if ( !fullSlot
00432                          ||slot->internalSize < fullSlot->internalSize){
00433                                 fullSlot = slot;
00434                                 if ( slot->internalSize == internalSize
00435                                  && emptySlots[0] )
00436                                         break;  /* All done, */
00437                         }
00438                 }
00439                 else if ( slot->mode == NOT_IN_USE ) {
00440                         if ( !emptySlots[0] )
00441                                 emptySlots[0] = slot;
00442                         else if ( !emptySlots[1] )
00443                                 emptySlots[1] = slot;
00444                         else if ( fullSlot
00445                          && fullSlot->internalSize == internalSize )
00446                                 break;  /* All done. */
00447                 }
00448                 slot++;
00449         }
00450         if ( !emptySlots[0] )
00451                 internalError();
00452 
00453         if ( !fullSlot ) {
00454                 /*
00455                  * I get here if I haven't been able to find a free buffer
00456                  * with all of the memory I need. I'll have to create more
00457                  * memory. I'll mark it all as free, and then split it into
00458                  * free and allocated portions later.
00459                  */
00460                 size_t  chunkSize = MEMORY_CREATION_SIZE;
00461 
00462                 if ( !emptySlots[1] )
00463                         internalError();
00464 
00465                 if ( chunkSize < internalSize )
00466                         chunkSize = internalSize;
00467 
00468                 if ( (slack = chunkSize % bytesPerPage) != 0 )
00469                         chunkSize += bytesPerPage - slack;
00470 
00471                 /* Use up one of the empty slots to make the full slot. */
00472                 fullSlot = emptySlots[0];
00473                 emptySlots[0] = emptySlots[1];
00474                 fullSlot->internalAddress = Page_Create(chunkSize);
00475                 fullSlot->internalSize = chunkSize;
00476                 fullSlot->mode = FREE;
00477                 unUsedSlots--;
00478         }
00479 
00480         /*
00481          * If I'm allocating memory for the allocator's own data structures,
00482          * mark it INTERNAL_USE so that no errant software will be able to
00483          * free it.
00484          */
00485         if ( internalUse )
00486                 fullSlot->mode = INTERNAL_USE;
00487         else
00488                 fullSlot->mode = ALLOCATED;
00489 
00490         /*
00491          * If the buffer I've found is larger than I need, split it into
00492          * an allocated buffer with the exact amount of memory I need, and
00493          * a free buffer containing the surplus memory.
00494          */
00495         if ( fullSlot->internalSize > internalSize ) {
00496                 emptySlots[0]->internalSize
00497                  = fullSlot->internalSize - internalSize;
00498                 emptySlots[0]->internalAddress
00499                  = ((char *)fullSlot->internalAddress) + internalSize;
00500                 emptySlots[0]->mode = FREE;
00501                 fullSlot->internalSize = internalSize;
00502                 unUsedSlots--;
00503         }
00504 
00505         if ( !EF_PROTECT_BELOW ) {
00506                 /*
00507                  * Arrange the buffer so that it is followed by an inaccessable
00508                  * memory page. A buffer overrun that touches that page will
00509                  * cause a segmentation fault.
00510                  */
00511                 address = (char *)fullSlot->internalAddress;
00512 
00513                 /* Set up the "live" page. */
00514                 Page_AllowAccess(
00515                  fullSlot->internalAddress
00516                 ,internalSize - bytesPerPage);
00517                         
00518                 address += internalSize - bytesPerPage;
00519 
00520                 /* Set up the "dead" page. */
00521                 if ( EF_PROTECT_FREE )
00522                         Page_Delete(address, bytesPerPage);
00523                 else
00524                         Page_DenyAccess(address, bytesPerPage);
00525 
00526                 /* Figure out what address to give the user. */
00527                 address -= userSize;
00528         }
00529         else {  /* EF_PROTECT_BELOW != 0 */
00530                 /*
00531                  * Arrange the buffer so that it is preceded by an inaccessable
00532                  * memory page. A buffer underrun that touches that page will
00533                  * cause a segmentation fault.
00534                  */
00535                 address = (char *)fullSlot->internalAddress;
00536 
00537                 /* Set up the "dead" page. */
00538                 if ( EF_PROTECT_FREE )
00539                         Page_Delete(address, bytesPerPage);
00540                 else
00541                         Page_DenyAccess(address, bytesPerPage);
00542                         
00543                 address += bytesPerPage;
00544 
00545                 /* Set up the "live" page. */
00546                 Page_AllowAccess(address, internalSize - bytesPerPage);
00547         }
00548 
00549         fullSlot->userAddress = address;
00550         fullSlot->userSize = userSize;
00551 
00552         /*
00553          * Make the pool's internal memory inaccessable, so that the program
00554          * being debugged can't stomp on it.
00555          */
00556         if ( !internalUse )
00557                 Page_DenyAccess(allocationList, allocationListSize);
00558 
00559         return address;
00560 }

void mprotectFailed void    [static]
 

Definition at line 882 of file efence.c.

References EF_Exit(), and stringErrorReport().

Referenced by Page_AllowAccess(), and Page_DenyAccess().

00883 {
00884         EF_Exit("mprotect() failed: %s", stringErrorReport());
00885 }

void Page_AllowAccess void *    address,
size_t    size
 

Definition at line 888 of file efence.c.

References mprotectFailed().

Referenced by allocateMoreSlots(), free(), memalign(), and realloc().

00889 {
00890         if ( mprotect((caddr_t)address, size, PROT_READ|PROT_WRITE) < 0 )
00891                 mprotectFailed();
00892 }

void* Page_Create size_t    size
 

Definition at line 841 of file efence.c.

References EF_Exit(), startAddr, and stringErrorReport().

Referenced by initialize(), and memalign().

00842 {
00843         static int      devZeroFd = -1;
00844         caddr_t         allocation;
00845 
00846         if ( devZeroFd == -1 ) {
00847                 devZeroFd = open("/dev/zero", O_RDWR);
00848                 if ( devZeroFd < 0 )
00849                         EF_Exit(
00850                          "open() on /dev/zero failed: %s"
00851                         ,stringErrorReport());
00852         }
00853 
00854         /*
00855          * In this version, "startAddr" is a _hint_, not a demand.
00856          * When the memory I map here is contiguous with other
00857          * mappings, the allocator can coalesce the memory from two
00858          * or more mappings into one large contiguous chunk, and thus
00859          * might be able to find a fit that would not otherwise have
00860          * been possible. I could _force_ it to be contiguous by using
00861          * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
00862          * generated by other software, etc.
00863          */
00864         allocation = mmap(
00865          startAddr
00866         ,(int)size
00867         ,PROT_READ|PROT_WRITE
00868         ,MAP_PRIVATE
00869         ,devZeroFd
00870         ,0);
00871 
00872         startAddr = allocation + size;
00873 
00874         if ( allocation == (caddr_t)-1 )
00875                 EF_Exit("mmap() failed: %s", stringErrorReport());
00876 
00877         return (void *)allocation;
00878 }

void Page_Delete void *    address,
size_t    size
 

Definition at line 902 of file efence.c.

References EF_Exit(), Page_DenyAccess(), and stringErrorReport().

Referenced by free(), and memalign().

00903 {
00904 /*
00905  * My SGI ONYX running IRIX 5.0 crashes reliably when "tstheap 3072" is
00906  * run with the munmap call below compiled in. I'd like to hear how well
00907  * other operating systems handle it, so that I can enable it on those
00908  * systems.
00909  */
00910 #if ( defined(_AIX) )
00911         if ( munmap((caddr_t)address, size) < 0 )
00912                 EF_Exit("munmap() failed: %s", stringErrorReport());
00913 #else
00914         Page_DenyAccess(address, size);
00915 #endif
00916 }

void Page_DenyAccess void *    address,
size_t    size
 

Definition at line 895 of file efence.c.

References mprotectFailed().

Referenced by free(), initialize(), memalign(), Page_Delete(), and realloc().

00896 {
00897         if ( mprotect((caddr_t)address, size, PROT_NONE) < 0 )
00898                 mprotectFailed();
00899 }

size_t Page_Size void   
 

Definition at line 933 of file efence.c.

References getpagesize().

Referenced by initialize().

00934 {
00935         return getpagesize();
00936 }

void printNumber unsigned int    number,
unsigned int    base
[static]
 

Definition at line 957 of file efence.c.

References base, EF_Abort(), NUMBER_BUFFER_SIZE, and write().

Referenced by vprint().

00958 {
00959         char            buffer[NUMBER_BUFFER_SIZE];
00960         char *          s = &buffer[NUMBER_BUFFER_SIZE];
00961         int             size;
00962         
00963         do {
00964                 unsigned int    digit;
00965 
00966                 if ( --s == buffer )
00967                         EF_Abort("Internal error printing number.");
00968 
00969                 digit = number % base;
00970 
00971                 if ( digit < 10 )
00972                         *s = '0' + digit;
00973                 else
00974                         *s = 'a' + digit - 10;
00975 
00976         } while ( (number /= base) > 0 );
00977 
00978         size = &buffer[NUMBER_BUFFER_SIZE] - s;
00979 
00980         if ( size > 0 )
00981                 write(2, s, size);
00982 }

C_LINKAGE void* realloc void *    oldBuffer,
size_t    newSize
 

Definition at line 707 of file efence.c.

References allocationListSize, EF_Abort(), free, malloc, noAllocationListProtection, Page_AllowAccess(), Page_DenyAccess(), slotForUserAddress(), and _Slot::userSize.

00708 {
00709         size_t  size;
00710         Slot *  slot;
00711         void *  newBuffer = malloc(newSize);
00712 
00713         if ( allocationList == 0 )
00714                 EF_Abort("realloc() called before first malloc().");
00715 
00716         Page_AllowAccess(allocationList, allocationListSize);
00717         noAllocationListProtection = 1;
00718         
00719         slot = slotForUserAddress(oldBuffer);
00720 
00721         if ( slot == 0 )
00722                 EF_Abort("free(%x): not from malloc().", oldBuffer);
00723 
00724         if ( newSize < (size = slot->userSize) )
00725                 size = newSize;
00726 
00727         if ( size > 0 )
00728                 memcpy(newBuffer, oldBuffer, size);
00729 
00730         free(oldBuffer);
00731         noAllocationListProtection = 0;
00732         Page_DenyAccess(allocationList, allocationListSize);
00733 
00734         if ( size < newSize )
00735                 memset(&(((char *)newBuffer)[size]), 0, newSize - size);
00736         
00737         /* Internal memory was re-protected in free() */
00738         return newBuffer;
00739 }

Slot* slotForInternalAddress void *    address [static]
 

Definition at line 584 of file efence.c.

References _Slot::internalAddress, and slotCount.

Referenced by free().

00585 {
00586         register Slot * slot = allocationList;
00587         register size_t count = slotCount;
00588         
00589         for ( ; count > 0; count-- ) {
00590                 if ( slot->internalAddress == address )
00591                         return slot;
00592                 slot++;
00593         }
00594         return 0;
00595 }

Slot* slotForInternalAddressPreviousTo void *    address [static]
 

Definition at line 603 of file efence.c.

References _Slot::internalAddress, _Slot::internalSize, and slotCount.

Referenced by free().

00604 {
00605         register Slot * slot = allocationList;
00606         register size_t count = slotCount;
00607         
00608         for ( ; count > 0; count-- ) {
00609                 if ( ((char *)slot->internalAddress)
00610                  + slot->internalSize == address )
00611                         return slot;
00612                 slot++;
00613         }
00614         return 0;
00615 }

Slot* slotForUserAddress void *    address [static]
 

Definition at line 566 of file efence.c.

References slotCount, and _Slot::userAddress.

Referenced by free(), and realloc().

00567 {
00568         register Slot * slot = allocationList;
00569         register size_t count = slotCount;
00570         
00571         for ( ; count > 0; count-- ) {
00572                 if ( slot->userAddress == address )
00573                         return slot;
00574                 slot++;
00575         }
00576 
00577         return 0;
00578 }

const char* stringErrorReport void    [static]
 

Definition at line 791 of file efence.c.

References strerror(), sys_errlist, and sys_nerr.

Referenced by mprotectFailed(), Page_Create(), and Page_Delete().

00792 {
00793 #if ( defined(sgi) )
00794         return strerror(oserror());
00795 #elif ( defined(_AIX) )
00796         return strerror(errno);
00797 #else
00798         if ( errno > 0 && errno < sys_nerr )
00799                 return sys_errlist[errno];
00800         else
00801                 return "Unknown error.\n";
00802 #endif
00803 }

C_LINKAGE void* valloc size_t    size
 

Definition at line 765 of file efence.c.

References bytesPerPage, and memalign().

00766 {
00767         return memalign(bytesPerPage, size);
00768 }

void vprint const char *    pattern,
va_list    args
[static]
 

Definition at line 985 of file efence.c.

References args, c, EF_Print(), printNumber(), u_int, and write().

Referenced by EF_Abort(), EF_Exit(), and EF_Print().

00986 {
00987         static const char       bad_pattern[] =
00988          "\nBad pattern specifier %%%c in EF_Print().\n";
00989         const char *    s = pattern;
00990         char            c;
00991 
00992         while ( (c = *s++) != '\0' ) {
00993                 if ( c == '%' ) {
00994                         c = *s++;
00995                         switch ( c ) {
00996                         case '%':
00997                                 (void) write(2, &c, 1);
00998                                 break;
00999                         case 's':
01000                                 {
01001                                         const char *    string;
01002                                         size_t          length;
01003 
01004                                         string = va_arg(args, char *);
01005                                         length = strlen(string);
01006 
01007                                         (void) write(2, string, length);
01008                                 }
01009                                 break;
01010                         case 'd':
01011                                 {
01012                                         int     n = va_arg(args, int);
01013 
01014                                         if ( n < 0 ) {
01015                                                 char    c = '-';
01016                                                 write(2, &c, 1);
01017                                                 n = -n;
01018                                         }
01019                                         printNumber(n, 10);
01020                                 }
01021                                 break;
01022                         case 'x':
01023                                 printNumber(va_arg(args, u_int), 0x10);
01024                                 break;
01025                         case 'c':
01026                                 {
01027                                         char    c = va_arg(args, char);
01028                                         
01029                                         (void) write(2, &c, 1);
01030                                 }
01031                                 break;
01032                         default:
01033                                 {
01034                                         EF_Print(bad_pattern, c);
01035                                 }
01036                 
01037                         }
01038                 }
01039                 else
01040                         (void) write(2, &c, 1);
01041         }
01042 }

Variable Documentation

Slot* allocationList = 0 [static]
 

Definition at line 125 of file efence.c.

size_t allocationListSize = 0 [static]
 

Definition at line 131 of file efence.c.

Referenced by allocateMoreSlots(), free(), initialize(), memalign(), and realloc().

size_t bytesPerPage = 0 [static]
 

Definition at line 169 of file efence.c.

Referenced by allocateMoreSlots(), initialize(), memalign(), and valloc().

int EF_ALIGNMENT = -1
 

Definition at line 88 of file efence.c.

Referenced by initialize(), and malloc().

int EF_ALLOW_MALLOC_0 = -1
 

Definition at line 119 of file efence.c.

Referenced by initialize(), and memalign().

int EF_PROTECT_BELOW = -1
 

Definition at line 113 of file efence.c.

Referenced by initialize(), and memalign().

int EF_PROTECT_FREE = -1
 

Definition at line 101 of file efence.c.

Referenced by initialize().

int internalUse = 0 [static]
 

Definition at line 155 of file efence.c.

Referenced by allocateMoreSlots(), free(), and memalign().

int noAllocationListProtection = 0 [static]
 

Definition at line 163 of file efence.c.

Referenced by allocateMoreSlots(), free(), memalign(), and realloc().

size_t slotCount = 0 [static]
 

Definition at line 136 of file efence.c.

Referenced by allocateMoreSlots(), initialize(), memalign(), slotForInternalAddress(), slotForInternalAddressPreviousTo(), and slotForUserAddress().

size_t slotsPerPage = 0 [static]
 

Definition at line 149 of file efence.c.

Referenced by allocateMoreSlots(), and initialize().

caddr_t startAddr = (caddr_t) 0 [static]
 

extern C_LINKAGE int mprotect(caddr_t addr, size_t len, int prot);

Definition at line 783 of file efence.c.

Referenced by Page_Create().

char* sys_errlist[]
 

Definition at line 787 of file efence.c.

Referenced by strerror(), and stringErrorReport().

int sys_nerr
 

Definition at line 786 of file efence.c.

Referenced by strerror(), and stringErrorReport().

size_t unUsedSlots = 0 [static]
 

Definition at line 143 of file efence.c.

Referenced by allocateMoreSlots(), free(), initialize(), and memalign().

const char version[] [static]
 

Initial value:

 "\n  Electric Fence 2.0.1"
 " Copyright (C) 1987-1993 Bruce Perens.\n"

Definition at line 45 of file efence.c.

Referenced by initialize().

 

Powered by Plone

This site conforms to the following standards: