cpu, mem: Changing AtomicOpFunctor* for unique_ptr<AtomicOpFunctor>
authorJordi Vaquero <jordi.vaquero@metempsy.com>
Tue, 10 Sep 2019 22:11:27 +0000 (00:11 +0200)
committerJordi Vaquero <jordi.vaquero@metempsy.com>
Mon, 23 Sep 2019 12:32:08 +0000 (12:32 +0000)
This change is based on modify the way we move the AtomicOpFunctor*
through gem5 in order to mantain proper ownership of the object and
ensuring its destruction when it is no longer used.

Doing that we fix at the same time a memory leak in Request.hh
where we were assigning a new AtomicOpFunctor* without destroying the
previous one.

This change creates a new type AtomicOpFunctor_ptr as a
std::unique_ptr<AtomicOpFunctor> and move its ownership as needed. Except
for its only usage when AtomicOpFunc() is called.

Change-Id: Ic516f9d8217cb1ae1f0a19500e5da0336da9fd4f
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20919
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
18 files changed:
src/arch/generic/memhelpers.hh
src/base/types.hh
src/cpu/base_dyn_inst.hh
src/cpu/checker/cpu.hh
src/cpu/exec_context.hh
src/cpu/minor/exec_context.hh
src/cpu/minor/lsq.cc
src/cpu/minor/lsq.hh
src/cpu/o3/cpu.hh
src/cpu/o3/lsq.hh
src/cpu/o3/lsq_impl.hh
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/cpu/simple/base.hh
src/cpu/simple/exec_context.hh
src/cpu/simple/timing.cc
src/cpu/simple/timing.hh
src/mem/request.hh

index 7fd4f70de8a5a60052132285ff7f025aa41b65c1..fa1af26946bcfdf19279c4bde5df5952dac2aea7 100644 (file)
@@ -125,15 +125,16 @@ writeMemAtomic(XC *xc, Trace::InstRecord *traceData, const MemT &mem,
 template <class XC, class MemT>
 Fault
 amoMemAtomic(XC *xc, Trace::InstRecord *traceData, MemT &mem, Addr addr,
-             Request::Flags flags, AtomicOpFunctor *amo_op)
+             Request::Flags flags, AtomicOpFunctor *_amo_op)
 {
-    assert(amo_op);
+    assert(_amo_op);
 
     // mem will hold the previous value at addr after the AMO completes
     memset(&mem, 0, sizeof(mem));
 
+    AtomicOpFunctorPtr amo_op = AtomicOpFunctorPtr(_amo_op);
     Fault fault = xc->amoMem(addr, (uint8_t *)&mem, sizeof(MemT), flags,
-                             amo_op);
+                             std::move(amo_op));
 
     if (fault == NoFault) {
         mem = TheISA::gtoh(mem);
@@ -147,10 +148,11 @@ amoMemAtomic(XC *xc, Trace::InstRecord *traceData, MemT &mem, Addr addr,
 template <class XC, class MemT>
 Fault
 initiateMemAMO(XC *xc, Trace::InstRecord *traceData, Addr addr, MemT& mem,
-               Request::Flags flags, AtomicOpFunctor *amo_op)
+               Request::Flags flags, AtomicOpFunctor *_amo_op)
 {
-    assert(amo_op);
-    return xc->initiateMemAMO(addr, sizeof(MemT), flags, amo_op);
+    assert(_amo_op);
+    AtomicOpFunctorPtr amo_op = AtomicOpFunctorPtr(_amo_op);
+    return xc->initiateMemAMO(addr, sizeof(MemT), flags, std::move(amo_op));
 }
 
 #endif
index d99384529b9a8824db4b083f05eab266b917a33a..453309416abf7b54ef372260fda5a74b2dfffd1c 100644 (file)
@@ -259,6 +259,8 @@ struct TypedAtomicOpFunctor : public AtomicOpFunctor
     virtual void execute(T * p) = 0;
 };
 
+typedef std::unique_ptr<AtomicOpFunctor> AtomicOpFunctorPtr;
+
 enum ByteOrder {
     BigEndianByteOrder,
     LittleEndianByteOrder
index de76559fb43aa273a3370d9b75b6d06172d5540d..4b4b05c1dbd210a1983230d6ad7b14ca015a0ae9 100644 (file)
@@ -311,7 +311,7 @@ class BaseDynInst : public ExecContext, public RefCounted
                    const std::vector<bool>& byteEnable = std::vector<bool>());
 
     Fault initiateMemAMO(Addr addr, unsigned size, Request::Flags flags,
-                         AtomicOpFunctor *amo_op);
+                         AtomicOpFunctorPtr amo_op);
 
     /** True if the DTB address translation has started. */
     bool translationStarted() const { return instFlags[TranslationStarted]; }
