2 +----------------------------------------------------------------------+
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"
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>
32 std::atomic
<void*> s_fakeRdsBase
{nullptr};
33 __thread
const VMProtect
* tl_active_prot
{nullptr};
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_acquire
)) {
39 rds::tl_base
= nullptr;
40 rds::threadInit(false /* shouldRegister */);
41 regState() = VMRegState::DIRTY
;
43 // The current thread may attempt to read the Gen numbers of the normal
44 // portion of rds. These will all be invalid. No writes to non-persistent
45 // rds should occur while this guard is active. Leave the first page
46 // unprotected since surprise flags live there and we still do things in
47 // the jit that could write to them (like allocating request memory).
49 static_cast<char*>(rds::tl_base
) + sysconf(_SC_PAGESIZE
);
50 auto const protlen
= rds::localSection().end() - base
;
52 auto const result
= mprotect(base
, protlen
, PROT_READ
);
53 always_assert(result
== 0);
55 s_fakeRdsBase
.store(rds::tl_base
, std::memory_order_release
);
58 rds::tl_base
= s_fakeRdsBase
.load(std::memory_order_acquire
);
60 VMProtect::is_protected
= true;
63 void unprotect(void* base
) {
64 assertx(rds::tl_base
== s_fakeRdsBase
.load(std::memory_order_acquire
));
66 VMProtect::is_protected
= false;
71 __thread
bool VMProtect::is_protected
{false};
73 VMProtect::VMProtect()
74 : m_oldBase(rds::tl_base
)
76 if (is_protected
) return;
78 assertx(tl_active_prot
== nullptr);
79 tl_active_prot
= this;
83 VMProtect::~VMProtect() {
84 if (tl_active_prot
!= this) return;
87 tl_active_prot
= nullptr;
90 VMProtect::Pause::Pause() {
91 if (!VMProtect::is_protected
) {
95 if (auto const prot
= tl_active_prot
) {
96 unprotect(prot
->m_oldBase
);
100 VMProtect::Pause::~Pause() {
101 if (!m_active
) return;
102 if (tl_active_prot
) protect();