Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 6 additions & 33 deletions mono/metadata/mempool.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

#include "mempool.h"
#include "mempool-internals.h"
#include "utils/mono-compiler.h"
#include "utils/atomic.h"

/*
* MonoMemPool is for fast allocation of memory. We free
Expand Down Expand Up @@ -94,18 +94,9 @@ mono_mempool_new (void)
/**
* mono_mempool_new_size:
*
* clang's ThreadSanitizer detects races of total_bytes_allocated and pool->d.allocated throughout the functions
* * mono_mempool_alloc
* * mono_mempool_new_size
* * mono_mempool_destroy
* while these races could lead to wrong values, total_bytes_allocated is just used for debugging / reporting and since
* the mempool.c functions are called quite often, a discussion led the the conclusion of ignoring these races:
* https://bugzilla.xamarin.com/show_bug.cgi?id=57936
*
* \param initial_size the amount of memory to initially reserve for the memory pool.
* \returns a new memory pool with a specific initial memory reservation.
*/
MONO_NO_SANITIZE_THREAD
MonoMemPool *
mono_mempool_new_size (int initial_size)
{
Expand All @@ -125,32 +116,23 @@ mono_mempool_new_size (int initial_size)
pool->pos = (guint8*)pool + SIZEOF_MEM_POOL; // Start after header
pool->end = (guint8*)pool + initial_size; // End at end of allocated space
pool->d.allocated = pool->size = initial_size;
total_bytes_allocated += initial_size;
InterlockedAdd64 ((gint64*)&total_bytes_allocated, (gint64)initial_size);
return pool;
}

