<commit_before>// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef COLLECTIVE_HPP
#define COLLECTIVE_HPP

//#include "Grappa.hpp"
//#include "ForkJoin.hpp"
#include "common.hpp"
#include "CompletionEvent.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Tasking.hpp"
#include "FullEmpty.hpp"
#include <functional>

#define COLL_MAX &collective_max
#define COLL_MIN &collective_min
#define COLL_ADD &collective_add
#define COLL_MULT &collective_mult

template< typename T >
T collective_add(const T& a, const T& b) {
  return a+b;
}
template< typename T >
T collective_max(const T& a, const T& b) {
  return (a>b) ? a : b;
}
template< typename T >
T collective_min(const T& a, const T& b) {
  return (a>b) ? a : b;
}
template< typename T >
T collective_mult(const T& a, const T& b) {
  return a*b;
}

namespace Grappa {
  namespace impl {
    const Core HOME_CORE = 0;
  }
}

extern Thread * reducing_thread;
extern Node reduction_reported_in;

// This class is just for holding the reduction
// value in a type-safe manner
template < typename T >
class Reductions {
  private:
    Reductions() {}
  public:
    static T reduction_result;
    static T final_reduction_result;
};

template <typename T>
T Reductions<T>::reduction_result;

template <typename T>
T Reductions<T>::final_reduction_result;

// wake the caller with the final reduction value set
template< typename T >
static void am_reduce_wake(T * val, size_t sz, void * payload, size_t psz) {
  Reductions<T>::final_reduction_result = *val;
  Grappa_wake(reducing_thread);
}

// wake the caller with the final reduction array value set
template< typename T >
static void am_reduce_array_wake(T * val, size_t sz, void * payload, size_t psz) {
  memcpy(Reductions<T*>::final_reduction_result, val, sz);
  Grappa_wake(reducing_thread);
}

// Grappa active message sent by every Node to Grappa::impl::HOME_CORE to perform reduction in one place
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
static void am_reduce(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == Grappa::impl::HOME_CORE);

  if (reduction_reported_in == 0) Reductions<T>::reduction_result = BaseVal;
  Reductions<T>::reduction_result = Reducer(Reductions<T>::reduction_result, *val);

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      T data = Reductions<T>::reduction_result;
      Grappa_call_on(n, &am_reduce_wake, &data);
    }
  }
}

// Grappa active message sent by every Node to Grappa::impl::HOME_CORE to perform reduction in one place
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
static void am_reduce_array(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == Grappa::impl::HOME_CORE);

  size_t nelem = sz / sizeof(T);

  if (reduction_reported_in == 0) {
    // allocate space for result
    Reductions<T*>::reduction_result = new T[nelem];
    for (size_t i=0; i<nelem; i++) Reductions<T*>::reduction_result[i] = BaseVal;
  }

  T * rarray = Reductions<T*>::reduction_result;
  for (size_t i=0; i<nelem; i++) {
    rarray[i] = Reducer(rarray[i], val[i]);
  }

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      Grappa_call_on(n, &am_reduce_array_wake, rarray, sizeof(T)*nelem);
    }
    delete [] Reductions<T*>::reduction_result;
  }
}

// am_reduce with no initial value
template< typename T, T (*Reducer)(const T&, const T&) >
static void am_reduce_noinit(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == Grappa::impl::HOME_CORE);

  if (reduction_reported_in == 0) Reductions<T>::reduction_result = *val; // no base val
  else Reductions<T>::reduction_result = Reducer(Reductions<T>::reduction_result, *val);

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      T data = Reductions<T>::reduction_result;
      Grappa_call_on(n, &am_reduce_wake, &data);
    }
  }
}

/// Global reduction across all nodes, returning the completely reduced value to everyone.
/// Notes:
///  - this suffices as a global barrier across *all nodes*
///  - as such, only one instance of this can be running at a given time
///  - and it must be called by every node or deadlock will occur
///
/// @tparam T type of the reduced values
/// @tparam Reducer commutative and associative reduce function
/// @tparam BaseVal initial value, e.g. 0 for a sum
///
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
T Grappa_allreduce(T myval) {
  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(Grappa::impl::HOME_CORE, &am_reduce<T,Reducer,BaseVal>, &myval);

  Grappa_suspend();

  return Reductions<T>::final_reduction_result;
}

// send one element for reduction
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
void allreduce_one_message(T * array, size_t nelem, T * result = NULL) {
  const size_t maxn = 2048 / sizeof(T);
  CHECK( nelem <= maxn );
  // default is to overwrite original array
  if (!result) result = array;
  Reductions<T*>::final_reduction_result = result;

  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(Grappa::impl::HOME_CORE, &am_reduce_array<T,Reducer,BaseVal>, array, sizeof(T)*nelem);
  Grappa_suspend();
}

/// Vector reduction.
/// That is, result[i] = node0.array[i] + node1.array[i] + ... + nodeN.array[i], for all i.
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
void Grappa_allreduce(T * array, size_t nelem, T * result = NULL) {
  const size_t maxn = 2048 / sizeof(T);

  for (size_t i=0; i<nelem; i+=maxn) {
    size_t n = MIN(maxn, nelem-i);
    allreduce_one_message<T,Reducer,BaseVal>(array+i, n, result);
  }
}

/// Global reduction across all nodes, returning the completely reduced value to everyone.
/// This variant uses no initial value for the reduction.
///
/// Notes:
///  - this suffices as a global barrier across *all nodes*
///  - as such, only one instance of this can be running at a given time
///  - and it must be called by every node or deadlock will occur
///
/// @tparam T type of the reduced values
/// @tparam Reducer commutative and associative reduce function
/// @tparam BaseVal initial value, e.g. 0 for a sum
///
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&) >
T Grappa_allreduce_noinit(T myval) {
  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(Grappa::impl::HOME_CORE, &am_reduce_noinit<T,Reducer>, &myval);

  Grappa_suspend();

  return Reductions<T>::final_reduction_result;
}

namespace Grappa {

  // Call message (work that cannot block) on all cores, block until ack received from all.
  template<typename F>
  void call_on_all_cores(F work) {
    Core origin = mycore();
    CompletionEvent ce(cores());
    MessagePool pool(cores() * sizeof(Message<std::function<void(F,Core,decltype(&ce))>>));

    for (Core c = 0; c < cores(); c++) {
      pool.send_message(c, [&ce, origin, work] {
        work();
        send_heap_message(origin, [&ce]{ ce.complete(); });
      });
    }
    ce.wait();
  }

  /// Spawn a private task on each core, block until all complete.
  /// To be used for any SPMD-style work (e.g. initializing globals).
  /// Also used as a primitive in Grappa system code where anything is done on all cores.
  template<typename F>
  void on_all_cores(F work) {

    CompletionEvent ce(cores());
    auto ce_addr = make_global(&ce);
    MessagePool pool(cores()*sizeof(Message<std::function<void(F,decltype(ce_addr))>>));

    for (Core c = 0; c < cores(); c++) {
      pool.send_message(c, [ce_addr, work] {
        privateTask([ce_addr, work] {
          work();
          complete(ce_addr);
        });
      });
    }
    ce.wait();
  }

  namespace impl {

    template<typename T>
    struct Reduction {
      static FullEmpty<T> result;
    };
    template<typename T> FullEmpty<T> Reduction<T>::result;

    template< typename T, T (*ReduceOp)(const T&, const T&) >
    void collect_reduction(const T& val) {
      static T total;
      static Core cores_in = 0;

      CHECK(mycore() == HOME_CORE);

      if (cores_in == 0) {
        total = val;
      } else {
        total = ReduceOp(total, val);
      }

      cores_in++;
      DVLOG(4) << "cores_in: " << cores_in;

      if (cores_in == cores()) {
        cores_in = 0;
        T tmp_total = total;
        for (Core c = 0; c < cores(); c++) {
          send_heap_message(c, [tmp_total] {
            Reduction<T>::result.writeXF(tmp_total);
          });
        }
      }
    }

  }

  /// Called from SPMD context, reduces values from all cores calling `allreduce` and returns reduced
  /// values to everyone. Blocks until reduction is complete, so suffices as a global barrier.
  template< typename T, T (*ReduceOp)(const T&, const T&) >
  T allreduce(T myval) {
    impl::Reduction<T>::result.reset();

    send_message(impl::HOME_CORE, [myval]{
      impl::collect_reduction<T,ReduceOp>(myval);
    });

    return impl::Reduction<T>::result.readFF();
  }

