home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / malloc / prmem.c < prev   
Encoding:
C/C++ Source or Header  |  1998-04-08  |  6.0 KB  |  234 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20. ** Thread safe versions of malloc, free, realloc, calloc and cfree.
  21. */
  22.  
  23. #include "primpl.h"
  24.  
  25. /*
  26. ** The PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free functions simply
  27. ** call their libc equivalents now.  This may seem redundant, but it
  28. ** ensures that we are calling into the same runtime library.  On
  29. ** Win32, it is possible to have multiple runtime libraries (e.g.,
  30. ** objects compiled with /MD and /MDd) in the same process, and
  31. ** they maintain separate heaps, which cannot be mixed.
  32. */
  33. PR_IMPLEMENT(void *) PR_Malloc(PRUint32 size)
  34. {
  35. #if defined (WIN16)
  36.     return PR_MD_malloc( (size_t) size);
  37. #else
  38.     return malloc(size);
  39. #endif
  40. }
  41.  
  42. PR_IMPLEMENT(void *) PR_Calloc(PRUint32 nelem, PRUint32 elsize)
  43. {
  44. #if defined (WIN16)
  45.     return PR_MD_calloc( (size_t)nelem, (size_t)elsize );
  46.     
  47. #else
  48.     return calloc(nelem, elsize);
  49. #endif
  50. }
  51.  
  52. PR_IMPLEMENT(void *) PR_Realloc(void *ptr, PRUint32 size)
  53. {
  54. #if defined (WIN16)
  55.     return PR_MD_realloc( ptr, (size_t) size);
  56. #else
  57.     return realloc(ptr, size);
  58. #endif
  59. }
  60.  
  61. PR_IMPLEMENT(void) PR_Free(void *ptr)
  62. {
  63. #if defined (WIN16)
  64.     PR_MD_free( ptr );
  65. #else
  66.     free(ptr);
  67. #endif
  68. }
  69.  
  70. /*
  71. ** Complexity alert!
  72. **
  73. ** If malloc/calloc/free (etc.) were implemented to use pr lock's then
  74. ** the entry points could block when called if some other thread had the
  75. ** lock.
  76. **
  77. ** Most of the time this isn't a problem. However, in the case that we
  78. ** are using the thread safe malloc code after PR_Init but before
  79. ** PR_AttachThread has been called (on a native thread that nspr has yet
  80. ** to be told about) we could get royally screwed if the lock was busy
  81. ** and we tried to context switch the thread away. In this scenario
  82. **     PR_CURRENT_THREAD() == NULL
  83. **
  84. ** To avoid this unfortunate case, we use the low level locking
  85. ** facilities for malloc protection instead of the slightly higher level
  86. ** locking. This makes malloc somewhat faster so maybe it's a good thing
  87. ** anyway.
  88. */
  89. #ifdef _PR_OVERRIDE_MALLOC
  90.  
  91. /* Imports */
  92. extern void *_PR_UnlockedMalloc(size_t size);
  93. extern void *_PR_UnlockedMemalign(size_t alignment, size_t size);
  94. extern void _PR_UnlockedFree(void *ptr);
  95. extern void *_PR_UnlockedRealloc(void *ptr, size_t size);
  96. extern void *_PR_UnlockedCalloc(size_t n, size_t elsize);
  97.  
  98. static PRBool _PR_malloc_initialised = PR_FALSE;
  99.  
  100. #ifdef _PR_PTHREADS
  101. static pthread_mutex_t _PR_MD_malloc_crustylock;
  102.  
  103. #define _PR_Lock_Malloc() {                        \
  104.                     if(PR_TRUE == _PR_malloc_initialised) { \
  105.                     PRStatus rv;            \
  106.                     rv = pthread_mutex_lock(&_PR_MD_malloc_crustylock); \
  107.                     PR_ASSERT(0 == rv);        \
  108.                 }
  109.  
  110. #define _PR_Unlock_Malloc()     if(PR_TRUE == _PR_malloc_initialised) { \
  111.                     PRStatus rv;            \
  112.                     rv = pthread_mutex_unlock(&_PR_MD_malloc_crustylock); \
  113.                     PR_ASSERT(0 == rv);        \
  114.                 }                    \
  115.               }
  116. #else /* _PR_PTHREADS */
  117. static _MDLock _PR_MD_malloc_crustylock;
  118.  
  119. #define _PR_Lock_Malloc() {                        \
  120.                PRIntn _is;                    \
  121.                     if(PR_TRUE == _PR_malloc_initialised) { \
  122.                 if (_PR_MD_CURRENT_THREAD() &&         \
  123.                     !_PR_IS_NATIVE_THREAD(         \
  124.                     _PR_MD_CURRENT_THREAD()))    \
  125.                         _PR_INTSOFF(_is);     \
  126.                     _PR_MD_LOCK(&_PR_MD_malloc_crustylock); \
  127.                 }
  128.  
  129. #define _PR_Unlock_Malloc()     if(PR_TRUE == _PR_malloc_initialised) { \
  130.                     _PR_MD_UNLOCK(&_PR_MD_malloc_crustylock); \
  131.                 if (_PR_MD_CURRENT_THREAD() &&         \
  132.                     !_PR_IS_NATIVE_THREAD(         \
  133.                     _PR_MD_CURRENT_THREAD()))    \
  134.                         _PR_INTSON(_is);    \
  135.                 }                    \
  136.               }
  137. #endif /* _PR_PTHREADS */
  138.  
  139. PR_IMPLEMENT(PRStatus) _PR_MallocInit(void)
  140. {
  141.     PRStatus rv = PR_SUCCESS;
  142.  
  143.     if( PR_TRUE == _PR_malloc_initialised ) return PR_SUCCESS;
  144.  
  145. #ifdef _PR_PTHREADS
  146.     {
  147.     int status;
  148.     pthread_mutexattr_t mattr;
  149.  
  150.     status = PTHREAD_MUTEXATTR_INIT(&mattr);
  151.     PR_ASSERT(0 == status);
  152.     status = PTHREAD_MUTEX_INIT(_PR_MD_malloc_crustylock, mattr);
  153.     PR_ASSERT(0 == status);
  154.     status = PTHREAD_MUTEXATTR_DESTROY(&mattr);
  155.     PR_ASSERT(0 == status);
  156.     }
  157. #else /* _PR_PTHREADS */
  158.     _MD_NEW_LOCK(&_PR_MD_malloc_crustylock);
  159. #endif /* _PR_PTHREADS */
  160.  
  161.     if( PR_SUCCESS == rv )
  162.     {
  163.         _PR_malloc_initialised = PR_TRUE;
  164.     }
  165.  
  166.     return rv;
  167. }
  168.  
  169. void *malloc(size_t size)
  170. {
  171.     void *p;
  172.     _PR_Lock_Malloc();
  173.     p = _PR_UnlockedMalloc(size);
  174.     _PR_Unlock_Malloc();
  175.     return p;
  176. }
  177.  
  178. #if defined(IRIX)
  179. void *memalign(size_t alignment, size_t size)
  180. {
  181.     void *p;
  182.     _PR_Lock_Malloc();
  183.     p = _PR_UnlockedMemalign(alignment, size);
  184.     _PR_Unlock_Malloc();
  185.     return p;
  186. }
  187.  
  188. void *valloc(size_t size)
  189. {
  190.     return(memalign(sysconf(_SC_PAGESIZE),size));
  191. }
  192. #endif    /* IRIX */
  193.  
  194. void free(void *ptr)
  195. {
  196.     _PR_Lock_Malloc();
  197.     _PR_UnlockedFree(ptr);
  198.     _PR_Unlock_Malloc();
  199. }
  200.  
  201. void *realloc(void *ptr, size_t size)
  202. {
  203.     void *p;
  204.     _PR_Lock_Malloc();
  205.     p = _PR_UnlockedRealloc(ptr, size);
  206.     _PR_Unlock_Malloc();
  207.     return p;
  208. }
  209.  
  210. void *calloc(size_t n, size_t elsize)
  211. {
  212.     void *p;
  213.     _PR_Lock_Malloc();
  214.     p = _PR_UnlockedCalloc(n, elsize);
  215.     _PR_Unlock_Malloc();
  216.     return p;
  217. }
  218.  
  219. void cfree(void *p)
  220. {
  221.     _PR_Lock_Malloc();
  222.     _PR_UnlockedFree(p);
  223.     _PR_Unlock_Malloc();
  224. }
  225.  
  226. void _PR_InitMem(void)
  227. {
  228.     PRStatus rv;
  229.     rv = _PR_MallocInit();
  230.     PR_ASSERT(PR_SUCCESS == rv);
  231. }
  232.  
  233. #endif /* _PR_OVERRIDE_MALLOC */
  234.