Merge "Explicitly show the destination filename for a bugreport."
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 0e9713d..86cf30d 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -992,10 +992,69 @@
            fb->GetVar("partition-type:vbmeta_b", &partition_type) == fastboot::SUCCESS;
 }
 
+static std::string fb_fix_numeric_var(std::string var) {
+    // Some bootloaders (angler, for example), send spurious leading whitespace.
+    var = android::base::Trim(var);
+    // Some bootloaders (hammerhead, for example) use implicit hex.
+    // This code used to use strtol with base 16.
+    if (!android::base::StartsWith(var, "0x")) var = "0x" + var;
+    return var;
+}
+
+static void copy_boot_avb_footer(const std::string& partition, struct fastboot_buffer* buf) {
+    if (buf->sz < AVB_FOOTER_SIZE) {
+        return;
+    }
+
+    std::string partition_size_str;
+    if (fb->GetVar("partition-size:" + partition, &partition_size_str) != fastboot::SUCCESS) {
+        die("cannot get boot partition size");
+    }
+
+    partition_size_str = fb_fix_numeric_var(partition_size_str);
+    int64_t partition_size;
+    if (!android::base::ParseInt(partition_size_str, &partition_size)) {
+        die("Couldn't parse partition size '%s'.", partition_size_str.c_str());
+    }
+    if (partition_size == buf->sz) {
+        return;
+    }
+    if (partition_size < buf->sz) {
+        die("boot partition is smaller than boot image");
+    }
+
+    std::string data;
+    if (!android::base::ReadFdToString(buf->fd, &data)) {
+        die("Failed reading from boot");
+    }
+
+    uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE;
+    if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) {
+        return;
+    }
+
+    int fd = make_temporary_fd("boot rewriting");
+    if (!android::base::WriteStringToFd(data, fd)) {
+        die("Failed writing to modified boot");
+    }
+    lseek(fd, partition_size - AVB_FOOTER_SIZE, SEEK_SET);
+    if (!android::base::WriteStringToFd(data.substr(footer_offset), fd)) {
+        die("Failed copying AVB footer in boot");
+    }
+    close(buf->fd);
+    buf->fd = fd;
+    buf->sz = partition_size;
+    lseek(fd, 0, SEEK_SET);
+}
+
 static void flash_buf(const std::string& partition, struct fastboot_buffer *buf)
 {
     sparse_file** s;
 
+    if (partition == "boot" || partition == "boot_a" || partition == "boot_b") {
+        copy_boot_avb_footer(partition, buf);
+    }
+
     // Rewrite vbmeta if that's what we're flashing and modification has been requested.
     if (g_disable_verity || g_disable_verification) {
         if (partition == "vbmeta" || partition == "vbmeta_a" || partition == "vbmeta_b") {
@@ -1491,15 +1550,6 @@
     fb->RawCommand(command, "");
 }
 
-static std::string fb_fix_numeric_var(std::string var) {
-    // Some bootloaders (angler, for example), send spurious leading whitespace.
-    var = android::base::Trim(var);
-    // Some bootloaders (hammerhead, for example) use implicit hex.
-    // This code used to use strtol with base 16.
-    if (!android::base::StartsWith(var, "0x")) var = "0x" + var;
-    return var;
-}
-
 static unsigned fb_get_flash_block_size(std::string name) {
     std::string sizeString;
     if (fb->GetVar(name, &sizeString) != fastboot::SUCCESS || sizeString.empty()) {
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index f5daf91..cd64599 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -162,10 +162,13 @@
     defaults: ["fs_mgr_defaults"],
     static_libs: [
         "libavb_user",
+        "libutils",
+        "libvold_binder",
     ],
     shared_libs: [
         "libbootloader_message",
         "libbase",
+        "libbinder",
         "libcutils",
         "libcrypto",
         "libext4_utils",
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 0c184af..0ae5787 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1044,7 +1044,8 @@
 
 class CheckpointManager {
   public:
-    CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
+    CheckpointManager(int needs_checkpoint = -1, bool metadata_encrypted = false)
+        : needs_checkpoint_(needs_checkpoint), metadata_encrypted_(metadata_encrypted) {}
 
     bool NeedsCheckpoint() {
         if (needs_checkpoint_ != UNKNOWN) {
@@ -1062,7 +1063,7 @@
             return true;
         }
 
-        if (entry->fs_mgr_flags.checkpoint_blk) {
+        if (entry->fs_mgr_flags.checkpoint_blk && !metadata_encrypted_) {
             call_vdc({"checkpoint", "restoreCheckpoint", entry->blk_device}, nullptr);
         }
 
@@ -1171,6 +1172,7 @@
 
     enum { UNKNOWN = -1, NO = 0, YES = 1 };
     int needs_checkpoint_;
+    bool metadata_encrypted_;
     std::map<std::string, std::string> device_map_;
 };
 
@@ -1804,11 +1806,11 @@
 // in turn, and stop on 1st success, or no more match.
 static int fs_mgr_do_mount_helper(Fstab* fstab, const std::string& n_name,
                                   const std::string& n_blk_device, const char* tmp_mount_point,
-                                  int needs_checkpoint) {
+                                  int needs_checkpoint, bool metadata_encrypted) {
     int mount_errors = 0;
     int first_mount_errno = 0;
     std::string mount_point;
-    CheckpointManager checkpoint_manager(needs_checkpoint);
+    CheckpointManager checkpoint_manager(needs_checkpoint, metadata_encrypted);
     AvbUniquePtr avb_handle(nullptr);
 
     if (!fstab) {
@@ -1918,12 +1920,13 @@
 }
 
 int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
-    return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1);
+    return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1, false);
 }
 
 int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
-                    bool needs_checkpoint) {
-    return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint);
+                    bool needs_checkpoint, bool metadata_encrypted) {
+    return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint,
+                                  metadata_encrypted);
 }
 
 /*
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 052efa7..b8b074e 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include <string>
+#include <thread>
 #include <utility>
 #include <vector>
 
@@ -31,6 +32,8 @@
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
+#include <android/os/IVold.h>
+#include <binder/IServiceManager.h>
 #include <bootloader_message/bootloader_message.h>
 #include <cutils/android_reboot.h>
 #include <fec/io.h>
@@ -103,8 +106,23 @@
     ::exit(0);  // SUCCESS
 }
 
+static android::sp<android::os::IVold> GetVold() {
+    while (true) {
+        if (auto sm = android::defaultServiceManager()) {
+            if (auto binder = sm->getService(android::String16("vold"))) {
+                if (auto vold = android::interface_cast<android::os::IVold>(binder)) {
+                    return vold;
+                }
+            }
+        }
+        std::this_thread::sleep_for(2s);
+    }
+}
+
 }  // namespace
 
+using namespace std::chrono_literals;
+
 enum RemountStatus {
     REMOUNT_SUCCESS = 0,
     NOT_USERDEBUG,
@@ -117,7 +135,9 @@
     BAD_OVERLAY,
     NO_MOUNTS,
     REMOUNT_FAILED,
-    MUST_REBOOT
+    MUST_REBOOT,
+    BINDER_ERROR,
+    CHECKPOINTING
 };
 
 static int do_remount(int argc, char* argv[]) {
@@ -194,6 +214,22 @@
         return NO_FSTAB;
     }
 
+    if (android::base::GetBoolProperty("ro.virtual_ab.enabled", false) &&
+        !android::base::GetBoolProperty("ro.virtual_ab.retrofit", false)) {
+        // Virtual A/B devices can use /data as backing storage; make sure we're
+        // not checkpointing.
+        auto vold = GetVold();
+        bool checkpointing = false;
+        if (!vold->isCheckpointing(&checkpointing).isOk()) {
+            LOG(ERROR) << "Could not determine checkpointing status.";
+            return BINDER_ERROR;
+        }
+        if (checkpointing) {
+            LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
+            return CHECKPOINTING;
+        }
+    }
+
     // Generate the list of supported overlayfs mount points.
     auto overlayfs_candidates = fs_mgr_overlayfs_candidate_list(fstab);
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 86090c1..2a67b8c 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -69,7 +69,7 @@
 int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
                     char* tmp_mount_point);
 int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
-                    char* tmp_mount_point, bool need_cp);
+                    char* tmp_mount_point, bool need_cp, bool metadata_encrypted);
 int fs_mgr_do_mount_one(const android::fs_mgr::FstabEntry& entry,
                         const std::string& mount_point = "");
 int fs_mgr_do_tmpfs_mount(const char *n_name);
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index f71d0c3..22f381c 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -311,6 +311,8 @@
     }
 };
 
+std::recursive_mutex FuseBridgeLoop::mutex_;
+
 FuseBridgeLoop::FuseBridgeLoop() : opened_(true) {
     base::unique_fd epoll_fd(epoll_create1(EPOLL_CLOEXEC));
     if (epoll_fd.get() == -1) {
@@ -328,7 +330,7 @@
 
     std::unique_ptr<FuseBridgeEntry> bridge(
         new FuseBridgeEntry(mount_id, std::move(dev_fd), std::move(proxy_fd)));
-    std::lock_guard<std::mutex> lock(mutex_);
+    std::lock_guard<std::recursive_mutex> lock(mutex_);
     if (!opened_) {
         LOG(ERROR) << "Tried to add a mount to a closed bridge";
         return false;
@@ -372,7 +374,7 @@
         const bool wait_result = epoll_controller_->Wait(bridges_.size(), &entries);
         LOG(VERBOSE) << "Receive epoll events";
         {
-            std::lock_guard<std::mutex> lock(mutex_);
+            std::lock_guard<std::recursive_mutex> lock(mutex_);
             if (!(wait_result && ProcessEventLocked(entries, callback))) {
                 for (auto it = bridges_.begin(); it != bridges_.end();) {
                     callback->OnClosed(it->second->mount_id());
@@ -385,5 +387,13 @@
     }
 }
 
+void FuseBridgeLoop::Lock() {
+    mutex_.lock();
+}
+
+void FuseBridgeLoop::Unlock() {
+    mutex_.unlock();
+}
+
 }  // namespace fuse
 }  // namespace android
diff --git a/libappfuse/include/libappfuse/FuseBridgeLoop.h b/libappfuse/include/libappfuse/FuseBridgeLoop.h
index 6bfda98..d5fc28f 100644
--- a/libappfuse/include/libappfuse/FuseBridgeLoop.h
+++ b/libappfuse/include/libappfuse/FuseBridgeLoop.h
@@ -50,6 +50,10 @@
     // thread from one which invokes |Start|.
     bool AddBridge(int mount_id, base::unique_fd dev_fd, base::unique_fd proxy_fd);
 
+    static void Lock();
+
+    static void Unlock();
+
   private:
     bool ProcessEventLocked(const std::unordered_set<FuseBridgeEntry*>& entries,
                             FuseBridgeLoopCallback* callback);
@@ -60,7 +64,7 @@
     std::map<int, std::unique_ptr<FuseBridgeEntry>> bridges_;
 
     // Lock for multi-threading.
-    std::mutex mutex_;
+    static std::recursive_mutex mutex_;
 
     bool opened_;
 
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index 0e39aab..5640900 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -96,7 +96,7 @@
           ((logger_list->start.tv_sec != buf.l.realtime.tv_sec) ||
            (logger_list->start.tv_nsec <= buf.l.realtime.tv_nsec)))) &&
         (!logger_list->pid || (logger_list->pid == buf.p.pid))) {
-      char* msg = reinterpret_cast<char*>(&log_msg->entry) + log_msg->entry.hdr_size;
+      char* msg = reinterpret_cast<char*>(&log_msg->entry) + sizeof(log_msg->entry);
       *msg = buf.prio;
       fd = atomic_load(&logger_list->fd);
       if (fd <= 0) {
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index ef9f1cf..dd779f9 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -61,7 +61,7 @@
     }
 }
 
-LogBufferElement::LogBufferElement(LogBufferElement&& elem)
+LogBufferElement::LogBufferElement(LogBufferElement&& elem) noexcept
     : uid_(elem.uid_),
       pid_(elem.pid_),
       tid_(elem.tid_),
@@ -134,7 +134,7 @@
     char* retval = nullptr;
     char buffer[256];
     snprintf(buffer, sizeof(buffer), "/proc/%u/comm", tid);
-    int fd = open(buffer, O_RDONLY);
+    int fd = open(buffer, O_RDONLY | O_CLOEXEC);
     if (fd >= 0) {
         ssize_t ret = read(fd, buffer, sizeof(buffer));
         if (ret >= (ssize_t)sizeof(buffer)) {
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index fd5d88f..b263ca5 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -37,7 +37,7 @@
     LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
                      uint64_t sequence, const char* msg, uint16_t len);
     LogBufferElement(const LogBufferElement& elem);
-    LogBufferElement(LogBufferElement&& elem);
+    LogBufferElement(LogBufferElement&& elem) noexcept;
     ~LogBufferElement();
 
     uint32_t GetTag() const;
diff --git a/logd/LogListener.h b/logd/LogListener.h
index c114e38..566af5b 100644
--- a/logd/LogListener.h
+++ b/logd/LogListener.h
@@ -20,7 +20,7 @@
 
 class LogListener {
   public:
-    LogListener(LogBuffer* buf);
+    explicit LogListener(LogBuffer* buf);
     bool StartListener();
 
   private:
diff --git a/logd/LogPermissions.cpp b/logd/LogPermissions.cpp
index 8f02d5a..3fd0ea1 100644
--- a/logd/LogPermissions.cpp
+++ b/logd/LogPermissions.cpp
@@ -89,7 +89,7 @@
     //
     for (int retry = 3; !(ret = foundGid && foundUid && foundLog) && retry;
          --retry) {
-        FILE* file = fopen(filename, "r");
+        FILE* file = fopen(filename, "re");
         if (!file) {
             continue;
         }
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index f71133d..6c97693 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -127,7 +127,7 @@
     if (cp) {
         logMask = 0;
         cp += sizeof(_logIds) - 1;
-        while (*cp && *cp != '\0') {
+        while (*cp != '\0') {
             int val = 0;
             while (isdigit(*cp)) {
                 val = val * 10 + *cp - '0';
diff --git a/logd/LogReaderThread.cpp b/logd/LogReaderThread.cpp
index dc8582d..4a8be01 100644
--- a/logd/LogReaderThread.cpp
+++ b/logd/LogReaderThread.cpp
@@ -25,8 +25,6 @@
 #include "LogBuffer.h"
 #include "LogReaderList.h"
 
-using namespace std::placeholders;
-
 LogReaderThread::LogReaderThread(LogBuffer* log_buffer, LogReaderList* reader_list,
                                  std::unique_ptr<LogWriter> writer, bool non_block,
                                  unsigned long tail, LogMask log_mask, pid_t pid,
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index d49982a..3cd8fde 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -88,7 +88,7 @@
     } else {
         char buffer[512];
         snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
-        int fd = open(buffer, O_RDONLY);
+        int fd = open(buffer, O_RDONLY | O_CLOEXEC);
         if (fd >= 0) {
             ssize_t ret = read(fd, buffer, sizeof(buffer));
             if (ret > 0) {
@@ -944,7 +944,7 @@
 uid_t pidToUid(pid_t pid) {
     char buffer[512];
     snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
-    FILE* fp = fopen(buffer, "r");
+    FILE* fp = fopen(buffer, "re");
     if (fp) {
         while (fgets(buffer, sizeof(buffer), fp)) {
             int uid = AID_LOGD;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 200c228..5f55802 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -128,9 +128,9 @@
             if (++index < (ssize_t)len) {
                 size_t num = len - index - 1;
                 if (num) {
-                    memmove(&out_keys[index + 1], &out_keys[index], num * sizeof(out_keys[0]));
+                    memmove(&out_keys[index + 1], &out_keys[index], num * sizeof(const TKey*));
                     memmove(&out_entries[index + 1], &out_entries[index],
-                            num * sizeof(out_entries[0]));
+                            num * sizeof(const TEntry*));
                 }
                 out_keys[index] = &key;
                 out_entries[index] = &entry;
@@ -477,15 +477,15 @@
                       tagNameTable.sizeOf() +
                       (pidTable.size() * sizeof(pidTable_t::iterator)) +
                       (tagTable.size() * sizeof(tagTable_t::iterator));
-        for (auto it : pidTable) {
+        for (const auto& it : pidTable) {
             const char* name = it.second.name();
             if (name) size += strlen(name) + 1;
         }
-        for (auto it : tidTable) {
+        for (const auto& it : tidTable) {
             const char* name = it.second.name();
             if (name) size += strlen(name) + 1;
         }
-        for (auto it : tagNameTable) {
+        for (const auto& it : tagNameTable) {
             size += sizeof(std::string);
             size_t len = it.first.size();
             // Account for short string optimization: if the string's length is <= 22 bytes for 64
@@ -505,7 +505,7 @@
     }
 
   public:
-    LogStatistics(bool enable_statistics);
+    explicit LogStatistics(bool enable_statistics);
 
     void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_);
     void Add(const LogStatisticsElement& entry) EXCLUDES(lock_);
diff --git a/logd/SerializedFlushToState.cpp b/logd/SerializedFlushToState.cpp
index 17ecb6d..6e2e8b0 100644
--- a/logd/SerializedFlushToState.cpp
+++ b/logd/SerializedFlushToState.cpp
@@ -60,7 +60,7 @@
     }
     log_position.read_offset = read_offset;
 
-    log_positions_[log_id].emplace(std::move(log_position));
+    log_positions_[log_id].emplace(log_position);
 }
 
 void SerializedFlushToState::AddMinHeapEntry(log_id_t log_id) {
@@ -149,7 +149,7 @@
         min_heap_.pop();
     }
     for (auto&& element : old_elements) {
-        min_heap_.emplace(std::move(element));
+        min_heap_.emplace(element);
     }
 
     // Finally set logs_needed_from_next_position_, so CheckForNewLogs() will re-create the
diff --git a/logd/SerializedLogBuffer.cpp b/logd/SerializedLogBuffer.cpp
index 8bda7cf..70b800f 100644
--- a/logd/SerializedLogBuffer.cpp
+++ b/logd/SerializedLogBuffer.cpp
@@ -208,6 +208,7 @@
     }
 
     // Otherwise we are stuck due to a reader, so mitigate it.
+    CHECK(oldest != nullptr);
     KickReader(oldest, log_id, bytes_to_free);
     return false;
 }
diff --git a/logd/SerializedLogBuffer.h b/logd/SerializedLogBuffer.h
index 27334ba..346f51f 100644
--- a/logd/SerializedLogBuffer.h
+++ b/logd/SerializedLogBuffer.h
@@ -33,7 +33,7 @@
 #include "SerializedLogEntry.h"
 #include "rwlock.h"
 
-class SerializedLogBuffer : public LogBuffer {
+class SerializedLogBuffer final : public LogBuffer {
   public:
     SerializedLogBuffer(LogReaderList* reader_list, LogTags* tags, LogStatistics* stats);
     ~SerializedLogBuffer();
diff --git a/logd/SerializedLogChunk.h b/logd/SerializedLogChunk.h
index 75cb936..a8ac8cd 100644
--- a/logd/SerializedLogChunk.h
+++ b/logd/SerializedLogChunk.h
@@ -25,7 +25,7 @@
 
 class SerializedLogChunk {
   public:
-    SerializedLogChunk(size_t size) : contents_(size) {}
+    explicit SerializedLogChunk(size_t size) : contents_(size) {}
     ~SerializedLogChunk();
 
     void Compress();
diff --git a/logd/SimpleLogBuffer.h b/logd/SimpleLogBuffer.h
index 2172507..9f7d699 100644
--- a/logd/SimpleLogBuffer.h
+++ b/logd/SimpleLogBuffer.h
@@ -31,7 +31,7 @@
   public:
     SimpleLogBuffer(LogReaderList* reader_list, LogTags* tags, LogStatistics* stats);
     ~SimpleLogBuffer();
-    void Init() override;
+    void Init() override final;
 
     int Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char* msg,
             uint16_t len) override;
@@ -42,7 +42,7 @@
 
     bool Clear(log_id_t id, uid_t uid) override;
     unsigned long GetSize(log_id_t id) override;
-    int SetSize(log_id_t id, unsigned long size) override;
+    int SetSize(log_id_t id, unsigned long size) override final;
 
     uint64_t sequence() const override { return sequence_.load(std::memory_order_relaxed); }
 
diff --git a/logd/rwlock.h b/logd/rwlock.h
index 2b27ff1..c37721e 100644
--- a/logd/rwlock.h
+++ b/logd/rwlock.h
@@ -43,7 +43,7 @@
 
 class SCOPED_CAPABILITY SharedLock {
   public:
-    SharedLock(RwLock& lock) ACQUIRE_SHARED(lock) : lock_(lock) { lock_.lock_shared(); }
+    explicit SharedLock(RwLock& lock) ACQUIRE_SHARED(lock) : lock_(lock) { lock_.lock_shared(); }
     ~SharedLock() RELEASE() { lock_.unlock(); }
 
     void lock_shared() ACQUIRE_SHARED() { lock_.lock_shared(); }