  /// Called from a single task (usually user_main), reduces values from all cores onto the calling node.
  /// Blocks until reduction is complete.
  template< typename T, T (*ReduceOp)(const T&, const T&) >
  T reduce(T * global_ptr) {
    CompletionEvent ce(cores()-1);
    MessagePool pool(cores() * sizeof(Message<std::function<void(T*)>>));

    T total = *global_ptr;
    Core origin = mycore();

    for (Core c=0; c<cores(); c++) {
      if (c != origin) {
        pool.send_message(c, [global_ptr, &ce, &total, origin]{
          T val = *global_ptr;
          send_heap_message(origin, [val,&ce,&total] {
            total = ReduceOp(total, val);
            ce.complete();
          });
        });
      }
    }
    ce.wait();
    return total;
  }

}

#endif // COLLECTIVE_HPP

<commit_msg>Fix sizeof(lambda) calculation for {call_,}on_all_cores<commit_after>// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef COLLECTIVE_HPP
#define COLLECTIVE_HPP

//#include "Grappa.hpp"
//#include "ForkJoin.hpp"
#include "common.hpp"
#include "CompletionEvent.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Tasking.hpp"
#include "FullEmpty.hpp"
#include <functional>

#define COLL_MAX &collective_max
#define COLL_MIN &collective_min
#define COLL_ADD &collective_add
#define COLL_MULT &collective_mult

template< typename T >
T collective_add(const T& a, const T& b) {
  return a+b;
}
template< typename T >
T collective_max(const T& a, const T& b) {
  return (a>b) ? a : b;
}
template< typename T >
T collective_min(const T& a, const T& b) {
  return (a>b) ? a : b;
}
template< typename T >
T collective_mult(const T& a, const T& b) {
  return a*b;
}

namespace Grappa {
  namespace impl {
    const Core HOME_CORE = 0;
  }
}

extern Thread * reducing_thread;
extern Node reduction_reported_in;

// This class is just for holding the reduction
// value in a type-safe manner
template < typename T >
class Reductions {
  private:
    Reductions() {}
  public:
    static T reduction_result;
    static T final_reduction_result;
};

template <typename T>
T Reductions<T>::reduction_result;

template <typename T>
T Reductions<T>::final_reduction_result;

// wake the caller with the final reduction value set
template< typename T >
static void am_reduce_wake(T * val, size_t sz, void * payload, size_t psz) {
  Reductions<T>::final_reduction_result = *val;
  Grappa_wake(reducing_thread);
}

// wake the caller with the final reduction array value set
template< typename T >
static void am_reduce_array_wake(T * val, size_t sz, void * payload, size_t psz) {
  memcpy(Reductions<T*>::final_reduction_result, val, sz);
  Grappa_wake(reducing_thread);
}

// Grappa active message sent by every Node to Grappa::impl::HOME_CORE to perform reduction in one place
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
static void am_reduce(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == Grappa::impl::HOME_CORE);

  if (reduction_reported_in == 0) Reductions<T>::reduction_result = BaseVal;
  Reductions<T>::reduction_result = Reducer(Reductions<T>::reduction_result, *val);

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      T data = Reductions<T>::reduction_result;
      Grappa_call_on(n, &am_reduce_wake, &data);
    }
  }
}

// Grappa active message sent by every Node to Grappa::impl::HOME_CORE to perform reduction in one place
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
static void am_reduce_array(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == Grappa::impl::HOME_CORE);

  size_t nelem = sz / sizeof(T);

  if (reduction_reported_in == 0) {
    // allocate space for result
    Reductions<T*>::reduction_result = new T[nelem];
    for (size_t i=0; i<nelem; i++) Reductions<T*>::reduction_result[i] = BaseVal;
  }

  T * rarray = Reductions<T*>::reduction_result;
  for (size_t i=0; i<nelem; i++) {
    rarray[i] = Reducer(rarray[i], val[i]);
  }

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      Grappa_call_on(n, &am_reduce_array_wake, rarray, sizeof(T)*nelem);
    }
    delete [] Reductions<T*>::reduction_result;
  }
}

// am_reduce with no initial value
template< typename T, T (*Reducer)(const T&, const T&) >
static void am_reduce_noinit(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == Grappa::impl::HOME_CORE);

  if (reduction_reported_in == 0) Reductions<T>::reduction_result = *val; // no base val
  else Reductions<T>::reduction_result = Reducer(Reductions<T>::reduction_result, *val);

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      T data = Reductions<T>::reduction_result;
      Grappa_call_on(n, &am_reduce_wake, &data);
    }
  }
}

/// Global reduction across all nodes, returning the completely reduced value to everyone.
/// Notes:
///  - this suffices as a global barrier across *all nodes*
///  - as such, only one instance of this can be running at a given time
///  - and it must be called by every node or deadlock will occur
///
/// @tparam T type of the reduced values
/// @tparam Reducer commutative and associative reduce function
/// @tparam BaseVal initial value, e.g. 0 for a sum
///
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
T Grappa_allreduce(T myval) {
  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(Grappa::impl::HOME_CORE, &am_reduce<T,Reducer,BaseVal>, &myval);

  Grappa_suspend();

  return Reductions<T>::final_reduction_result;
}

// send one element for reduction
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
void allreduce_one_message(T * array, size_t nelem, T * result = NULL) {
  const size_t maxn = 2048 / sizeof(T);
  CHECK( nelem <= maxn );
  // default is to overwrite original array
  if (!result) result = array;
  Reductions<T*>::final_reduction_result = result;

  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(Grappa::impl::HOME_CORE, &am_reduce_array<T,Reducer,BaseVal>, array, sizeof(T)*nelem);
  Grappa_suspend();
}

/// Vector reduction.
/// That is, result[i] = node0.array[i] + node1.array[i] + ... + nodeN.array[i], for all i.
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
void Grappa_allreduce(T * array, size_t nelem, T * result = NULL) {
  const size_t maxn = 2048 / sizeof(T);

  for (size_t i=0; i<nelem; i+=maxn) {
    size_t n = MIN(maxn, nelem-i);
    allreduce_one_message<T,Reducer,BaseVal>(array+i, n, result);
  }
}

/// Global reduction across all nodes, returning the completely reduced value to everyone.
/// This variant uses no initial value for the reduction.
///
/// Notes:
///  - this suffices as a global barrier across *all nodes*
///  - as such, only one instance of this can be running at a given time
///  - and it must be called by every node or deadlock will occur
///
/// @tparam T type of the reduced values
/// @tparam Reducer commutative and associative reduce function
/// @tparam BaseVal initial value, e.g. 0 for a sum
///
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&) >
T Grappa_allreduce_noinit(T myval) {
  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(Grappa::impl::HOME_CORE, &am_reduce_noinit<T,Reducer>, &myval);

  Grappa_suspend();

  return Reductions<T>::final_reduction_result;
}

namespace Grappa {

  // Call message (work that cannot block) on all cores, block until ack received from all.
  template<typename F>
  void call_on_all_cores(F work) {
    Core origin = mycore();
    CompletionEvent ce(cores());

    auto lsz = [&ce,origin,work]{};
    MessagePool pool(cores()*(sizeof(Message<decltype(lsz)>)));

    for (Core c = 0; c < cores(); c++) {
      pool.send_message(c, [&ce, origin, work] {
        work();
        send_heap_message(origin, [&ce]{ ce.complete(); });
      });
    }
    ce.wait();
  }

  /// Spawn a private task on each core, block until all complete.
  /// To be used for any SPMD-style work (e.g. initializing globals).
  /// Also used as a primitive in Grappa system code where anything is done on all cores.
  template<typename F>
  void on_all_cores(F work) {

    CompletionEvent ce(cores());
    auto ce_addr = make_global(&ce);

    auto lsz = [ce_addr,work]{};
    MessagePool pool(cores()*(sizeof(Message<decltype(lsz)>)));

    for (Core c = 0; c < cores(); c++) {
      pool.send_message(c, [ce_addr, work] {
        privateTask([ce_addr, work] {
          work();
          complete(ce_addr);
        });
      });
    }
    ce.wait();
  }

  namespace impl {

    template<typename T>
    struct Reduction {
      static FullEmpty<T> result;
    };
    template<typename T> FullEmpty<T> Reduction<T>::result;

