DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (409f3966645a)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_recordreplay_ThreadSnapshot_h
#define mozilla_recordreplay_ThreadSnapshot_h

#include "File.h"
#include "ProcessRewind.h"
#include "Thread.h"

namespace mozilla {
namespace recordreplay {

// Thread Snapshots Overview.
//
// The functions below are used when a thread saves or restores its stack and
// register state at a checkpoint. The steps taken in saving and restoring a
// thread snapshot are as follows:
//
// 1. Before idling (non-main threads) or before reaching a checkpoint (main
//    thread), the thread calls SaveThreadState. This saves the register state
//    for the thread as well as a portion of the top of the stack, and after
//    saving the state it returns true.
//
// 2. Once all other threads are idle, the main thread saves the remainder of
//    all thread stacks. (The portion saved earlier gives threads leeway to
//    perform operations after saving their stack, mainly for entering an idle
//    state.)
//
// 3. The thread stacks are now stored on the heap. Later on, the main thread
//    may ensure that all threads are idle and then call, for all threads,
//    RestoreStackForLoadingByThread. This prepares the stacks for restoring by
//    the associated threads.
//
// 4. While still in their idle state, threads call ShouldRestoreThreadStack to
//    see if there is stack information for them to restore.
//
// 5. If ShouldRestoreThreadStack returns true, RestoreThreadStack is then
//    called to restore the stack and register state to the point where
//    SaveThreadState was originally called.
//
// 6. RestoreThreadStack does not return. Instead, control transfers to the
//    call to SaveThreadState, which returns false after being restored to.

// aStackSeparator is a pointer into the stack. Values shallower than this in
// the stack will be preserved as they are at the time of the SaveThreadState
// call, whereas deeper values will be preserved as they are at the point where
// the main thread saves the remainder of the stack.
bool SaveThreadState(size_t aId, int* aStackSeparator);

// Information saved about the state of a thread.
struct SavedThreadStack
{
  // Saved stack pointer.
  void* mStackPointer;

  // Saved stack contents, starting at |mStackPointer|.
  uint8_t* mStack;
  size_t mStackBytes;

  // Saved register state.
  jmp_buf mRegisters;

  SavedThreadStack()
  {
    PodZero(this);
  }

  void ReleaseContents() {
    if (mStackBytes) {
      DeallocateMemory(mStack, mStackBytes, MemoryKind::ThreadSnapshot);
    }
  }
};

struct SavedCheckpoint
{
  CheckpointId mCheckpoint;
  SavedThreadStack mStacks[MaxRecordedThreadId];

  explicit SavedCheckpoint(CheckpointId aCheckpoint)
    : mCheckpoint(aCheckpoint)
  {}

  void ReleaseContents() {
    for (SavedThreadStack& stack : mStacks) {
      stack.ReleaseContents();
    }
  }
};

// When all other threads are idle, the main thread may call this to save its
// own stack and the stacks of all other threads. The return value is true if
// the stacks were just saved, or false if they were just restored due to a
// rewind from a later point of execution.
bool SaveAllThreads(SavedCheckpoint& aSavedCheckpoint);

// Restore the saved stacks for a checkpoint and rewind state to that point.
// This function does not return.
void RestoreAllThreads(const SavedCheckpoint& aSavedCheckpoint);

// After rewinding to an earlier checkpoint, the main thread will call this to
// ensure that each thread has woken up and restored its own stack contents.
// The main thread does not itself write to the stacks of other threads.
void WaitForIdleThreadsToRestoreTheirStacks();

bool ShouldRestoreThreadStack(size_t aId);
void RestoreThreadStack(size_t aId);

// Initialize state for taking thread snapshots.
void InitializeThreadSnapshots(size_t aNumThreads);

} // namespace recordreplay
} // namespace mozilla

#endif // mozilla_recordreplay_ThreadSnapshot_h