@@ -986,7 +986,7 @@ template<class Impl>
 Fault
 BaseDynInst<Impl>::initiateMemAMO(Addr addr, unsigned size,
                                   Request::Flags flags,
-                                  AtomicOpFunctor *amo_op)
+                                  AtomicOpFunctorPtr amo_op)
 {
     // atomic memory instructions do not have data to be written to memory yet
     // since the atomic operations will be executed directly in cache/memory.
@@ -995,7 +995,8 @@ BaseDynInst<Impl>::initiateMemAMO(Addr addr, unsigned size,
     // memory
     return cpu->pushRequest(
             dynamic_cast<typename DynInstPtr::PtrType>(this),
-            /* atomic */ false, nullptr, size, addr, flags, nullptr, amo_op);
+            /* atomic */ false, nullptr, size, addr, flags, nullptr,
+            std::move(amo_op));
 }
 
 #endif // __CPU_BASE_DYN_INST_HH__
index 440fe81b5f16868a625f0cc797d770310b63fb10..8db6aa376801d0f347e81294b103f1fd51229f02 100644 (file)
@@ -565,7 +565,7 @@ class CheckerCPU : public BaseCPU, public ExecContext
         override;
 
     Fault amoMem(Addr addr, uint8_t* data, unsigned size,
-                 Request::Flags flags, AtomicOpFunctor *amo_op) override
+                 Request::Flags flags, AtomicOpFunctorPtr amo_op) override
     {
         panic("AMO is not supported yet in CPU checker\n");
     }
index b294387e2f8e485071a239a6f3da88b36ab4b7f2..a2b3924928d8ed8b077842940d168bc5532f1639 100644 (file)
@@ -270,7 +270,7 @@ class ExecContext {
      */
     virtual Fault amoMem(Addr addr, uint8_t *data, unsigned int size,
                          Request::Flags flags,
-                         AtomicOpFunctor *amo_op)
+                         AtomicOpFunctorPtr amo_op)
     {
         panic("ExecContext::amoMem() should be overridden\n");
     }
@@ -281,7 +281,7 @@ class ExecContext {
      */
     virtual Fault initiateMemAMO(Addr addr, unsigned int size,
                                  Request::Flags flags,
-                                 AtomicOpFunctor *amo_op)
+                                 AtomicOpFunctorPtr amo_op)
     {
         panic("ExecContext::initiateMemAMO() should be overridden\n");
     }
index 1871e24794d3622fd75a9a2e691eb690e9097922..87787f011c2c41135b3754b7105a00a1252b560e 100644 (file)
@@ -133,11 +133,11 @@ class ExecContext : public ::ExecContext
 
     Fault
     initiateMemAMO(Addr addr, unsigned int size, Request::Flags flags,
-                   AtomicOpFunctor *amo_op) override
+                   AtomicOpFunctorPtr amo_op) override
     {
         // AMO requests are pushed through the store path
         return execute.getLSQ().pushRequest(inst, false /* amo */, nullptr,
-            size, addr, flags, nullptr, amo_op);
+            size, addr, flags, nullptr, std::move(amo_op));
     }
 
     RegVal
index 1e5e89647b67b81e4455ba39b6ce2c22776c4713..629d89dc60e70a13c7a65421687cfb2e624be28c 100644 (file)
@@ -1573,7 +1573,7 @@ LSQ::needsToTick()
 Fault
 LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
                  unsigned int size, Addr addr, Request::Flags flags,
-                 uint64_t *res, AtomicOpFunctor *amo_op,
+                 uint64_t *res, AtomicOpFunctorPtr amo_op,
                  const std::vector<bool>& byteEnable)
 {
     assert(inst->translationFault == NoFault || inst->inLSQ);
@@ -1635,7 +1635,7 @@ LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
     request->request->setVirt(0 /* asid */,
         addr, size, flags, cpu.dataMasterId(),
         /* I've no idea why we need the PC, but give it */
-        inst->pc.instAddr(), amo_op);
+        inst->pc.instAddr(), std::move(amo_op));
     request->request->setByteEnable(byteEnable);
 
     requests.push(request);