    template< typename T, T (*ReduceOp)(const T&, const T&) >
    void collect_reduction(const T& val) {
      static T total;
      static Core cores_in = 0;

      CHECK(mycore() == HOME_CORE);

      if (cores_in == 0) {
        total = val;
      } else {
        total = ReduceOp(total, val);
      }

      cores_in++;
      DVLOG(4) << "cores_in: " << cores_in;

      if (cores_in == cores()) {
        cores_in = 0;
        T tmp_total = total;
        for (Core c = 0; c < cores(); c++) {
          send_heap_message(c, [tmp_total] {
            Reduction<T>::result.writeXF(tmp_total);
          });
        }
      }
    }

  }

  /// Called from SPMD context, reduces values from all cores calling `allreduce` and returns reduced
  /// values to everyone. Blocks until reduction is complete, so suffices as a global barrier.
  template< typename T, T (*ReduceOp)(const T&, const T&) >
  T allreduce(T myval) {
    impl::Reduction<T>::result.reset();

    send_message(impl::HOME_CORE, [myval]{
      impl::collect_reduction<T,ReduceOp>(myval);
    });

    return impl::Reduction<T>::result.readFF();
  }

  /// Called from a single task (usually user_main), reduces values from all cores onto the calling node.
  /// Blocks until reduction is complete.
  template< typename T, T (*ReduceOp)(const T&, const T&) >
  T reduce(T * global_ptr) {
    CompletionEvent ce(cores()-1);
    MessagePool pool(cores() * sizeof(Message<std::function<void(T*)>>));

    T total = *global_ptr;
    Core origin = mycore();

    for (Core c=0; c<cores(); c++) {
      if (c != origin) {
        pool.send_message(c, [global_ptr, &ce, &total, origin]{
          T val = *global_ptr;
          send_heap_message(origin, [val,&ce,&total] {
            total = ReduceOp(total, val);
            ce.complete();
          });
        });
      }
    }
    ce.wait();
    return total;
  }

}

#endif // COLLECTIVE_HPP

<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// File: oapis.hpp
//
// Desc: OpenCVR API - OpenCVR API.
//
// Copyright (c) 2014-2018 opencvr.com. All rights reserved.
//------------------------------------------------------------------------------
#ifndef __VSC_OAPIS_H_
#define __VSC_OAPIS_H_
#include "oapicmn.hpp"
#include "factory.hpp"
#include "oapiproto.hpp"
#include "XSDK/XHash.h"
#include "XSDK/TimeUtils.h"
#include "XSDK/XSocket.h"
#include "XSDK/XSSLSocket.h"

using namespace XSDK;
using namespace std;
using namespace oapi;

class OAPIConverter
{
public:
	inline static BOOL Converter(VSCDeviceData__ &from, oapi::Device &to);
	inline static BOOL Converter(oapi::Device &from, VSCDeviceData__ &to);
};

/* a internal thread to process all the request of XSocket */
class OAPIServer
{
public:
	inline OAPIServer(XRef<XSocket> pSocket, Factory &pFactory);
	inline ~OAPIServer();
public:
	inline BOOL Process(OAPIHeader &header);

public:
	inline BOOL ProcessGetDevice(s32 len);
public:
	void Lock()
	{
		m_Lock.lock();
	}
	void UnLock()
	{
		m_Lock.unlock();
	}

private:
	fast_mutex m_Lock;
	XRef<XSocket> m_pSocket;
	Factory &m_pFactory;
};

#include "oapisimpl.hpp"
#endif<commit_msg>add liveview command<commit_after>//------------------------------------------------------------------------------
// File: oapis.hpp
//
// Desc: OpenCVR API - OpenCVR API.
//
// Copyright (c) 2014-2018 opencvr.com. All rights reserved.
//------------------------------------------------------------------------------
#ifndef __VSC_OAPIS_H_
#define __VSC_OAPIS_H_
#include "oapicmn.hpp"
#include "factory.hpp"
#include "oapiproto.hpp"
#include "XSDK/XHash.h"
#include "XSDK/TimeUtils.h"
#include "XSDK/XSocket.h"
#include "XSDK/XSSLSocket.h"

using namespace XSDK;
using namespace std;
using namespace oapi;

class OAPIConverter
{
public:
	inline static BOOL Converter(VSCDeviceData__ &from, oapi::Device &to);
	inline static BOOL Converter(oapi::Device &from, VSCDeviceData__ &to);
};

/* a internal thread to process all the request of XSocket */
class OAPIServer
{
public:
	inline OAPIServer(XRef<XSocket> pSocket, Factory &pFactory);
	inline ~OAPIServer();
public:
	inline BOOL Process(OAPIHeader &header);

public:
	inline BOOL ProcessGetDevice(s32 len);
	inline BOOL ProcessStartLive(s32 len);
	inline BOOL ProcessStopLive(s32 len);
public:
	inline void DataHandler1(VideoFrame& frame);
	inline static void DataHandler(VideoFrame& frame, void * pParam);
public:
	void Lock()
	{
		m_Lock.lock();
	}
	void UnLock()
	{
		m_Lock.unlock();
	}

private:
	fast_mutex m_Lock;
	XRef<XSocket> m_pSocket;
	Factory &m_pFactory;
	int m_nLiveviewId;
};

#include "oapisimpl.hpp"
#endif<|endoftext|>


<commit_before>#include <v8.h>
#include <iostream>

#include "advertisement.hpp"
#include "browser.hpp"
#include "resolver.hpp"

extern "C"
void
init (v8::Handle<v8::Object> target) {
    using namespace node_mdns;
    v8::HandleScope scope;

    Advertisement::Initialize( target );
    Browser::Initialize( target );
    Resolver::Initialize( target );

    // DNS Classes
    NODE_DEFINE_CONSTANT(target, kDNSServiceClass_IN);

    // DNS Error Codes
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoError);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Unknown);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoSuchName);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoMemory);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadParam);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadReference);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadState);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadFlags);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Unsupported);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NotInitialized);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_AlreadyRegistered);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NameConflict);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Invalid);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Firewall);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Incompatible);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadInterfaceIndex);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Refused);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoSuchRecord);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoAuth);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoSuchKey);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NATTraversal);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_DoubleNAT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadTime);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadSig);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadKey);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Transient);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_ServiceNotRunning);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NATPortMappingUnsupported);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NATPortMappingDisabled);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoRouter);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_PollingMode);

    // DNS Service Types
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_A);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NS);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MD);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MF);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_CNAME);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SOA);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MB);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MG);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NULL);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_WKS);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_PTR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_HINFO);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MINFO);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MX);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_TXT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_RP);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_AFSDB);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_X25);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_ISDN);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_RT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSAP);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSAP_PTR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SIG);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_KEY);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_PX);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_GPOS);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_AAAA);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_LOC);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NXT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_EID);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NIMLOC);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SRV);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_ATMA);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NAPTR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_KX);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_CERT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_A6);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_DNAME);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SINK);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_OPT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_APL);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_DS);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SSHFP);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_IPSECKEY);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_RRSIG);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSEC);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_DNSKEY);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_DHCID);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSEC3);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSEC3PARAM);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_HIP);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SPF);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_UINFO);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_UID);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_GID);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_UNSPEC);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_TKEY);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_TSIG);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_IXFR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_AXFR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MAILB);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MAILA);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_ANY);

    // General Flags
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsMoreComing);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsAdd);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsDefault);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsNoAutoRename);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsShared);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsUnique);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsBrowseDomains);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsRegistrationDomains);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsLongLivedQuery);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsAllowRemoteQuery);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsForceMulticast);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsForce);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsReturnIntermediates);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsNonBrowsable);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsShareConnection);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsSuppressUnusable);

}
<commit_msg>guard possibly undefined constants<commit_after>#include <v8.h>
#include <iostream>

#include "advertisement.hpp"
#include "browser.hpp"
#include "resolver.hpp"

extern "C"
void
init (v8::Handle<v8::Object> target) {
    using namespace node_mdns;
    v8::HandleScope scope;

    Advertisement::Initialize( target );
    Browser::Initialize( target );
    Resolver::Initialize( target );

    // DNS Classes
    NODE_DEFINE_CONSTANT(target, kDNSServiceClass_IN);

    // DNS Error Codes
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoError);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Unknown);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoSuchName);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoMemory);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadParam);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadReference);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadState);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadFlags);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Unsupported);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NotInitialized);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_AlreadyRegistered);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NameConflict);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Invalid);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Firewall);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Incompatible);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadInterfaceIndex);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Refused);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoSuchRecord);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoAuth);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoSuchKey);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NATTraversal);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_DoubleNAT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadTime);
#ifdef kDNSServiceErr_BadSig
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadSig);
#endif
#ifdef kDNSServiceErr_BadKey
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_BadKey);
#endif
#ifdef kDNSServiceErr_Transient
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_Transient);
#endif
#ifdef kDNSServiceErr_ServiceNotRunning
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_ServiceNotRunning);
#endif
#ifdef kDNSServiceErr_NATPortMappingUnsupported
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NATPortMappingUnsupported);
#endif
#ifdef kDNSServiceErr_NATPortMappingDisabled
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NATPortMappingDisabled);
#endif
#ifdef kDNSServiceErr_NoRouter
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_NoRouter);
#endif
#ifdef kDNSServiceErr_PollingMode
    NODE_DEFINE_CONSTANT(target, kDNSServiceErr_PollingMode);
