diff --git a/core/thread/inc/TWin32Mutex.h b/core/thread/inc/TWin32Mutex.h
index 29a10a6d08187c63a84b680d50c17092da594c29..64206686096ec85adbe6acdf7b25e67c7bf86c98 100644
--- a/core/thread/inc/TWin32Mutex.h
+++ b/core/thread/inc/TWin32Mutex.h
@@ -36,6 +36,8 @@ friend class TWin32Condition;
 private:
    CRITICAL_SECTION fCritSect;
 
+   constexpr static int kIsRecursive = BIT(14);
+   
 public:
    TWin32Mutex(Bool_t recursive=kFALSE);
    virtual ~TWin32Mutex();
@@ -44,6 +46,9 @@ public:
    Int_t  UnLock();
    Int_t  TryLock();
 
+   std::unique_ptr<TVirtualMutex::State> Reset();
+   void Restore(std::unique_ptr<TVirtualMutex::State> &&);
+
    ClassDef(TWin32Mutex,0)  // Win32 mutex lock
 };
 
diff --git a/core/thread/src/TWin32Mutex.cxx b/core/thread/src/TWin32Mutex.cxx
index 4eb2af63212f8d2eabb041fefe57a87561f5f094..14140756cd40760d640712cf4ba5f7039c7b34de 100644
--- a/core/thread/src/TWin32Mutex.cxx
+++ b/core/thread/src/TWin32Mutex.cxx
@@ -69,3 +69,55 @@ Int_t TWin32Mutex::UnLock(void)
    ::LeaveCriticalSection(&fCritSect);
    return 0;
 }
+
+namespace {
+  struct TWin32MutexState: public TVirtualMutex::State {
+     int fLockCount = 0;
+  };
+}
+  
+////////////////////////////////////////////////////////////////////////////////
+/// Reset the mutex state to unlocked. The state before resetting to unlocked is
+/// returned and can be passed to `Restore()` later on. This function must only
+/// be called while the mutex is locked.
+
+std::unique_ptr<TVirtualMutex::State> TWin32Mutex::Reset()
+{
+   std::unique_ptr<TWin32MutexState> pState(new TWin32MutexState);
+   if (TestBit(kIsRecursive)) {
+      while (!UnLock())
+         ++pState->fLockCount;
+      return std::move(pState);
+   }
+   // Not recursive. Unlocking a non-recursive, non-robust, unlocked mutex has an
+   // undefined return value - so we cannot *guarantee* that the mutex is locked.
+   // But we can try.
+   if (int rc = UnLock()) {
+      SysError("Reset", "pthread_mutex_unlock failed with %d, "
+                        "but Reset() must be called on locked mutex!",
+               rc);
+      return std::move(pState);
+   }
+   ++pState->fLockCount;
+   return std::move(pState);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Restore the mutex state to the state pointed to by `state`. This function
+/// must only be called while the mutex is unlocked.
+
+void TWin32Mutex::Restore(std::unique_ptr<TVirtualMutex::State> &&state)
+{
+  TWin32MutexState *pState = dynamic_cast<TWin32MutexState *>(state.get());
+   if (!pState) {
+      if (state) {
+         SysError("Restore", "LOGIC ERROR - invalid state object!");
+         return;
+      }
+      // No state, do nothing.
+      return;
+   }
+   do {
+      Lock();
+   } while (--pState->fLockCount);
+}