/**
* mono_mempool_destroy:
*
* clang's ThreadSanitizer detects races of total_bytes_allocated and pool->d.allocated throughout the functions
* * mono_mempool_alloc
* * mono_mempool_new_size
* * mono_mempool_destroy
* while these races could lead to wrong values, total_bytes_allocated is just used for debugging / reporting and since
* the mempool.c functions are called quite often, a discussion led the the conclusion of ignoring these races:
* https://bugzilla.xamarin.com/show_bug.cgi?id=57936
*
* \param pool the memory pool to destroy
*
* Free all memory associated with this pool.
*/
MONO_NO_SANITIZE_THREAD
void
mono_mempool_destroy (MonoMemPool *pool)
{
MonoMemPool *p, *n;

total_bytes_allocated -= pool->d.allocated;
InterlockedSubtract64 ((gint64*)&total_bytes_allocated, (gint64)pool->d.allocated);

p = pool;
while (p) {
Expand Down Expand Up @@ -273,22 +255,13 @@ get_next_size (MonoMemPool *pool, int size)
/**
* mono_mempool_alloc:
*
* clang's ThreadSanitizer detects races of total_bytes_allocated and pool->d.allocated throughout the functions
* * mono_mempool_alloc
* * mono_mempool_new_size
* * mono_mempool_destroy
* while these races could lead to wrong values, total_bytes_allocated is just used for debugging / reporting and since
* the mempool.c functions are called quite often, a discussion led the the conclusion of ignoring these races:
* https://bugzilla.xamarin.com/show_bug.cgi?id=57936
*
* \param pool the memory pool to use
* \param size size of the memory block
*
* Allocates a new block of memory in \p pool .
*
* \returns the address of a newly allocated memory block.
*/
MONO_NO_SANITIZE_THREAD
gpointer
mono_mempool_alloc (MonoMemPool *pool, guint size)
{
Expand Down Expand Up @@ -318,7 +291,7 @@ mono_mempool_alloc (MonoMemPool *pool, guint size)
np->size = new_size;
pool->next = np;
pool->d.allocated += new_size;
total_bytes_allocated += new_size;
InterlockedAdd64 ((gint64*)&total_bytes_allocated, (gint64)new_size);

rval = (guint8*)np + SIZEOF_MEM_POOL;
} else {
Expand All @@ -332,7 +305,7 @@ mono_mempool_alloc (MonoMemPool *pool, guint size)
pool->pos = (guint8*)np + SIZEOF_MEM_POOL;
pool->end = (guint8*)np + new_size;
pool->d.allocated += new_size;
total_bytes_allocated += new_size;
InterlockedAdd64 ((gint64*)&total_bytes_allocated, (gint64)new_size);

rval = pool->pos;
pool->pos += size;
Expand Down Expand Up @@ -462,5 +435,5 @@ mono_mempool_get_allocated (MonoMemPool *pool)
long
mono_mempool_get_bytes_allocated (void)
{
return total_bytes_allocated;
return InterlockedRead64 ((gint64*)&total_bytes_allocated);
}
82 changes: 82 additions & 0 deletions mono/utils/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,47 @@ static inline gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
#endif
#endif

/* InterlockedSubtract and InterlockedSubtract64 are not defined anywhere
* which is why we can safely define them without major checks */

#if defined(__sync_sub_and_fetch)

static inline gint32 InterlockedSubtract(volatile gint32 *dest, gint32 sub)
{
return __sync_sub_and_fetch (dest, sub);
}

static inline gint64 InterlockedSubtract64(volatile gint64 *dest, gint64 sub)
{
return __sync_sub_and_fetch (dest, sub);
}

#else

static inline gint32 InterlockedSubtract(volatile gint32 *dest, gint32 sub)
{
gint32 prev_value;

do {
prev_value = *dest;
} while (prev_value != InterlockedCompareExchange(dest, prev_value - sub, prev_value));

return prev_value - sub;
}

static inline gint64 InterlockedSubtract64(volatile gint64 *dest, gint64 sub)
{
gint64 prev_value;

do {
prev_value = *dest;
} while (prev_value != InterlockedCompareExchange64(dest, prev_value - sub, prev_value));

return prev_value - sub;
}

#endif

#ifdef HOST_WIN32
#define TO_INTERLOCKED_ARGP(ptr) ((volatile LONG*)(ptr))
#else
Expand Down Expand Up @@ -230,6 +271,11 @@ static inline gint32 InterlockedAdd(volatile gint32 *dest, gint32 add)
return gcc_sync_add_and_fetch (dest, add);
}

static inline gint32 InterlockedSubtract(volatile gint32 *dest, gint32 sub)
{
return gcc_sync_sub_and_fetch (dest, sub);
}

static inline gint32 InterlockedIncrement(volatile gint32 *val)
{
return gcc_sync_add_and_fetch (val, 1);
Expand Down Expand Up @@ -323,6 +369,11 @@ static inline gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
return gcc_sync_add_and_fetch (dest, add);
}

static inline gint64 InterlockedSubtract64(volatile gint64 *dest, gint64 sub)
{
return gcc_sync_sub_and_fetch (dest, sub);
}

static inline gint64 InterlockedIncrement64(volatile gint64 *val)
{
return gcc_sync_add_and_fetch (val, 1);
Expand Down Expand Up @@ -393,6 +444,16 @@ static inline gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
return set;
}

static inline gint64 InterlockedSubtract64(volatile gint64 *dest, gint64 sub)
{
gint64 get, set;
do {
get = *dest;
set = get - sub;
} while (InterlockedCompareExchange64 (dest, set, get) != get);
return set;
}

static inline gint64 InterlockedRead64(volatile gint64 *src)
{
return InterlockedCompareExchange64 (src, 0, 0);
Expand Down Expand Up @@ -456,6 +517,27 @@ extern void InterlockedWrite(volatile gint32 *dst, gint32 val);
extern void InterlockedWrite64(volatile gint64 *dst, gint64 val);
extern void InterlockedWritePointer(volatile gpointer *dst, gpointer val);

/* Since InterlockedSubtract and InterlockedSubtract64 are not part
* of any standard, we can safely define them */

static inline gint32 InterlockedSubtract(volatile gint32 *dest, gint32 sub)
{
gint32 prev_value;
do {
prev_value = *dest;
} while (prev_value != InterlockedCompareExchange(dest, prev_value - sub, prev_value));
return prev_value - sub;
}

static inline gint64 InterlockedSubtract64(volatile gint64 *dest, gint64 sub)
{
gint64 prev_value;
do {
prev_value = *dest;
} while (prev_value != InterlockedCompareExchange64(dest, prev_value - sub, prev_value));
return prev_value - sub;
}

#endif

#if SIZEOF_VOID_P == 4
Expand Down