#endif

    // DNS Service Types
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_A);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NS);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MD);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MF);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_CNAME);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SOA);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MB);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MG);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NULL);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_WKS);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_PTR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_HINFO);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MINFO);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MX);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_TXT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_RP);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_AFSDB);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_X25);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_ISDN);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_RT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSAP);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSAP_PTR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SIG);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_KEY);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_PX);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_GPOS);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_AAAA);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_LOC);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NXT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_EID);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NIMLOC);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SRV);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_ATMA);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NAPTR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_KX);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_CERT);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_A6);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_DNAME);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SINK);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_OPT);
#ifdef kDNSServiceType_APL
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_APL);
#endif
#ifdef kDNSServiceType_DS
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_DS);
#endif
#ifdef kDNSServiceType_SSHFP
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SSHFP);
#endif
#ifdef kDNSServiceType_IPSECKEY
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_IPSECKEY);
#endif
#ifdef kDNSServiceType_RRSIG
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_RRSIG);
#endif
#ifdef kDNSServiceType_NSEC
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSEC);
#endif
#ifdef kDNSServiceType_DNSKEY
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_DNSKEY);
#endif
#ifdef kDNSServiceType_DHCID
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_DHCID);
#endif
#ifdef kDNSServiceType_NSEC3
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSEC3);
#endif
#ifdef kDNSServiceType_NSEC3PARAM
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_NSEC3PARAM);
#endif
#ifdef kDNSServiceType_HIP
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_HIP);
#endif
#ifdef kDNSServiceType_SPF
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_SPF);
#endif
#ifdef kDNSServiceType_UINFO
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_UINFO);
#endif
#ifdef kDNSServiceType_UID
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_UID);
#endif
#ifdef kDNSServiceType_GID
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_GID);
#endif
#ifdef kDNSServiceType_UNSPEC
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_UNSPEC);
#endif
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_TKEY);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_TSIG);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_IXFR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_AXFR);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MAILB);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_MAILA);
    NODE_DEFINE_CONSTANT(target, kDNSServiceType_ANY);

    // General Flags
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsMoreComing);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsAdd);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsDefault);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsNoAutoRename);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsShared);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsUnique);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsBrowseDomains);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsRegistrationDomains);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsLongLivedQuery);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsAllowRemoteQuery);
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsForceMulticast);
#ifdef kDNSServiceFlagsForce
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsForce);
#endif
#ifdef kDNSServiceFlagsReturnIntermediates
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsReturnIntermediates);
#endif
#ifdef kDNSServiceFlagsNonBrowsable
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsNonBrowsable);
#endif
#ifdef kDNSServiceFlagsShareConnection
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsShareConnection);
#endif
#ifdef kDNSServiceFlagsSuppressUnusable
    NODE_DEFINE_CONSTANT(target, kDNSServiceFlagsSuppressUnusable);
#endif

}
<|endoftext|>


<commit_before>#include <uclog/bprintf.hpp>
#include <stdint.h>
#include <cstring>
#include <cctype>

namespace uclog
{

enum arg_type
{
    arg_type_none,
    arg_type_char,
    arg_type_short,
    arg_type_int,
    arg_type_long,
    arg_type_long_long,
    arg_type_pointer,
    arg_type_string,
    arg_type_float,
    arg_type_double
};

struct arg_spec
{
    arg_type type;
};

static size_t arg_decode(const char* fmt, arg_spec* spec)
{
    const char* start = fmt;

    spec->type = arg_type_none;

    for (; *fmt ; ++fmt)
    {
        if (*fmt == '%')
        {
            break;
        }
    }

    if (!*fmt)
    {
        return fmt - start;
    }

    // flags
    for (bool found = true; found;)
    {
        ++fmt;

        switch (*fmt)
        {
        case '-':
        case '+':
        case ' ':
        case '#':
        case '0':
            break;
        default:
            found = false;
            break;
        }
    }

    // width
    while (isdigit(*fmt))
    {
        ++fmt;
    }

    // precision
    if (*fmt == '.')
    {
        ++fmt;
        while (isdigit(*fmt))
        {
            ++fmt;
        }
    }

    spec->type = arg_type_int;
    if (*fmt == 'h' || *fmt == 'l')
    {
        char qualifier = *fmt++;
        if (qualifier == *fmt)
        {
            spec->type = (qualifier == 'h') ? arg_type_char : arg_type_long_long;
            ++fmt;
        }
        else
        {
            spec->type = (qualifier == 'h') ? arg_type_short : arg_type_long;
        }
    }

    switch (*fmt)
    {
    case 'c':
        spec->type = arg_type_char;
        return ++fmt - start;
    case 's':
        spec->type = arg_type_string;
        return ++fmt - start;
    case 'p':
        spec->type = arg_type_pointer;
        return ++fmt - start;
    case 'o':
    case 'x':
    case 'X':
    case 'd':
    case 'i':
    case 'u':
        // type of integer has already been determined
        return ++fmt - start;
    case 'f':
    case 'e':
    case 'g':
    case 'a':
    case 'F':
    case 'E':
    case 'G':
    case 'A':
        // slight deviation from standard:
        // %f treated as float, %lf as double,
        // like in scanf functions
        spec->type = (spec->type == arg_type_long) ? arg_type_double : arg_type_float;
        return ++fmt - start;
    case '%':
        spec->type = arg_type_none;
        return ++fmt - start;
    default:
        spec->type = arg_type_none;
        return fmt - start;
    }
}

size_t vsnbprintf(uint8_t* buf, size_t size, const char* fmt, va_list args)
{
    /// 6.5.2.2/6 defines "default argument promotions",
    /// and /7 states that default argument promotions
    /// are applied to "trailing arguments", that is varargs denoted by ....
#define save_arg(type)                                  \
do                                                      \
{                                                       \
    type value;                                         \
    if (sizeof(type) == sizeof(unsigned long long))     \
    {                                                   \
        value = va_arg(args, unsigned long long);       \
    }                                                   \
    else                                                \
    {                                                   \
        value = va_arg(args, int);                      \
    }                                                   \
    if (buf + sizeof(type) <= end)                      \
    {                                                   \
        memcpy(buf, &value, sizeof(type));              \
        buf += sizeof(type);                            \
    }                                                   \
} while (0)

#define save_float_arg(type)                            \
do                                                      \
{                                                       \
    type value = va_arg(args, double);                  \
    if (buf + sizeof(type) <= end)                      \
    {                                                   \
        memcpy(buf, &value, sizeof(type));              \
        buf += sizeof(type);                            \
    }                                                   \
} while (0)

    arg_spec spec = { arg_type_none };
    const uint8_t* start = buf;
    const uint8_t* end = buf + size;

    while (*fmt)
    {
        int read = arg_decode(fmt, &spec);

        fmt += read;

        switch (spec.type)
        {
        case arg_type_none:
            break;
        case arg_type_char:
            save_arg(char);
            break;
        case arg_type_short:
            save_arg(short);
            break;
        case arg_type_int:
            save_arg(int);
            break;
        case arg_type_long:
            save_arg(long);
            break;
        case arg_type_long_long:
            save_arg(long long);
            break;
        case arg_type_float:
            save_float_arg(float);
            break;
        case arg_type_double:
            save_float_arg(double);
            break;
        case arg_type_pointer:
            save_arg(uintptr_t);
            break;
        case arg_type_string:
            {
                const char* str = va_arg(args, const char*);
                size_t len = strlen(str) + 1;
                if (buf + len <= end)
                {
                    memcpy(buf, str, len);
                    buf += len;
                }
                break;
            }
        }
    }

    return buf - start;
#undef save_arg
#undef save_float_arg
}

size_t snbprintf(uint8_t* buf, size_t size, const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    size_t read = vsnbprintf(buf, size, fmt, args);
    va_end(args);
    return read;
}

} // namespace uclog
<commit_msg>description changed<commit_after>#include <uclog/bprintf.hpp>
#include <stdint.h>
#include <cstring>
#include <cctype>