index a7c7cb6327c6f9c2bc707f9841c0056eacdc167b..c4baad8267ea6b3e7f08f330abd351d62acb935e 100644 (file)
@@ -708,7 +708,7 @@ class LSQ : public Named
      *  the LSQ */
     Fault pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
                       unsigned int size, Addr addr, Request::Flags flags,
-                      uint64_t *res, AtomicOpFunctor *amo_op,
+                      uint64_t *res, AtomicOpFunctorPtr amo_op,
                       const std::vector<bool>& byteEnable =
                           std::vector<bool>());
 
index ac917dba901cd74b46e2028fbe41dbfb747885ec..b06182d43d5f8167f9ddf653b72631aa2a685bbf 100644 (file)
@@ -713,13 +713,13 @@ class FullO3CPU : public BaseO3CPU
     /** CPU pushRequest function, forwards request to LSQ. */
     Fault pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data,
                       unsigned int size, Addr addr, Request::Flags flags,
-                      uint64_t *res, AtomicOpFunctor *amo_op = nullptr,
+                      uint64_t *res, AtomicOpFunctorPtr amo_op = nullptr,
                       const std::vector<bool>& byteEnable =
                           std::vector<bool>())
 
     {
         return iew.ldstQueue.pushRequest(inst, isLoad, data, size, addr,
-                flags, res, amo_op, byteEnable);
+                flags, res, std::move(amo_op), byteEnable);
     }
 
     /** CPU read function, forwards read to LSQ. */
index cc14ae42319174957bdbb32d9df7797f4376d4f5..6225c507d31d047ca9b25af21ffa3f04ab8b58a6 100644 (file)
@@ -299,7 +299,7 @@ class LSQ
         const Request::Flags _flags;
         std::vector<bool> _byteEnable;
         uint32_t _numOutstandingPackets;
-        AtomicOpFunctor *_amo_op;
+        AtomicOpFunctorPtr _amo_op;
       protected:
         LSQUnit* lsqUnit() { return &_port; }
         LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad) :
@@ -318,7 +318,7 @@ class LSQ
                    const Addr& addr, const uint32_t& size,
                    const Request::Flags& flags_,
                    PacketDataPtr data = nullptr, uint64_t* res = nullptr,
-                   AtomicOpFunctor* amo_op = nullptr)
+                   AtomicOpFunctorPtr amo_op = nullptr)
             : _state(State::NotIssued), _senderState(nullptr),
             numTranslatedFragments(0),
             numInTranslationFragments(0),
@@ -326,7 +326,7 @@ class LSQ
             _res(res), _addr(addr), _size(size),
             _flags(flags_),
             _numOutstandingPackets(0),
-            _amo_op(amo_op)
+            _amo_op(std::move(amo_op))
         {
             flags.set(Flag::IsLoad, isLoad);
             flags.set(Flag::WbStore,
@@ -412,7 +412,8 @@ class LSQ
                 isAnyActiveElement(byteEnable.begin(), byteEnable.end())) {
                 auto request = std::make_shared<Request>(_inst->getASID(),
                         addr, size, _flags, _inst->masterId(),
-                        _inst->instAddr(), _inst->contextId(), _amo_op);
+                        _inst->instAddr(), _inst->contextId(),
+                        std::move(_amo_op));
                 if (!byteEnable.empty()) {
                     request->setByteEnable(byteEnable);
                 }
@@ -721,9 +722,9 @@ class LSQ
                           const Request::Flags& flags_,
                           PacketDataPtr data = nullptr,
                           uint64_t* res = nullptr,
-                          AtomicOpFunctor* amo_op = nullptr) :
+                          AtomicOpFunctorPtr amo_op = nullptr) :
             LSQRequest(port, inst, isLoad, addr, size, flags_, data, res,
-                       amo_op) {}
+                       std::move(amo_op)) {}
 
         inline virtual ~SingleDataRequest() {}
         virtual void initiateTranslation();
@@ -1032,7 +1033,7 @@ class LSQ
 
     Fault pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data,
                       unsigned int size, Addr addr, Request::Flags flags,
-                      uint64_t *res, AtomicOpFunctor *amo_op,
+                      uint64_t *res, AtomicOpFunctorPtr amo_op,
                       const std::vector<bool>& byteEnable);
 
     /** The CPU pointer. */
