LCOV - app.info - nsprpub/pr/src/malloc/prmem.c

LCOV - code coverage report
| Current view: | directory - nsprpub/pr/src/malloc - prmem.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 197 | 29 | 14.7 %
| Date: | 2012-07-07 | Functions: | 12 | 7 | 58.3 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is the Netscape Portable Runtime (NSPR).
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998-2000
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : /*
          39                 : ** Thread safe versions of malloc, free, realloc, calloc and cfree.
          40                 : */
          41                 :
          42                 : #include "primpl.h"
          43                 :
          44                 : #ifdef _PR_ZONE_ALLOCATOR
          45                 :
          46                 : /*
          47                 : ** The zone allocator code must use native mutexes and cannot
          48                 : ** use PRLocks because PR_NewLock calls PR_Calloc, resulting
          49                 : ** in cyclic dependency of initialization.
          50                 : */
          51                 :
          52                 : #include <string.h>
          53                 :
          54                 : union memBlkHdrUn;
          55                 :
          56                 : typedef struct MemoryZoneStr {
          57                 :     union memBlkHdrUn    *head;         /* free list */
          58                 :     pthread_mutex_t       lock;
          59                 :     size_t                blockSize;    /* size of blocks on this free list */
          60                 :     PRUint32              locked;       /* current state of lock */
          61                 :     PRUint32              contention;   /* counter: had to wait for lock */
          62                 :     PRUint32              hits;         /* allocated from free list */
          63                 :     PRUint32              misses;       /* had to call malloc */
          64                 :     PRUint32              elements;     /* on free list */
          65                 : } MemoryZone;
          66                 :
          67                 : typedef union memBlkHdrUn {
          68                 :     unsigned char filler[48];  /* fix the size of this beast */
          69                 :     struct memBlkHdrStr {
          70                 :         union memBlkHdrUn    *next;
          71                 :         MemoryZone           *zone;
          72                 :         size_t                blockSize;
          73                 :         size_t                requestedSize;
          74                 :         PRUint32              magic;
          75                 :     } s;
          76                 : } MemBlockHdr;
          77                 :
          78                 : #define MEM_ZONES     7
          79                 : #define THREAD_POOLS 11  /* prime number for modulus */
          80                 : #define ZONE_MAGIC  0x0BADC0DE
          81                 :
          82                 : static MemoryZone zones[MEM_ZONES][THREAD_POOLS];
          83                 :
          84                 : static PRBool use_zone_allocator = PR_FALSE;
          85                 :
          86                 : static void pr_ZoneFree(void *ptr);
          87                 :
          88                 : void
          89             140 : _PR_DestroyZones(void)
          90                 : {
          91                 :     int i, j;
          92                 :
          93             140 :     if (!use_zone_allocator)
          94             140 :         return;
          95                 :
          96               0 :     for (j = 0; j < THREAD_POOLS; j++) {
          97               0 :         for (i = 0; i < MEM_ZONES; i++) {
          98               0 :             MemoryZone *mz = &zones[i][j];
          99               0 :             pthread_mutex_destroy(&mz->lock);
         100               0 :             while (mz->head) {
         101               0 :                 MemBlockHdr *hdr = mz->head;
         102               0 :                 mz->head = hdr->s.next;  /* unlink it */
         103               0 :                 free(hdr);
         104               0 :                 mz->elements--;
         105                 :             }
         106                 :         }
         107                 :     }
         108               0 :     use_zone_allocator = PR_FALSE;
         109                 : }
         110                 :
         111                 : /*
         112                 : ** pr_FindSymbolInProg
         113                 : **
         114                 : ** Find the specified data symbol in the program and return
         115                 : ** its address.
         116                 : */
         117                 :
         118                 : #ifdef HAVE_DLL
         119                 :
         120                 : #if defined(USE_DLFCN) && !defined(NO_DLOPEN_NULL)
         121                 :
         122                 : #include <dlfcn.h>
         123                 :
         124                 : static void *
         125           20034 : pr_FindSymbolInProg(const char *name)
         126                 : {
         127                 :     void *h;
         128                 :     void *sym;
         129                 :
         130           20034 :     h = dlopen(0, RTLD_LAZY);
         131           20034 :     if (h == NULL)
         132               0 :         return NULL;
         133           20034 :     sym = dlsym(h, name);
         134           20034 :     (void)dlclose(h);
         135           20034 :     return sym;
         136                 : }
         137                 :
         138                 : #elif defined(USE_HPSHL)
         139                 :
         140                 : #include <dl.h>
         141                 :
         142                 : static void *
         143                 : pr_FindSymbolInProg(const char *name)
         144                 : {
         145                 :     shl_t h = NULL;
         146                 :     void *sym;
         147                 :
         148                 :     if (shl_findsym(&h, name, TYPE_DATA, &sym) == -1)
         149                 :         return NULL;
         150                 :     return sym;
         151                 : }
         152                 :
         153                 : #elif defined(USE_MACH_DYLD) || defined(NO_DLOPEN_NULL)
         154                 :
         155                 : static void *
         156                 : pr_FindSymbolInProg(const char *name)
         157                 : {
         158                 :     /* FIXME: not implemented */
         159                 :     return NULL;
         160                 : }
         161                 :
         162                 : #else
         163                 :
         164                 : #error "The zone allocator is not supported on this platform"
         165                 :
         166                 : #endif
         167                 :
         168                 : #else /* !defined(HAVE_DLL) */
         169                 :
         170                 : static void *
         171                 : pr_FindSymbolInProg(const char *name)
         172                 : {
         173                 :     /* can't be implemented */
         174                 :     return NULL;
         175                 : }
         176                 :
         177                 : #endif /* HAVE_DLL */
         178                 :
         179                 : void
         180           20034 : _PR_InitZones(void)
         181                 : {
         182                 :     int i, j;
         183                 :     char *envp;
         184                 :     PRBool *sym;
         185                 :
         186           20034 :     if ((sym = (PRBool *)pr_FindSymbolInProg("nspr_use_zone_allocator")) != NULL) {
         187            1441 :         use_zone_allocator = *sym;
         188           18593 :     } else if ((envp = getenv("NSPR_USE_ZONE_ALLOCATOR")) != NULL) {
         189               0 :         use_zone_allocator = (atoi(envp) == 1);
         190                 :     }
         191                 :
         192           20034 :     if (!use_zone_allocator)
         193           20034 :         return;
         194                 :
         195               0 :     for (j = 0; j < THREAD_POOLS; j++) {
         196               0 :         for (i = 0; i < MEM_ZONES; i++) {
         197               0 :             MemoryZone *mz = &zones[i][j];
         198               0 :             int rv = pthread_mutex_init(&mz->lock, NULL);
         199               0 :             PR_ASSERT(0 == rv);
         200               0 :             if (rv != 0) {
         201               0 :                 goto loser;
         202                 :             }
         203               0 :             mz->blockSize = 16 << ( 2 * i);
         204                 :         }
         205                 :     }
         206               0 :     return;
         207                 :
         208                 : loser:
         209               0 :     _PR_DestroyZones();
         210               0 :     return;
         211                 : }
         212                 :
         213                 : PR_IMPLEMENT(void)
         214               0 : PR_FPrintZoneStats(PRFileDesc *debug_out)
         215                 : {
         216                 :     int i, j;
         217                 :
         218               0 :     for (j = 0; j < THREAD_POOLS; j++) {
         219               0 :         for (i = 0; i < MEM_ZONES; i++) {
         220               0 :             MemoryZone   *mz   = &zones[i][j];
         221               0 :             MemoryZone    zone = *mz;
         222               0 :             if (zone.elements || zone.misses || zone.hits) {
         223               0 :                 PR_fprintf(debug_out,
         224                 : "pool: %d, zone: %d, size: %d, free: %d, hit: %d, miss: %d, contend: %d\n",
         225                 :                     j, i, zone.blockSize, zone.elements,
         226                 :                     zone.hits, zone.misses, zone.contention);
         227                 :             }
         228                 :         }
         229                 :     }
         230               0 : }
         231                 :
         232                 : static void *
         233               0 : pr_ZoneMalloc(PRUint32 size)
         234                 : {
         235                 :     void         *rv;
         236                 :     unsigned int  zone;
         237                 :     size_t        blockSize;
         238                 :     MemBlockHdr  *mb, *mt;
         239                 :     MemoryZone   *mz;
         240                 :
         241                 :     /* Always allocate a non-zero amount of bytes */
         242               0 :     if (size < 1) {
         243               0 :         size = 1;
         244                 :     }
         245               0 :     for (zone = 0, blockSize = 16; zone < MEM_ZONES; ++zone, blockSize <<= 2) {
         246               0 :         if (size <= blockSize) {
         247               0 :             break;
         248                 :         }
         249                 :     }
         250               0 :     if (zone < MEM_ZONES) {
         251               0 :         pthread_t me = pthread_self();
         252               0 :         unsigned int pool = (PRUptrdiff)me % THREAD_POOLS;
         253                 :         PRUint32     wasLocked;
         254               0 :         mz = &zones[zone][pool];
         255               0 :         wasLocked = mz->locked;
         256               0 :         pthread_mutex_lock(&mz->lock);
         257               0 :         mz->locked = 1;
         258               0 :         if (wasLocked)
         259               0 :             mz->contention++;
         260               0 :         if (mz->head) {
         261               0 :             mb = mz->head;
         262               0 :             PR_ASSERT(mb->s.magic == ZONE_MAGIC);
         263               0 :             PR_ASSERT(mb->s.zone  == mz);
         264               0 :             PR_ASSERT(mb->s.blockSize == blockSize);
         265               0 :             PR_ASSERT(mz->blockSize == blockSize);
         266                 :
         267               0 :             mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
         268               0 :             PR_ASSERT(mt->s.magic == ZONE_MAGIC);
         269               0 :             PR_ASSERT(mt->s.zone  == mz);
         270               0 :             PR_ASSERT(mt->s.blockSize == blockSize);
         271                 :
         272               0 :             mz->hits++;
         273               0 :             mz->elements--;
         274               0 :             mz->head = mb->s.next;    /* take off free list */
         275               0 :             mz->locked = 0;
         276               0 :             pthread_mutex_unlock(&mz->lock);
         277                 :
         278               0 :             mt->s.next          = mb->s.next          = NULL;
         279               0 :             mt->s.requestedSize = mb->s.requestedSize = size;
         280                 :
         281               0 :             rv = (void *)(mb + 1);
         282               0 :             return rv;
         283                 :         }
         284                 :
         285               0 :         mz->misses++;
         286               0 :         mz->locked = 0;
         287               0 :         pthread_mutex_unlock(&mz->lock);
         288                 :
         289               0 :         mb = (MemBlockHdr *)malloc(blockSize + 2 * (sizeof *mb));
         290               0 :         if (!mb) {
         291               0 :             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
         292               0 :             return NULL;
         293                 :         }
         294               0 :         mb->s.next          = NULL;
         295               0 :         mb->s.zone          = mz;
         296               0 :         mb->s.magic         = ZONE_MAGIC;
         297               0 :         mb->s.blockSize     = blockSize;
         298               0 :         mb->s.requestedSize = size;
         299                 :
         300               0 :         mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
         301               0 :         memcpy(mt, mb, sizeof *mb);
         302                 :
         303               0 :         rv = (void *)(mb + 1);
         304               0 :         return rv;
         305                 :     }
         306                 :
         307                 :     /* size was too big.  Create a block with no zone */
         308               0 :     blockSize = (size & 15) ? size + 16 - (size & 15) : size;
         309               0 :     mb = (MemBlockHdr *)malloc(blockSize + 2 * (sizeof *mb));
         310               0 :     if (!mb) {
         311               0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
         312               0 :         return NULL;
         313                 :     }
         314               0 :     mb->s.next          = NULL;
         315               0 :     mb->s.zone          = NULL;
         316               0 :     mb->s.magic         = ZONE_MAGIC;
         317               0 :     mb->s.blockSize     = blockSize;
         318               0 :     mb->s.requestedSize = size;
         319                 :
         320               0 :     mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
         321               0 :     memcpy(mt, mb, sizeof *mb);
         322                 :
         323               0 :     rv = (void *)(mb + 1);
         324               0 :     return rv;
         325                 : }
         326                 :
         327                 :
         328                 : static void *
         329               0 : pr_ZoneCalloc(PRUint32 nelem, PRUint32 elsize)
         330                 : {
         331               0 :     PRUint32 size = nelem * elsize;
         332               0 :     void *p = pr_ZoneMalloc(size);
         333               0 :     if (p) {
         334               0 :         memset(p, 0, size);
         335                 :     }
         336               0 :     return p;
         337                 : }
         338                 :
         339                 : static void *
         340               0 : pr_ZoneRealloc(void *oldptr, PRUint32 bytes)
         341                 : {
         342                 :     void         *rv;
         343                 :     MemBlockHdr  *mb;
         344                 :     int           ours;
         345                 :     MemBlockHdr   phony;
         346                 :
         347               0 :     if (!oldptr)
         348               0 :         return pr_ZoneMalloc(bytes);
         349               0 :     mb = (MemBlockHdr *)((char *)oldptr - (sizeof *mb));
         350               0 :     if (mb->s.magic != ZONE_MAGIC) {
         351                 :         /* Maybe this just came from ordinary malloc */
         352                 : #ifdef DEBUG
         353               0 :         fprintf(stderr,
         354                 :             "Warning: reallocing memory block %p from ordinary malloc\n",
         355                 :             oldptr);
         356                 : #endif
         357                 :         /*
         358                 :          * We are going to realloc oldptr.  If realloc succeeds, the
         359                 :          * original value of oldptr will point to freed memory.  So this
         360                 :          * function must not fail after a successfull realloc call.  We
         361                 :          * must perform any operation that may fail before the realloc
         362                 :          * call.
         363                 :          */
         364               0 :         rv = pr_ZoneMalloc(bytes);  /* this may fail */
         365               0 :         if (!rv) {
         366               0 :             return rv;
         367                 :         }
         368                 :
         369                 :         /* We don't know how big it is.  But we can fix that. */
         370               0 :         oldptr = realloc(oldptr, bytes);
         371                 :         /*
         372                 :          * If realloc returns NULL, this function loses the original
         373                 :          * value of oldptr.  This isn't a leak because the caller of
         374                 :          * this function still has the original value of oldptr.
         375                 :          */
         376               0 :         if (!oldptr) {
         377               0 :             if (bytes) {
         378               0 :                 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
         379               0 :                 pr_ZoneFree(rv);
         380               0 :                 return oldptr;
         381                 :             }
         382                 :         }
         383               0 :         phony.s.requestedSize = bytes;
         384               0 :         mb = &phony;
         385               0 :         ours = 0;
         386                 :     } else {
         387               0 :         size_t blockSize = mb->s.blockSize;
         388               0 :         MemBlockHdr *mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
         389                 :
         390               0 :         PR_ASSERT(mt->s.magic == ZONE_MAGIC);
         391               0 :         PR_ASSERT(mt->s.zone  == mb->s.zone);
         392               0 :         PR_ASSERT(mt->s.blockSize == blockSize);
         393                 :
         394               0 :         if (bytes <= blockSize) {
         395                 :             /* The block is already big enough. */
         396               0 :             mt->s.requestedSize = mb->s.requestedSize = bytes;
         397               0 :             return oldptr;
         398                 :         }
         399               0 :         ours = 1;
         400               0 :         rv = pr_ZoneMalloc(bytes);
         401               0 :         if (!rv) {
         402               0 :             return rv;
         403                 :         }
         404                 :     }
         405                 :
         406               0 :     if (oldptr && mb->s.requestedSize)
         407               0 :         memcpy(rv, oldptr, mb->s.requestedSize);
         408               0 :     if (ours)
         409               0 :         pr_ZoneFree(oldptr);
         410               0 :     else if (oldptr)
         411               0 :         free(oldptr);
         412               0 :     return rv;
         413                 : }
         414                 :
         415                 : static void
         416               0 : pr_ZoneFree(void *ptr)
         417                 : {
         418                 :     MemBlockHdr  *mb, *mt;
         419                 :     MemoryZone   *mz;
         420                 :     size_t        blockSize;
         421                 :     PRUint32      wasLocked;
         422                 :
         423               0 :     if (!ptr)
         424               0 :         return;
         425                 :
         426               0 :     mb = (MemBlockHdr *)((char *)ptr - (sizeof *mb));
         427                 :
         428               0 :     if (mb->s.magic != ZONE_MAGIC) {
         429                 :         /* maybe this came from ordinary malloc */
         430                 : #ifdef DEBUG
         431               0 :         fprintf(stderr,
         432                 :             "Warning: freeing memory block %p from ordinary malloc\n", ptr);
         433                 : #endif
         434               0 :         free(ptr);
         435               0 :         return;
         436                 :     }
         437                 :
         438               0 :     blockSize = mb->s.blockSize;
         439               0 :     mz        = mb->s.zone;
         440               0 :     mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
         441               0 :     PR_ASSERT(mt->s.magic == ZONE_MAGIC);
         442               0 :     PR_ASSERT(mt->s.zone  == mz);
         443               0 :     PR_ASSERT(mt->s.blockSize == blockSize);
         444               0 :     if (!mz) {
         445               0 :         PR_ASSERT(blockSize > 65536);
         446                 :         /* This block was not in any zone.  Just free it. */
         447               0 :         free(mb);
         448               0 :         return;
         449                 :     }
         450               0 :     PR_ASSERT(mz->blockSize == blockSize);
         451               0 :     wasLocked = mz->locked;
         452               0 :     pthread_mutex_lock(&mz->lock);
         453               0 :     mz->locked = 1;
         454               0 :     if (wasLocked)
         455               0 :         mz->contention++;
         456               0 :     mt->s.next = mb->s.next = mz->head;        /* put on head of list */
         457               0 :     mz->head = mb;
         458               0 :     mz->elements++;
         459               0 :     mz->locked = 0;
         460               0 :     pthread_mutex_unlock(&mz->lock);
         461                 : }
         462                 :
         463         1751618 : PR_IMPLEMENT(void *) PR_Malloc(PRUint32 size)
         464                 : {
         465         1751618 :     if (!_pr_initialized) _PR_ImplicitInitialization();
         466                 :
         467         1751618 :     return use_zone_allocator ? pr_ZoneMalloc(size) : malloc(size);
         468                 : }
         469                 :
         470         2704553 : PR_IMPLEMENT(void *) PR_Calloc(PRUint32 nelem, PRUint32 elsize)
         471                 : {
         472         2704553 :     if (!_pr_initialized) _PR_ImplicitInitialization();
         473                 :
         474         5409106 :     return use_zone_allocator ?
         475         2704553 :         pr_ZoneCalloc(nelem, elsize) : calloc(nelem, elsize);
         476                 : }
         477                 :
         478           88393 : PR_IMPLEMENT(void *) PR_Realloc(void *ptr, PRUint32 size)
         479                 : {
         480           88393 :     if (!_pr_initialized) _PR_ImplicitInitialization();
         481                 :
         482           88393 :     return use_zone_allocator ? pr_ZoneRealloc(ptr, size) : realloc(ptr, size);
         483                 : }
         484                 :
         485         3667720 : PR_IMPLEMENT(void) PR_Free(void *ptr)
         486                 : {
         487         3667720 :     if (use_zone_allocator)
         488               0 :         pr_ZoneFree(ptr);
         489                 :     else
         490         3667720 :         free(ptr);
         491         3667720 : }
         492                 :
         493                 : #else /* !defined(_PR_ZONE_ALLOCATOR) */
         494                 :
         495                 : /*
         496                 : ** The PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free functions simply
         497                 : ** call their libc equivalents now.  This may seem redundant, but it
         498                 : ** ensures that we are calling into the same runtime library.  On
         499                 : ** Win32, it is possible to have multiple runtime libraries (e.g.,
         500                 : ** objects compiled with /MD and /MDd) in the same process, and
         501                 : ** they maintain separate heaps, which cannot be mixed.
         502                 : */
         503                 : PR_IMPLEMENT(void *) PR_Malloc(PRUint32 size)
         504                 : {
         505                 : #if defined (WIN16)
         506                 :     return PR_MD_malloc( (size_t) size);
         507                 : #else
         508                 :     return malloc(size);
         509                 : #endif
         510                 : }
         511                 :
         512                 : PR_IMPLEMENT(void *) PR_Calloc(PRUint32 nelem, PRUint32 elsize)
         513                 : {
         514                 : #if defined (WIN16)
         515                 :     return PR_MD_calloc( (size_t)nelem, (size_t)elsize );
         516                 :
         517                 : #else
         518                 :     return calloc(nelem, elsize);
         519                 : #endif
         520                 : }
         521                 :
         522                 : PR_IMPLEMENT(void *) PR_Realloc(void *ptr, PRUint32 size)
         523                 : {
         524                 : #if defined (WIN16)
         525                 :     return PR_MD_realloc( ptr, (size_t) size);
         526                 : #else
         527                 :     return realloc(ptr, size);
         528                 : #endif
         529                 : }
         530                 :
         531                 : PR_IMPLEMENT(void) PR_Free(void *ptr)
         532                 : {
         533                 : #if defined (WIN16)
         534                 :     PR_MD_free( ptr );
         535                 : #else
         536                 :     free(ptr);
         537                 : #endif
         538                 : }
         539                 :
         540                 : #endif /* _PR_ZONE_ALLOCATOR */
         541                 :
         542                 : /*
         543                 : ** Complexity alert!
         544                 : **
         545                 : ** If malloc/calloc/free (etc.) were implemented to use pr lock's then
         546                 : ** the entry points could block when called if some other thread had the
         547                 : ** lock.
         548                 : **
         549                 : ** Most of the time this isn't a problem. However, in the case that we
         550                 : ** are using the thread safe malloc code after PR_Init but before
         551                 : ** PR_AttachThread has been called (on a native thread that nspr has yet
         552                 : ** to be told about) we could get royally screwed if the lock was busy
         553                 : ** and we tried to context switch the thread away. In this scenario
         554                 : **      PR_CURRENT_THREAD() == NULL
         555                 : **
         556                 : ** To avoid this unfortunate case, we use the low level locking
         557                 : ** facilities for malloc protection instead of the slightly higher level
         558                 : ** locking. This makes malloc somewhat faster so maybe it's a good thing
         559                 : ** anyway.
         560                 : */
         561                 : #ifdef _PR_OVERRIDE_MALLOC
         562                 :
         563                 : /* Imports */
         564                 : extern void *_PR_UnlockedMalloc(size_t size);
         565                 : extern void *_PR_UnlockedMemalign(size_t alignment, size_t size);
         566                 : extern void _PR_UnlockedFree(void *ptr);
         567                 : extern void *_PR_UnlockedRealloc(void *ptr, size_t size);
         568                 : extern void *_PR_UnlockedCalloc(size_t n, size_t elsize);
         569                 :
         570                 : static PRBool _PR_malloc_initialised = PR_FALSE;
         571                 :
         572                 : #ifdef _PR_PTHREADS
         573                 : static pthread_mutex_t _PR_MD_malloc_crustylock;
         574                 :
         575                 : #define _PR_Lock_Malloc() {                                             \
         576                 :                                 if(PR_TRUE == _PR_malloc_initialised) { \
         577                 :                                         PRStatus rv;                    \
         578                 :                                         rv = pthread_mutex_lock(&_PR_MD_malloc_crustylock); \
         579                 :                                         PR_ASSERT(0 == rv);             \
         580                 :                                 }
         581                 :
         582                 : #define _PR_Unlock_Malloc()     if(PR_TRUE == _PR_malloc_initialised) { \
         583                 :                                         PRStatus rv;                    \
         584                 :                                         rv = pthread_mutex_unlock(&_PR_MD_malloc_crustylock); \
         585                 :                                         PR_ASSERT(0 == rv);             \
         586                 :                                 }                                       \
         587                 :                           }
         588                 : #else /* _PR_PTHREADS */
         589                 : static _MDLock _PR_MD_malloc_crustylock;
         590                 :
         591                 : #ifdef IRIX
         592                 : #define _PR_Lock_Malloc() {                                             \
         593                 :                            PRIntn _is;                                  \
         594                 :                                 if(PR_TRUE == _PR_malloc_initialised) { \
         595                 :                                 if (_PR_MD_GET_ATTACHED_THREAD() &&             \
         596                 :                                         !_PR_IS_NATIVE_THREAD(          \
         597                 :                                         _PR_MD_GET_ATTACHED_THREAD()))  \
         598                 :                                                 _PR_INTSOFF(_is);       \
         599                 :                                         _PR_MD_LOCK(&_PR_MD_malloc_crustylock); \
         600                 :                                 }
         601                 :
         602                 : #define _PR_Unlock_Malloc()     if(PR_TRUE == _PR_malloc_initialised) { \
         603                 :                                         _PR_MD_UNLOCK(&_PR_MD_malloc_crustylock); \
         604                 :                                 if (_PR_MD_GET_ATTACHED_THREAD() &&             \
         605                 :                                         !_PR_IS_NATIVE_THREAD(          \
         606                 :                                         _PR_MD_GET_ATTACHED_THREAD()))  \
         607                 :                                                 _PR_INTSON(_is);        \
         608                 :                                 }                                       \
         609                 :                           }
         610                 : #else   /* IRIX */
         611                 : #define _PR_Lock_Malloc() {                                             \
         612                 :                            PRIntn _is;                                  \
         613                 :                                 if(PR_TRUE == _PR_malloc_initialised) { \
         614                 :                                 if (_PR_MD_CURRENT_THREAD() &&          \
         615                 :                                         !_PR_IS_NATIVE_THREAD(          \
         616                 :                                         _PR_MD_CURRENT_THREAD()))       \
         617                 :                                                 _PR_INTSOFF(_is);       \
         618                 :                                         _PR_MD_LOCK(&_PR_MD_malloc_crustylock); \
         619                 :                                 }
         620                 :
         621                 : #define _PR_Unlock_Malloc()     if(PR_TRUE == _PR_malloc_initialised) { \
         622                 :                                         _PR_MD_UNLOCK(&_PR_MD_malloc_crustylock); \
         623                 :                                 if (_PR_MD_CURRENT_THREAD() &&          \
         624                 :                                         !_PR_IS_NATIVE_THREAD(          \
         625                 :                                         _PR_MD_CURRENT_THREAD()))       \
         626                 :                                                 _PR_INTSON(_is);        \
         627                 :                                 }                                       \
         628                 :                           }
         629                 : #endif  /* IRIX */
         630                 : #endif /* _PR_PTHREADS */
         631                 :
         632                 : PR_IMPLEMENT(PRStatus) _PR_MallocInit(void)
         633                 : {
         634                 :     PRStatus rv = PR_SUCCESS;
         635                 :
         636                 :     if( PR_TRUE == _PR_malloc_initialised ) return PR_SUCCESS;
         637                 :
         638                 : #ifdef _PR_PTHREADS
         639                 :     {
         640                 :         int status;
         641                 :         pthread_mutexattr_t mattr;
         642                 :
         643                 :         status = _PT_PTHREAD_MUTEXATTR_INIT(&mattr);
         644                 :         PR_ASSERT(0 == status);
         645                 :         status = _PT_PTHREAD_MUTEX_INIT(_PR_MD_malloc_crustylock, mattr);
         646                 :         PR_ASSERT(0 == status);
         647                 :         status = _PT_PTHREAD_MUTEXATTR_DESTROY(&mattr);
         648                 :         PR_ASSERT(0 == status);
         649                 :     }
         650                 : #else /* _PR_PTHREADS */
         651                 :     _MD_NEW_LOCK(&_PR_MD_malloc_crustylock);
         652                 : #endif /* _PR_PTHREADS */
         653                 :
         654                 :     if( PR_SUCCESS == rv )
         655                 :     {
         656                 :         _PR_malloc_initialised = PR_TRUE;
         657                 :     }
         658                 :
         659                 :     return rv;
         660                 : }
         661                 :
         662                 : void *malloc(size_t size)
         663                 : {
         664                 :     void *p;
         665                 :     _PR_Lock_Malloc();
         666                 :     p = _PR_UnlockedMalloc(size);
         667                 :     _PR_Unlock_Malloc();
         668                 :     return p;
         669                 : }
         670                 :
         671                 : #if defined(IRIX)
         672                 : void *memalign(size_t alignment, size_t size)
         673                 : {
         674                 :     void *p;
         675                 :     _PR_Lock_Malloc();
         676                 :     p = _PR_UnlockedMemalign(alignment, size);
         677                 :     _PR_Unlock_Malloc();
         678                 :     return p;
         679                 : }
         680                 :
         681                 : void *valloc(size_t size)
         682                 : {
         683                 :     return(memalign(sysconf(_SC_PAGESIZE),size));
         684                 : }
         685                 : #endif  /* IRIX */
         686                 :
         687                 : void free(void *ptr)
         688                 : {
         689                 :     _PR_Lock_Malloc();
         690                 :     _PR_UnlockedFree(ptr);
         691                 :     _PR_Unlock_Malloc();
         692                 : }
         693                 :
         694                 : void *realloc(void *ptr, size_t size)
         695                 : {
         696                 :     void *p;
         697                 :     _PR_Lock_Malloc();
         698                 :     p = _PR_UnlockedRealloc(ptr, size);
         699                 :     _PR_Unlock_Malloc();
         700                 :     return p;
         701                 : }
         702                 :
         703                 : void *calloc(size_t n, size_t elsize)
         704                 : {
         705                 :     void *p;
         706                 :     _PR_Lock_Malloc();
         707                 :     p = _PR_UnlockedCalloc(n, elsize);
         708                 :     _PR_Unlock_Malloc();
         709                 :     return p;
         710                 : }
         711                 :
         712                 : void cfree(void *p)
         713                 : {
         714                 :     _PR_Lock_Malloc();
         715                 :     _PR_UnlockedFree(p);
         716                 :     _PR_Unlock_Malloc();
         717                 : }
         718                 :
         719                 : void _PR_InitMem(void)
         720                 : {
         721                 :     PRStatus rv;
         722                 :     rv = _PR_MallocInit();
         723                 :     PR_ASSERT(PR_SUCCESS == rv);
         724                 : }
         725                 :
         726                 : #endif /* _PR_OVERRIDE_MALLOC */

Generated by: LCOV version 1.7