namespace uclog
{

enum arg_type
{
    arg_type_none,
    arg_type_char,
    arg_type_short,
    arg_type_int,
    arg_type_long,
    arg_type_long_long,
    arg_type_pointer,
    arg_type_string,
    arg_type_float,
    arg_type_double
};

struct arg_spec
{
    arg_type type;
};

static size_t arg_decode(const char* fmt, arg_spec* spec)
{
    const char* start = fmt;

    spec->type = arg_type_none;

    for (; *fmt ; ++fmt)
    {
        if (*fmt == '%')
        {
            break;
        }
    }

    if (!*fmt)
    {
        return fmt - start;
    }

    // flags
    for (bool found = true; found;)
    {
        ++fmt;

        switch (*fmt)
        {
        case '-':
        case '+':
        case ' ':
        case '#':
        case '0':
            break;
        default:
            found = false;
            break;
        }
    }

    // width
    while (isdigit(*fmt))
    {
        ++fmt;
    }

    // precision
    if (*fmt == '.')
    {
        ++fmt;
        while (isdigit(*fmt))
        {
            ++fmt;
        }
    }

    spec->type = arg_type_int;
    if (*fmt == 'h' || *fmt == 'l')
    {
        char qualifier = *fmt++;
        if (qualifier == *fmt)
        {
            spec->type = (qualifier == 'h') ? arg_type_char : arg_type_long_long;
            ++fmt;
        }
        else
        {
            spec->type = (qualifier == 'h') ? arg_type_short : arg_type_long;
        }
    }

    switch (*fmt)
    {
    case 'c':
        spec->type = arg_type_char;
        return ++fmt - start;
    case 's':
        spec->type = arg_type_string;
        return ++fmt - start;
    case 'p':
        spec->type = arg_type_pointer;
        return ++fmt - start;
    case 'o':
    case 'x':
    case 'X':
    case 'd':
    case 'i':
    case 'u':
        // type of integer has already been determined
        return ++fmt - start;
    case 'f':
    case 'e':
    case 'g':
    case 'a':
    case 'F':
    case 'E':
    case 'G':
    case 'A':
        // slight deviation from standard:
        // %f treated as float, %lf as double,
        // like in scanf functions
        spec->type = (spec->type == arg_type_long) ? arg_type_double : arg_type_float;
        return ++fmt - start;
    case '%':
        spec->type = arg_type_none;
        return ++fmt - start;
    default:
        spec->type = arg_type_none;
        return fmt - start;
    }
}

size_t vsnbprintf(uint8_t* buf, size_t size, const char* fmt, va_list args)
{
    /// due to "default argument promotions" as described in 6.5.2.2/6,
    /// char and short arguments are promoted to int
#define save_arg(type)                                  \
do                                                      \
{                                                       \
    type value;                                         \
    if (sizeof(type) == sizeof(unsigned long long))     \
    {                                                   \
        value = va_arg(args, unsigned long long);       \
    }                                                   \
    else                                                \
    {                                                   \
        value = va_arg(args, int);                      \
    }                                                   \
    if (buf + sizeof(type) <= end)                      \
    {                                                   \
        memcpy(buf, &value, sizeof(type));              \
        buf += sizeof(type);                            \
    }                                                   \
} while (0)

    /// due to "default argument promotions" as described in 6.5.2.2/6,
    /// float is promoted to double
#define save_float_arg(type)                            \
do                                                      \
{                                                       \
    type value = va_arg(args, double);                  \
    if (buf + sizeof(type) <= end)                      \
    {                                                   \
        memcpy(buf, &value, sizeof(type));              \
        buf += sizeof(type);                            \
    }                                                   \
} while (0)

    arg_spec spec = { arg_type_none };
    const uint8_t* start = buf;
    const uint8_t* end = buf + size;

    while (*fmt)
    {
        int read = arg_decode(fmt, &spec);

        fmt += read;

        switch (spec.type)
        {
        case arg_type_none:
            break;
        case arg_type_char:
            save_arg(char);
            break;
        case arg_type_short:
            save_arg(short);
            break;
        case arg_type_int:
            save_arg(int);
            break;
        case arg_type_long:
            save_arg(long);
            break;
        case arg_type_long_long:
            save_arg(long long);
            break;
        case arg_type_float:
            save_float_arg(float);
            break;
        case arg_type_double:
            save_float_arg(double);
            break;
        case arg_type_pointer:
            save_arg(uintptr_t);
            break;
        case arg_type_string:
            {
                const char* str = va_arg(args, const char*);
                size_t len = strlen(str) + 1;
                if (buf + len <= end)
                {
                    memcpy(buf, str, len);
                    buf += len;
                }
                break;
            }
        }
    }

    return buf - start;
#undef save_arg
#undef save_float_arg
}

size_t snbprintf(uint8_t* buf, size_t size, const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    size_t read = vsnbprintf(buf, size, fmt, args);
    va_end(args);
    return read;
}

} // namespace uclog
<|endoftext|>


<commit_before>#include "buffers.h"
#include "strutil.h"
#include "log.h"

void processQueue(ByteQueue* queue, bool (*callback)(uint8_t*)) {
    uint8_t snapshot[QUEUE_MAX_LENGTH(uint8_t)];
    queue_snapshot(queue, snapshot);
    if(callback == NULL) {
        debug("Callback is NULL (%p) -- unable to handle queue at %p\r\n",
                callback, queue);
        return;
    }

    if(callback(snapshot)) {
        queue_init(queue);
    } else if(queue_full(queue)) {
        debug("Incoming write is too long\r\n");
        queue_init(queue);
    } else if(strnchr((char*)snapshot, queue_length(queue) - 1, '\0') != NULL) {
        debug("Incoming buffered write corrupted (%s) -- clearing buffer\r\n",
                snapshot);
        queue_init(queue);
    }
}
<commit_msg>Make snapshot buffer shorter so we don't touch uninitialized memory.<commit_after>#include "buffers.h"
#include "strutil.h"
#include "log.h"

void processQueue(ByteQueue* queue, bool (*callback)(uint8_t*)) {
    uint8_t snapshot[queue_length(queue)];
    queue_snapshot(queue, snapshot);
    if(callback == NULL) {
        debug("Callback is NULL (%p) -- unable to handle queue at %p\r\n",
                callback, queue);
        return;
    }

    if(callback(snapshot)) {
        queue_init(queue);
    } else if(queue_full(queue)) {
        debug("Incoming write is too long\r\n");
        queue_init(queue);
    } else if(strnchr((char*)snapshot, queue_length(queue) - 1, '\0') != NULL) {
        debug("Incoming buffered write corrupted (%s) -- clearing buffer\r\n",
                snapshot);
        queue_init(queue);
    }
}
<|endoftext|>


<commit_before>#include "vm.hpp"
#include "state.hpp"
#include "memory.hpp"
#include "global_cache.hpp"
#include "environment.hpp"
#include "memory/gc.hpp"

#include "object_utils.hpp"

#include "builtin/array.hpp"
#include "builtin/class.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/array.hpp"
#include "builtin/list.hpp"
#include "builtin/lookup_table.hpp"
#include "builtin/symbol.hpp"
#include "builtin/thread.hpp"
#include "builtin/tuple.hpp"
#include "builtin/string.hpp"
#include "builtin/system.hpp"
#include "builtin/fiber.hpp"
#include "builtin/location.hpp"
#include "builtin/native_method.hpp"
#include "builtin/channel.hpp"
#include "builtin/call_site.hpp"
#include "builtin/exception.hpp"
#include "builtin/jit.hpp"
#include "variable_scope.hpp"

#include "instruments/tooling.hpp"
#include "instruments/rbxti-internal.hpp"
#include "instruments/timing.hpp"

#include "config_parser.hpp"
#include "config.h"

#include "call_frame.hpp"
#include "signal.hpp"
#include "configuration.hpp"
#include "helpers.hpp"

#include "util/thread.hpp"

#include "park.hpp"

#include <iostream>
#include <iomanip>
#include <signal.h>
#ifndef RBX_WINDOWS
#include <sys/resource.h>
#endif

// Reset macros since we're inside state
#undef G
#undef GO
#define G(whatever) globals().whatever.get()
#define GO(whatever) globals().whatever

