Changeset: 9682c557c929 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=9682c557c929
Modified Files:
        gdk/gdk_utils.c
Branch: Feb2013
Log Message:

Use atomic operations to count memory use.
This implies no explicit locking.
Implemented for both GNU and Micorsoft compilers with a fallback using
locks for other compilers.


diffs (truncated from 332 to 300 lines):

diff --git a/gdk/gdk_utils.c b/gdk/gdk_utils.c
--- a/gdk/gdk_utils.c
+++ b/gdk/gdk_utils.c
@@ -313,10 +313,98 @@ int GDK_vm_trim = 1;
        } while (0)
 #endif
 
-static volatile size_t GDK_mallocedbytes_estimate = 0;
-static volatile size_t GDK_vm_cursize = 0;
-
+/* This block is to provide atomic addition and subtraction to select
+ * variables.  We use intrinsic functions (recognized and inlined by
+ * the compiler) for both the GNU C compiler and Microsoft Visual
+ * Studio.  By doing this, we avoid locking overhead.  There is also a
+ * fall-back for other compilers. */
+#if defined(__GNUC__)
+#if SIZEOF_SSIZE_T == SIZEOF_LONG_LONG
+static volatile long long GDK_mallocedbytes_estimate = 0;
+static volatile long long GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile long long GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile long long GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
+#define ATOMIC_ADD(var, val)   __sync_add_and_fetch(&var, (long long) (val))
+#define ATOMIC_INC(var)                __sync_add_and_fetch(&var, (long long) 
1)
+#define ATOMIC_SUB(var, val)   __sync_sub_and_fetch(&var, (long long) (val))
+#define ATOMIC_DEC(var)                __sync_sub_and_fetch(&var, (long long) 
1)
+#else
+static volatile long GDK_mallocedbytes_estimate = 0;
+static volatile long GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile long GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile long GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
+#define ATOMIC_ADD(var, val)   __sync_add_and_fetch(&var, (long) (val))
+#define ATOMIC_INC(var)                __sync_add_and_fetch(&var, (long) 1)
+#define ATOMIC_SUB(var, val)   __sync_sub_and_fetch(&var, (long) (val))
+#define ATOMIC_DEC(var)                __sync_sub_and_fetch(&var, (long) 1)
+#endif
+#define ATOMIC_START(func)
+#define ATOMIC_END(func)
+#define ATOMIC_INIT(func)
+#elif defined(_MSC_VER)
+#include <intrin.h>
+#if SIZEOF_SSIZE_T == SIZEOF___INT64
+static volatile __int64 GDK_mallocedbytes_estimate = 0;
+static volatile __int64 GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile __int64 GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile __int64 GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
+#define ATOMIC_ADD(var, val)   _InterlockedExchangeAdd64(&var, (__int64) (val))
+#define ATOMIC_INC(var)                _InterlockedIncrement64(&var)
+#define ATOMIC_SUB(var, val)   _InterlockedExchangeAdd64(&var, -(__int64) 
(val))
+#define ATOMIC_DEC(var)                _InterlockedDecrement64(&var)
+#pragma intrinsic(_InterlockedExchangeAdd64)
+#pragma intrinsic(_InterlockedIncrement64)
+#pragma intrinsic(_InterlockedDecrement64)
+#else
+static volatile long GDK_mallocedbytes_estimate = 0;
+static volatile long GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile long GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile long GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
+#define ATOMIC_ADD(var, val)   _InterlockedExchangeAdd(&var, (long) (val))
+#define ATOMIC_INC(var)                _InterlockedIncrement(&var)
+#define ATOMIC_SUB(var, val)   _InterlockedExchangeAdd(&var, -(long) (val))
+#define ATOMIC_DEC(var)                _InterlockedDecrement(&var)
+#pragma intrinsic(_InterlockedExchangeAdd)
+#pragma intrinsic(_InterlockedIncrement)
+#pragma intrinsic(_InterlockedDecrement)
+#endif
+#define ATOMIC_START(func)
+#define ATOMIC_END(func)
+#define ATOMIC_INIT(func)
+#else
+static volatile ssize_t GDK_mallocedbytes_estimate = 0;
+static volatile ssize_t GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile ssize_t GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile ssize_t GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
 static MT_Lock mbyteslock;
+#define ATOMIC_ADD(var, val)   var += (ssize_t) (val)
+#define ATOMIC_INC(var)                var++
+#define ATOMIC_SUB(var, val)   var -= (ssize_t) (val)
+#define ATOMIC_DEC(var)                var--
+#define ATOMIC_START(func)     MT_lock_set(&mbyteslock, func)
+#define ATOMIC_END(func)       MT_lock_unset(&mbyteslock, func)
+#define ATOMIC_INIT(func)      MT_lock_init(&mbyteslock, func)
+#endif
 
 size_t _MT_pagesize = 0;       /* variable holding memory size */
 size_t _MT_npages = 0;         /* variable holding page size */
