Bug 1132966 - use relaxed Atomic integers for tracking graphics surface memory usage; r=njn

Graphics surface memory usage tracking is done manually, with a global
array containing the number of bytes per each type of surface used.
Since the members of the array can be touched by several different
threads, dynamic race checkers such as TSan complain about To assuage
TSan's sensibilities, we need to use atomics with relaxed memory
consistency; this change generates code identical to what we had before,
but the atomic type assures TSan that it's OK to access members on
multiple threads.  We use the relaxed memory consistency to avoid memory
barriers in the generated code.
This commit is contained in:
Nathan Froyd 2015-07-31 22:43:24 -04:00
Родитель 2fdf1a9679
Коммит e622b5e3e8
1 изменённых файлов: 19 добавлений и 5 удалений

Просмотреть файл

@ -564,13 +564,25 @@ PR_STATIC_ASSERT(uint32_t(CAIRO_SURFACE_TYPE_SKIA) ==
/* Surface size memory reporting */
static int64_t gSurfaceMemoryUsed[size_t(gfxSurfaceType::Max)] = { 0 };
class SurfaceMemoryReporter final : public nsIMemoryReporter
{
~SurfaceMemoryReporter() {}
// We can touch this array on several different threads, and we don't
// want to introduce memory barriers when recording the memory used. To
// assure dynamic race checkers like TSan that this is OK, we use
// relaxed memory ordering here.
static Atomic<size_t, Relaxed> sSurfaceMemoryUsed[size_t(gfxSurfaceType::Max)];
public:
static void AdjustUsedMemory(gfxSurfaceType aType, int32_t aBytes)
{
// A read-modify-write operation like += would require a memory barrier
// here, which would defeat the purpose of using relaxed memory
// ordering. So separate out the read and write operations.
sSurfaceMemoryUsed[size_t(aType)] = sSurfaceMemoryUsed[size_t(aType)] + aBytes;
};
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb,
@ -578,7 +590,7 @@ public:
{
const size_t len = ArrayLength(sSurfaceMemoryReporterAttrs);
for (size_t i = 0; i < len; i++) {
int64_t amount = gSurfaceMemoryUsed[i];
int64_t amount = sSurfaceMemoryUsed[i];
if (amount != 0) {
const char *path = sSurfaceMemoryReporterAttrs[i].path;
@ -589,7 +601,7 @@ public:
nsresult rv = aCb->Callback(EmptyCString(), nsCString(path),
KIND_OTHER, UNITS_BYTES,
gSurfaceMemoryUsed[i],
amount,
nsCString(desc), aClosure);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -599,6 +611,8 @@ public:
}
};
Atomic<size_t, Relaxed> SurfaceMemoryReporter::sSurfaceMemoryUsed[size_t(gfxSurfaceType::Max)];
NS_IMPL_ISUPPORTS(SurfaceMemoryReporter, nsIMemoryReporter)
void
@ -616,7 +630,7 @@ gfxASurface::RecordMemoryUsedForSurfaceType(gfxSurfaceType aType,
registered = true;
}
gSurfaceMemoryUsed[size_t(aType)] += aBytes;
SurfaceMemoryReporter::AdjustUsedMemory(aType, aBytes);
}
void