Skip to content

Commit ce00c8b

Browse files
committed
GPU: Make memory allocation and freeing of individual stacked memory thread-safe
1 parent 070eaae commit ce00c8b

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

GPU/GPUTracking/Base/GPUReconstruction.cxx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
#include "GPULogging.h"
4242
#include "utils/strtag.h"
43+
#include "utils/stdspinlock.h"
4344

4445
#ifdef GPUCA_O2_LIB
4546
#include "GPUO2InterfaceConfiguration.h"
@@ -589,6 +590,7 @@ size_t GPUReconstruction::AllocateRegisteredMemoryHelper(GPUMemoryResource* res,
589590
throw std::bad_alloc();
590591
}
591592
size_t retVal;
593+
stdspinlock spinlock(mMemoryMutex);
592594
if ((res->mType & GPUMemoryResource::MEMORY_STACK) && memorypoolend) {
593595
retVal = ptrDiff((res->*setPtr)((char*)1), (char*)(1));
594596
memorypoolend = (void*)((char*)memorypoolend - GPUProcessor::getAlignmentMod<GPUCA_MEMALIGN>(memorypoolend));
@@ -642,6 +644,7 @@ void GPUReconstruction::AllocateRegisteredMemoryInternal(GPUMemoryResource* res,
642644
std::cout << (res->mReuse >= 0 ? "Reused " : "Allocated ") << res->mName << ": " << res->mSize << " (individual" << ((res->mType & GPUMemoryResource::MEMORY_STACK) ? " stack" : "") << ")\n";
643645
}
644646
if (res->mType & GPUMemoryResource::MEMORY_STACK) {
647+
stdspinlock spinlock(mMemoryMutex);
645648
mNonPersistentIndividualAllocations.emplace_back(res);
646649
}
647650
if ((size_t)res->mPtr % GPUCA_BUFFER_ALIGNMENT) {
@@ -722,6 +725,7 @@ size_t GPUReconstruction::AllocateRegisteredMemory(int16_t ires, GPUOutputContro
722725

723726
void* GPUReconstruction::AllocateDirectMemory(size_t size, int32_t type)
724727
{
728+
stdspinlock spinlock(mMemoryMutex);
725729
if (GetProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) {
726730
char* retVal = new (std::align_val_t(GPUCA_BUFFER_ALIGNMENT)) char[size];
727731
if ((type & GPUMemoryResource::MEMORY_STACK)) {
@@ -763,6 +767,7 @@ void* GPUReconstruction::AllocateDirectMemory(size_t size, int32_t type)
763767

764768
void* GPUReconstruction::AllocateVolatileDeviceMemory(size_t size)
765769
{
770+
stdspinlock spinlock(mMemoryMutex);
766771
if (mVolatileMemoryStart == nullptr) {
767772
mVolatileMemoryStart = mDeviceMemoryPool;
768773
}
@@ -788,6 +793,7 @@ void* GPUReconstruction::AllocateVolatileMemory(size_t size, bool device)
788793
return AllocateVolatileDeviceMemory(size);
789794
}
790795
char* retVal = new (std::align_val_t(GPUCA_BUFFER_ALIGNMENT)) char[size];
796+
stdspinlock spinlock(mMemoryMutex);
791797
mVolatileChunks.emplace_back(retVal, alignedDeleter());
792798
return retVal;
793799
}
@@ -912,6 +918,7 @@ void GPUReconstruction::PopNonPersistentMemory(RecoStep step, uint64_t tag, cons
912918
res->mPtrDevice = nullptr;
913919
}
914920
if (!proc) {
921+
stdspinlock spinlock(mMemoryMutex);
915922
mHostMemoryPoolEnd = std::get<0>(mNonPersistentMemoryStack.back());
916923
mDeviceMemoryPoolEnd = std::get<1>(mNonPersistentMemoryStack.back());
917924
mNonPersistentIndividualAllocations.resize(std::get<2>(mNonPersistentMemoryStack.back()));

GPU/GPUTracking/Base/GPUReconstruction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <functional>
2626
#include <unordered_map>
2727
#include <unordered_set>
28+
#include <atomic>
2829

2930
#include "GPUDataTypes.h"
3031
#include "GPUMemoryResource.h"
@@ -390,6 +391,7 @@ class GPUReconstruction
390391
std::vector<std::unique_ptr<char[], alignedDeleter>> mNonPersistentIndividualDirectAllocations;
391392
std::vector<std::unique_ptr<char[], alignedDeleter>> mDirectMemoryChunks;
392393
std::vector<std::unique_ptr<char[], alignedDeleter>> mVolatileChunks;
394+
std::atomic_flag mMemoryMutex = ATOMIC_FLAG_INIT;
393395

394396
std::unique_ptr<GPUReconstructionPipelineContext> mPipelineContext;
395397

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file stdspinlock.h
13+
/// \author David Rohr
14+
15+
#ifndef Q_STDSPINLOCK_H
16+
#define Q_STDSPINLOCK_H
17+
18+
#include <atomic>
19+
20+
class stdspinlock
21+
{
22+
public:
23+
stdspinlock(std::atomic_flag& flag) : mFlag(&flag)
24+
{
25+
while (flag.test_and_set(std::memory_order_acquire)) {
26+
}
27+
}
28+
void release()
29+
{
30+
if (mFlag) {
31+
mFlag->clear(std::memory_order_release);
32+
mFlag = nullptr;
33+
}
34+
}
35+
~stdspinlock()
36+
{
37+
release();
38+
}
39+
40+
private:
41+
std::atomic_flag* mFlag;
42+
};
43+
44+
#endif // Q_STDSPINLOCK_H

0 commit comments

Comments
 (0)