@@ -432,9 +520,9 @@ GDKmem_inuse(void)
        /* RAM/swapmem that Monet is really using now */
        size_t mem_mallocedbytes_estimate;
 
-       MT_lock_set(&mbyteslock, "GDKmem_inuse");
-       mem_mallocedbytes_estimate = GDK_mallocedbytes_estimate;
-       MT_lock_unset(&mbyteslock, "GDKmem_inuse");
+       ATOMIC_START("GDKmem_inuse");
+       mem_mallocedbytes_estimate = (size_t) GDK_mallocedbytes_estimate;
+       ATOMIC_END("GDKmem_inuse");
 
        return mem_mallocedbytes_estimate;
 }
@@ -445,127 +533,90 @@ GDKvm_cursize(void)
        /* current Monet VM address space usage */
        size_t vm_cursize;
 
-       MT_lock_set(&mbyteslock, "GDKvm_cursize");
-       vm_cursize = GDK_vm_cursize;
-       MT_lock_unset(&mbyteslock, "GDKvm_cursize");
+       ATOMIC_START("GDKvm_cursize");
+       vm_cursize = (size_t) GDK_vm_cursize;
+       ATOMIC_END("GDKvm_cursize");
 
        return vm_cursize + GDKmem_inuse();
 }
 
-#ifdef GDK_VM_KEEPHISTO
-volatile ssize_t GDK_vm_nallocs[MAX_BIT] = { 0 };
-#endif
 #ifdef GDK_MEM_KEEPHISTO