namespace rubinius {

  unsigned long VM::cStackDepthMax = 655300;

#ifndef RBX_WINDOWS
  /**
   * Maximum amount of stack space to use.
   * getrlimit can report there is 4G of stack (ie, unlimited).  Even when
   * there is unlimited stack, we clamp the max to this value (currently 128M).
   */
  static rlim_t cMaxStack = (1024 * 1024 * 128);
#endif

  VM::VM(uint32_t id, SharedState& shared, const char* name)
    : memory::ManagedThread(id, shared, memory::ManagedThread::eRuby, name)
    , call_frame_(0)
    , thread_nexus_(shared.thread_nexus())
    , saved_call_site_information_(0)
    , fiber_stacks_(this, shared)
    , park_(new Park)
    , tooling_env_(NULL)
    , interrupt_lock_()
    , method_missing_reason_(eNone)
    , constant_missing_reason_(vFound)
    , zombie_(false)
    , main_thread_(false)
    , thread_phase_(ThreadNexus::cUnmanaged)
    , shared(shared)
    , waiting_channel_(this, nil<Channel>())
    , interrupted_exception_(this, nil<Exception>())
    , thread(this, nil<Thread>())
    , current_fiber(this, nil<Fiber>())
    , root_fiber(this, nil<Fiber>())
    , waiting_object_(this, cNil)
    , custom_wakeup_(0)
    , custom_wakeup_data_(0)
    , thread_state_(this)
  {
    if(memory()) {
      local_slab_.refill(0, 0);
    }

    tooling_env_ = rbxti::create_env(this);
    tooling_ = false;

    allocation_tracking_ = shared.config.allocation_tracking;
  }

  VM::~VM() {
    rbxti::destroy_env(tooling_env_);
    delete park_;
  }

  void VM::discard(STATE, VM* vm) {
    state->vm()->metrics().system.threads_destroyed++;

    delete vm;
  }

  void VM::push_call_frame(CallFrame* frame, CallFrame*& previous_frame) {
    previous_frame = call_frame_;
    frame->previous = call_frame_;
    call_frame_ = frame;
  }

  CallFrame* VM::get_call_frame(ssize_t up) {
    CallFrame* frame = call_frame_;

    while(frame && up-- > 0) {
      frame = frame->previous;
    }

    return frame;
  }

  CallFrame* VM::get_ruby_frame(ssize_t up) {
    CallFrame* frame = call_frame_;

    while(frame && up-- > 0) {
      frame = frame->previous;
    }

    while(frame) {
      if(!frame->native_method_p()) return frame;
      frame = frame->previous;
    }

    return NULL;
  }

  CallFrame* VM::get_variables_frame(ssize_t up) {
    CallFrame* frame = call_frame_;

    while(frame && up-- > 0) {
      frame = frame->previous;
    }

    while(frame) {
      if(!frame->is_inline_block()
          && !frame->native_method_p()
          && frame->scope)
      {
        return frame;
      }

      frame = frame->previous;
    }

    return NULL;
  }

  CallFrame* VM::get_scope_frame(ssize_t up) {
    CallFrame* frame = call_frame_;

    while(frame && up-- > 0) {
      frame = frame->previous;
    }

    while(frame) {
      if(frame->scope) return frame;
      frame = frame->previous;
    }

    return NULL;
  }

  bool VM::scope_valid_p(VariableScope* scope) {
    CallFrame* frame = call_frame_;

    while(frame) {
      if(frame->scope && frame->scope->on_heap() == scope) {
        return true;
      }

      frame = frame->previous;
    }

    return false;
  }

  void VM::collect_maybe(STATE) {
    memory()->collect_maybe(state);
  }

  void VM::become_managed() {
    thread_nexus_->managed_lock(this);
  }

  void VM::set_zombie(STATE) {
    state->shared().thread_nexus()->delete_vm(this);
    thread.set(nil<Thread>());
    zombie_ = true;
  }

  void VM::initialize_config() {
    State state(this);

#ifdef ENABLE_LLVM
    Array* ary = Array::create(&state, 3);

    G(jit)->available(&state, cTrue);
    G(jit)->properties(&state, ary);

    if(!shared.config.jit_disabled) {
      ary->append(&state, state.symbol("usage"));
      if(shared.config.jit_inline_generic) {
        ary->append(&state, state.symbol("inline_generic"));
      }

      if(shared.config.jit_inline_blocks) {
        ary->append(&state, state.symbol("inline_blocks"));
      }
      G(jit)->enabled(&state, cTrue);
    } else {
      G(jit)->enabled(&state, cFalse);
    }
#else
    G(jit)->available(&state, cFalse);
    G(jit)->properties(&state, nil<Array>());
    G(jit)->enabled(&state, cFalse);
#endif
  }

  /**
   * Returns the current VM executing on this pthread.
   */
  VM* VM::current() {
    return memory::ManagedThread::current()->as_vm();
  }

  /**
   * Sets this VM instance as the current VM on this pthread.
   */
  void VM::set_current_thread() {
    memory::ManagedThread::set_current_thread(this);
  }

  void type_assert(STATE, Object* obj, object_type type, const char* reason) {
    if((obj->reference_p() && obj->type_id() != type)
        || (type == FixnumType && !obj->fixnum_p())) {
      std::ostringstream msg;
      msg << reason << ": " << obj->to_string(state, true);
      Exception::raise_type_error(state, type, obj, msg.str().c_str());
    }
  }

  void VM::init_stack_size() {
#ifndef RBX_WINDOWS
    struct rlimit rlim;
    if(getrlimit(RLIMIT_STACK, &rlim) == 0) {
      rlim_t space = rlim.rlim_cur/5;

      if(space > 1024*1024) space = 1024*1024;
      rlim_t adjusted = (rlim.rlim_cur - space);

      if(adjusted > cMaxStack) {
        cStackDepthMax = cMaxStack;
      } else {
        cStackDepthMax = adjusted;
      }
    }
#endif
  }

  TypeInfo* VM::find_type(int type) {
    return memory()->type_info[type];
  }

  void VM::after_fork_child(STATE) {
    utilities::logger::set_label();

    thread_nexus_->after_fork_child(state);

    interrupt_lock_.init();
    set_main_thread();
    become_managed();

    // TODO: Remove need for root_vm.
    state->shared().env()->set_root_vm(state->vm());
  }

  void VM::set_const(const char* name, Object* val) {
    State state(this);
    globals().object->set_const(&state, (char*)name, val);
  }

  void VM::set_const(Module* mod, const char* name, Object* val) {
    State state(this);
    mod->set_const(&state, (char*)name, val);
  }

  Object* VM::path2class(const char* path) {
    State state(this);
    Module* mod = shared.globals.object.get();

    char* copy = strdup(path);
    char* cur = copy;

    for(;;) {
      char* pos = strstr(cur, "::");
      if(pos) *pos = 0;

      Object* obj = mod->get_const(&state, state.symbol(cur));

      if(pos) {
        if(Module* m = try_as<Module>(obj)) {
          mod = m;
        } else {
          free(copy);
          return cNil;
        }
      } else {
        free(copy);
        return obj;
      }

      cur = pos + 2;
    }
  }

  void VM::print_backtrace() {
    abort();
  }

  void VM::interrupt_with_signal() {
    vm_jit_.interrupt_with_signal_ = true;
  }

  bool VM::wakeup(STATE) {
    utilities::thread::SpinLock::LockGuard guard(interrupt_lock_);

    set_check_local_interrupts();
    Object* wait = waiting_object_.get();

    if(park_->parked_p()) {
      park_->unpark();
      return true;
    } else if(vm_jit_.interrupt_with_signal_) {
#ifdef RBX_WINDOWS
      // TODO: wake up the thread
#else
      pthread_kill(os_thread_, SIGVTALRM);
#endif
      interrupt_lock_.unlock();
      // Wakeup any locks hanging around with contention
      memory()->release_contention(state);
      return true;
    } else if(!wait->nil_p()) {
      // We shouldn't hold the VM lock and the IH lock at the same time,
      // other threads can grab them and deadlock.
      InflatedHeader* ih = wait->inflated_header(state);
      interrupt_lock_.unlock();
      ih->wakeup(state, wait);
      return true;
    } else {
      Channel* chan = waiting_channel_.get();

      if(!chan->nil_p()) {
        interrupt_lock_.unlock();
        memory()->release_contention(state);
        chan->send(state, cNil);
        return true;
      } else if(custom_wakeup_) {
        interrupt_lock_.unlock();
        memory()->release_contention(state);
        (*custom_wakeup_)(custom_wakeup_data_);
        return true;
      }

      return false;
    }
  }

