<commit_before>
// Copyright (c) 2015-2016 niXman (i dot nixman dog gmail dot com). All
// rights reserved.
//
// This file is part of CSPROT(https://github.com/niXman/csprot) project.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
//
//
// Boost Software License - Version 1.0 - August 17th, 2003
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#ifndef _csprot_hpp_
#define _csprot_hpp_

#include <cstdint>

#if __cplusplus < 201402L
#	error C++14 or greater is required
#endif

namespace csprot {

/**************************************************************************/

namespace {

template<typename>
struct xor_char_type;

template<>
struct xor_char_type<char> {
	static constexpr const char plain_xor = 0;
	static constexpr const char xored_xor = 177;
};

template<>
struct xor_char_type<wchar_t> {
	static constexpr const wchar_t plain_xor = 0;
	static constexpr const wchar_t xored_xor = 157;
};

// holder
template<bool, typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
struct string_holder;

} // anon ns

/**************************************************************************/

namespace {

// spec for plain strings
template<typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
struct string_holder<false, CharType, XorChar, FirstChar, SecondChars...> {
protected:
	static constexpr CharType _data[] = { FirstChar^XorChar, SecondChars^XorChar ..., '\0' };

	constexpr const CharType* c_str() const { return _data; }
};
template <typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
constexpr const CharType string_holder<false, CharType, XorChar, FirstChar, SecondChars...>::_data[];

// spec for xor`ed strings
template<typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
struct string_holder<true, CharType, XorChar, FirstChar, SecondChars...> {
	static constexpr CharType _data[] = { FirstChar^XorChar, SecondChars^XorChar ..., '\0' };
	mutable char _plain[sizeof(_data)];

	constexpr const CharType* c_str() const {
		std::size_t i = 0;
		for ( ; i < 1+sizeof...(SecondChars); ++i ) {
			_plain[i] = _data[i]^XorChar;
		}
		_plain[i]=0;

		return _plain;
	}
};
template <typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
constexpr const CharType string_holder<true, CharType, XorChar, FirstChar, SecondChars...>::_data[];

} // anon ns

/**************************************************************************/

template <typename CharType, CharType XorChar, CharType... Chars>
class cstring;

template <typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
struct cstring<CharType, XorChar, FirstChar, SecondChars...>
	:string_holder<XorChar==xor_char_type<CharType>::xored_xor, CharType, XorChar, FirstChar, SecondChars...> {
private:
	using holder_type = string_holder<XorChar==xor_char_type<CharType>::xored_xor, CharType, XorChar, FirstChar, SecondChars...>;
public:
	constexpr cstring() = default;

	constexpr std::size_t     size()   const { return 1+sizeof...(SecondChars); }
	constexpr std::size_t     length() const { return size(); }
	constexpr bool            empty()  const { return false; }
	constexpr bool            is_plain()  const { return XorChar == xor_char_type<CharType>::plain_xor; }
	constexpr bool            is_xored()  const { return XorChar == xor_char_type<CharType>::xored_xor; }
	constexpr const CharType* data()   const { return holder_type::_data; }
	using holder_type::c_str;

	template<
		 CharType XorChar2
		,CharType... Chars
	>
	constexpr int compare(const cstring<CharType, XorChar2, Chars...>& other) const {
		for ( std::size_t i = 0; i < size() && i < other.size(); ++i ) {
			if (data()[i] < other.data()[i]) return -1;
			if (data()[i] > other.data()[i]) return 1;
		}

		if (size() < other.size()) return -1;
		if (size() > other.size()) return 1;

		return 0;
	}
};

// spec for empty strings
template<typename CharType, CharType XorChar>
struct cstring<CharType, XorChar> {
private:
	static constexpr CharType _data = '\0';

public:
	constexpr cstring() = default;

	constexpr std::size_t     size()   const { return 0; }
	constexpr std::size_t     length() const { return 0; }
	constexpr bool            empty()  const { return true; }
	constexpr bool            is_plain()  const { return XorChar == xor_char_type<CharType>::plain_xor; }
	constexpr bool            is_xored()  const { return XorChar == xor_char_type<CharType>::xored_xor; }
	constexpr const CharType* data()  const { return &_data; }
	constexpr const CharType* c_str() const { return &_data; }

	template <CharType... OtherChars>
	constexpr int compare(const cstring<CharType, XorChar, OtherChars...>& other) const {
		return other.empty() ? 0 : -1;
	}
};
template<typename CharType, CharType XorChar>
constexpr const CharType cstring<CharType, XorChar>::_data;

/*****************************************************************************/

// for plain strings
template<typename CharType, CharType... Chars>
constexpr cstring<CharType, xor_char_type<CharType>::plain_xor, Chars...> operator"" _S() {
	return cstring<CharType, xor_char_type<CharType>::plain_xor, Chars...>();
}

// for xor`ed strings
template<typename CharType, CharType... Chars>
constexpr cstring<CharType, xor_char_type<CharType>::xored_xor, Chars...> operator"" _XS() {
	return cstring<CharType, xor_char_type<CharType>::xored_xor, Chars...>();
}

/**************************************************************************/

template<
	 typename CharType
	,CharType XorChar
	,CharType... LeftChars
	,CharType... RightChars
>
constexpr auto operator+ (const cstring<CharType, XorChar, LeftChars...> &,
								  const cstring<CharType, XorChar, RightChars...> &)
{
	return cstring<CharType, XorChar, LeftChars..., RightChars...>();
}

template<
	 typename CharType
	,CharType XorChar
	,CharType... LeftChars
	,CharType... RightChars
>
constexpr bool operator== (const cstring<CharType, XorChar, LeftChars...>& lhs,
									const cstring<CharType, XorChar, RightChars...>& rhs)
{
	return (lhs.compare(rhs) == 0);
}

template<
	 typename CharType
	,CharType XorCharLeft
	,CharType XorCharRight
	,CharType... LeftChars
	,CharType... RightChars
>
constexpr bool operator== (const cstring<CharType, XorCharLeft, LeftChars...>& lhs,
									const cstring<CharType, XorCharRight, RightChars...>& rhs)
{
	return (lhs.compare(rhs) == 0);
}

template<
	 typename CharType
	,CharType XorChar
	,CharType... LeftChars
	,CharType... RightChars
>
constexpr bool operator!= (const cstring<CharType, XorChar, LeftChars...>& lhs,
									const cstring<CharType, XorChar, RightChars...>& rhs)
{
	return !operator==(lhs, rhs);
}

template<
	 typename CharType
	,CharType XorCharLeft
	,CharType XorCharRight
	,CharType... LeftChars
	,CharType... RightChars
>
constexpr bool operator!= (const cstring<CharType, XorCharLeft, LeftChars...>& lhs,
									const cstring<CharType, XorCharRight, RightChars...>& rhs)
{
	return !operator==(lhs, rhs);
}

/**************************************************************************/

} // ns csprot

#endif // _csprot_hpp_
<commit_msg>some simplifications<commit_after>
// Copyright (c) 2015-2016 niXman (i dot nixman dog gmail dot com). All
// rights reserved.
//
// This file is part of CSPROT(https://github.com/niXman/csprot) project.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
//
//
// Boost Software License - Version 1.0 - August 17th, 2003
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#ifndef _csprot_hpp_
#define _csprot_hpp_

#include <cstdint>

#if __cplusplus < 201402L
#	error C++14 or greater is required
#endif

namespace csprot {

/**************************************************************************/

namespace {

template<typename>
struct xor_char_type;

template<>
struct xor_char_type<char> {
	static constexpr const char plain_xor = 0;
	static constexpr const char xored_xor = 177;
};

template<>
struct xor_char_type<wchar_t> {
	static constexpr const wchar_t plain_xor = 0;
	static constexpr const wchar_t xored_xor = 157;
};

// holder
template<bool, typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
struct string_holder;

} // anon ns

/**************************************************************************/

namespace {

// spec for plain strings
template<typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
struct string_holder<false, CharType, XorChar, FirstChar, SecondChars...> {
protected:
	static constexpr CharType _data[] = { FirstChar^XorChar, SecondChars^XorChar ..., '\0' };

	constexpr const CharType* c_str() const { return _data; }
};
template <typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
constexpr const CharType string_holder<false, CharType, XorChar, FirstChar, SecondChars...>::_data[];

// spec for xor`ed strings
template<typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
struct string_holder<true, CharType, XorChar, FirstChar, SecondChars...> {
	static constexpr CharType _data[] = { FirstChar^XorChar, SecondChars^XorChar ..., '\0' };
	mutable char _plain[sizeof(_data)];

	constexpr const CharType* c_str() const {
		std::size_t i = 0;
		for ( ; i < 1+sizeof...(SecondChars); ++i ) {
			_plain[i] = _data[i]^XorChar;
		}
		_plain[i]=0;

		return _plain;
	}
};
template <typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
constexpr const CharType string_holder<true, CharType, XorChar, FirstChar, SecondChars...>::_data[];

} // anon ns

/**************************************************************************/

template <typename CharType, CharType XorChar, CharType... Chars>
class cstring;

template <typename CharType, CharType XorChar, CharType FirstChar, CharType... SecondChars>
struct cstring<CharType, XorChar, FirstChar, SecondChars...>
	:string_holder<XorChar==xor_char_type<CharType>::xored_xor, CharType, XorChar, FirstChar, SecondChars...> {
private:
	using holder_type = string_holder<XorChar==xor_char_type<CharType>::xored_xor, CharType, XorChar, FirstChar, SecondChars...>;
public:
	constexpr cstring() = default;

	constexpr std::size_t     size()     const { return 1+sizeof...(SecondChars); }
	constexpr std::size_t     length()   const { return size(); }
	constexpr bool            empty()    const { return false; }
	constexpr bool            is_plain() const { return XorChar == xor_char_type<CharType>::plain_xor; }
	constexpr bool            is_xored() const { return XorChar == xor_char_type<CharType>::xored_xor; }
	constexpr const CharType* data()     const { return holder_type::_data; }
	using holder_type::c_str;

	template<
		 CharType XorChar2
		,CharType... Chars
	>
	constexpr int compare(const cstring<CharType, XorChar2, Chars...>& other) const {
		for ( std::size_t i = 0; i < size() && i < other.size(); ++i ) {
			if (data()[i] < other.data()[i]) return -1;
			if (data()[i] > other.data()[i]) return 1;
		}

		if (size() < other.size()) return -1;
		if (size() > other.size()) return 1;

		return 0;
	}
};

// spec for empty strings
template<typename CharType, CharType XorChar>
struct cstring<CharType, XorChar> {
private:
	static constexpr CharType _data = '\0';

public:
	constexpr cstring() = default;

	constexpr std::size_t     size()     const { return 0; }
	constexpr std::size_t     length()   const { return 0; }
	constexpr bool            empty()    const { return true; }
	constexpr bool            is_plain() const { return XorChar == xor_char_type<CharType>::plain_xor; }
	constexpr bool            is_xored() const { return XorChar == xor_char_type<CharType>::xored_xor; }
	constexpr const CharType* data()     const { return &_data; }
	constexpr const CharType* c_str()    const { return &_data; }

