Codemod asserts to assertxs in the runtime
[hiphop-php.git] / hphp / runtime / vm / jit / vm-protect.cpp
blob4d7419e167e36a5ce0be332a9b52bc34b0b406ac
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/vm/jit/vm-protect.h"
19 #ifndef NDEBUG
21 #include "hphp/runtime/base/rds.h"
22 #include "hphp/runtime/vm/vm-regs.h"
24 #include <folly/portability/SysMman.h>
25 #include <folly/portability/Unistd.h>
27 namespace HPHP { namespace jit {
29 namespace {
31 std::mutex s_lock;
32 std::atomic<void*> s_fakeRdsBase{nullptr};
33 __thread const VMProtect* tl_active_prot{nullptr};
35 void protect() {
36 if (UNLIKELY(!s_fakeRdsBase.load(std::memory_order_acquire))) {
37 std::lock_guard<std::mutex> guard(s_lock);
38 if (!s_fakeRdsBase.load(std::memory_order_relaxed)) {
39 rds::tl_base = nullptr;
40 rds::threadInit(false /* shouldRegister */);
42 // The current thread may attempt to read the Gen numbers of the normal
43 // portion of rds. These will all be invalid. No writes to non-persistent
44 // rds should occur while this guard is active. Leave the first page
45 // unprotected since surprise flags live there and we still do things in
46 // the jit that could write to them (like allocating request memory).
47 auto const base =
48 static_cast<char*>(rds::tl_base) + sysconf(_SC_PAGESIZE);
49 auto const protlen = rds::persistentSection().begin() - base;
50 if (protlen > 0) {
51 auto const result = mprotect(base, protlen, PROT_READ);
52 always_assert(result == 0);
54 s_fakeRdsBase.store(rds::tl_base, std::memory_order_release);
57 rds::tl_base = s_fakeRdsBase.load(std::memory_order_acquire);
59 tl_regState = VMRegState::DIRTY;
60 VMProtect::is_protected = true;
63 void unprotect(void* base, VMRegState state) {
64 assertx(rds::tl_base == s_fakeRdsBase.load(std::memory_order_relaxed));
65 rds::tl_base = base;
66 tl_regState = state;
67 VMProtect::is_protected = false;
72 __thread bool VMProtect::is_protected{false};
74 VMProtect::VMProtect()
75 : m_oldBase(rds::tl_base)
76 , m_oldState(tl_regState)
78 if (is_protected) return;
80 assertx(tl_active_prot == nullptr);
81 tl_active_prot = this;
82 protect();
85 VMProtect::~VMProtect() {
86 if (tl_active_prot != this) return;
88 unprotect(m_oldBase, m_oldState);
89 tl_active_prot = nullptr;
92 VMProtect::Pause::Pause() {
93 if (auto const prot = tl_active_prot) {
94 unprotect(prot->m_oldBase, prot->m_oldState);
98 VMProtect::Pause::~Pause() {
99 if (tl_active_prot) protect();
104 #endif