  void VM::clear_waiter() {
    utilities::thread::SpinLock::LockGuard guard(shared.wait_lock());

    vm_jit_.interrupt_with_signal_ = false;
    waiting_channel_.set(nil<Channel>());
    waiting_object_.set(cNil);
    custom_wakeup_ = 0;
    custom_wakeup_data_ = 0;
  }

  void VM::wait_on_channel(Channel* chan) {
    utilities::thread::SpinLock::LockGuard guard(interrupt_lock_);

    thread->sleep(this, cTrue);
    waiting_channel_.set(chan);
  }

  void VM::wait_on_inflated_lock(Object* wait) {
    utilities::thread::SpinLock::LockGuard guard(shared.wait_lock());

    waiting_object_.set(wait);
  }

  void VM::wait_on_custom_function(void (*func)(void*), void* data) {
    utilities::thread::SpinLock::LockGuard guard(shared.wait_lock());

    custom_wakeup_ = func;
    custom_wakeup_data_ = data;
  }

  void VM::set_sleeping() {
    thread->sleep(this, cTrue);
  }

  void VM::clear_sleeping() {
    thread->sleep(this, cFalse);
  }

  void VM::reset_parked() {
    park_->reset_parked();
  }

  void VM::register_raise(STATE, Exception* exc) {
    utilities::thread::SpinLock::LockGuard guard(interrupt_lock_);
    interrupted_exception_.set(exc);
    set_check_local_interrupts();
  }

  void VM::register_kill(STATE) {
    utilities::thread::SpinLock::LockGuard guard(interrupt_lock_);
    set_interrupt_by_kill();
    set_check_local_interrupts();
  }

  void VM::set_current_fiber(Fiber* fib) {
    set_stack_bounds((uintptr_t)fib->stack_start(), fib->stack_size());
    current_fiber.set(fib);
  }

  memory::VariableRootBuffers& VM::current_root_buffers() {
    if(current_fiber->nil_p() || current_fiber->root_p()) {
      return variable_root_buffers();
    }

    return current_fiber->variable_root_buffers();
  }

  void VM::gc_scan(memory::GarbageCollector* gc) {
    gc->walk_call_frame(call_frame_);

    if(CallSiteInformation* info = saved_call_site_information()) {
      info->executable = as<Executable>(gc->mark_object(info->executable));
    }

    State ls(this);

    shared.tool_broker()->at_gc(&ls);
  }

  void VM::gc_fiber_clear_mark() {
    fiber_stacks_.gc_clear_mark();
  }

  void VM::gc_fiber_scan(memory::GarbageCollector* gc, bool only_marked) {
    fiber_stacks_.gc_scan(gc, only_marked);
  }

  void VM::gc_verify(memory::GarbageCollector* gc) {
    gc->verify_call_frame(call_frame_);

    if(CallSiteInformation* info = saved_call_site_information()) {
      info->executable->validate();
    }
  }
};
<commit_msg>Initialize NativeMethodEnvironment* to NULL.<commit_after>#include "vm.hpp"
#include "state.hpp"
#include "memory.hpp"
#include "global_cache.hpp"
#include "environment.hpp"
#include "memory/gc.hpp"

#include "object_utils.hpp"

#include "builtin/array.hpp"
#include "builtin/class.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/array.hpp"
#include "builtin/list.hpp"
#include "builtin/lookup_table.hpp"
#include "builtin/symbol.hpp"
#include "builtin/thread.hpp"
#include "builtin/tuple.hpp"
#include "builtin/string.hpp"
#include "builtin/system.hpp"
#include "builtin/fiber.hpp"
#include "builtin/location.hpp"
#include "builtin/native_method.hpp"
#include "builtin/channel.hpp"
#include "builtin/call_site.hpp"
#include "builtin/exception.hpp"
#include "builtin/jit.hpp"
#include "variable_scope.hpp"

#include "instruments/tooling.hpp"
#include "instruments/rbxti-internal.hpp"
#include "instruments/timing.hpp"

#include "config_parser.hpp"
#include "config.h"

#include "call_frame.hpp"
#include "signal.hpp"
#include "configuration.hpp"
#include "helpers.hpp"

#include "util/thread.hpp"

#include "park.hpp"

#include <iostream>
#include <iomanip>
#include <signal.h>
#ifndef RBX_WINDOWS
#include <sys/resource.h>
#endif

// Reset macros since we're inside state
#undef G
#undef GO
#define G(whatever) globals().whatever.get()
#define GO(whatever) globals().whatever

namespace rubinius {

  unsigned long VM::cStackDepthMax = 655300;

#ifndef RBX_WINDOWS
  /**
   * Maximum amount of stack space to use.
   * getrlimit can report there is 4G of stack (ie, unlimited).  Even when
   * there is unlimited stack, we clamp the max to this value (currently 128M).
   */
  static rlim_t cMaxStack = (1024 * 1024 * 128);
#endif

  VM::VM(uint32_t id, SharedState& shared, const char* name)
    : memory::ManagedThread(id, shared, memory::ManagedThread::eRuby, name)
    , call_frame_(NULL)
    , thread_nexus_(shared.thread_nexus())
    , saved_call_site_information_(NULL)
    , fiber_stacks_(this, shared)
    , park_(new Park)
    , tooling_env_(NULL)
    , interrupt_lock_()
    , method_missing_reason_(eNone)
    , constant_missing_reason_(vFound)
    , zombie_(false)
    , main_thread_(false)
    , thread_phase_(ThreadNexus::cUnmanaged)
    , shared(shared)
    , waiting_channel_(this, nil<Channel>())
    , interrupted_exception_(this, nil<Exception>())
    , thread(this, nil<Thread>())
    , current_fiber(this, nil<Fiber>())
    , root_fiber(this, nil<Fiber>())
    , waiting_object_(this, cNil)
    , native_method_environment(NULL)
    , custom_wakeup_(NULL)
    , custom_wakeup_data_(NULL)
    , thread_state_(this)
  {
    if(memory()) {
      local_slab_.refill(0, 0);
    }

    tooling_env_ = rbxti::create_env(this);
    tooling_ = false;

    allocation_tracking_ = shared.config.allocation_tracking;
  }

  VM::~VM() {
    rbxti::destroy_env(tooling_env_);
    delete park_;
  }

  void VM::discard(STATE, VM* vm) {
    state->vm()->metrics().system.threads_destroyed++;

    delete vm;
  }

  void VM::push_call_frame(CallFrame* frame, CallFrame*& previous_frame) {
    previous_frame = call_frame_;
    frame->previous = call_frame_;
    call_frame_ = frame;
  }

  CallFrame* VM::get_call_frame(ssize_t up) {
    CallFrame* frame = call_frame_;

    while(frame && up-- > 0) {
      frame = frame->previous;
    }

    return frame;
  }

  CallFrame* VM::get_ruby_frame(ssize_t up) {
    CallFrame* frame = call_frame_;

    while(frame && up-- > 0) {
      frame = frame->previous;
    }

    while(frame) {
      if(!frame->native_method_p()) return frame;
      frame = frame->previous;
    }

    return NULL;
  }

  CallFrame* VM::get_variables_frame(ssize_t up) {
    CallFrame* frame = call_frame_;

    while(frame && up-- > 0) {
      frame = frame->previous;
    }

    while(frame) {
      if(!frame->is_inline_block()
          && !frame->native_method_p()
          && frame->scope)
      {
        return frame;
      }

      frame = frame->previous;
    }

    return NULL;
  }

  CallFrame* VM::get_scope_frame(ssize_t up) {
    CallFrame* frame = call_frame_;

    while(frame && up-- > 0) {
      frame = frame->previous;
    }

    while(frame) {
      if(frame->scope) return frame;
      frame = frame->previous;
    }

    return NULL;
  }

  bool VM::scope_valid_p(VariableScope* scope) {
    CallFrame* frame = call_frame_;

    while(frame) {
      if(frame->scope && frame->scope->on_heap() == scope) {
        return true;
      }

      frame = frame->previous;
    }

    return false;
  }

  void VM::collect_maybe(STATE) {
    memory()->collect_maybe(state);
  }

  void VM::become_managed() {
    thread_nexus_->managed_lock(this);
  }

  void VM::set_zombie(STATE) {
    state->shared().thread_nexus()->delete_vm(this);
    thread.set(nil<Thread>());
    zombie_ = true;
  }