	template <CharType... OtherChars>
	constexpr int compare(const cstring<CharType, XorChar, OtherChars...>& other) const {
		return other.empty() ? 0 : -1;
	}
};
template<typename CharType, CharType XorChar>
constexpr const CharType cstring<CharType, XorChar>::_data;

/*****************************************************************************/

// for plain strings
template<typename CharType, CharType... Chars>
constexpr auto operator"" _S() {
	return cstring<CharType, xor_char_type<CharType>::plain_xor, Chars...>();
}

// for xor`ed strings
template<typename CharType, CharType... Chars>
constexpr auto operator"" _XS() {
	return cstring<CharType, xor_char_type<CharType>::xored_xor, Chars...>();
}

/**************************************************************************/

template<
	 typename CharType
	,CharType XorChar
	,CharType... LeftChars
	,CharType... RightChars
>
constexpr auto operator+ (const cstring<CharType, XorChar, LeftChars...> &,
								  const cstring<CharType, XorChar, RightChars...> &)
{
	return cstring<CharType, XorChar, LeftChars..., RightChars...>();
}

template<
	 typename CharType
	,CharType XorCharLeft
	,CharType XorCharRight
	,CharType... LeftChars
	,CharType... RightChars
>
constexpr bool operator== (const cstring<CharType, XorCharLeft, LeftChars...>& lhs,
									const cstring<CharType, XorCharRight, RightChars...>& rhs)
{
	return (lhs.compare(rhs) == 0);
}

template<
	 typename CharType
	,CharType XorCharLeft
	,CharType XorCharRight
	,CharType... LeftChars
	,CharType... RightChars
>
constexpr bool operator!= (const cstring<CharType, XorCharLeft, LeftChars...>& lhs,
									const cstring<CharType, XorCharRight, RightChars...>& rhs)
{
	return !operator==(lhs, rhs);
}

/**************************************************************************/

} // ns csprot

#endif // _csprot_hpp_
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id: rdrand.cc 11496 2012-10-09 15:16:48Z sshwarts $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2012  The Bochs Project
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
//
/////////////////////////////////////////////////////////////////////////

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#include "cpu.h"
#define LOG_THIS BX_CPU_THIS_PTR
#include <openssl/aes.h>
#include <stdlib.h>

#define HW_RANDOM_GENERATOR_READY (1)

BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDRAND_Ew(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDRAND_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDRAND, 0);
    }
  }
#endif

  Bit16u val_16 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_16 |= rand() & 0xff;  // hack using std C rand() function
    val_16 <<= 8;
    val_16 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_16BIT_REG(i->dst(), val_16);

  BX_NEXT_INSTR(i);
}

BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDRAND_Ed(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDRAND_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDRAND, 0);
    }
  }
#endif

  Bit32u val_32 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_32 |= rand() & 0xff;  // hack using std C rand() function
    val_32 <<= 8;
    val_32 |= rand() & 0xff;
    val_32 <<= 8;
    val_32 |= rand() & 0xff;
    val_32 <<= 8;
    val_32 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_32BIT_REGZ(i->dst(), val_32);

  BX_NEXT_INSTR(i);
}

/* this is the one we want to use as output covert channel */
#if BX_SUPPORT_X86_64
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDRAND_Eq(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDRAND_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDRAND, 0);
    }
  }
#endif

  Bit64u val_64 = 0;
  uint8_t ibuf [16];
  /* input buffer is organized like this:
     8 bytes -- counter
     6 bytes of padding
     1 byte -- evilstatus
     1 byte -- evilbyte */
  uint8_t obuf [16];
  AES_KEY keyctx;

  if (HW_RANDOM_GENERATOR_READY) {
    AES_set_encrypt_key(BX_CPU_THIS_PTR evil.aes_key, 128, &keyctx);

    memcpy(ibuf,             &(BX_CPU_THIS_PTR evil.counter),    8);
    memset(ibuf + 8,         0xfe,                               6);
    memcpy(ibuf + 8 + 6,     &(BX_CPU_THIS_PTR evil.evilstatus), 1);
    memcpy(ibuf + 8 + 6 + 1, &(BX_CPU_THIS_PTR evil.evilbyte),   1);

    AES_encrypt(ibuf, obuf, &keyctx);

    if (BX_CPU_THIS_PTR evil.out_stat == 0) {   /* output high half */
        memcpy(&val_64, obuf, 8);
        BX_CPU_THIS_PTR evil.out_stat = 1;
    } else {                                    /* output lo half */
        memcpy(&val_64, obuf + 8, 8);
        BX_CPU_THIS_PTR evil.out_stat = 0;
/*        BX_CPU_THIS_PTR evil.counter++; */
    }

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_64BIT_REG(i->dst(), val_64);

  BX_NEXT_INSTR(i);
}
#endif

BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDSEED_Ew(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDSEED_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDSEED, 0);
    }
  }
#endif

  Bit16u val_16 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_16 |= rand() & 0xff;  // hack using std C rand() function
    val_16 <<= 8;
    val_16 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_16BIT_REG(i->dst(), val_16);

  BX_NEXT_INSTR(i);
}

BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDSEED_Ed(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDSEED_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDSEED, 0);
    }
  }
#endif

  Bit32u val_32 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_32 |= rand() & 0xff;  // hack using std C rand() function
    val_32 <<= 8;
    val_32 |= rand() & 0xff;
    val_32 <<= 8;
    val_32 |= rand() & 0xff;
    val_32 <<= 8;
    val_32 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_32BIT_REGZ(i->dst(), val_32);

  BX_NEXT_INSTR(i);
}

#if BX_SUPPORT_X86_64
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDSEED_Eq(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDSEED_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDSEED, 0);
    }
  }
#endif

  Bit64u val_64 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_64 |= rand() & 0xff;  // hack using std C rand() function
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_64BIT_REG(i->dst(), val_64);

  BX_NEXT_INSTR(i);
}
#endif
<commit_msg>move the counter<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id: rdrand.cc 11496 2012-10-09 15:16:48Z sshwarts $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2012  The Bochs Project
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
//
/////////////////////////////////////////////////////////////////////////

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#include "cpu.h"
#define LOG_THIS BX_CPU_THIS_PTR
#include <openssl/aes.h>
#include <stdlib.h>

#define HW_RANDOM_GENERATOR_READY (1)

BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDRAND_Ew(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDRAND_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDRAND, 0);
    }
  }
#endif

  Bit16u val_16 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_16 |= rand() & 0xff;  // hack using std C rand() function
    val_16 <<= 8;
    val_16 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_16BIT_REG(i->dst(), val_16);

  BX_NEXT_INSTR(i);
}

BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDRAND_Ed(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDRAND_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDRAND, 0);
    }
  }
#endif

  Bit32u val_32 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_32 |= rand() & 0xff;  // hack using std C rand() function
    val_32 <<= 8;
    val_32 |= rand() & 0xff;
    val_32 <<= 8;
    val_32 |= rand() & 0xff;
    val_32 <<= 8;
    val_32 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_32BIT_REGZ(i->dst(), val_32);

  BX_NEXT_INSTR(i);
}

/* this is the one we want to use as output covert channel */
#if BX_SUPPORT_X86_64
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDRAND_Eq(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDRAND_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDRAND, 0);
    }
  }
#endif

  Bit64u val_64 = 0;
  uint8_t ibuf [16];
  /* input buffer is organized like this:
     8 bytes -- counter
     6 bytes of padding
     1 byte -- evilstatus
     1 byte -- evilbyte */
  uint8_t obuf [16];
  AES_KEY keyctx;

  if (HW_RANDOM_GENERATOR_READY) {
    AES_set_encrypt_key(BX_CPU_THIS_PTR evil.aes_key, 128, &keyctx);

    memcpy(ibuf,             &(BX_CPU_THIS_PTR evil.counter),    8);
    memset(ibuf + 8,         0xfe,                               6);
    memcpy(ibuf + 8 + 6,     &(BX_CPU_THIS_PTR evil.evilstatus), 1);
    memcpy(ibuf + 8 + 6 + 1, &(BX_CPU_THIS_PTR evil.evilbyte),   1);

    AES_encrypt(ibuf, obuf, &keyctx);

    if (BX_CPU_THIS_PTR evil.out_stat == 0) {   /* output high half */
        memcpy(&val_64, obuf, 8);
        BX_CPU_THIS_PTR evil.out_stat = 1;
    } else {                                    /* output lo half */
        memcpy(&val_64, obuf + 8, 8);
        BX_CPU_THIS_PTR evil.out_stat = 0;
        BX_CPU_THIS_PTR evil.counter++;
    }

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_64BIT_REG(i->dst(), val_64);

  BX_NEXT_INSTR(i);
}
#endif

BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDSEED_Ew(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDSEED_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDSEED, 0);
    }
  }
#endif

  Bit16u val_16 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_16 |= rand() & 0xff;  // hack using std C rand() function
    val_16 <<= 8;
    val_16 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_16BIT_REG(i->dst(), val_16);

  BX_NEXT_INSTR(i);
}

BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDSEED_Ed(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDSEED_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDSEED, 0);
    }
  }
#endif

  Bit32u val_32 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_32 |= rand() & 0xff;  // hack using std C rand() function
    val_32 <<= 8;
    val_32 |= rand() & 0xff;
    val_32 <<= 8;
    val_32 |= rand() & 0xff;
    val_32 <<= 8;
    val_32 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_32BIT_REGZ(i->dst(), val_32);

  BX_NEXT_INSTR(i);
}

#if BX_SUPPORT_X86_64
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDSEED_Eq(bxInstruction_c *i)
{
#if BX_SUPPORT_VMX
  if (BX_CPU_THIS_PTR in_vmx_guest) {
    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDSEED_VMEXIT)) {
      VMexit(VMX_VMEXIT_RDSEED, 0);
    }
  }
#endif

  Bit64u val_64 = 0;

  if (HW_RANDOM_GENERATOR_READY) {
    val_64 |= rand() & 0xff;  // hack using std C rand() function
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;
    val_64 <<= 8;
    val_64 |= rand() & 0xff;

    setEFlagsOSZAPC(EFlagsCFMask);
  }
  else {
    setEFlagsOSZAPC(0);
  }

  BX_WRITE_64BIT_REG(i->dst(), val_64);

  BX_NEXT_INSTR(i);
}
#endif
<|endoftext|>


<commit_before>#include "vboMesh.h"
#include "platform.h"

#define MAX_INDEX_VALUE 65535 // Maximum value of GLushort

int VboMesh::s_validGeneration = 0;

VboMesh::VboMesh() {
    m_glVertexBuffer = 0;
    m_glIndexBuffer = 0;
    m_nVertices = 0;
    m_nIndices = 0;
    m_dirtyOffset = 0;
    m_dirtySize = 0;

    m_dirty = false;
    m_isUploaded = false;
    m_isCompiled = false;

    m_generation = -1;
}