index e885e61728cfe8de074d925890e666bec769b33a..c2d5e90b4396a3550d36c95682f560727323e2eb 100644 (file)
@@ -687,7 +687,7 @@ template<class Impl>
 Fault
 LSQ<Impl>::pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data,
                        unsigned int size, Addr addr, Request::Flags flags,
-                       uint64_t *res, AtomicOpFunctor *amo_op,
+                       uint64_t *res, AtomicOpFunctorPtr amo_op,
                        const std::vector<bool>& byteEnable)
 {
     // This comming request can be either load, store or atomic.
@@ -717,7 +717,7 @@ LSQ<Impl>::pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data,
                     size, flags, data, res);
         } else {
             req = new SingleDataRequest(&thread[tid], inst, isLoad, addr,
-                    size, flags, data, res, amo_op);
+                    size, flags, data, res, std::move(amo_op));
         }
         assert(req);
         if (!byteEnable.empty()) {
index a873e6de7e03a89efff78bd8ad2196b9ff91e5db..9052cee2efa822015f9a4dc3de5cab52f6796cf1 100644 (file)
@@ -566,7 +566,7 @@ AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size, Addr addr,
 
 Fault
 AtomicSimpleCPU::amoMem(Addr addr, uint8_t* data, unsigned size,
-                        Request::Flags flags, AtomicOpFunctor *amo_op)
+                        Request::Flags flags, AtomicOpFunctorPtr amo_op)
 {
     SimpleExecContext& t_info = *threadInfo[curThread];
     SimpleThread* thread = t_info.thread;
@@ -596,7 +596,7 @@ AtomicSimpleCPU::amoMem(Addr addr, uint8_t* data, unsigned size,
 
     req->taskId(taskId());
     req->setVirt(0, addr, size, flags, dataMasterId(),
-                 thread->pcState().instAddr(), amo_op);
+                 thread->pcState().instAddr(), std::move(amo_op));
 
     // translate to physical address
     Fault fault = thread->dtb->translateAtomic(req, thread->getTC(),
index 69ac09e4c467be4864a1afae9c254e8bb2ac52b8..121cecd65de7d18c48e848528dbff088edbf0c4c 100644 (file)
@@ -227,7 +227,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
         override;
 
     Fault amoMem(Addr addr, uint8_t* data, unsigned size,
-                 Request::Flags flags, AtomicOpFunctor *amo_op) override;
+                 Request::Flags flags, AtomicOpFunctorPtr amo_op) override;
 
     void regProbePoints() override;
 
index 5404e5df8d33a4835b9a07617a9c7eb65688c6c2..f8e534c85af0055bcc31bce6b8bda31e6968da44 100644 (file)
@@ -162,12 +162,12 @@ class BaseSimpleCPU : public BaseCPU
 
     virtual Fault amoMem(Addr addr, uint8_t* data, unsigned size,
                          Request::Flags flags,
-                         AtomicOpFunctor *amo_op)
+                         AtomicOpFunctorPtr amo_op)
     { panic("amoMem() is not implemented\n"); }
 
     virtual Fault initiateMemAMO(Addr addr, unsigned size,
                                  Request::Flags flags,
-                                 AtomicOpFunctor *amo_op)
+                                 AtomicOpFunctorPtr amo_op)
     { panic("initiateMemAMO() is not implemented\n"); }
 
     void countInst();
