LCOV - code coverage report
Current view: top level - nsprpub/pr/src/malloc - prmem.c (source / functions) Hit Total Coverage
Test: output.info Lines: 21 193 10.9 %
Date: 2017-07-14 16:53:18 Functions: 2 8 25.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13