  void VM::initialize_config() {
    State state(this);

#ifdef ENABLE_LLVM
    Array* ary = Array::create(&state, 3);

    G(jit)->available(&state, cTrue);
    G(jit)->properties(&state, ary);

    if(!shared.config.jit_disabled) {
      ary->append(&state, state.symbol("usage"));
      if(shared.config.jit_inline_generic) {
        ary->append(&state, state.symbol("inline_generic"));
      }

      if(shared.config.jit_inline_blocks) {
        ary->append(&state, state.symbol("inline_blocks"));
      }
      G(jit)->enabled(&state, cTrue);
    } else {
      G(jit)->enabled(&state, cFalse);
    }
#else
    G(jit)->available(&state, cFalse);
    G(jit)->properties(&state, nil<Array>());
    G(jit)->enabled(&state, cFalse);
#endif
  }

  /**
   * Returns the current VM executing on this pthread.
   */
  VM* VM::current() {
    return memory::ManagedThread::current()->as_vm();
  }

  /**
   * Sets this VM instance as the current VM on this pthread.
   */
  void VM::set_current_thread() {
    memory::ManagedThread::set_current_thread(this);
  }

  void type_assert(STATE, Object* obj, object_type type, const char* reason) {
    if((obj->reference_p() && obj->type_id() != type)
        || (type == FixnumType && !obj->fixnum_p())) {
      std::ostringstream msg;
      msg << reason << ": " << obj->to_string(state, true);
      Exception::raise_type_error(state, type, obj, msg.str().c_str());
    }
  }

  void VM::init_stack_size() {
#ifndef RBX_WINDOWS
    struct rlimit rlim;
    if(getrlimit(RLIMIT_STACK, &rlim) == 0) {
      rlim_t space = rlim.rlim_cur/5;

      if(space > 1024*1024) space = 1024*1024;
      rlim_t adjusted = (rlim.rlim_cur - space);

      if(adjusted > cMaxStack) {
        cStackDepthMax = cMaxStack;
      } else {
        cStackDepthMax = adjusted;
      }
    }
#endif
  }

  TypeInfo* VM::find_type(int type) {
    return memory()->type_info[type];
  }

  void VM::after_fork_child(STATE) {
    utilities::logger::set_label();

    thread_nexus_->after_fork_child(state);

    interrupt_lock_.init();
    set_main_thread();
    become_managed();

    // TODO: Remove need for root_vm.
    state->shared().env()->set_root_vm(state->vm());
  }

  void VM::set_const(const char* name, Object* val) {
    State state(this);
    globals().object->set_const(&state, (char*)name, val);
  }

  void VM::set_const(Module* mod, const char* name, Object* val) {
    State state(this);
    mod->set_const(&state, (char*)name, val);
  }

  Object* VM::path2class(const char* path) {
    State state(this);
    Module* mod = shared.globals.object.get();

    char* copy = strdup(path);
    char* cur = copy;

    for(;;) {
      char* pos = strstr(cur, "::");
      if(pos) *pos = 0;

      Object* obj = mod->get_const(&state, state.symbol(cur));

      if(pos) {
        if(Module* m = try_as<Module>(obj)) {
          mod = m;
        } else {
          free(copy);
          return cNil;
        }
      } else {
        free(copy);
        return obj;
      }

      cur = pos + 2;
    }
  }

  void VM::print_backtrace() {
    abort();
  }

  void VM::interrupt_with_signal() {
    vm_jit_.interrupt_with_signal_ = true;
  }

  bool VM::wakeup(STATE) {
    utilities::thread::SpinLock::LockGuard guard(interrupt_lock_);

    set_check_local_interrupts();
    Object* wait = waiting_object_.get();

    if(park_->parked_p()) {
      park_->unpark();
      return true;
    } else if(vm_jit_.interrupt_with_signal_) {
#ifdef RBX_WINDOWS
      // TODO: wake up the thread
#else
      pthread_kill(os_thread_, SIGVTALRM);
#endif
      interrupt_lock_.unlock();
      // Wakeup any locks hanging around with contention
      memory()->release_contention(state);
      return true;
    } else if(!wait->nil_p()) {
      // We shouldn't hold the VM lock and the IH lock at the same time,
      // other threads can grab them and deadlock.
      InflatedHeader* ih = wait->inflated_header(state);
      interrupt_lock_.unlock();
      ih->wakeup(state, wait);
      return true;
    } else {
      Channel* chan = waiting_channel_.get();

      if(!chan->nil_p()) {
        interrupt_lock_.unlock();
        memory()->release_contention(state);
        chan->send(state, cNil);
        return true;
      } else if(custom_wakeup_) {
        interrupt_lock_.unlock();
        memory()->release_contention(state);
        (*custom_wakeup_)(custom_wakeup_data_);
        return true;
      }

      return false;
    }
  }

  void VM::clear_waiter() {
    utilities::thread::SpinLock::LockGuard guard(shared.wait_lock());

    vm_jit_.interrupt_with_signal_ = false;
    waiting_channel_.set(nil<Channel>());
    waiting_object_.set(cNil);
    custom_wakeup_ = 0;
    custom_wakeup_data_ = 0;
  }

  void VM::wait_on_channel(Channel* chan) {
    utilities::thread::SpinLock::LockGuard guard(interrupt_lock_);

    thread->sleep(this, cTrue);
    waiting_channel_.set(chan);
  }

  void VM::wait_on_inflated_lock(Object* wait) {
    utilities::thread::SpinLock::LockGuard guard(shared.wait_lock());

    waiting_object_.set(wait);
  }

  void VM::wait_on_custom_function(void (*func)(void*), void* data) {
    utilities::thread::SpinLock::LockGuard guard(shared.wait_lock());

    custom_wakeup_ = func;
    custom_wakeup_data_ = data;
  }

  void VM::set_sleeping() {
    thread->sleep(this, cTrue);
  }

  void VM::clear_sleeping() {
    thread->sleep(this, cFalse);
  }

  void VM::reset_parked() {
    park_->reset_parked();
  }

  void VM::register_raise(STATE, Exception* exc) {
    utilities::thread::SpinLock::LockGuard guard(interrupt_lock_);
    interrupted_exception_.set(exc);
    set_check_local_interrupts();
  }

  void VM::register_kill(STATE) {
    utilities::thread::SpinLock::LockGuard guard(interrupt_lock_);
    set_interrupt_by_kill();
    set_check_local_interrupts();
  }

  void VM::set_current_fiber(Fiber* fib) {
    set_stack_bounds((uintptr_t)fib->stack_start(), fib->stack_size());
    current_fiber.set(fib);
  }

  memory::VariableRootBuffers& VM::current_root_buffers() {
    if(current_fiber->nil_p() || current_fiber->root_p()) {
      return variable_root_buffers();
    }

    return current_fiber->variable_root_buffers();
  }

  void VM::gc_scan(memory::GarbageCollector* gc) {
    gc->walk_call_frame(call_frame_);

    if(CallSiteInformation* info = saved_call_site_information()) {
      info->executable = as<Executable>(gc->mark_object(info->executable));
    }

    State ls(this);

    shared.tool_broker()->at_gc(&ls);
  }

  void VM::gc_fiber_clear_mark() {
    fiber_stacks_.gc_clear_mark();
  }

  void VM::gc_fiber_scan(memory::GarbageCollector* gc, bool only_marked) {
    fiber_stacks_.gc_scan(gc, only_marked);
  }

  void VM::gc_verify(memory::GarbageCollector* gc) {
    gc->verify_call_frame(call_frame_);

    if(CallSiteInformation* info = saved_call_site_information()) {
      info->executable->validate();
    }
  }
};
<|endoftext|>


<commit_before>{
   gSystem.Load("/usr/X11R6/lib/libXmu.so");
   gSystem.Load("/soft/Mesa-3.0/lib/libMesaGL.so");
   gSystem.Load("/soft/Mesa-3.0/lib/libMesaGLU.so");
   gSystem.Load("$ROOTSYS/lib/libRGL.so");
}
<commit_msg>Macro named<commit_after>void GLfca()
{
   gSystem.Load("/usr/X11R6/lib/libXmu.so");
   gSystem.Load("/soft/Mesa-3.0/lib/libMesaGL.so");
   gSystem.Load("/soft/Mesa-3.0/lib/libMesaGLU.so");
   gSystem.Load("$ROOTSYS/lib/libRGL.so");
}
<|endoftext|>