Skip to content

Commit 924c96c

Browse files
committed
Fix lua GC to support allocations across multiple threads (e.g. threads sharedserialize)
1 parent e7f2a2a commit 924c96c

File tree

3 files changed

+105
-14
lines changed

3 files changed

+105
-14
lines changed

THAtomic.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,61 @@ int THAtomicCompareAndSwap(int volatile *a, int oldvalue, int newvalue)
101101
return 0;
102102
#endif
103103
}
104+
105+
long THAtomicGetLong(long volatile *a)
106+
{
107+
#if defined(USE_C11_ATOMICS)
108+
return atomic_load(a);
109+
#else
110+
long value;
111+
do {
112+
value = *a;
113+
} while (!THAtomicCompareAndSwapLong(a, value, value));
114+
return value;
115+
#endif
116+
}
117+
118+
long THAtomicAddLong(long volatile *a, long value)
119+
{
120+
#if defined(USE_C11_ATOMICS)
121+
return atomic_fetch_add(a, value);
122+
#elif defined(USE_MSC_ATOMICS)
123+
return _InterlockedExchangeAdd(a, value);
124+
#elif defined(USE_GCC_ATOMICS)
125+
return __sync_fetch_and_add(a, value);
126+
#else
127+
long oldvalue;
128+
do {
129+
oldvalue = *a;
130+
} while (!THAtomicCompareAndSwapLong(a, oldvalue, (oldvalue + value)));
131+
return oldvalue;
132+
#endif
133+
}
134+
135+
long THAtomicCompareAndSwapLong(long volatile *a, long oldvalue, long newvalue)
136+
{
137+
#if defined(USE_C11_ATOMICS)
138+
return atomic_compare_exchange_strong(a, &oldvalue, newvalue);
139+
#elif defined(USE_MSC_ATOMICS)
140+
return (_InterlockedCompareExchange(a, newvalue, oldvalue) == oldvalue);
141+
#elif defined(USE_GCC_ATOMICS)
142+
return __sync_bool_compare_and_swap(a, oldvalue, newvalue);
143+
#elif defined(USE_PTHREAD_ATOMICS)
144+
long ret = 0;
145+
pthread_mutex_lock(&ptm);
146+
if(*a == oldvalue) {
147+
*a = newvalue;
148+
ret = 1;
149+
}
150+
pthread_mutex_unlock(&ptm);
151+
return ret;
152+
#else
153+
#warning THAtomic is not thread safe
154+
if(*a == oldvalue) {
155+
*a = newvalue;
156+
return 1;
157+
}
158+
else
159+
return 0;
160+
#endif
161+
}

THAtomic.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,28 @@ TH_API void THAtomicIncrementRef(int volatile *a);
5757
*/
5858
TH_API int THAtomicDecrementRef(int volatile *a);
5959

60+
61+
62+
/******************************************************************************
63+
* functions for long type
64+
******************************************************************************/
65+
66+
/*
67+
* return *a
68+
*/
69+
TH_API long THAtomicGetLong(long volatile *a);
70+
71+
/*
72+
* *a += value,
73+
* return previous *a
74+
*/
75+
TH_API long THAtomicAddLong(long volatile *a, long value);
76+
77+
/*
78+
* check if (*a == oldvalue)
79+
* if true: set *a to newvalue, return 1
80+
* if false: return 0
81+
*/
82+
TH_API long THAtomicCompareAndSwapLong(long volatile *a, long oldvalue, long newvalue);
83+
6084
#endif

THGeneral.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#include "THGeneral.h"
2+
#include "THAtomic.h"
23

34
#ifndef TH_HAVE_THREAD
45
#define __thread
56
#endif
67

7-
#if defined(TH_DISABLE_HEAP_TRACKING)
8-
#elif (defined(__unix) || defined(_WIN32))
8+
#if (defined(__unix) || defined(_WIN32))
99
#include <malloc.h>
1010
#elif defined(__APPLE__)
1111
#include <malloc/malloc.h>
@@ -101,8 +101,10 @@ void THSetArgErrorHandler( void (*torchArgErrorHandlerFunction_)(int argNumber,
101101

102102
static __thread void (*torchGCFunction)(void *data) = NULL;
103103
static __thread void *torchGCData;
104-
static __thread long torchHeapSize = 0;
105-
static __thread long torchHeapSizeSoftMax = 300000000; // 300MB, adjusted upward dynamically
104+
static long heapSize = 0;
105+
static __thread long heapSoftmax = 300000000; // 300MB, adjusted upward dynamically
106+
static const double heapSoftmaxGrowthThresh = 0.8; // grow softmax if >80% max after GC
107+
static const double heapSoftmaxGrowthFactor = 1.4; // grow softmax by 40%
106108

107109
/* Optional hook for integrating with a garbage-collected frontend.
108110
*
@@ -121,9 +123,7 @@ void THSetGCHandler( void (*torchGCFunction_)(void *data), void *data )
121123
}
122124

123125
static long getAllocSize(void *ptr) {
124-
#if defined(TH_DISABLE_HEAP_TRACKING)
125-
return 0;
126-
#elif defined(__unix)
126+
#if defined(__unix)
127127
return malloc_usable_size(ptr);
128128
#elif defined(__APPLE__)
129129
return malloc_size(ptr);
@@ -138,20 +138,29 @@ static long getAllocSize(void *ptr) {
138138
* (2) if post-GC heap size exceeds 80% of the soft max, increase the
139139
* soft max by 40%
140140
*/
141-
static void maybeTriggerGC() {
142-
if(torchGCFunction && torchHeapSize > torchHeapSizeSoftMax) {
141+
static void maybeTriggerGC(long curHeapSize) {
142+
if(torchGCFunction && curHeapSize > heapSoftmax ) {
143143
torchGCFunction(torchGCData);
144-
if(torchHeapSize > torchHeapSizeSoftMax * 0.8) {
145-
torchHeapSizeSoftMax = torchHeapSizeSoftMax * 1.4;
144+
long newHeapSize = THAtomicGetLong(&heapSize);
145+
if(newHeapSize > heapSoftmax * heapSoftmaxGrowthThresh) {
146+
heapSoftmax = heapSoftmax * heapSoftmaxGrowthFactor;
146147
}
147148
}
148149
}
149150

150151
// hooks into the TH heap tracking
151152
void THHeapUpdate(long size) {
152-
torchHeapSize += size;
153-
if (size > 0)
154-
maybeTriggerGC();
153+
long newHeapSize = THAtomicAddLong(&heapSize, size) + size;
154+
155+
# ifdef TH_CHECK_HEAP_UPDATE
156+
if (newHeapSize < 0) {
157+
THError("Torch heap size <0 ?");
158+
}
159+
#endif
160+
161+
if (size > 0) {
162+
maybeTriggerGC(newHeapSize);
163+
}
155164
}
156165

157166
static void* THAllocInternal(long size)

0 commit comments

Comments
 (0)