VboMesh::VboMesh(std::shared_ptr<VertexLayout> _vertexLayout, GLenum _drawMode, GLenum _hint) : VboMesh() {
    m_vertexLayout = _vertexLayout;
    m_hint = _hint;

    setDrawMode(_drawMode);
}

VboMesh::~VboMesh() {
    if (m_glVertexBuffer) glDeleteBuffers(1, &m_glVertexBuffer);
    if (m_glIndexBuffer) glDeleteBuffers(1, &m_glIndexBuffer);

    delete[] m_glVertexData;
    delete[] m_glIndexData;
}

void VboMesh::setVertexLayout(std::shared_ptr<VertexLayout> _vertexLayout) {
    m_vertexLayout = _vertexLayout;
}

void VboMesh::setDrawMode(GLenum _drawMode) {
    switch (_drawMode) {
        case GL_POINTS:
        case GL_LINE_STRIP:
        case GL_LINE_LOOP:
        case GL_LINES:
        case GL_TRIANGLE_STRIP:
        case GL_TRIANGLE_FAN:
        case GL_TRIANGLES:
            m_drawMode = _drawMode;
            break;
        default:
            logMsg("WARNING: Invalid draw mode for mesh! Defaulting to GL_TRIANGLES\n");
            m_drawMode = GL_TRIANGLES;
    }
}

void VboMesh::update(intptr_t _offset, long _size, unsigned char* _data) {
    if (m_hint == GL_STATIC_DRAW) {
        logMsg("WARNING: wrong usage hint provided to the Vbo\n");
    }

    std::memcpy(m_glVertexData + _offset, _data, _size);

    m_dirtyOffset = _offset;
    m_dirtySize = _size;

    m_dirty = true;
}

void VboMesh::subDataUpload() {
    if (m_dirtySize != 0) {
        glBindBuffer(GL_ARRAY_BUFFER, m_glVertexBuffer);

        long vertexBytes = m_nVertices * m_vertexLayout->getStride();

        // updating the entire buffer
        if (std::abs(m_dirtySize - vertexBytes) < m_vertexLayout->getStride()) {

            // invalidate the data store on the driver
            glBufferData(GL_ARRAY_BUFFER, vertexBytes, NULL, m_hint);

            // if this buffer is still used by gpu on current frame this call will not wait
            // for the frame to finish using the vbo but directly upload the data
            glBufferData(GL_ARRAY_BUFFER, vertexBytes, m_glVertexData, m_hint);
        } else {
            // perform simple sub data upload for part of the buffer
            glBufferSubData(GL_ARRAY_BUFFER, m_dirtyOffset, m_dirtySize, m_glVertexData + m_dirtyOffset);
        }

        m_dirtyOffset = 0;
        m_dirtySize = 0;
    }

    m_dirty = false;
}

void VboMesh::upload() {
    // Generate vertex buffer, if needed
    if (m_glVertexBuffer == 0) {
        glGenBuffers(1, &m_glVertexBuffer);
    }

    // TODO check if compiled?
    // Buffer vertex data
    int vertexBytes = m_nVertices * m_vertexLayout->getStride();

    glBindBuffer(GL_ARRAY_BUFFER, m_glVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertexBytes, m_glVertexData, m_hint);

    if (m_glIndexData) {

        if (m_glIndexBuffer == 0) {
            glGenBuffers(1, &m_glIndexBuffer);
        }

        // Buffer element index data
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glIndexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_nIndices * sizeof(GLushort), m_glIndexData, m_hint);
    }

    // m_glVertexData.resize(0);
    // m_glIndexData.resize(0);

    // TODO: For now, we retain copies of the vertex and index data in CPU memory to allow VBOs
    // to easily rebuild themselves after GL context loss. For optimizing memory usage (and for
    // other reasons) we'll want to change this in the future. This probably means going back to
    // data sources and styles to rebuild the vertex data.

    m_generation = s_validGeneration;

    m_isUploaded = true;

}

void VboMesh::draw(const std::shared_ptr<ShaderProgram> _shader) {

    checkValidity();

    if (!m_isCompiled) return;

    if (m_nVertices == 0) return;

    // Ensure that geometry is buffered into GPU
    if (!m_isUploaded) {
        upload();
    }

    if (m_dirty) {
        subDataUpload();
    }

    // Bind buffers for drawing
    glBindBuffer(GL_ARRAY_BUFFER, m_glVertexBuffer);

    if (m_nIndices > 0) {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glIndexBuffer);
    }

    // Enable shader program
    _shader->use();

    size_t indiceOffset = 0;
    size_t vertexOffset = 0;

    for (auto& o : m_vertexOffsets) {
        uint32_t nIndices = o.first;
        uint32_t nVertices = o.second;

        size_t byteOffset = vertexOffset * m_vertexLayout->getStride();

        // Enable vertex attribs via vertex layout object
        m_vertexLayout->enable(_shader, byteOffset);

        // Draw as elements or arrays
        if (nIndices > 0) {
            glDrawElements(m_drawMode, nIndices, GL_UNSIGNED_SHORT,
                           (void*)(indiceOffset * sizeof(GLushort)));
        } else if (nVertices > 0) {
            glDrawArrays(m_drawMode, 0, nVertices);
        }

        vertexOffset += nVertices;
        indiceOffset += nIndices;
    }
}

void VboMesh::checkValidity() {
    if (m_generation != s_validGeneration) {
        m_isUploaded = false;
        m_glVertexBuffer = 0;
        m_glIndexBuffer = 0;

        m_generation = s_validGeneration;
    }
}

void VboMesh::invalidateAllVBOs() {

    ++s_validGeneration;

}
<commit_msg>subDataUpload<commit_after>#include "vboMesh.h"
#include "platform.h"

#define MAX_INDEX_VALUE 65535 // Maximum value of GLushort

int VboMesh::s_validGeneration = 0;

VboMesh::VboMesh() {
    m_glVertexBuffer = 0;
    m_glIndexBuffer = 0;
    m_nVertices = 0;
    m_nIndices = 0;
    m_dirtyOffset = 0;
    m_dirtySize = 0;

    m_dirty = false;
    m_isUploaded = false;
    m_isCompiled = false;

    m_generation = -1;
}

VboMesh::VboMesh(std::shared_ptr<VertexLayout> _vertexLayout, GLenum _drawMode, GLenum _hint) : VboMesh() {
    m_vertexLayout = _vertexLayout;
    m_hint = _hint;

    setDrawMode(_drawMode);
}

VboMesh::~VboMesh() {
    if (m_glVertexBuffer) glDeleteBuffers(1, &m_glVertexBuffer);
    if (m_glIndexBuffer) glDeleteBuffers(1, &m_glIndexBuffer);

    delete[] m_glVertexData;
    delete[] m_glIndexData;
}

void VboMesh::setVertexLayout(std::shared_ptr<VertexLayout> _vertexLayout) {
    m_vertexLayout = _vertexLayout;
}

void VboMesh::setDrawMode(GLenum _drawMode) {
    switch (_drawMode) {
        case GL_POINTS:
        case GL_LINE_STRIP:
        case GL_LINE_LOOP:
        case GL_LINES:
        case GL_TRIANGLE_STRIP:
        case GL_TRIANGLE_FAN:
        case GL_TRIANGLES:
            m_drawMode = _drawMode;
            break;
        default:
            logMsg("WARNING: Invalid draw mode for mesh! Defaulting to GL_TRIANGLES\n");
            m_drawMode = GL_TRIANGLES;
    }
}

void VboMesh::update(intptr_t _offset, long _size, unsigned char* _data) {
    if (m_hint == GL_STATIC_DRAW) {
        logMsg("WARNING: wrong usage hint provided to the Vbo\n");
    }

    std::memcpy(m_glVertexData + _offset, _data, _size);

    m_dirtyOffset = _offset;
    m_dirtySize = _size;

    m_dirty = true;
}

void VboMesh::subDataUpload() {
    if (m_dirtySize != 0) {
        glBindBuffer(GL_ARRAY_BUFFER, m_glVertexBuffer);

        long vertexBytes = m_nVertices * m_vertexLayout->getStride();

        // updating the entire buffer
        if (std::abs(m_dirtySize - vertexBytes) < m_vertexLayout->getStride()) {

            // invalidate the data store on the driver
            glBufferData(GL_ARRAY_BUFFER, vertexBytes, NULL, m_hint);

            // if this buffer is still used by gpu on current frame this call will not wait
            // for the frame to finish using the vbo but directly upload the data
            glBufferData(GL_ARRAY_BUFFER, vertexBytes, m_glVertexData, m_hint);
        } else {
            // perform simple sub data upload for part of the buffer
            glBufferSubData(GL_ARRAY_BUFFER, m_dirtyOffset, m_dirtySize, m_glVertexData + m_dirtyOffset);
        }

        m_dirtyOffset = 0;
        m_dirtySize = 0;
    }

    m_dirty = false;
}

void VboMesh::upload() {
    // Generate vertex buffer, if needed
    if (m_glVertexBuffer == 0) {
        glGenBuffers(1, &m_glVertexBuffer);
    }

    // TODO check if compiled?
    // Buffer vertex data
    int vertexBytes = m_nVertices * m_vertexLayout->getStride();

    glBindBuffer(GL_ARRAY_BUFFER, m_glVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertexBytes, m_glVertexData, m_hint);

    if (m_glIndexData) {

        if (m_glIndexBuffer == 0) {
            glGenBuffers(1, &m_glIndexBuffer);
        }

        // Buffer element index data
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glIndexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_nIndices * sizeof(GLushort), m_glIndexData, m_hint);
    }

    // m_glVertexData.resize(0);
    // m_glIndexData.resize(0);

    // TODO: For now, we retain copies of the vertex and index data in CPU memory to allow VBOs
    // to easily rebuild themselves after GL context loss. For optimizing memory usage (and for
    // other reasons) we'll want to change this in the future. This probably means going back to
    // data sources and styles to rebuild the vertex data.

    m_generation = s_validGeneration;

    m_isUploaded = true;

}

void VboMesh::draw(const std::shared_ptr<ShaderProgram> _shader) {

    checkValidity();

    if (!m_isCompiled) return;

    if (m_nVertices == 0) return;

    // Ensure that geometry is buffered into GPU
    if (!m_isUploaded) {
        upload();
    } else if (m_dirty) {
        subDataUpload();
    }

    // Bind buffers for drawing
    glBindBuffer(GL_ARRAY_BUFFER, m_glVertexBuffer);

    if (m_nIndices > 0) {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_glIndexBuffer);
    }

    // Enable shader program
    _shader->use();

    size_t indiceOffset = 0;
    size_t vertexOffset = 0;

    for (auto& o : m_vertexOffsets) {
        uint32_t nIndices = o.first;
        uint32_t nVertices = o.second;

        size_t byteOffset = vertexOffset * m_vertexLayout->getStride();

        // Enable vertex attribs via vertex layout object
        m_vertexLayout->enable(_shader, byteOffset);

        // Draw as elements or arrays
        if (nIndices > 0) {
            glDrawElements(m_drawMode, nIndices, GL_UNSIGNED_SHORT,
                           (void*)(indiceOffset * sizeof(GLushort)));
        } else if (nVertices > 0) {
            glDrawArrays(m_drawMode, 0, nVertices);
        }

        vertexOffset += nVertices;
        indiceOffset += nIndices;
    }
}

