tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

register_state_check.h (4177B)


      1 /*
      2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 
     12 #ifndef AOM_TEST_REGISTER_STATE_CHECK_H_
     13 #define AOM_TEST_REGISTER_STATE_CHECK_H_
     14 
     15 #include "gtest/gtest.h"
     16 
     17 #include "config/aom_config.h"
     18 
     19 #include "aom/aom_integer.h"
     20 
     21 // API_REGISTER_STATE_CHECK(function)
     22 //   Validates the environment pre & post function execution to ensure the
     23 //   environment is in a consistent state. This should be used with API
     24 //   function sand assembly functions which are not expected to fully restore
     25 //   the system state.
     26 //   See platform implementations of RegisterStateCheck and
     27 //   RegisterStateCheckMMX for details.
     28 
     29 #if defined(_WIN64) && AOM_ARCH_X86_64
     30 
     31 #undef NOMINMAX
     32 #define NOMINMAX
     33 #undef WIN32_LEAN_AND_MEAN
     34 #define WIN32_LEAN_AND_MEAN
     35 #include <windows.h>
     36 #include <winnt.h>
     37 
     38 inline bool operator==(const M128A &lhs, const M128A &rhs) {
     39  return (lhs.Low == rhs.Low && lhs.High == rhs.High);
     40 }
     41 
     42 namespace libaom_test {
     43 
     44 // Compares the state of xmm[6-15] at construction with their state at
     45 // destruction. These registers should be preserved by the callee on
     46 // Windows x64.
     47 class RegisterStateCheck {
     48 public:
     49  RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); }
     50  ~RegisterStateCheck() { Check(); }
     51 
     52 private:
     53  static bool StoreRegisters(CONTEXT *const context) {
     54    const HANDLE this_thread = GetCurrentThread();
     55    EXPECT_NE(this_thread, nullptr);
     56    context->ContextFlags = CONTEXT_FLOATING_POINT;
     57    const bool context_saved = GetThreadContext(this_thread, context) == TRUE;
     58    EXPECT_TRUE(context_saved) << "GetLastError: " << GetLastError();
     59    return context_saved;
     60  }
     61 
     62  // Compares the register state. Returns true if the states match.
     63  void Check() const {
     64    ASSERT_TRUE(initialized_);
     65    CONTEXT post_context;
     66    ASSERT_TRUE(StoreRegisters(&post_context));
     67 
     68    const M128A *xmm_pre = &pre_context_.Xmm6;
     69    const M128A *xmm_post = &post_context.Xmm6;
     70    for (int i = 6; i <= 15; ++i) {
     71      EXPECT_EQ(*xmm_pre, *xmm_post) << "xmm" << i << " has been modified!";
     72      ++xmm_pre;
     73      ++xmm_post;
     74    }
     75  }
     76 
     77  bool initialized_;
     78  CONTEXT pre_context_;
     79 };
     80 }  // namespace libaom_test
     81 
     82 #else
     83 
     84 namespace libaom_test {
     85 
     86 class RegisterStateCheck {};
     87 }  // namespace libaom_test
     88 
     89 #endif  // _WIN64 && AOM_ARCH_X86_64
     90 
     91 #if (AOM_ARCH_X86 || AOM_ARCH_X86_64) && defined(__GNUC__)
     92 namespace libaom_test {
     93 
     94 // Checks the FPU tag word pre/post execution to ensure emms has been called.
     95 class RegisterStateCheckMMX {
     96 public:
     97  RegisterStateCheckMMX() {
     98    __asm__ volatile("fstenv %0" : "=rm"(pre_fpu_env_));
     99  }
    100  ~RegisterStateCheckMMX() { Check(); }
    101 
    102 private:
    103  // Checks the FPU tag word pre/post execution, returning false if not cleared
    104  // to 0xffff.
    105  void Check() const {
    106    EXPECT_EQ(0xffff, pre_fpu_env_[4])
    107        << "FPU was in an inconsistent state prior to call";
    108 
    109    uint16_t post_fpu_env[14];
    110    __asm__ volatile("fstenv %0" : "=rm"(post_fpu_env));
    111    EXPECT_EQ(0xffff, post_fpu_env[4])
    112        << "FPU was left in an inconsistent state after call";
    113  }
    114 
    115  uint16_t pre_fpu_env_[14];
    116 };
    117 }  // namespace libaom_test
    118 
    119 #else
    120 namespace libaom_test {
    121 
    122 class RegisterStateCheckMMX {};
    123 }  // namespace libaom_test
    124 
    125 #endif  // (AOM_ARCH_X86 || AOM_ARCH_X86_64) && defined(__GNUC__)
    126 
    127 #define API_REGISTER_STATE_CHECK(statement)           \
    128  do {                                                \
    129    libaom_test::RegisterStateCheck reg_check;        \
    130    libaom_test::RegisterStateCheckMMX reg_check_mmx; \
    131    statement;                                        \
    132    (void)reg_check_mmx;                              \
    133    (void)reg_check;                                  \
    134  } while (false)
    135 
    136 #endif  // AOM_TEST_REGISTER_STATE_CHECK_H_