-volatile ssize_t GDK_nmallocs[MAX_BIT] = { 0 };
-#endif
-
-static volatile int GDK_heapcheck_last = 0;
-
-static void
-GDKmem_heapcheck(int t)
-{
-       /* correct heap estimate with the real thing */
-       struct Mallinfo m = MT_mallinfo();
-
-       GDK_mallocedbytes_estimate = (size_t) (m.usmblks + m.uordblks + 
m.hblkhd);
-       GDK_heapcheck_last = t;
-}
-
-#ifdef GDK_MEM_KEEPHISTO
-#define heapinc(_memdelta)                                     \
-       do {                                                    \
-               int _idx;                                       \
-                                                               \
-               MT_lock_set(&mbyteslock, "heapinc");            \
-               GDK_mallocedbytes_estimate += (_memdelta);      \
-               GDKmallidx(_idx, _memdelta);                    \
-               GDK_nmallocs[_idx]++;                           \
-               MT_lock_unset(&mbyteslock, "heapinc");          \
+#define heapinc(_memdelta)                                             \
+       do {                                                            \
+               int _idx;                                               \
+                                                                       \
+               ATOMIC_START("heapinc");                                \
+               ATOMIC_ADD(GDK_mallocedbytes_estimate, _memdelta);      \
+               GDKmallidx(_idx, _memdelta);                            \
+               ATOMIC_INC(GDK_nmallocs[_idx]);                         \
+               ATOMIC_END("heapinc");                                  \
        } while (0)
 #define heapdec(memdelta)                                              \
        do {                                                            \
-               size_t _memdelta = (size_t) (memdelta);                 \
+               ssize_t _memdelta = (ssize_t) (memdelta);               \
                int _idx;                                               \
                                                                        \
-               MT_lock_set(&mbyteslock, "heapdec");                    \
-               if (_memdelta > GDK_mallocedbytes_estimate) {           \
-                       /* clearly, the stats are off: it should never  \
-                        * become less-than-zero */                     \
-                       GDKmem_heapcheck(GDKms());                      \
-               } else {                                                \
-                       GDK_mallocedbytes_estimate -= _memdelta;        \
-               }                                                       \
+               ATOMIC_START("heapdec");                                \
+               ATOMIC_SUB(GDK_mallocedbytes_estimate, _memdelta);      \
                GDKmallidx(_idx, _memdelta);                            \
-               GDK_nmallocs[_idx]--;                                   \
-               MT_lock_unset(&mbyteslock, "heapdec");                  \
+               ATOMIC_DEC(GDK_nmallocs[_idx]);                         \
+               ATOMIC_END("heapdec");                                  \
        } while (0)
 #else
-#define heapinc(_memdelta)                                     \
-       do {                                                    \
-               MT_lock_set(&mbyteslock, "heapinc");            \
-               GDK_mallocedbytes_estimate += (_memdelta);      \
-               MT_lock_unset(&mbyteslock, "heapinc");          \
+#define heapinc(_memdelta)                                             \
+       do {                                                            \
+               ATOMIC_START("heapinc");                                \
+               ATOMIC_ADD(GDK_mallocedbytes_estimate, _memdelta);      \
+               ATOMIC_END("heapinc");                                  \
        } while (0)
 #define heapdec(memdelta)                                              \
        do {                                                            \
-               size_t _memdelta = (size_t) (memdelta);                 \
-               MT_lock_set(&mbyteslock, "heapdec");                    \
-               if (_memdelta > GDK_mallocedbytes_estimate) {           \
-                       /* clearly, the stats are off: it should never  \
-                        * become less-than-zero */                     \
-                       GDKmem_heapcheck(GDKms());                      \
-               } else {                                                \
-                       GDK_mallocedbytes_estimate -= _memdelta;        \
-               }                                                       \
-               MT_lock_unset(&mbyteslock, "heapdec");                  \
+               ssize_t _memdelta = (ssize_t) (memdelta);               \
+               ATOMIC_START("heapdec");                                \
+               ATOMIC_SUB(GDK_mallocedbytes_estimate, _memdelta);      \
+               ATOMIC_END("heapdec");                                  \
        } while (0)
 #endif
 
 #ifdef GDK_VM_KEEPHISTO
 #define meminc(vmdelta, fcn)                                           \
        do {                                                            \
-               size_t _vmdelta = (size_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
+               ssize_t _vmdelta = (ssize_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
                int _idx;                                               \
                                                                        \
-               MT_lock_set(&mbyteslock, fcn);                          \
+               ATOMIC_START(fcn);                                      \
                GDKmallidx(_idx, _vmdelta);                             \
-               GDK_vm_nallocs[_idx]++;                                 \
-               GDK_vm_cursize += _vmdelta;                             \
-               MT_lock_unset(&mbyteslock, fcn);                        \
+               ATOMIC_INC(GDK_vm_nallocs[_idx]);                       \
+               ATOMIC_ADD(GDK_vm_cursize, _vmdelta);                   \
+               ATOMIC_END(fcn);                                        \
        } while (0)
 #define memdec(vmdelta, fcn)                                           \
        do {                                                            \
-               size_t _vmdelta = (size_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
+               ssize_t _vmdelta = (ssize_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
                int _idx;                                               \
                                                                        \
-               MT_lock_set(&mbyteslock, fcn);                          \
+               ATOMIC_START(fcn);                                      \
                GDKmallidx(_idx, _vmdelta);                             \
-               GDK_vm_nallocs[_idx]--;                                 \
-               if (_vmdelta > GDK_vm_cursize)                          \
-                       GDK_vm_cursize = 0;                             \
-               else                                                    \
-                       GDK_vm_cursize -= _vmdelta;                     \
-               MT_lock_unset(&mbyteslock, fcn);                        \
+               ATOMIC_DEC(GDK_vm_nallocs[_idx]);                       \
+               ATOMIC_SUB(GDK_vm_cursize, _vmdelta);                   \
+               ATOMIC_END(fcn);                                        \
        } while (0)
 #else
 #define meminc(vmdelta, fcn)                                           \
        do {                                                            \
-               size_t _vmdelta = (size_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
+               ssize_t _vmdelta = (ssize_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
                                                                        \
-               MT_lock_set(&mbyteslock, fcn);                          \
-               GDK_vm_cursize += _vmdelta;                             \
-               MT_lock_unset(&mbyteslock, fcn);                        \
+               ATOMIC_START(fcn);                                      \
+               ATOMIC_ADD(GDK_vm_cursize, _vmdelta);                   \
+               ATOMIC_END(fcn);                                        \
        } while (0)
 #define memdec(vmdelta, fcn)                                           \
        do {                                                            \
-               size_t _vmdelta = (size_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
+               ssize_t _vmdelta = (ssize_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
                                                                        \
-               MT_lock_set(&mbyteslock, fcn);                          \
-               if (_vmdelta > GDK_vm_cursize)                          \
-                       GDK_vm_cursize = 0;                             \
-               else                                                    \
-                       GDK_vm_cursize -= _vmdelta;                     \
-               MT_lock_unset(&mbyteslock, fcn);                        \
+               ATOMIC_START(fcn);                                      \
+               ATOMIC_SUB(GDK_vm_cursize, _vmdelta);                   \
+               ATOMIC_END(fcn);                                        \
        } while (0)
 #endif
 
@@ -589,28 +640,28 @@ GDKmemdump(void)
        {
                int i;
 
-               MT_lock_set(&mbyteslock, "GDKmemdump");
+               ATOMIC_START("GDKmemdump");
                THRprintf(GDKstdout, "#memory histogram\n");
                for (i = 3; i < GDK_HISTO_MAX_BIT - 1; i++) {
                        size_t j = 1 << i;
 
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to