void VboMesh::checkValidity() {
    if (m_generation != s_validGeneration) {
        m_isUploaded = false;
        m_glVertexBuffer = 0;
        m_glIndexBuffer = 0;

        m_generation = s_validGeneration;
    }
}

void VboMesh::invalidateAllVBOs() {

    ++s_validGeneration;

}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 * Copyright (c) 2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file df_ms5607_wrapper.cpp
 * Lightweight driver to access the MS5607 of the DriverFramework.
 */

#include <px4_config.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <px4_getopt.h>
#include <errno.h>

#include <systemlib/perf_counter.h>
#include <systemlib/err.h>

#include <drivers/drv_baro.h>

#include <board_config.h>

#include <ms5607/MS5607.hpp>
#include <DevMgr.hpp>

extern "C" { __EXPORT int df_ms5607_wrapper_main(int argc, char *argv[]); }

using namespace DriverFramework;

class DfMS5607Wrapper : public MS5607
{
public:
	DfMS5607Wrapper();
	~DfMS5607Wrapper();

	/**
	 * Start automatic measurement.
	 *
	 * @return 0 on success
	 */
	int		start();

	/**
	 * Stop automatic measurement.
	 *
	 * @return 0 on success
	 */
	int		stop();

private:
	int _publish(struct baro_sensor_data &data);

	orb_advert_t		_baro_topic;

	int			_baro_orb_class_instance;

	perf_counter_t		_baro_sample_perf;

};

DfMS5607Wrapper::DfMS5607Wrapper() :
	MS5607(BARO_DEVICE_PATH),
	_baro_topic(nullptr),
	_baro_orb_class_instance(-1),
	_baro_sample_perf(perf_alloc(PC_ELAPSED, "df_baro_read"))
{
}

DfMS5607Wrapper::~DfMS5607Wrapper()
{
	perf_free(_baro_sample_perf);
}

int DfMS5607Wrapper::start()
{
	/* Init device and start sensor. */
	int ret = init();

	if (ret != 0) {
		PX4_ERR("MS5607 init fail: %d", ret);
		return ret;
	}

	ret = MS5607::start();

	if (ret != 0) {
		PX4_ERR("MS5607 start fail: %d", ret);
		return ret;
	}

	return 0;
}

int DfMS5607Wrapper::stop()
{
	/* Stop sensor. */
	int ret = MS5607::stop();

	if (ret != 0) {
		PX4_ERR("MS5607 stop fail: %d", ret);
		return ret;
	}

	return 0;
}

int DfMS5607Wrapper::_publish(struct baro_sensor_data &data)
{
	perf_begin(_baro_sample_perf);

	baro_report baro_report = {};
	baro_report.timestamp = hrt_absolute_time();

	baro_report.pressure = data.pressure_pa;
	baro_report.temperature = data.temperature_c;

	// TODO: verify this, it's just copied from the MS5611 driver.

	// Constant for now
	const double MSL_PRESSURE_KPA = 101325.0 / 1000.0;

	/* tropospheric properties (0-11km) for standard atmosphere */
	const double T1 = 15.0 + 273.15;	/* temperature at base height in Kelvin */
	const double a  = -6.5 / 1000;	/* temperature gradient in degrees per metre */
	const double g  = 9.80665;	/* gravity constant in m/s/s */
	const double R  = 287.05;	/* ideal gas constant in J/kg/K */

	/* current pressure at MSL in kPa */
	double p1 = MSL_PRESSURE_KPA;

	/* measured pressure in kPa */
	double p = static_cast<double>(data.pressure_pa) / 1000.0;

	/*
	 * Solve:
	 *
	 *     /        -(aR / g)     \
	 *    | (p / p1)          . T1 | - T1
	 *     \                      /
	 * h = -------------------------------  + h1
	 *                   a
	 */
	baro_report.altitude = (((pow((p / p1), (-(a * R) / g))) * T1) - T1) / a;

	// TODO: when is this ever blocked?
	if (!(m_pub_blocked)) {

		if (_baro_topic == nullptr) {
		  _baro_topic = orb_advertise_multi(ORB_ID(sensor_baro), &baro_report,
		                                    &_baro_orb_class_instance, ORB_PRIO_DEFAULT);

		} else {
			orb_publish(ORB_ID(sensor_baro), _baro_topic, &baro_report);
		}
	}

	/* Notify anyone waiting for data. */
	DevMgr::updateNotify(*this);

	perf_end(_baro_sample_perf);

	return 0;
};

namespace df_ms5607_wrapper
{

DfMS5607Wrapper *g_dev = nullptr;

int start(/* enum Rotation rotation */);
int stop();
int info();
void usage();

int start(/*enum Rotation rotation*/)
{
	g_dev = new DfMS5607Wrapper(/*rotation*/);

	if (g_dev == nullptr) {
		PX4_ERR("failed instantiating DfMS5607Wrapper object");
		return -1;
	}

	int ret = g_dev->start();

	if (ret != 0) {
		PX4_ERR("DfMS5607Wrapper start failed");
		return ret;
	}

	// Open the IMU sensor
	DevHandle h;
	DevMgr::getHandle(BARO_DEVICE_PATH, h);

	if (!h.isValid()) {
		DF_LOG_INFO("Error: unable to obtain a valid handle for the receiver at: %s (%d)",
			    BARO_DEVICE_PATH, h.getError());
		return -1;
	}

	DevMgr::releaseHandle(h);

	return 0;
}

int stop()
{
	if (g_dev == nullptr) {
		PX4_ERR("driver not running");
		return 1;
	}

	int ret = g_dev->stop();

	if (ret != 0) {
		PX4_ERR("driver could not be stopped");
		return ret;
	}

	delete g_dev;
	g_dev = nullptr;
	return 0;
}

/**
 * Print a little info about the driver.
 */
int
info()
{
	if (g_dev == nullptr) {
		PX4_ERR("driver not running");
		return 1;
	}

	PX4_DEBUG("state @ %p", g_dev);

	return 0;
}

void
usage()
{
	PX4_WARN("Usage: df_ms5607_wrapper 'start', 'info', 'stop'");
}

} // namespace df_ms5607_wrapper