index de98d6efd934c3ed34a1b4dcae43cb3f743c6c31..91f7ec5268f77a44763d4b0f55a8ea9c2191c101 100644 (file)
@@ -463,16 +463,16 @@ class SimpleExecContext : public ExecContext {
     }
 
     Fault amoMem(Addr addr, uint8_t *data, unsigned int size,
-                 Request::Flags flags, AtomicOpFunctor *amo_op) override
+                 Request::Flags flags, AtomicOpFunctorPtr amo_op) override
     {
-        return cpu->amoMem(addr, data, size, flags, amo_op);
+        return cpu->amoMem(addr, data, size, flags, std::move(amo_op));
     }
 
     Fault initiateMemAMO(Addr addr, unsigned int size,
                          Request::Flags flags,
-                         AtomicOpFunctor *amo_op) override
+                         AtomicOpFunctorPtr amo_op) override
     {
-        return cpu->initiateMemAMO(addr, size, flags, amo_op);
+        return cpu->initiateMemAMO(addr, size, flags, std::move(amo_op));
     }
 
     /**
index 4aa008e33afd64ef55ba4302caadf6a46b01dc8e..d05eece27f3e3953fa117cac2969ab8fd208f2cf 100644 (file)
@@ -564,7 +564,7 @@ TimingSimpleCPU::writeMem(uint8_t *data, unsigned size,
 Fault
 TimingSimpleCPU::initiateMemAMO(Addr addr, unsigned size,
                                 Request::Flags flags,
-                                AtomicOpFunctor *amo_op)
+                                AtomicOpFunctorPtr amo_op)
 {
     SimpleExecContext &t_info = *threadInfo[curThread];
     SimpleThread* thread = t_info.thread;
@@ -579,7 +579,8 @@ TimingSimpleCPU::initiateMemAMO(Addr addr, unsigned size,
         traceData->setMem(addr, size, flags);
 
     RequestPtr req = make_shared<Request>(asid, addr, size, flags,
-                            dataMasterId(), pc, thread->contextId(), amo_op);
+                            dataMasterId(), pc, thread->contextId(),
+                            std::move(amo_op));
 
     assert(req->hasAtomicOpFunctor());
 
index 53e0ed7e1daf118cf363c25c226a180b9fddd967..27faa177a83ae9b52aed5cf6ac91d738c68a3224 100644 (file)
@@ -293,7 +293,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
         override;
 
     Fault initiateMemAMO(Addr addr, unsigned size, Request::Flags flags,
-                         AtomicOpFunctor *amo_op) override;
+                         AtomicOpFunctorPtr amo_op) override;
 
     void fetch();
     void sendFetch(const Fault &fault,
index 324ae382e712d439ac6a66572e5b5ffb739fdc37..50944932e78de12b9c70fe74d61f293ca43c7f2d 100644 (file)
@@ -389,7 +389,7 @@ class Request
     InstSeqNum _reqInstSeqNum;
 
     /** A pointer to an atomic operation */
-    AtomicOpFunctor *atomicOpFunctor;
+    AtomicOpFunctorPtr atomicOpFunctor;
 
   public:
 
@@ -470,9 +470,9 @@ class Request
 
     Request(uint64_t asid, Addr vaddr, unsigned size, Flags flags,
             MasterID mid, Addr pc, ContextID cid,
-            AtomicOpFunctor *atomic_op)
+            AtomicOpFunctorPtr atomic_op)
     {
-        setVirt(asid, vaddr, size, flags, mid, pc, atomic_op);
+        setVirt(asid, vaddr, size, flags, mid, pc, std::move(atomic_op));
         setContext(cid);
     }
 
@@ -489,19 +489,13 @@ class Request
           translateDelta(other.translateDelta),
           accessDelta(other.accessDelta), depth(other.depth)
     {
-        if (other.atomicOpFunctor)
-            atomicOpFunctor = (other.atomicOpFunctor)->clone();
-        else
-            atomicOpFunctor = nullptr;
-    }
 
-    ~Request()
-    {
-        if (hasAtomicOpFunctor()) {
-            delete atomicOpFunctor;
-        }
+        atomicOpFunctor.reset(other.atomicOpFunctor ?
+                                other.atomicOpFunctor->clone() : nullptr);
     }
 
+    ~Request() {}
+
     /**
      * Set up Context numbers.
      */
@@ -533,7 +527,7 @@ class Request
      */
     void
     setVirt(uint64_t asid, Addr vaddr, unsigned size, Flags flags,
-            MasterID mid, Addr pc, AtomicOpFunctor *amo_op = nullptr)
+            MasterID mid, Addr pc, AtomicOpFunctorPtr amo_op = nullptr)
     {
         _asid = asid;
         _vaddr = vaddr;
@@ -549,7 +543,7 @@ class Request
         depth = 0;
         accessDelta = 0;
         translateDelta = 0;
-        atomicOpFunctor = amo_op;
+        atomicOpFunctor = std::move(amo_op);
     }
 
     /**
@@ -669,14 +663,14 @@ class Request
     bool
     hasAtomicOpFunctor()
     {
-        return atomicOpFunctor != NULL;
+        return (bool)atomicOpFunctor;
     }
 
     AtomicOpFunctor *
     getAtomicOpFunctor()
     {
-        assert(atomicOpFunctor != NULL);
-        return atomicOpFunctor;
+        assert(atomicOpFunctor);
+        return atomicOpFunctor.get();
     }
 
     /** Accessor for flags. */