int
df_ms5607_wrapper_main(int argc, char *argv[])
{
	int ret = 0;
	int myoptind = 1;

	if (argc <= 1) {
		df_ms5607_wrapper::usage();
		return 1;
	}

	const char *verb = argv[myoptind];

	if (!strcmp(verb, "start")) {
		ret = df_ms5607_wrapper::start();
	}

	else if (!strcmp(verb, "stop")) {
		ret = df_ms5607_wrapper::stop();
	}

	else if (!strcmp(verb, "info")) {
		ret = df_ms5607_wrapper::info();
	}

	else {
		df_ms5607_wrapper::usage();
		return 1;
	}

	return ret;
}
<commit_msg>df_ms5607_wrapper: astyle (#4853)<commit_after>/****************************************************************************
 *
 * Copyright (c) 2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file df_ms5607_wrapper.cpp
 * Lightweight driver to access the MS5607 of the DriverFramework.
 */

#include <px4_config.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <px4_getopt.h>
#include <errno.h>

#include <systemlib/perf_counter.h>
#include <systemlib/err.h>

#include <drivers/drv_baro.h>

#include <board_config.h>

#include <ms5607/MS5607.hpp>
#include <DevMgr.hpp>

extern "C" { __EXPORT int df_ms5607_wrapper_main(int argc, char *argv[]); }

using namespace DriverFramework;

class DfMS5607Wrapper : public MS5607
{
public:
	DfMS5607Wrapper();
	~DfMS5607Wrapper();

	/**
	 * Start automatic measurement.
	 *
	 * @return 0 on success
	 */
	int		start();

	/**
	 * Stop automatic measurement.
	 *
	 * @return 0 on success
	 */
	int		stop();

private:
	int _publish(struct baro_sensor_data &data);

	orb_advert_t		_baro_topic;

	int			_baro_orb_class_instance;

	perf_counter_t		_baro_sample_perf;

};

DfMS5607Wrapper::DfMS5607Wrapper() :
	MS5607(BARO_DEVICE_PATH),
	_baro_topic(nullptr),
	_baro_orb_class_instance(-1),
	_baro_sample_perf(perf_alloc(PC_ELAPSED, "df_baro_read"))
{
}

DfMS5607Wrapper::~DfMS5607Wrapper()
{
	perf_free(_baro_sample_perf);
}

int DfMS5607Wrapper::start()
{
	/* Init device and start sensor. */
	int ret = init();

	if (ret != 0) {
		PX4_ERR("MS5607 init fail: %d", ret);
		return ret;
	}

	ret = MS5607::start();

	if (ret != 0) {
		PX4_ERR("MS5607 start fail: %d", ret);
		return ret;
	}

	return 0;
}

int DfMS5607Wrapper::stop()
{
	/* Stop sensor. */
	int ret = MS5607::stop();

	if (ret != 0) {
		PX4_ERR("MS5607 stop fail: %d", ret);
		return ret;
	}

	return 0;
}

int DfMS5607Wrapper::_publish(struct baro_sensor_data &data)
{
	perf_begin(_baro_sample_perf);

	baro_report baro_report = {};
	baro_report.timestamp = hrt_absolute_time();

	baro_report.pressure = data.pressure_pa;
	baro_report.temperature = data.temperature_c;

	// TODO: verify this, it's just copied from the MS5611 driver.

	// Constant for now
	const double MSL_PRESSURE_KPA = 101325.0 / 1000.0;

	/* tropospheric properties (0-11km) for standard atmosphere */
	const double T1 = 15.0 + 273.15;	/* temperature at base height in Kelvin */
	const double a  = -6.5 / 1000;	/* temperature gradient in degrees per metre */
	const double g  = 9.80665;	/* gravity constant in m/s/s */
	const double R  = 287.05;	/* ideal gas constant in J/kg/K */

	/* current pressure at MSL in kPa */
	double p1 = MSL_PRESSURE_KPA;

	/* measured pressure in kPa */
	double p = static_cast<double>(data.pressure_pa) / 1000.0;

	/*
	 * Solve:
	 *
	 *     /        -(aR / g)     \
	 *    | (p / p1)          . T1 | - T1
	 *     \                      /
	 * h = -------------------------------  + h1
	 *                   a
	 */
	baro_report.altitude = (((pow((p / p1), (-(a * R) / g))) * T1) - T1) / a;

	// TODO: when is this ever blocked?
	if (!(m_pub_blocked)) {

		if (_baro_topic == nullptr) {
			_baro_topic = orb_advertise_multi(ORB_ID(sensor_baro), &baro_report,
							  &_baro_orb_class_instance, ORB_PRIO_DEFAULT);

		} else {
			orb_publish(ORB_ID(sensor_baro), _baro_topic, &baro_report);
		}
	}

	/* Notify anyone waiting for data. */
	DevMgr::updateNotify(*this);

	perf_end(_baro_sample_perf);

	return 0;
};

namespace df_ms5607_wrapper
{

DfMS5607Wrapper *g_dev = nullptr;

int start(/* enum Rotation rotation */);
int stop();
int info();
void usage();

int start(/*enum Rotation rotation*/)
{
	g_dev = new DfMS5607Wrapper(/*rotation*/);

	if (g_dev == nullptr) {
		PX4_ERR("failed instantiating DfMS5607Wrapper object");
		return -1;
	}

	int ret = g_dev->start();

	if (ret != 0) {
		PX4_ERR("DfMS5607Wrapper start failed");
		return ret;
	}

	// Open the IMU sensor
	DevHandle h;
	DevMgr::getHandle(BARO_DEVICE_PATH, h);

	if (!h.isValid()) {
		DF_LOG_INFO("Error: unable to obtain a valid handle for the receiver at: %s (%d)",
			    BARO_DEVICE_PATH, h.getError());
		return -1;
	}

	DevMgr::releaseHandle(h);

	return 0;
}

int stop()
{
	if (g_dev == nullptr) {
		PX4_ERR("driver not running");
		return 1;
	}

	int ret = g_dev->stop();

	if (ret != 0) {
		PX4_ERR("driver could not be stopped");
		return ret;
	}

	delete g_dev;
	g_dev = nullptr;
	return 0;
}

/**
 * Print a little info about the driver.
 */
int
info()
{
	if (g_dev == nullptr) {
		PX4_ERR("driver not running");
		return 1;
	}

	PX4_DEBUG("state @ %p", g_dev);

	return 0;
}

void
usage()
{
	PX4_WARN("Usage: df_ms5607_wrapper 'start', 'info', 'stop'");
}

} // namespace df_ms5607_wrapper

int
df_ms5607_wrapper_main(int argc, char *argv[])
{
	int ret = 0;
	int myoptind = 1;

	if (argc <= 1) {
		df_ms5607_wrapper::usage();
		return 1;
	}

	const char *verb = argv[myoptind];

	if (!strcmp(verb, "start")) {
		ret = df_ms5607_wrapper::start();
	}

	else if (!strcmp(verb, "stop")) {
		ret = df_ms5607_wrapper::stop();
	}

	else if (!strcmp(verb, "info")) {
		ret = df_ms5607_wrapper::info();
	}

	else {
		df_ms5607_wrapper::usage();
		return 1;
	}

	return ret;
}
<|endoftext|>


<commit_before>// Parse test application
// Based upon: parsetest.cpp from xmlpp

// needed includes
#include <fstream>
#include <iostream>
//#include <ctime>
#include <cppdom/cppdom.h>

#include <testHelpers.h>

// namespace includes
using namespace cppdom;
using namespace std;

void process_xml( std::string filename )
{
   cout << "processing [" << filename << "] ..." << endl;

   ContextPtr context( new Context );
   Document node( context );
   ifstream istr( filename.c_str() );

   // Verify that file opened
   if(!istr)
   {
      std::cerr << "Bad file: " << filename << std::endl;
      return;
   }

   try
   {
//      clock_t tstart = ::clock();

      node.load( istr, context );

//      clock_t tstop = ::clock();
//      cout << " needed " <<
//         (tstop-tstart)/static_cast<float>(CLOCKS_PER_SEC)
//         << " seconds." << endl;

      testHelpers::dump_node( node );

      ofstream ostr( "parsetest.xml" );
      node.save( ostr );
      ostr.close();

   }
   catch (Error e)
   {
      Location where( context->getLocation() );
      std::string errmsg;
      e.getStrError(errmsg);

      // print out where the error occured
      cout << filename << ":" << where.getLine() << " ";
      cout << "at position " << where.getPos();
      cout << ": error: " << errmsg.c_str();
      cout << endl;

      // print out line where the error occured
      ifstream errfile( filename.c_str() );
      if(!errfile)
      {
         std::cerr << "Can't open file [" << filename << "] to output error" << std::endl;
      }

      int linenr = where.getLine();
      char linebuffer[1024];
      for(int i=0; i<linenr && !errfile.eof(); i++)
         errfile.getline( linebuffer,1024 );

      int pos = where.getPos();
      if (pos>=80)
         pos %= 80;

      std::string err_line( linebuffer + (where.getPos()-pos) );
      if (err_line.length()>=79)
         err_line.erase(79);
      cout << err_line << std::flush;
      cout << err_line.c_str() << std::endl;
      cout << linebuffer << std::endl;
      for(int j=2;j<pos;j++)
         std::cout << " ";
      cout << '^' << endl;
   }
}

int main(int argc, char* argv[])
{
   for(int i=1;i<argc;i++)
   {
      process_xml( std::string(argv[i]) );
   }

   return 0;
}
<commit_msg>Fix up the test build that someone broke a couple of days ago.<commit_after>// Parse test application
// Based upon: parsetest.cpp from xmlpp

// needed includes
#include <fstream>
#include <iostream>
//#include <ctime>
#include <cppdom/cppdom.h>

#include <testHelpers.h>

// namespace includes
using namespace cppdom;
using namespace std;

void process_xml( std::string filename )
{
   cout << "processing [" << filename << "] ..." << endl;

   ContextPtr context( new Context );
   Document node( context );
   ifstream istr( filename.c_str() );

   // Verify that file opened
   if(!istr)
   {
      std::cerr << "Bad file: " << filename << std::endl;
      return;
   }

   try
   {
//      clock_t tstart = ::clock();

      node.load( istr, context );

//      clock_t tstop = ::clock();
//      cout << " needed " <<
//         (tstop-tstart)/static_cast<float>(CLOCKS_PER_SEC)
//         << " seconds." << endl;

      testHelpers::dump_node( node );

      ofstream ostr( "parsetest.xml" );
      node.save( ostr );
      ostr.close();

   }
   catch (Error e)
   {
      Location where( context->getLocation() );
      std::string errmsg = e.getStrError();

      // print out where the error occured
      cout << filename << ":" << where.getLine() << " ";
      cout << "at position " << where.getPos();
      cout << ": error: " << errmsg.c_str();
      cout << endl;

      // print out line where the error occured
      ifstream errfile( filename.c_str() );
      if(!errfile)
      {
         std::cerr << "Can't open file [" << filename << "] to output error" << std::endl;
      }

      int linenr = where.getLine();
      char linebuffer[1024];
      for(int i=0; i<linenr && !errfile.eof(); i++)
         errfile.getline( linebuffer,1024 );

      int pos = where.getPos();
      if (pos>=80)
         pos %= 80;

      std::string err_line( linebuffer + (where.getPos()-pos) );
      if (err_line.length()>=79)
         err_line.erase(79);
      cout << err_line << std::flush;
      cout << err_line.c_str() << std::endl;
      cout << linebuffer << std::endl;
      for(int j=2;j<pos;j++)
         std::cout << " ";
      cout << '^' << endl;
   }
}

int main(int argc, char* argv[])
{
   for(int i=1;i<argc;i++)
   {
      process_xml( std::string(argv[i]) );
   }

   return 0;
}
<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#ifdef GOOGLE_CUDA
#include "tensorflow/stream_executor/cuda/cuda_activation.h"
#include "third_party/gpus/cuda/include/cuda.h"
#include "third_party/gpus/cuda/include/cuda_runtime_api.h"
#endif  // GOOGLE_CUDA

#include "tensorflow/core/common_runtime/gpu/gpu_cudamallocasync_allocator.h"

#include "tensorflow/core/common_runtime/device/device_id_utils.h"
#include "tensorflow/core/common_runtime/gpu/gpu_id.h"
#include "tensorflow/core/common_runtime/gpu/gpu_init.h"
#include "tensorflow/core/framework/allocator.h"
#include "tensorflow/core/platform/stream_executor.h"
#include "tensorflow/core/util/env_var.h"

namespace tensorflow {

GpuCudaMallocAsyncAllocator::GpuCudaMallocAsyncAllocator(
    PlatformGpuId platform_gpu_id, size_t pool_size,
    bool reserve_memory, bool compute_stats)
    : name_(absl::StrCat("gpu_async_", platform_gpu_id.value())) {
  stream_exec_ =
      DeviceIdUtil::ExecutorForPlatformDeviceId(GPUMachineManager(),
                                                platform_gpu_id).ValueOrDie();

#if CUDA_VERSION < 11020
  LOG(FATAL) << "TF_GPU_ALLOCATOR=cuda_malloc_async need CUDA 11.2 or higher to compile.";
#elif !defined(GOOGLE_CUDA)
  LOG(FATAL) << "GOOGLE_CUDA not defined";
#else
  // Initialized here as it only exist if compiled with a recent
  // enough CUDA.
  pool_ = nullptr;
  cuda_stream_ = nullptr;
  // WAR an CUDA 11.2 driver bug for multiple-GPU. It currently
  // request that the context on GPU 0 is initialized. Which isn't the
  // case for TF+horovod.
  if (platform_gpu_id.value() > 0) {
    CUcontext pctx; // We loose track of it. But this is fine.
    CUresult err = cuDevicePrimaryCtxRetain(&pctx, 0);
    if (err != CUDA_SUCCESS){
      LOG(FATAL) << "Failed to create the context on device 0.";
    }
  }

  se::cuda::ScopedActivateExecutorContext scoped_activation{stream_exec_};
  int cuda_malloc_async_supported;
  cudaDeviceGetAttribute(&cuda_malloc_async_supported,
                         cudaDevAttrMemoryPoolsSupported,
                         platform_gpu_id.value());
  if (!cuda_malloc_async_supported) {
    LOG(FATAL) << "TF_GPU_ALLOCATOR=cuda_malloc_async isn't currently supported."
               << " Possible causes: device not supported, driver too old, "
               << " OS not supported, CUDA version too old.";
  }

  cudaError_t cerr = cudaStreamCreate(&cuda_stream_);
  if (cerr != cudaSuccess) {
    LOG(FATAL) << "could not allocate CUDA stream for context : "
               << cudaGetErrorString(cerr);
  }

  cerr = cudaDeviceGetDefaultMemPool(&pool_, platform_gpu_id.value());
  if (cerr != cudaSuccess) {
    LOG(FATAL) << "could not get the default CUDA pool : "
               << cudaGetErrorString(cerr);
  }
  VLOG(1) << Name() << " CudaMallocAsync initialized on platform: "
          << platform_gpu_id.value() << " with pool size of: "
          << pool_size << " this ptr: " << this;
  cerr = cudaMemPoolSetAttribute(pool_, cudaMemPoolAttrReleaseThreshold,
                                 reinterpret_cast<void*>(&pool_size));
  if (compute_stats) {
    mutex_lock lock(lock_);
    stats_.bytes_limit = static_cast<int64>(pool_size);
  } // If not set, it means we do not compute stats.
  if (cerr != cudaSuccess) {
    LOG(FATAL) << "could not set the default CUDA pool memory threshold : "
               << cudaGetErrorString(cerr);
    pool_ = nullptr;
  }

  // If in TF_DETERMINISTIC_OPS is set, then make the allocator behave
  // determistically.
  bool deterministic_ops = false;
  TF_CHECK_OK(tensorflow::ReadBoolFromEnvVar("TF_DETERMINISTIC_OPS",
                                             /*default_val=*/false,
                                             &deterministic_ops));
  if (deterministic_ops) {
    cudaMemPoolSetAttribute(pool_, cudaMemPoolReuseAllowOpportunistic, 0);
    cudaMemPoolSetAttribute(pool_, cudaMemPoolReuseAllowInternalDependencies, 0);
  }
#endif

  VLOG(2) << Name() << " GpuCudaMallocAsyncAllocator PoolSize " << pool_size;
  if (reserve_memory) {
    void* ptr = AllocateRaw(0, pool_size);
    DeallocateRaw(ptr);
    VLOG(2) << Name() << " GpuCudaMallocAsyncAllocator reserved the pool";
    ClearStats();
  }
}

GpuCudaMallocAsyncAllocator::~GpuCudaMallocAsyncAllocator() {
#ifdef GOOGLE_CUDA
  cuStreamDestroy(cuda_stream_);
#endif
}

void* GpuCudaMallocAsyncAllocator::AllocateRaw(size_t alignment,
                                               size_t num_bytes) {
#if CUDA_VERSION < 11020 || !defined(GOOGLE_CUDA)
  return nullptr;
#else
  if (pool_ == nullptr) {
    LOG(FATAL) << "The instantiation of GpuCudaMallocAsyncAllocator failed."
               << " See previous errors.";
  }
  se::cuda::ScopedActivateExecutorContext scoped_activation{stream_exec_};
  void* ptr = 0;
  cudaError_t res = cudaMallocFromPoolAsync(&ptr, num_bytes, pool_, cuda_stream_);
  if (res != cudaSuccess) {
    size_t free, total;
    cudaMemGetInfo(&free, &total);
    mutex_lock lock(lock_);
    LOG(ERROR) << Name() << " cudaMallocAsync failed to allocate " << num_bytes
               << "\n Error name: " << cudaGetErrorName(res)
               << "\n Error string: " << cudaGetErrorString(res)
               << "\n Free memory/Total memory: " << free << "/" << total
               << "\n Stats: \n" << stats_.DebugString();
    return nullptr;
  }

  // Update stats.
  if (stats_.bytes_limit.has_value()) {
    mutex_lock lock(lock_);
    ++stats_.num_allocs;
    stats_.bytes_in_use += num_bytes;
    stats_.peak_bytes_in_use =
        std::max(stats_.peak_bytes_in_use, stats_.bytes_in_use);
    stats_.largest_alloc_size =
        std::max<std::size_t>(stats_.largest_alloc_size, num_bytes);
    size_map_[ptr] = num_bytes;
  }
  VLOG(10) << Name() << " Allocated " << num_bytes << " at " << ptr;
  return ptr;
#endif
}
void GpuCudaMallocAsyncAllocator::DeallocateRaw(void* ptr) {
#if CUDA_VERSION < 11020 || !defined(GOOGLE_CUDA)
#else
  cudaError_t res = cudaFreeAsync(ptr, cuda_stream_);
  if (res == cudaErrorCudartUnloading) {
    // It happens with multi-GPU that TF free the GPU allocation after
    // the driver is unloaded. It is safe to ignore this error here.
    // TODO: Find how to fix the shutdown steps in TF.
    VLOG(1) << "Ignoring Error: " << cudaGetErrorName(res)
	    << " \nError string: " << cudaGetErrorString(res);
  } else if (res != cudaSuccess) {
    size_t free, total;
    se::cuda::ScopedActivateExecutorContext scoped_activation{stream_exec_};
    cudaMemGetInfo(&free, &total);
    LOG(ERROR) << "cudaFreeAsync failed to free " << ptr
               << "\n Error name: " << cudaGetErrorName(res)
               << "\n Error string: " << cudaGetErrorString(res)
               << "\n Free memory/Total memory: " << free << "/" << total
               << "\n Stats: \n" << stats_.DebugString();
  }

  // Updates the stats.
  if (stats_.bytes_limit.has_value()) {
    mutex_lock lock(lock_);
    DCHECK(size_map_.contains(ptr));
    size_t size = size_map_[ptr];
    stats_.bytes_in_use -= size;
    size_map_.erase(ptr);
  }

  VLOG(10) << Name() << " Freed ptr: " << ptr;
#endif  // GOOGLE_CUDA
}

bool GpuCudaMallocAsyncAllocator::TracksAllocationSizes() const {
  return stats_.bytes_limit.has_value();
}

size_t GpuCudaMallocAsyncAllocator::RequestedSize(const void* ptr) const {
  CHECK(ptr);
  return size_map_.at(ptr);
}

size_t GpuCudaMallocAsyncAllocator::AllocatedSize(const void* ptr) const {
  CHECK(ptr);
  return size_map_.at(ptr);
}

absl::optional<AllocatorStats> GpuCudaMallocAsyncAllocator::GetStats() {
  mutex_lock l(lock_);
  return stats_;
}

void GpuCudaMallocAsyncAllocator::ClearStats() {
  mutex_lock l(lock_);
  stats_.num_allocs = 0;
  stats_.peak_bytes_in_use = stats_.bytes_in_use;
  stats_.largest_alloc_size = 0;
}

}  // namespace tensorflow
<commit_msg>cudaMallocAsync: allow to preallocate memory with the env variable TF_CUDA_MALLOC_ASYNC_PREALLOC=num_bytes. -1 preallocate the full pool size.<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#ifdef GOOGLE_CUDA
#include "tensorflow/stream_executor/cuda/cuda_activation.h"
#include "third_party/gpus/cuda/include/cuda.h"
#include "third_party/gpus/cuda/include/cuda_runtime_api.h"
#endif  // GOOGLE_CUDA

#include "tensorflow/core/common_runtime/gpu/gpu_cudamallocasync_allocator.h"

#include "tensorflow/core/common_runtime/device/device_id_utils.h"
#include "tensorflow/core/common_runtime/gpu/gpu_id.h"
#include "tensorflow/core/common_runtime/gpu/gpu_init.h"
#include "tensorflow/core/framework/allocator.h"
#include "tensorflow/core/platform/stream_executor.h"
#include "tensorflow/core/util/env_var.h"

namespace tensorflow {

GpuCudaMallocAsyncAllocator::GpuCudaMallocAsyncAllocator(
    PlatformGpuId platform_gpu_id, size_t pool_size,
    bool reserve_memory, bool compute_stats)
    : name_(absl::StrCat("gpu_async_", platform_gpu_id.value())) {
  stream_exec_ =
      DeviceIdUtil::ExecutorForPlatformDeviceId(GPUMachineManager(),
                                                platform_gpu_id).ValueOrDie();

#if CUDA_VERSION < 11020
  LOG(FATAL) << "TF_GPU_ALLOCATOR=cuda_malloc_async need CUDA 11.2 or higher to compile.";
#elif !defined(GOOGLE_CUDA)
  LOG(FATAL) << "GOOGLE_CUDA not defined";
#else
  // Initialized here as it only exist if compiled with a recent
  // enough CUDA.
  pool_ = nullptr;
  cuda_stream_ = nullptr;
  // WAR an CUDA 11.2 driver bug for multiple-GPU. It currently
  // request that the context on GPU 0 is initialized. Which isn't the
  // case for TF+horovod.
  if (platform_gpu_id.value() > 0) {
    CUcontext pctx; // We loose track of it. But this is fine.
    CUresult err = cuDevicePrimaryCtxRetain(&pctx, 0);
    if (err != CUDA_SUCCESS){
      LOG(FATAL) << "Failed to create the context on device 0.";
    }
  }

  se::cuda::ScopedActivateExecutorContext scoped_activation{stream_exec_};
  int cuda_malloc_async_supported;
  cudaDeviceGetAttribute(&cuda_malloc_async_supported,
                         cudaDevAttrMemoryPoolsSupported,
                         platform_gpu_id.value());
  if (!cuda_malloc_async_supported) {
    LOG(FATAL) << "TF_GPU_ALLOCATOR=cuda_malloc_async isn't currently supported."
               << " Possible causes: device not supported, driver too old, "
               << " OS not supported, CUDA version too old.";
  }

  cudaError_t cerr = cudaStreamCreate(&cuda_stream_);
  if (cerr != cudaSuccess) {
    LOG(FATAL) << "could not allocate CUDA stream for context : "
               << cudaGetErrorString(cerr);
  }

  cerr = cudaDeviceGetDefaultMemPool(&pool_, platform_gpu_id.value());
  if (cerr != cudaSuccess) {
    LOG(FATAL) << "could not get the default CUDA pool : "
               << cudaGetErrorString(cerr);
  }
  VLOG(1) << Name() << " CudaMallocAsync initialized on platform: "
          << platform_gpu_id.value() << " with pool size of: "
          << pool_size << " this ptr: " << this;
  cerr = cudaMemPoolSetAttribute(pool_, cudaMemPoolAttrReleaseThreshold,
                                 reinterpret_cast<void*>(&pool_size));
  if (compute_stats) {
    mutex_lock lock(lock_);
    stats_.bytes_limit = static_cast<int64>(pool_size);
  } // If not set, it means we do not compute stats.
  if (cerr != cudaSuccess) {
    LOG(FATAL) << "could not set the default CUDA pool memory threshold : "
               << cudaGetErrorString(cerr);
    pool_ = nullptr;
  }

  // If in TF_DETERMINISTIC_OPS is set, then make the allocator behave
  // determistically.
  bool deterministic_ops = false;
  TF_CHECK_OK(tensorflow::ReadBoolFromEnvVar("TF_DETERMINISTIC_OPS",
                                             /*default_val=*/false,
                                             &deterministic_ops));
  if (deterministic_ops) {
    cudaMemPoolSetAttribute(pool_, cudaMemPoolReuseAllowOpportunistic, 0);
    cudaMemPoolSetAttribute(pool_, cudaMemPoolReuseAllowInternalDependencies, 0);
  }
#endif

  VLOG(2) << Name() << " GpuCudaMallocAsyncAllocator PoolSize " << pool_size;
  int64 prealloc_size = 0;
  // TF_CUDA_MALLOC_ASYNC_PREALLOC=-1 is a special value that
  // preallocates the total pool size.
  ReadInt64FromEnvVar("TF_CUDA_MALLOC_ASYNC_PREALLOC", 0,
                      &prealloc_size);
  if (prealloc_size == -1) {
    prealloc_size = pool_size;
  } else if (reserve_memory) {
    prealloc_size = pool_size;
  }
  if (prealloc_size != 0) {
    void* ptr = AllocateRaw(0, prealloc_size);
    DeallocateRaw(ptr);
    VLOG(2) << Name() << " GpuCudaMallocAsyncAllocator reserved the pool for "
            << prealloc_size << " bytes";
    ClearStats();
  }
}

GpuCudaMallocAsyncAllocator::~GpuCudaMallocAsyncAllocator() {
#ifdef GOOGLE_CUDA
  cuStreamDestroy(cuda_stream_);
#endif
}

void* GpuCudaMallocAsyncAllocator::AllocateRaw(size_t alignment,
                                               size_t num_bytes) {
#if CUDA_VERSION < 11020 || !defined(GOOGLE_CUDA)
  return nullptr;
#else
  if (pool_ == nullptr) {
    LOG(FATAL) << "The instantiation of GpuCudaMallocAsyncAllocator failed."
               << " See previous errors.";
  }
  se::cuda::ScopedActivateExecutorContext scoped_activation{stream_exec_};
  void* ptr = 0;
  cudaError_t res = cudaMallocFromPoolAsync(&ptr, num_bytes, pool_, cuda_stream_);
  if (res != cudaSuccess) {
    size_t free, total;
    cudaMemGetInfo(&free, &total);
    mutex_lock lock(lock_);
    LOG(ERROR) << Name() << " cudaMallocAsync failed to allocate " << num_bytes
               << "\n Error name: " << cudaGetErrorName(res)
               << "\n Error string: " << cudaGetErrorString(res)
               << "\n Free memory/Total memory: " << free << "/" << total
               << "\n Stats: \n" << stats_.DebugString();
    return nullptr;
  }

  // Update stats.
  if (stats_.bytes_limit.has_value()) {
    mutex_lock lock(lock_);
    ++stats_.num_allocs;
    stats_.bytes_in_use += num_bytes;
    stats_.peak_bytes_in_use =
        std::max(stats_.peak_bytes_in_use, stats_.bytes_in_use);
    stats_.largest_alloc_size =
        std::max<std::size_t>(stats_.largest_alloc_size, num_bytes);
    size_map_[ptr] = num_bytes;
  }
  VLOG(10) << Name() << " Allocated " << num_bytes << " at " << ptr;
  return ptr;
#endif
}
void GpuCudaMallocAsyncAllocator::DeallocateRaw(void* ptr) {
#if CUDA_VERSION < 11020 || !defined(GOOGLE_CUDA)
#else
  cudaError_t res = cudaFreeAsync(ptr, cuda_stream_);
  if (res == cudaErrorCudartUnloading) {
    // It happens with multi-GPU that TF free the GPU allocation after
    // the driver is unloaded. It is safe to ignore this error here.
    // TODO: Find how to fix the shutdown steps in TF.
    VLOG(1) << "Ignoring Error: " << cudaGetErrorName(res)
	    << " \nError string: " << cudaGetErrorString(res);
  } else if (res != cudaSuccess) {
    size_t free, total;
    se::cuda::ScopedActivateExecutorContext scoped_activation{stream_exec_};
    cudaMemGetInfo(&free, &total);
    LOG(ERROR) << "cudaFreeAsync failed to free " << ptr
               << "\n Error name: " << cudaGetErrorName(res)
               << "\n Error string: " << cudaGetErrorString(res)
               << "\n Free memory/Total memory: " << free << "/" << total
               << "\n Stats: \n" << stats_.DebugString();
  }

  // Updates the stats.
  if (stats_.bytes_limit.has_value()) {
    mutex_lock lock(lock_);
    DCHECK(size_map_.contains(ptr));
    size_t size = size_map_[ptr];
    stats_.bytes_in_use -= size;
    size_map_.erase(ptr);
  }

  VLOG(10) << Name() << " Freed ptr: " << ptr;
#endif  // GOOGLE_CUDA
}

bool GpuCudaMallocAsyncAllocator::TracksAllocationSizes() const {
  return stats_.bytes_limit.has_value();
}

size_t GpuCudaMallocAsyncAllocator::RequestedSize(const void* ptr) const {
  CHECK(ptr);
  return size_map_.at(ptr);
}

size_t GpuCudaMallocAsyncAllocator::AllocatedSize(const void* ptr) const {
  CHECK(ptr);
  return size_map_.at(ptr);
}

absl::optional<AllocatorStats> GpuCudaMallocAsyncAllocator::GetStats() {
  mutex_lock l(lock_);
  return stats_;
}

void GpuCudaMallocAsyncAllocator::ClearStats() {
  mutex_lock l(lock_);
  stats_.num_allocs = 0;
  stats_.peak_bytes_in_use = stats_.bytes_in_use;
  stats_.largest_alloc_size = 0;
}

}  // namespace tensorflow
<|endoftext|>


<commit_before>// $Header$

#include "StraightLineSetGL.h"
#include <Reve/StraightLineSet.h>
#include <Reve/GLUtilNS.h>

#include <TGLDrawFlags.h>

#ifdef WIN32
#include "Windows4root.h"
#endif
#include <GL/gl.h>
#include <GL/glu.h>

using namespace Reve;

//______________________________________________________________________
// StraightLineSetGL
//

ClassImp(StraightLineSetGL)

StraightLineSetGL::StraightLineSetGL() : TGLObject(), fM(0)
{
  // fCached = false; // Disable display list.
}

StraightLineSetGL::~StraightLineSetGL()
{}

/**************************************************************************/

Bool_t StraightLineSetGL::SetModel(TObject* obj)
{
  if(SetModelCheckClass(obj, StraightLineSet::Class())) {
    fM = dynamic_cast<StraightLineSet*>(obj);
    return kTRUE;
  }
  return kFALSE;
}

void StraightLineSetGL::SetBBox()
{
  // !! This ok if master sub-classed from TAttBBox
  SetAxisAlignedBBox(((StraightLineSet*)fExternalObj)->AssertBBox());
}

//______________________________________________________________________________
Bool_t StraightLineSetGL::ShouldCache(const TGLDrawFlags & flags) const
{
   // Override from TGLDrawable.
   // To account for large point-sizes we modify the projection matrix
   // during selection and thus we need a direct draw.

   if (flags.Selection()) return kFALSE;
   return fCached;
}

/**************************************************************************/

void StraightLineSetGL::DirectDraw(const TGLDrawFlags & flags) const
{
  // printf("StraightLineSetGL::DirectDraw Style %d, LOD %d\n", flags.Style(), flags.LOD());

  StraightLineSet& mL = * fM;

  glPushAttrib(GL_POINT_BIT | GL_LINE_BIT | GL_ENABLE_BIT);
  GLUtilNS::GL_Capability_Switch lights_off(GL_LIGHTING, false);

  if(mL.fRnrLines)
  {
    UChar_t color[4];
    ColorFromIdx(mL.GetMainColor(), color);
    glColor4ubv(color);

    VoidCPlex::iterator li(mL.fLinePlex);
    if(flags.SecSelection())
    {
      GLuint name = 0;
      glPushName(1);
      glPushName(0);
      while (li.next())
      {
	StraightLineSet::Line& l = * (StraightLineSet::Line*) li();
	glLoadName(name);
	{
	  glBegin(GL_LINES);
	  glVertex3f(l.fV1[0], l.fV1[1], l.fV1[2]);
	  glVertex3f(l.fV2[0], l.fV2[1], l.fV2[2]);
	  glEnd();
	}
	name ++;
      }
      glPopName();
      glPopName();
    }
    else
    {
      glBegin(GL_LINES);
      while (li.next())
      {
	StraightLineSet::Line& l = * (StraightLineSet::Line*) li();
	glVertex3f(l.fV1[0], l.fV1[1], l.fV1[2]);
	glVertex3f(l.fV2[0], l.fV2[1], l.fV2[2]);
      }
      glEnd();
    }
  }

  if(mL.fRnrMarkers)
  {
    UChar_t color[4];
    ColorFromIdx(mL.GetMarkerColor(), color);
    glColor4ubv(color);

    VoidCPlex::iterator mi(mL.fMarkerPlex);
    Float_t* pnts = new Float_t[mL.fMarkerPlex.Size()*3];
    Float_t* pnt  = pnts;
    Int_t lidx = -1;
    while (mi.next())
    {
      StraightLineSet::Marker& m = * (StraightLineSet::Marker*) mi();
      lidx = m.fLineID;
      StraightLineSet::Line& l = * (StraightLineSet::Line*) mL.fLinePlex.Atom(lidx);
      pnt[0] = l.fV1[0] + (l.fV2[0] - l.fV1[0])*m.fPos;
      pnt[1] = l.fV1[1] + (l.fV2[1] - l.fV1[1])*m.fPos;
      pnt[2] = l.fV1[2] + (l.fV2[2] - l.fV1[2])*m.fPos;;
      pnt   += 3;
    }
    if(flags.SecSelection()) glPushName(2);
    GLUtilNS::RenderPolyMarkers((TAttMarker&)mL, pnts, mL.fLinePlex.Size(), flags.Selection(), flags.SecSelection());
    if(flags.SecSelection()) glPopName();
    delete [] pnts;
  }

  glPopAttrib();
}

/**************************************************************************/

void StraightLineSetGL::ProcessSelection(UInt_t* ptr, TGLViewer*, TGLScene*)
{
  if (ptr[0] != 3) return;
  ptr += 3; // skip n, zmin, zmax
  if(ptr[1] == 1)
  {
    printf("selected line %d\n", ptr[2]);
  }
  else
  {
   StraightLineSet::Marker& m = * (StraightLineSet::Marker*) fM->fMarkerPlex.Atom(ptr[2]);
   printf("Selected point %d on line %d\n", ptr[2], m.fLineID);
  }
}
<commit_msg>Bugfix; wrong size passed to marker renderer.<commit_after>// $Header$

#include "StraightLineSetGL.h"
#include <Reve/StraightLineSet.h>
#include <Reve/GLUtilNS.h>

#include <TGLDrawFlags.h>

#ifdef WIN32
#include "Windows4root.h"
#endif
#include <GL/gl.h>
#include <GL/glu.h>

using namespace Reve;

//______________________________________________________________________
// StraightLineSetGL
//

ClassImp(StraightLineSetGL)

StraightLineSetGL::StraightLineSetGL() : TGLObject(), fM(0)
{
  // fCached = false; // Disable display list.
}

StraightLineSetGL::~StraightLineSetGL()
{}

/**************************************************************************/

Bool_t StraightLineSetGL::SetModel(TObject* obj)
{
  if(SetModelCheckClass(obj, StraightLineSet::Class())) {
    fM = dynamic_cast<StraightLineSet*>(obj);
    return kTRUE;
  }
  return kFALSE;
}

void StraightLineSetGL::SetBBox()
{
  // !! This ok if master sub-classed from TAttBBox
  SetAxisAlignedBBox(((StraightLineSet*)fExternalObj)->AssertBBox());
}

//______________________________________________________________________________
Bool_t StraightLineSetGL::ShouldCache(const TGLDrawFlags & flags) const
{
   // Override from TGLDrawable.
   // To account for large point-sizes we modify the projection matrix
   // during selection and thus we need a direct draw.

   if (flags.Selection()) return kFALSE;
   return fCached;
}

/**************************************************************************/

void StraightLineSetGL::DirectDraw(const TGLDrawFlags & flags) const
{
  // printf("StraightLineSetGL::DirectDraw Style %d, LOD %d\n", flags.Style(), flags.LOD());

  StraightLineSet& mL = * fM;

  glPushAttrib(GL_POINT_BIT | GL_LINE_BIT | GL_ENABLE_BIT);
  GLUtilNS::GL_Capability_Switch lights_off(GL_LIGHTING, false);

  if(mL.fRnrLines && mL.fLinePlex.Size() > 0)
  {
    UChar_t color[4];
    ColorFromIdx(mL.GetMainColor(), color);
    glColor4ubv(color);

    VoidCPlex::iterator li(mL.fLinePlex);
    if(flags.SecSelection())
    {
      GLuint name = 0;
      glPushName(1);
      glPushName(0);
      while (li.next())
      {
	StraightLineSet::Line& l = * (StraightLineSet::Line*) li();
	glLoadName(name);
	{
	  glBegin(GL_LINES);
	  glVertex3f(l.fV1[0], l.fV1[1], l.fV1[2]);
	  glVertex3f(l.fV2[0], l.fV2[1], l.fV2[2]);
	  glEnd();
	}
	name ++;
      }
      glPopName();
      glPopName();
    }
    else
    {
      glBegin(GL_LINES);
      while (li.next())
      {
	StraightLineSet::Line& l = * (StraightLineSet::Line*) li();
	glVertex3f(l.fV1[0], l.fV1[1], l.fV1[2]);
	glVertex3f(l.fV2[0], l.fV2[1], l.fV2[2]);
      }
      glEnd();
    }
  }

  if(mL.fRnrMarkers && mL.fMarkerPlex.Size() > 0)
  {
    UChar_t color[4];
    ColorFromIdx(mL.GetMarkerColor(), color);
    glColor4ubv(color);

    VoidCPlex::iterator mi(mL.fMarkerPlex);
    Float_t* pnts = new Float_t[mL.fMarkerPlex.Size()*3];
    Float_t* pnt  = pnts;
    Int_t lidx = -1;
    while (mi.next())
    {
      StraightLineSet::Marker& m = * (StraightLineSet::Marker*) mi();
      lidx = m.fLineID;
      StraightLineSet::Line& l = * (StraightLineSet::Line*) mL.fLinePlex.Atom(lidx);
      pnt[0] = l.fV1[0] + (l.fV2[0] - l.fV1[0])*m.fPos;
      pnt[1] = l.fV1[1] + (l.fV2[1] - l.fV1[1])*m.fPos;
      pnt[2] = l.fV1[2] + (l.fV2[2] - l.fV1[2])*m.fPos;;
      pnt   += 3;
    }
    if(flags.SecSelection()) glPushName(2);
    GLUtilNS::RenderPolyMarkers((TAttMarker&)mL, pnts, mL.fMarkerPlex.Size(),
				flags.Selection(), flags.SecSelection());
    if(flags.SecSelection()) glPopName();
    delete [] pnts;
  }

  glPopAttrib();
}

/**************************************************************************/

void StraightLineSetGL::ProcessSelection(UInt_t* ptr, TGLViewer*, TGLScene*)
{
  if (ptr[0] != 3) return;
  ptr += 3; // skip n, zmin, zmax
  if(ptr[1] == 1)
  {
    printf("selected line %d\n", ptr[2]);
  }
  else
  {
   StraightLineSet::Marker& m = * (StraightLineSet::Marker*) fM->fMarkerPlex.Atom(ptr[2]);
   printf("Selected point %d on line %d\n", ptr[2], m.fLineID);
  }
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "../elib/lang.h"
#include "common.h"
#include <io.h>
#include "elib.h"

PFN_NOTIFY_SYS g_fnNotifySys = NULL;
HWND ehwnd = NULL;
string epath;

extern bool CompileILByFile(const char* path, const char* savePath);

INT WINAPI NotifySys(INT nMsg, DWORD dwParam1, DWORD dwParam2)
{
	if (g_fnNotifySys != NULL) return g_fnNotifySys(nMsg, dwParam1, dwParam2);
	else return 0;
}

INT WINAPI notify_lib(INT nMsg, DWORD dwParam1, DWORD dwParam2)
{
	switch (nMsg)
	{
	case NL_SYS_NOTIFY_FUNCTION:
		g_fnNotifySys = (PFN_NOTIFY_SYS)dwParam1;
		ehwnd = (HWND)g_fnNotifySys(NES_GET_MAIN_HWND, 0, 0);
		char path[MAX_PATH];
		g_fnNotifySys(NAS_GET_PATH, 1002, D(path));
		epath = path;
		return NR_OK;
	default:
		return NR_ERR;
	}
}

LIB_CONST_INFO s_const_info[] =
{
	{ TEXT(""), TEXT("null"), NULL, LVL_SIMPLE, CT_NULL, NULL, NULL }
};

INT WINAPI addin_func(INT nAddInFnIndex)
{
	char title[MAX_PATH];
	GetWindowText(ehwnd, title, MAX_PATH);
	vector<string> arr = split(title, " - ");
	if (arr.size() > 2)
	{
		string path = arr[1];
		if (access(path.c_str(), 0) == 0)
		{
			switch (nAddInFnIndex)
			{
			case 0:
			{
				int index = path.find_last_of("\\");
				string dic = path.substr(0, index);
				CompileILByFile(path.c_str(), dic.c_str());
				break;
			}
			case 1:
			{
				path = epath + "gff.exe \"" + path + "\"";
				WinExec(path.c_str(), SW_SHOWNORMAL);
				break;
			}
			}
		}
	}
	return TRUE;
}

LIB_INFO s_lib_info =
{
	LIB_FORMAT_VER,
	TEXT(LI_LIB_GUID_STR),
	1,
	0,
	0,
	0,
	0,
	0,
	0,
	TEXT(".net"),
	__GBK_LANG_VER,
	TEXT("ԴΪ.net"),
	NULL,
	TEXT("Ϊо"),
	TEXT("100000"),
	TEXT("qq:514543271"),
	TEXT("qq:514543271"),
	TEXT("514543271"),
	TEXT("514543271@qq.com"),
	TEXT("http://wnxd.me"),
	TEXT("ΪԴĿ https://github.com/wnxd/e.net"),
	0,
	NULL,
	1,
	TEXT("0000.net\0"),
	0,
	NULL,
	NULL,
	addin_func,
	TEXT("e.net\0Ϊ.net\0DoNET\0޸ĵǰԴ\0\0"),
	notify_lib,
	NULL,
	NULL,
	sizeof(s_const_info) / sizeof(LIB_CONST_INFO),
	s_const_info,
	NULL
};

extern "C" PLIB_INFO WINAPI GetNewInf()
{
	return &s_lib_info;
}<commit_msg>dir切换<commit_after>#include "stdafx.h"
#include "../elib/lang.h"
#include "common.h"
#include <io.h>
#include "elib.h"

PFN_NOTIFY_SYS g_fnNotifySys = NULL;
HWND ehwnd = NULL;
string epath;

extern bool CompileILByFile(const char* path, const char* savePath);

INT WINAPI NotifySys(INT nMsg, DWORD dwParam1, DWORD dwParam2)
{
	if (g_fnNotifySys != NULL) return g_fnNotifySys(nMsg, dwParam1, dwParam2);
	else return 0;
}

INT WINAPI notify_lib(INT nMsg, DWORD dwParam1, DWORD dwParam2)
{
	switch (nMsg)
	{
	case NL_SYS_NOTIFY_FUNCTION:
		g_fnNotifySys = (PFN_NOTIFY_SYS)dwParam1;
		ehwnd = (HWND)g_fnNotifySys(NES_GET_MAIN_HWND, 0, 0);
		char path[MAX_PATH];
		g_fnNotifySys(NAS_GET_PATH, 1002, D(path));
		epath = path;
		return NR_OK;
	default:
		return NR_ERR;
	}
}

LIB_CONST_INFO s_const_info[] =
{
	{ TEXT(""), TEXT("null"), NULL, LVL_SIMPLE, CT_NULL, NULL, NULL }
};

INT WINAPI addin_func(INT nAddInFnIndex)
{
	char title[MAX_PATH];
	GetWindowText(ehwnd, title, MAX_PATH);
	vector<string> arr = split(title, " - ");
	if (arr.size() > 2)
	{
		string path = arr[1];
		if (access(path.c_str(), 0) == 0)
		{
			switch (nAddInFnIndex)
			{
			case 0:
			{
				int index = path.find_last_of("\\");
				string dic = path.substr(0, index);
				char cur[MAX_PATH];
				GetCurrentDirectory(MAX_PATH, cur);
				SetCurrentDirectory(dic.c_str());
				CompileILByFile(path.c_str(), dic.c_str());
				SetCurrentDirectory(cur);
				break;
			}
			case 1:
			{
				path = epath + "gff.exe \"" + path + "\"";
				WinExec(path.c_str(), SW_SHOWNORMAL);
				break;
			}
			}
		}
	}
	return TRUE;
}

LIB_INFO s_lib_info =
{
	LIB_FORMAT_VER,
	TEXT(LI_LIB_GUID_STR),
	1,
	1,
	1120,
	0,
	0,
	0,
	0,
	TEXT(".net"),
	__GBK_LANG_VER,
	TEXT("ԴΪ.net"),
	NULL,
	TEXT("Ϊо"),
	TEXT("100000"),
	TEXT("qq:514543271"),
	TEXT("qq:514543271"),
	TEXT("514543271"),
	TEXT("514543271@qq.com"),
	TEXT("http://wnxd.me"),
	TEXT("ΪԴĿ https://github.com/wnxd/e.net"),
	0,
	NULL,
	1,
	TEXT("0000.net\0"),
	0,
	NULL,
	NULL,
	addin_func,
	TEXT("e.net\0Ϊ.net\0DoNET\0޸ĵǰԴ\0\0"),
	notify_lib,
	NULL,
	NULL,
	sizeof(s_const_info) / sizeof(LIB_CONST_INFO),
	s_const_info,
	NULL
};

extern "C" PLIB_INFO WINAPI GetNewInf()
{
	return &s_lib_info;
}<|endoftext|>