Commit 763326c7 by Tobias Fuchs

Merge remote-tracking branch 'origin/development' into embb327_llx_scx

parents b3b79150 2c72c7eb
......@@ -125,6 +125,8 @@ CheckPartestInstall(${BUILD_TESTS} partest_includepath partest_libpath)
add_subdirectory(base_c)
add_subdirectory(base_cpp)
add_subdirectory(mtapi_c)
add_subdirectory(mtapi_network_c)
add_subdirectory(mtapi_opencl_c)
add_subdirectory(tasks_cpp)
add_subdirectory(mtapi_cpp)
add_subdirectory(containers_cpp)
......
......@@ -316,8 +316,6 @@ code using Cppcheck, a static analysis tool for C++.
Known Bugs and Limitations
--------------------------
- The MTAPI implementation is currently limited to homogeneous systems.
Support for heterogeneous systems will be added in the near future.
- For memory management reasons, the number of threads EMB² can deal with
is bounded by a predefined but modifiable constant (see functions
embb_thread_get_max_count() / embb_thread_set_max_count() and class
......
......@@ -31,10 +31,19 @@ namespace embb {
namespace dataflow {
namespace internal {
class Scheduler;
class ClockListener;
struct InitData {
Scheduler * sched;
ClockListener * sink_listener;
};
class ClockListener {
public:
virtual ~ClockListener() {}
virtual void OnClock(int /*clock*/) = 0;
virtual void OnInit(InitData * /*sched*/) = 0;
};
} // namespace internal
......
......@@ -56,6 +56,11 @@ class ConstantSource
GetOutput<0>().Send(Signal<Type>(clock, value_));
}
virtual void Init(InitData * init_data) {
SetScheduler(init_data->sched);
GetOutput<0>().SendInit(init_data);
}
virtual bool Start(int clock) {
Run(clock);
return true;
......
......@@ -39,6 +39,8 @@ namespace embb {
namespace dataflow {
namespace internal {
class Scheduler;
template <typename, int>
class Out;
......@@ -95,6 +97,10 @@ class In {
lock_.Unlock();
#endif
}
void ReceiveInit(InitData * init_data) {
listener_->OnInit(init_data);
}
};
} // namespace internal
......
......@@ -57,6 +57,7 @@ class Inputs<Slices, embb::base::internal::Nil, embb::base::internal::Nil,
bool AreNoneBlank(int /*clock*/) { return false; }
bool AreAtClock(int /*clock*/) { return true; }
virtual void OnClock(int /*clock*/) {}
virtual void OnInit(InitData * /*init_data*/) {}
};
template <int Slices, typename T1>
......@@ -70,6 +71,7 @@ class Inputs<Slices, T1, embb::base::internal::Nil, embb::base::internal::Nil,
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 1;
test_count_ = 1;
}
void SetListener(ClockListener * listener) {
listener_ = listener;
......@@ -97,8 +99,14 @@ class Inputs<Slices, T1, embb::base::internal::Nil, embb::base::internal::Nil,
listener_->OnClock(clock);
}
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
int test_count_;
ClockListener * listener_;
};
......@@ -112,6 +120,7 @@ class Inputs<Slices, T1, T2, embb::base::internal::Nil,
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 2;
test_count_ = 2;
}
void SetListener(ClockListener * listener) {
listener_ = listener;
......@@ -143,8 +152,14 @@ class Inputs<Slices, T1, T2, embb::base::internal::Nil,
listener_->OnClock(clock);
}
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
int test_count_;
ClockListener * listener_;
};
......@@ -158,6 +173,7 @@ class Inputs<Slices, T1, T2, T3, embb::base::internal::Nil,
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 3;
test_count_ = 3;
}
void SetListener(ClockListener * listener) {
listener_ = listener;
......@@ -193,8 +209,14 @@ class Inputs<Slices, T1, T2, T3, embb::base::internal::Nil,
listener_->OnClock(clock);
}
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
int test_count_;
ClockListener * listener_;
};
......@@ -207,6 +229,7 @@ class Inputs<Slices, T1, T2, T3, T4, embb::base::internal::Nil>
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 4;
test_count_ = 4;
}
void SetListener(ClockListener * listener) {
listener_ = listener;
......@@ -246,8 +269,14 @@ class Inputs<Slices, T1, T2, T3, T4, embb::base::internal::Nil>
listener_->OnClock(clock);
}
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
int test_count_;
ClockListener * listener_;
};
......@@ -261,6 +290,7 @@ class Inputs
Inputs() {
for (int ii = 0; ii < Slices; ii++)
count_[ii] = 5;
test_count_ = 5;
}
void SetListener(ClockListener * listener) {
listener_ = listener;
......@@ -304,8 +334,14 @@ class Inputs
listener_->OnClock(clock);
}
}
virtual void OnInit(InitData * init_data) {
if (--test_count_ == 0) {
listener_->OnInit(init_data);
}
}
private:
embb::base::Atomic<int> count_[Slices];
int test_count_;
ClockListener * listener_;
};
......
......@@ -30,6 +30,7 @@
#include <cstddef>
#include <embb/base/exceptions.h>
#include <embb/dataflow/internal/scheduler.h>
#include <embb/dataflow/internal/clock_listener.h>
namespace embb {
namespace dataflow {
......@@ -46,12 +47,13 @@ class Node {
EMBB_THROW(embb::base::ErrorException,
"Nodes are started implicitly.");
}
void SetScheduler(Scheduler * sched) { sched_ = sched; }
virtual void Init(InitData * init_data) = 0;
protected:
Scheduler * sched_;
static int next_process_id_;
void SetScheduler(Scheduler * sched) { sched_ = sched; }
static int GetNextProcessID() { return next_process_id_++; }
};
......
......@@ -35,6 +35,8 @@ namespace embb {
namespace dataflow {
namespace internal {
class Scheduler;
template <typename Type, int Slices>
class Out {
public:
......@@ -50,6 +52,12 @@ class Out {
}
}
void SendInit(InitData * init_data) {
for (size_t ii = 0; ii < targets_.size(); ii++) {
targets_[ii]->ReceiveInit(init_data);
}
}
void Connect(InType & input) {
if (input.IsConnected()) {
EMBB_THROW(embb::base::ErrorException,
......
......@@ -78,6 +78,11 @@ class Process< Slices, Serial, Inputs<Slices, I1, I2, I3, I4, I5>,
executor_.Execute(clock, inputs_, outputs_);
}
virtual void Init(InitData * init_data) {
SetScheduler(init_data->sched);
executor_.Init(init_data, outputs_);
}
InputsType & GetInputs() {
return inputs_;
}
......@@ -142,6 +147,10 @@ class Process< Slices, Serial, Inputs<Slices, I1, I2, I3, I4, I5>,
}
}
virtual void OnInit(InitData * init_data) {
Init(init_data);
}
private:
InputsType inputs_;
OutputsType outputs_;
......
......@@ -62,6 +62,10 @@ class ProcessExecutor< Inputs<Slices, I1>, Outputs<Slices, O1> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1> & outputs) {
outputs.template Get<0>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -91,6 +95,11 @@ class ProcessExecutor< Inputs<Slices, I1>, Outputs<Slices, O1, O2> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1, O2> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -124,6 +133,12 @@ class ProcessExecutor< Inputs<Slices, I1>, Outputs<Slices, O1, O2, O3> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1, O2, O3> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
outputs.template Get<2>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -161,6 +176,13 @@ class ProcessExecutor< Inputs<Slices, I1>, Outputs<Slices, O1, O2, O3, O4> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1, O2, O3, O4> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
outputs.template Get<2>().SendInit(init_data);
outputs.template Get<3>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -189,6 +211,10 @@ class ProcessExecutor< Inputs<Slices, I1, I2>, Outputs<Slices, O1> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1> & outputs) {
outputs.template Get<0>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -220,6 +246,11 @@ class ProcessExecutor< Inputs<Slices, I1, I2>, Outputs<Slices, O1, O2> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1, O2> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -255,6 +286,12 @@ class ProcessExecutor< Inputs<Slices, I1, I2>, Outputs<Slices, O1, O2, O3> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1, O2, O3> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
outputs.template Get<2>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -284,6 +321,10 @@ class ProcessExecutor< Inputs<Slices, I1, I2, I3>, Outputs<Slices, O1> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1> & outputs) {
outputs.template Get<0>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -317,6 +358,11 @@ class ProcessExecutor< Inputs<Slices, I1, I2, I3>, Outputs<Slices, O1, O2> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1, O2> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -348,6 +394,10 @@ class ProcessExecutor< Inputs<Slices, I1, I2, I3, I4>, Outputs<Slices, O1> > {
}
}
void Init(InitData * init_data, Outputs<Slices, O1> & outputs) {
outputs.template Get<0>().SendInit(init_data);
}
private:
FunctionType function_;
};
......
......@@ -81,6 +81,11 @@ class Select
}
}
virtual void Init(InitData * init_data) {
SetScheduler(init_data->sched);
GetOutput<0>().SendInit(init_data);
}
InputsType & GetInputs() {
return inputs_;
}
......@@ -112,6 +117,10 @@ class Select
Run(clock);
}
virtual void OnInit(InitData * init_data) {
Init(init_data);
}
private:
InputsType inputs_;
OutputsType outputs_;
......
......@@ -72,6 +72,12 @@ class Sink< Slices, Inputs<Slices, I1, I2, I3, I4, I5> >
listener_->OnClock(clock);
}
virtual void Init(InitData * init_data) {
SetListener(init_data->sink_listener);
SetScheduler(init_data->sched);
listener_->OnInit(init_data);
}
InputsType & GetInputs() {
return inputs_;
}
......@@ -115,6 +121,10 @@ class Sink< Slices, Inputs<Slices, I1, I2, I3, I4, I5> >
}
}
virtual void OnInit(InitData * init_data) {
Init(init_data);
}
private:
InputsType inputs_;
ExecutorType executor_;
......
......@@ -59,6 +59,11 @@ class Source< Slices, Outputs<Slices, O1, O2, O3, O4, O5> >
not_done_ = executor_.Execute(clock, outputs_);
}
virtual void Init(InitData * init_data) {
SetScheduler(init_data->sched);
executor_.Init(init_data, outputs_);
}
virtual bool Start(int clock) {
if (not_done_) {
Run(clock);
......
......@@ -36,6 +36,8 @@ namespace embb {
namespace dataflow {
namespace internal {
class Scheduler;
template <class OUTPUTS>
class SourceExecutor;
......@@ -55,6 +57,10 @@ class SourceExecutor< Outputs<Slices, O1> > {
return result;
}
void Init(InitData * init_data, Outputs<Slices, O1> & outputs) {
outputs.template Get<0>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -77,6 +83,11 @@ class SourceExecutor< Outputs<Slices, O1, O2> > {
return result;
}
void Init(InitData * init_data, Outputs<Slices, O1, O2> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -101,6 +112,12 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3> > {
return result;
}
void Init(InitData * init_data, Outputs<Slices, O1, O2, O3> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
outputs.template Get<2>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -127,6 +144,13 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3, O4> > {
return result;
}
void Init(InitData * init_data, Outputs<Slices, O1, O2, O3, O4> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
outputs.template Get<2>().SendInit(init_data);
outputs.template Get<3>().SendInit(init_data);
}
private:
FunctionType function_;
};
......@@ -156,6 +180,15 @@ class SourceExecutor< Outputs<Slices, O1, O2, O3, O4, O5> > {
return result;
}
void Init(
InitData * init_data, Outputs<Slices, O1, O2, O3, O4, O5> & outputs) {
outputs.template Get<0>().SendInit(init_data);
outputs.template Get<1>().SendInit(init_data);
outputs.template Get<2>().SendInit(init_data);
outputs.template Get<3>().SendInit(init_data);
outputs.template Get<4>().SendInit(init_data);
}
private:
FunctionType function_;
};
......
......@@ -78,6 +78,12 @@ class Switch
}
}
virtual void Init(InitData * init_data) {
SetScheduler(init_data->sched);
GetOutput<0>().SendInit(init_data);
GetOutput<1>().SendInit(init_data);
}
InputsType & GetInputs() {
return inputs_;
}
......@@ -109,6 +115,10 @@ class Switch
Run(clock);
}
virtual void OnInit(InitData * init_data) {
Init(init_data);
}
private:
InputsType inputs_;
OutputsType outputs_;
......
......@@ -246,13 +246,6 @@ class Network {
};
/**
* Adds a new serial process to the network.
* \param proc The process to add.
*/
template <class Inputs, class Outputs>
void Add(SerialProcess<Inputs, Outputs> & proc);
/**
* Generic parallel process template.
*
* Implements a generic parallel process in the network that may have one to
......@@ -334,13 +327,6 @@ class Network {
};
/**
* Adds a new parallel process to the network.
* \param proc The process to add.
*/
template <class Inputs, class Outputs>
void Add(ParallelProcess<Inputs, Outputs> & proc);
/**
* Switch process template.
*
* A switch has 2 inputs and 2 outputs. Input port 0 is of type boolean and
......@@ -412,13 +398,6 @@ class Network {
};
/**
* Adds a new switch process to the network.
* \param sw The switch process to add.
*/
template <typename Type>
void Add(Switch<Type> & sw);
/**
* Select process template.
*
* A select has 3 inputs and 1 output. Input port 0 is of type boolean and
......@@ -490,13 +469,6 @@ class Network {
};
/**
* Adds a new select process to the network.
* \param sel The select process to add.
*/
template <typename Type>
void Add(Select<Type> & sel);
/**
* Sink process template.
*
* A sink marks the end of a particular processing chain. It can have one to
......@@ -557,13 +529,6 @@ class Network {
};
/**
* Adds a new sink process to the network.
* \param sink The sink process to add.
*/
template<typename I1, typename I2, typename I3, typename I4, typename I5>
void Add(Sink<I1, I2, I3, I4, I5> & sink);
/**
* Source process template.
*
* A source marks the start of a processing chain. It can have one to five
......@@ -635,7 +600,7 @@ class Network {
* \param source The source process to add.
*/
template<typename O1, typename O2, typename O3, typename O4, typename O5>
void Add(Source<O1, O2, O3, O4, O5> & source);
void AddSource(Source<O1, O2, O3, O4, O5> & source);
/**
* Constant source process template.
......@@ -694,7 +659,7 @@ class Network {
* \param source The constant source process to add.
*/
template<typename Type>
void Add(ConstantSource<Type> & source);
void AddSource(ConstantSource<Type> & source);
/**
* Executes the network until one of the the sources returns \c false.
......@@ -748,11 +713,6 @@ class Network : public internal::ClockListener {
}
};
template <class Inputs, class Outputs>
void Add(SerialProcess<Inputs, Outputs> & proc) {
processes_.push_back(&proc);
}
template <class Inputs, class Outputs> class ParallelProcess;
template <
......@@ -776,31 +736,16 @@ class Network : public internal::ClockListener {
}
};
template <class Inputs, class Outputs>
void Add(ParallelProcess<Inputs, Outputs> & proc) {
processes_.push_back(&proc);
}
template<typename Type>
class Switch : public internal::Switch<Slices, Type> {
public:
};
template <typename Type>
void Add(Switch<Type> & sw) {
processes_.push_back(&sw);
}
template<typename Type>
class Select : public internal::Select<Slices, Type> {
public:
};
template <typename Type>
void Add(Select<Type> & sel) {
processes_.push_back(&sel);
}
template<typename I1, typename I2 = embb::base::internal::Nil,
typename I3 = embb::base::internal::Nil,
typename I4 = embb::base::internal::Nil,
......@@ -818,12 +763,6 @@ class Network : public internal::ClockListener {
}
};
template<typename I1, typename I2, typename I3, typename I4, typename I5>
void Add(Sink<I1, I2, I3, I4, I5> & sink) {
sink.SetListener(this);
sinks_.push_back(&sink);
}
template<typename O1, typename O2 = embb::base::internal::Nil,
typename O3 = embb::base::internal::Nil,
typename O4 = embb::base::internal::Nil,
......@@ -843,7 +782,7 @@ class Network : public internal::ClockListener {
};
template<typename O1, typename O2, typename O3, typename O4, typename O5>
void Add(Source<O1, O2, O3, O4, O5> & source) {
void AddSource(Source<O1, O2, O3, O4, O5> & source) {
sources_.push_back(&source);
}
......@@ -857,7 +796,7 @@ class Network : public internal::ClockListener {
};
template<typename Type>
void Add(ConstantSource<Type> & source) {
void AddSource(ConstantSource<Type> & source) {
sources_.push_back(&source);
}
......@@ -866,19 +805,20 @@ class Network : public internal::ClockListener {
internal::SchedulerMTAPI<Slices> sched_mtapi;
internal::Scheduler * sched = &sched_mtapi;
internal::InitData init_data;
init_data.sched = sched;
init_data.sink_listener = this;
sink_count_ = 0;
for (size_t it = 0; it < sources_.size(); it++)
sources_[it]->SetScheduler(sched);
for (size_t it = 0; it < processes_.size(); it++)
processes_[it]->SetScheduler(sched);
for (size_t it = 0; it < sinks_.size(); it++)
sinks_[it]->SetScheduler(sched);
sources_[it]->Init(&init_data);
for (int ii = 0; ii < Slices; ii++) sink_count_[ii] = 0;
for (int ii = 0; ii < Slices; ii++) sink_counter_[ii] = 0;
int clock = 0;
while (clock >= 0) {
const int idx = clock % Slices;
while (sink_count_[idx] > 0) embb::base::Thread::CurrentYield();
while (sink_counter_[idx] > 0) embb::base::Thread::CurrentYield();
sched->WaitForSlice(idx);
if (!SpawnClock(clock))
break;
......@@ -889,7 +829,7 @@ class Network : public internal::ClockListener {
if (ii < 0) ii = 0;
for (; ii < clock; ii++) {
const int idx = ii % Slices;
while (sink_count_[idx] > 0) embb::base::Thread::CurrentYield();
while (sink_counter_[idx] > 0) embb::base::Thread::CurrentYield();
sched->WaitForSlice(idx);
}
}
......@@ -902,17 +842,28 @@ class Network : public internal::ClockListener {
*/
virtual void OnClock(int clock) {
const int idx = clock % Slices;
const int cnt = --sink_count_[idx];
const int cnt = --sink_counter_[idx];
if (cnt < 0)
EMBB_THROW(embb::base::ErrorException,
"More sinks than expected signaled reception of given clock.")
}
/**
* Internal.
* \internal
* Gets called when an init token has reached all sinks.
*/
virtual void OnInit(internal::InitData * /*sched*/) {
sink_count_++;
}
private:
std::vector<internal::Node*> processes_;
std::vector<internal::Node*> sources_;
std::vector<internal::Node*> sinks_;
embb::base::Atomic<int> sink_count_[Slices];
embb::base::Atomic<int> sink_counter_[Slices];
int sink_count_;
#if EMBB_DATAFLOW_TRACE_SIGNAL_HISTORY
std::vector<int> spawn_history_[Slices];
#endif
......@@ -923,7 +874,7 @@ class Network : public internal::ClockListener {
#if EMBB_DATAFLOW_TRACE_SIGNAL_HISTORY
spawn_history_[idx].push_back(clock);
#endif
sink_count_[idx] = static_cast<int>(sinks_.size());
sink_counter_[idx] = sink_count_;
for (size_t kk = 0; kk < sources_.size(); kk++) {
result &= sources_[kk]->Start(clock);
}
......
......@@ -186,17 +186,8 @@ void SimpleTest::TestBasic() {
sel.GetOutput<0>() >> sink.GetInput<0>();
network.Add(constant);
network.Add(source);
network.Add(filter);
network.Add(mult);
network.Add(pred);
network.Add(sw);
network.Add(sel);
network.Add(sink);
network.AddSource(constant);
network.AddSource(source);
network();
......
......@@ -10,6 +10,9 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../../base_cpp/include
${CMAKE_CURRENT_BINARY_DIR}/../../base_cpp/include
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_c/src
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_network_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_opencl_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../../mtapi_cpp/include
${CMAKE_CURRENT_SOURCE_DIR}/../../tasks_cpp/include
${CMAKE_CURRENT_BINARY_DIR}/../../tasks_cpp/include
......@@ -20,9 +23,16 @@ include_directories(
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-std=c++11")
set (EXTRA_LIBS dl)
endif()
IF(MSVC)
set (EXTRA_LIBS ws2_32)
ENDIF()
add_executable(examples ${EXAMPLES_SOURCES})
target_link_libraries(examples embb_dataflow_cpp embb_algorithms_cpp embb_tasks_cpp embb_mtapi_cpp
embb_mtapi_c embb_base_cpp embb_base_c embb_containers_cpp ${compiler_libs})
embb_mtapi_network_c embb_mtapi_opencl_c embb_mtapi_c
embb_base_cpp embb_base_c embb_containers_cpp
${EXTRA_LIBS} ${compiler_libs})
CopyBin(BIN examples DEST ${local_install_dir})
nw.Add(read);
nw.Add(replace);
nw.Add(write);
nw.AddSource(read);
......@@ -14,7 +14,7 @@
source4(
embb::base::MakeFunction(producer4, &Producer<int>::Run) );
nw.Add(source1);
nw.Add(source2);
nw.Add(source3);
nw.Add(source4);
nw.AddSource(source1);
nw.AddSource(source2);
nw.AddSource(source3);
nw.AddSource(source4);
......@@ -60,19 +60,11 @@ void RunDataflowNonLinear() {
process4( embb::base::MakeFunction(comparator, &Comparator<int>::Run) ),
process5( embb::base::MakeFunction(comparator, &Comparator<int>::Run) );
nw.Add(process1);
nw.Add(process2);
nw.Add(process3);
nw.Add(process4);
nw.Add(process5);
Consumer<int> consumer;
Network::Sink<int, int, int, int>
sink1(embb::base::MakeFunction(consumer, &Consumer<int>::Run));
nw.Add(sink1);
source1.GetOutput<0>() >> process1.GetInput<0>();
source2.GetOutput<0>() >> process2.GetInput<0>();
source3.GetOutput<0>() >> process1.GetInput<1>();
......
......@@ -28,6 +28,9 @@
#include <embb/base/c/thread.h>
void RunMTAPI_C();
void RunMTAPI_C_Plugin();
void RunMTAPI_C_Network();
void RunMTAPI_C_OpenCL();
void RunMTAPI_CPP();
void RunTasks();
void RunDataflowLinear();
......@@ -55,6 +58,18 @@ int main() {
RunMTAPI_C();
std::cout << "RunMTAPI_C() ... done" << std::endl;
std::cout << "RunMTAPI_C_Plugin() ..." << std::endl;
RunMTAPI_C_Plugin();
std::cout << "RunMTAPI_C_Plugin() ... done" << std::endl;
std::cout << "RunMTAPI_C_Network() ..." << std::endl;
RunMTAPI_C_Network();
std::cout << "RunMTAPI_C_Network() ... done" << std::endl;
std::cout << "RunMTAPI_C_OpenCL() ..." << std::endl;
RunMTAPI_C_OpenCL();
std::cout << "RunMTAPI_C_OpenCL() ... done" << std::endl;
std::cout << "RunMTAPI_CPP() ..." << std::endl;
RunMTAPI_CPP();
std::cout << "RunMTAPI_CPP() ... done" << std::endl;
......
/*
* Copyright (c) 2014-2015, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb/mtapi/c/mtapi.h>
#include "mtapi_network_c_header-snippet.h"
#include <embb/base/c/internal/unused.h>
#include "mtapi_check_status-snippet.h"
#define NETWORK_DOMAIN 1
#define NETWORK_LOCAL_NODE 3
#define NETWORK_LOCAL_JOB 3
#define NETWORK_REMOTE_NODE 3
#define NETWORK_REMOTE_JOB 4
#include "mtapi_network_c_action_function-snippet.h"
void RunMTAPI_C_Network() {
mtapi_status_t status;
mtapi_job_hndl_t job;
mtapi_task_hndl_t task;
mtapi_action_hndl_t network_action, local_action;
const int kElements = 64;
float arguments[kElements * 2];
float results[kElements];
for (int ii = 0; ii < kElements; ii++) {
arguments[ii] = static_cast<float>(ii);
arguments[ii + kElements] = static_cast<float>(ii);
}
mtapi_initialize(
NETWORK_DOMAIN,
NETWORK_LOCAL_NODE,
MTAPI_DEFAULT_NODE_ATTRIBUTES,
MTAPI_NULL,
&status);
MTAPI_CHECK_STATUS(status);
#include "mtapi_network_c_plugin_initialize-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_network_c_remote_action_create-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_network_c_local_action_create-snippet.h"
MTAPI_CHECK_STATUS(status);
job = mtapi_job_get(NETWORK_LOCAL_JOB, NETWORK_DOMAIN, &status);
MTAPI_CHECK_STATUS(status);
task = mtapi_task_start(
MTAPI_TASK_ID_NONE,
job,
arguments, kElements * 2 * sizeof(float),
results, kElements*sizeof(float),
MTAPI_DEFAULT_TASK_ATTRIBUTES,
MTAPI_GROUP_NONE,
&status);
MTAPI_CHECK_STATUS(status);
mtapi_task_wait(task, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
for (int ii = 0; ii < kElements; ii++) {
if (results[ii] != ii * 2 + 1) {
printf("result %d was expected to be %d but was %f.\n",
ii, ii * 2 + 1, results[ii]);
exit(MTAPI_ERR_UNKNOWN);
}
}
#include "mtapi_network_c_plugin_finalize-snippet.h"
MTAPI_CHECK_STATUS(status);
mtapi_finalize(&status);
MTAPI_CHECK_STATUS(status);
}
/*
* Copyright (c) 2014-2015, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb/mtapi/c/mtapi.h>
#include "mtapi_opencl_c_header-snippet.h"
#include "mtapi_check_status-snippet.h"
#define OPENCL_DOMAIN 1
#define OPENCL_NODE 2
#define OPENCL_JOB 2
// OpenCL Kernel Function for element by element vector addition
#include "mtapi_opencl_c_kernel-snippet.h"
void RunMTAPI_C_OpenCL() {
mtapi_status_t status;
mtapi_job_hndl_t job;
mtapi_task_hndl_t task;
mtapi_action_hndl_t action;
const int kElements = 64;
float arguments[kElements * 2];
float results[kElements];
for (int ii = 0; ii < kElements; ii++) {
arguments[ii] = static_cast<float>(ii);
arguments[ii + kElements] = static_cast<float>(ii);
}
mtapi_initialize(
OPENCL_DOMAIN,
OPENCL_NODE,
MTAPI_DEFAULT_NODE_ATTRIBUTES,
MTAPI_NULL,
&status);
MTAPI_CHECK_STATUS(status);
#include "mtapi_opencl_c_plugin_initialize-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_opencl_c_action_create-snippet.h"
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
job = mtapi_job_get(OPENCL_JOB, OPENCL_DOMAIN, &status);
MTAPI_CHECK_STATUS(status);
task = mtapi_task_start(
MTAPI_TASK_ID_NONE,
job,
arguments, kElements * 2 * sizeof(float),
results, kElements*sizeof(float),
MTAPI_DEFAULT_TASK_ATTRIBUTES,
MTAPI_GROUP_NONE,
&status);
MTAPI_CHECK_STATUS(status);
mtapi_task_wait(task, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
for (int ii = 0; ii < kElements; ii++) {
if (results[ii] != ii * 2 + 1) {
printf("result %d was expected to be %d but was %f.\n",
ii, ii * 2 + 1, results[ii]);
exit(MTAPI_ERR_UNKNOWN);
}
}
#include "mtapi_opencl_c_plugin_finalize-snippet.h"
MTAPI_CHECK_STATUS(status);
mtapi_finalize(&status);
MTAPI_CHECK_STATUS(status);
}
/*
* Copyright (c) 2014-2015, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb/mtapi/c/mtapi.h>
#include <embb/mtapi/c/mtapi_ext.h>
#include <embb_mtapi_task_t.h>
#include <embb_mtapi_action_t.h>
#include <embb_mtapi_node_t.h>
#include <mtapi_status_t.h>
#include <embb/base/c/memory_allocation.h>
#include <embb/base/c/thread.h>
#include <embb/base/c/atomic.h>
#include <embb/base/c/internal/unused.h>
#define PLUGIN_DOMAIN_ID 1
#define PLUGIN_NODE_ID 1
#define PLUGIN_JOB_ID 1
#include "mtapi_check_status-snippet.h"
#include "mtapi_c_plugin_task_schedule-snippet.h"
#include "mtapi_c_plugin_task_start_cb-snippet.h"
#include "mtapi_c_plugin_task_cancel_cb-snippet.h"
#include "mtapi_c_plugin_action_finalize_cb-snippet.h"
void RunMTAPI_C_Plugin() {
mtapi_status_t status;
mtapi_job_hndl_t job;
mtapi_action_hndl_t action;
mtapi_task_hndl_t task;
mtapi_initialize(
PLUGIN_DOMAIN_ID,
PLUGIN_NODE_ID,
MTAPI_DEFAULT_NODE_ATTRIBUTES,
MTAPI_NULL,
&status);
MTAPI_CHECK_STATUS(status);
#include "mtapi_c_plugin_action_create-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_c_plugin_get_job-snippet.h"
MTAPI_CHECK_STATUS(status);
#include "mtapi_c_plugin_task_start-snippet.h"
MTAPI_CHECK_STATUS(status);
mtapi_task_wait(task, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
mtapi_finalize(&status);
MTAPI_CHECK_STATUS(status);
}
action = mtapi_ext_plugin_action_create(
PLUGIN_JOB_ID,
plugin_task_start,
plugin_task_cancel,
plugin_action_finalize,
MTAPI_NULL,
MTAPI_NULL,
0,
MTAPI_DEFAULT_ACTION_ATTRIBUTES,
&status);
void plugin_action_finalize(
MTAPI_IN mtapi_action_hndl_t action,
MTAPI_OUT mtapi_status_t* status
) {
EMBB_UNUSED(action);
// nothing to do for tearing down the plugin action
mtapi_status_set(status, MTAPI_SUCCESS);
}
job = mtapi_job_get(
PLUGIN_JOB_ID,
PLUGIN_DOMAIN_ID,
&status);
void plugin_task_cancel(
MTAPI_IN mtapi_task_hndl_t task,
MTAPI_OUT mtapi_status_t* status
) {
EMBB_UNUSED(task);
// nothing to cancel in this simple example
mtapi_status_set(status, MTAPI_SUCCESS);
}
void plugin_task_schedule(embb_mtapi_task_t* local_task) {
// here the task might be dispatched to some hardware or separate thread
// mark the task as running
embb_mtapi_task_set_state(local_task, MTAPI_TASK_RUNNING);
// nothing to do to execute the no-op task
// just mark the task as done
embb_mtapi_task_set_state(local_task, MTAPI_TASK_COMPLETED);
}
task = mtapi_task_start(
MTAPI_TASK_ID_NONE,
job,
MTAPI_NULL, 0,
MTAPI_NULL, 0,
MTAPI_DEFAULT_TASK_ATTRIBUTES,
MTAPI_GROUP_NONE,
&status);
void plugin_task_start(
MTAPI_IN mtapi_task_hndl_t task,
MTAPI_OUT mtapi_status_t* status) {
mtapi_status_t local_status = MTAPI_ERR_UNKNOWN;
// do we have a node?
if (embb_mtapi_node_is_initialized()) {
// get the node instance
embb_mtapi_node_t * node = embb_mtapi_node_get_instance();
// is this a valid task?
if (embb_mtapi_task_pool_is_handle_valid(node->task_pool, task)) {
// get the tasks storage
embb_mtapi_task_t * local_task =
embb_mtapi_task_pool_get_storage_for_handle(node->task_pool, task);
// dispatch the task
plugin_task_schedule(local_task);
local_status = MTAPI_SUCCESS;
}
else {
local_status = MTAPI_ERR_TASK_INVALID;
}
}
else {
local_status = MTAPI_ERR_NODE_NOTINIT;
}
mtapi_status_set(status, local_status);
}
static void AddVectorAction(
void const * arguments,
mtapi_size_t arguments_size,
void * result_buffer,
mtapi_size_t result_buffer_size,
void const * node_local_data,
mtapi_size_t node_local_data_size,
mtapi_task_context_t * context) {
EMBB_UNUSED(context);
EMBB_UNUSED(result_buffer_size);
EMBB_UNUSED(node_local_data_size);
int elements = static_cast<int>(arguments_size / sizeof(float) / 2);
float const * a = reinterpret_cast<float const *>(arguments);
float const * b = reinterpret_cast<float const *>(arguments)+elements;
float * c = reinterpret_cast<float*>(result_buffer);
float const * d = reinterpret_cast<float const *>(node_local_data);
for (int ii = 0; ii < elements; ii++) {
c[ii] = a[ii] + b[ii] + d[0];
}
}
#include <embb/mtapi/c/mtapi_network.h>
network_action = mtapi_network_action_create(
NETWORK_DOMAIN,
NETWORK_LOCAL_JOB,
NETWORK_REMOTE_JOB,
"127.0.0.1", 12345,
&status);
mtapi_network_plugin_initialize("127.0.0.1", 12345, 5,
kElements * 4 * 3 + 32, &status);
float node_remote = 1.0f;
local_action = mtapi_action_create(
NETWORK_REMOTE_JOB,
AddVectorAction,
&node_remote, sizeof(float),
MTAPI_DEFAULT_ACTION_ATTRIBUTES,
&status);
float node_local = 1.0f;
action = mtapi_opencl_action_create(
OPENCL_JOB,
kernel, "AddVector", 32, 4,
&node_local, sizeof(float),
&status);
#include <embb/mtapi/c/mtapi_opencl.h>
const char * kernel =
"__kernel void AddVector(\n"
" __global void* arguments,\n"
" int arguments_size,\n"
" __global void* result_buffer,\n"
" int result_buffer_size,\n"
" __global void* node_local_data,\n"
" int node_local_data_size) {\n"
" int ii = get_global_id(0);\n"
" int elements = arguments_size / sizeof(float) / 2;\n"
" if (ii >= elements)"
" return;"
" __global float* a = (__global float*)arguments;\n"
" __global float* b = ((__global float*)arguments) + elements;\n"
" __global float* c = (__global float*)result_buffer;\n"
" __global float* d = (__global float*)node_local_data;\n"
" c[ii] = a[ii] + b[ii] + d[0];\n"
"}\n";
......@@ -152,7 +152,10 @@ INPUT = "@CMAKE_SOURCE_DIR@/doc/reference/embb.dox" \
"@CMAKE_SOURCE_DIR@/mtapi_cpp/include" \
"@CMAKE_SOURCE_DIR@/base_cpp/include" \
"@CMAKE_SOURCE_DIR@/mtapi_c/include" \
"@CMAKE_SOURCE_DIR@/base_c/include"
"@CMAKE_SOURCE_DIR@/base_c/include" \
"@CMAKE_SOURCE_DIR@/mtapi_opencl_c/include" \
"@CMAKE_SOURCE_DIR@/mtapi_network_c/include"
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.h \
*.cc \
......
......@@ -142,7 +142,7 @@ is used to construct the sink:
\emph{\textbf{Note:} If you parallelize your own application using \embb and your compiler emits a lengthy error message containing lots of templates, it is very likely that for at least one process, the ports and their directions do not match the signature of the given function.}
The network needs to know about the processes declared above, so we add them to our network:
The network needs to know about the source declared above, so we add it to our network:
%
\\\inputlisting{../examples/dataflow/dataflow_add-snippet.h}
%
......@@ -303,11 +303,11 @@ The class-based approach has several advantages besides the use of templates: Fi
Each instance of the class \lstinline|Network| maintains a list of source processes that belong to the network.
% When you create a source process using \lstinline|MakeSource|, it is automatically added to this list. Otherwise, you must explicitly add it by a call to \lstinline|Add|. For example, if we want to feed our sorting network \lstinline|nw| with streams of integer values, we may write:
You must explicitly add all processes to the network by a call to \lstinline|Add|. For example, if we want to feed our sorting network \lstinline|nw| with four streams of integer values, we may write:
You must explicitly add all sources to the network by a call to \lstinline|AddSource|. For example, if we want to feed our sorting network \lstinline|nw| with four streams of integer values, we may write:
%
\\\inputlisting{../examples/dataflow/dataflow_declare_add_sources-snippet.h}
%
%This is only necessary for source processes. All other processes are automatically found via a depth-first search starting from the source processes.
This is only necessary for source processes. All other processes are automatically found via a depth-first search starting from the source processes.
The code for the comparators looks like this:
%
......
......@@ -202,3 +202,126 @@ Again, the started task has to be waited for (using \lstinline|embb::mtapi::Task
The registered action will be unregistered when it goes out of scope.
The runtime needs to be shut down by calling:
\\\inputlisting{../examples/mtapi/mtapi_cpp_finalize-snippet.h}
\section{Plugins}
The \embb implementation of MTAPI provides an extension to allow for custom actions that are not executed by the scheduler for software actions as detailed in the previous sections.
Two plugins are delivered with \embb, one for supporting distributed systems through TCP/IP networking and the other to allow for transparently using OpenCL accelerators.
\subsection{Plugin API}
The plugin API consists of a single function named \lstinline|mtapi_ext_plugin_action_create()| contained in the mtapi\_ext.h header file. It is used to associate the plugin action with a specific job ID:
\begin{lstlisting}
mtapi_action_hndl_t mtapi_ext_plugin_action_create(
MTAPI_IN mtapi_job_id_t job_id,
MTAPI_IN mtapi_ext_plugin_task_start_function_t task_start_function,
MTAPI_IN mtapi_ext_plugin_task_cancel_function_t task_cancel_function,
MTAPI_IN mtapi_ext_plugin_action_finalize_function_t action_finalize_function,
MTAPI_IN void* plugin_data,
MTAPI_IN void* node_local_data,
MTAPI_IN mtapi_size_t node_local_data_size,
MTAPI_IN mtapi_action_attributes_t* attributes,
MTAPI_OUT mtapi_status_t* status
);
\end{lstlisting}
The plugin action is implemented through 3 callbacks, task start, task cancel and action finalize.
\lstinline|task_start_function| is called when the user requests execution of the plugin action by calling \lstinline|mtapi_task_start()| or \lstinline|mtapi_task_enqueue()|. To those functions the fact that they operate on a plugin action is transparent, they only require the job handle of the job the action was registered with.
\lstinline|task_cancel_function| is called when the user requests cancelation of a tasks by calling \lstinline|mtapi_task_cancel()| or by calling \lstinline|mtapi_queue_disable()| on a non-retaining queue.
\lstinline|action_finalize_function| is called when the node is finalized and the action is deleted, or when the user explicitly deletes the action by calling \lstinline|mtapi_action_delete()|.
For illustration our example plugin will provide a no-op action. The task start callback in that case looks like this:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_start_cb-snippet.h}
%
The scheduling operation is responsible for bringing the task to execution, this might involve instructing some hardware to execute the task or pushing the task into a queue for execution by a separate worker thread. Here however, the task is executed directly:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_schedule-snippet.h}
%
Since the task gets executed right away, it cannot be canceled and the task cancel callback implementation is empty:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_cancel_cb-snippet.h}
%
The plugin action did not acquire any resources so the action finalize callback is empty as well:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_action_finalize_cb-snippet.h}
%
Now that the callbacks are in place, the action can be registered with a job after the node was initialized using \lstinline|mtapi_initialize()|:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_action_create-snippet.h}
%
The job handle can now be obtained the normal MTAPI way. The fact that there is a plugin working behind the scenes is transparent by now:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_get_job-snippet.h}
%
Using the job handle tasks can be started like normal MTAPI tasks:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_start-snippet.h}
%
This call will lead to the invocation of then \lstinline|plugin_task_start| callback function, where the plugin implementor is responsible for bringing the task to execution.
\subsection{Network}
The MTAPI network plugin provides a means to distribute tasks over a TCP/IP network. As an example the following vector addition action is used:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_action_function-snippet.h}
%
It adds two float vectors and a float from node local data and writes the result into the result float vector. In the example code the vectors will hold \lstinline|kElements| floats each.
To use the network plugin, its header file needs to be included first:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_header-snippet.h}
%
After initializing the node using \lstinline|mtapi_initialize()|, the plugin itself needs to be initialized:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_plugin_initialize-snippet.h}
%
This will set up a listening socket on the localhost interface (127.0.0.1) at port 12345. The socket will allow a maximum of 5 connections and have a maximum transfer buffer size of \lstinline|kElements * 4 * 3 + 32|. This buffer size needs to be big enough to fit at least the argument and result buffer sizes at once. The example uses 3 vectors of \lstinline|kElements| floats using \lstinline|kElements * sizeof(float) * 3| bytes.
Since the example connects to itself on localhost, the "remote" action needs to be registered with the \lstinline|NETWORK_REMOTE_JOB|:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_remote_action_create-snippet.h}
%
After that, the local network action is created, that maps \lstinline|NETWORK_LOCAL_JOB| to \lstinline|NETWORK_REMOTE_JOB| through the network:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_local_action_create-snippet.h}
%
Now, \lstinline|NETWORK_LOCAL_JOB| can be used to execute tasks by simply calling \lstinline|mtapi_task_start()|. Their parameters will be transmitted through a socket connection and are consumed by the network plugin worker thread. The thread will start a task using the \lstinline|NETWORK_REMOTE_JOB|. When this task is finished, the results will be collected and sent back through the network. Again the network plugin thread will receive the results, provide them to the \lstinline|NETWORK_LOCAL_JOB| task and mark that task as finished.
When all work is done, the plugin needs to be finalized. This will stop the plugin worker thread and close the sockets:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_plugin_finalize-snippet.h}
%
Then the node may be finalized by calling \lstinline|mtapi_finalize()|.
\subsection{OpenCL}
The MTAPI OpenCL plugin allows the user to incorporate the computational power of an OpenCL accelerator, if one is available in the system.
The vector addition example from the network plugin is used again. However, the action function is an OpenCL kernel now:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_kernel-snippet.h}
%
The OpenCL plugin header file needs to be included first:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_header-snippet.h}
%
As with the network plugin, the OpenCL plugin needs to be initialized after the node has been initialized:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_plugin_initialize-snippet.h}
%
Then the plugin action can be registered with the \lstinline|OPENCL_JOB|:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_action_create-snippet.h}
%
The kernel source and the name of the kernel to use (AddVector) need to be specified while creating the action. The kernel will be compiled using the OpenCL runtime and the provided node local data transferred to accelerator memory. The local work size is the number of threads that will share OpenCL local memory, in this case 32. The element size instructs the OpenCL plugin how many bytes a single element in the result buffer consumes, in this case 4, as a single result is a single float. The OpenCL plugin will launch \lstinline|result_buffer_size/element_size| OpenCL threads to calculate the result.
Now the \lstinline|OPENCL_JOB| can be used like a normal MTAPI job to start tasks.
After all work is done, the plugin needs to be finalized. This will free all memory on the accelerator and delete the corresponding OpenCL context:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_plugin_finalize-snippet.h}
%
......@@ -557,6 +557,17 @@ enum mtapi_node_attributes_enum {
#define MTAPI_NODE_TYPE_SMP 1
#define MTAPI_NODE_TYPE_DSP 2
/**
* Task handle type.
* \memberof mtapi_task_hndl_struct
*/
typedef struct mtapi_task_hndl_struct mtapi_task_hndl_t;
/** task completion callback */
typedef void(*mtapi_task_complete_function_t)(
MTAPI_IN mtapi_task_hndl_t task,
MTAPI_OUT mtapi_status_t* status);
/** task attributes */
enum mtapi_task_attributes_enum {
MTAPI_TASK_DETACHED, /**< task is detached, i.e., the runtime
......@@ -574,7 +585,9 @@ enum mtapi_task_attributes_enum {
executed n times, if possible in
parallel */
MTAPI_TASK_PRIORITY,
MTAPI_TASK_AFFINITY
MTAPI_TASK_AFFINITY,
MTAPI_TASK_USER_DATA,
MTAPI_TASK_COMPLETE_FUNCTION
};
/** size of the \a MTAPI_TASK_DETACHED attribute */
#define MTAPI_TASK_DETACHED_SIZE sizeof(mtapi_boolean_t)
......@@ -671,6 +684,10 @@ struct mtapi_task_attributes_struct {
mtapi_uint_t num_instances; /**< stores MTAPI_TASK_INSTANCES */
mtapi_uint_t priority; /**< stores MTAPI_TASK_PRIORITY */
mtapi_affinity_t affinity; /**< stores MTAPI_TASK_AFFINITY */
void * user_data; /**< stores MTAPI_TASK_USER_DATA */
mtapi_task_complete_function_t
complete_func; /**< stores
MTAPI_TASK_COMPLETE_FUNCTION */
};
/**
......@@ -869,11 +886,8 @@ struct mtapi_task_hndl_struct {
mtapi_task_id_t id; /**< pool index of this handle */
};
/**
* Task handle type.
* \memberof mtapi_task_hndl_struct
*/
typedef struct mtapi_task_hndl_struct mtapi_task_hndl_t;
// was forward declared
//typedef struct mtapi_task_hndl_struct mtapi_task_hndl_t;
/* ---- BASIC CONSTANTS ---------------------------------------------------- */
......
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef EMBB_MTAPI_C_MTAPI_EXT_H_
#define EMBB_MTAPI_C_MTAPI_EXT_H_
#include <embb/mtapi/c/mtapi.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup C_MTAPI_EXT MTAPI Extensions
*
* \ingroup C_MTAPI
*
* Provides extensions to the standard MTAPI API.
*
* There is a single extension function defined here to support user defined
* behavior of an action to allow for actions that are not implemented locally
* in software but e.g. on a remote node in a network or on an accelerator
* device like a GPU or FPGA.
*/
/**
* Represents a callback function that is called when a plugin action is about
* to start a plugin task.
* This function should return MTAPI_SUCCESS if the task could be started and
* the appropriate MTAPI_ERR_* if not.
*
* \ingroup C_MTAPI_EXT
*/
typedef void(*mtapi_ext_plugin_task_start_function_t)(
MTAPI_IN mtapi_task_hndl_t task,
MTAPI_OUT mtapi_status_t* status
);
/**
* Represents a callback function that is called when a plugin task is about
* to be canceled.
* This function should return MTAPI_SUCCESS if the task could be canceled and
* the appropriate MTAPI_ERR_* if not.
*
* \ingroup C_MTAPI_EXT
*/
typedef void(*mtapi_ext_plugin_task_cancel_function_t)(
MTAPI_IN mtapi_task_hndl_t task,
MTAPI_OUT mtapi_status_t* status
);
/**
* Represents a callback function that is called when a plugin action is about
* to be finalized.
* This function should return MTAPI_SUCCESS if the action could be deleted and
* the appropriate MTAPI_ERR_* if not.
*
* \ingroup C_MTAPI_EXT
*/
typedef void(*mtapi_ext_plugin_action_finalize_function_t)(
MTAPI_IN mtapi_action_hndl_t action,
MTAPI_OUT mtapi_status_t* status
);
/**
* This function creates a plugin action.
*
* It is called on the node where the plugin action is implemented. A plugin
* action is an abstract encapsulation of a user defined action that is needed
* to implement a job that does not represent a software action. A plugin
* action contains a reference to a job, callback functions to start and cancel
* tasks and a reference to an callback function to finalize the action.
* After a plugin action is created, it is referenced by the application using
* a node-local handle of type \c mtapi_action_hndl_t, or indirectly through a
* node-local job handle of type \c mtapi_job_hndl_t. A plugin action's
* life-cycle begins with mtapi_ext_plugin_action_create(), and ends when
* mtapi_action_delete() or mtapi_finalize() is called.
*
* To create an action, the application must supply the domain-wide job ID of
* the job associated with the action. Job IDs must be predefined in the
* application and runtime, of type \c mtapi_job_id_t, which is an
* implementation-defined type. The job ID is unique in the sense that it is
* unique for the job implemented by the action. However several actions may
* implement the same job for load balancing purposes.
*
* If \c node_local_data_size is not zero, \c node_local_data specifies the
* start of node local data shared by action functions executed on the same
* node. \c node_local_data_size can be used by the runtime for cache coherency
* operations.
*
* On success, an action handle is returned and \c *status is set to
* \c MTAPI_SUCCESS. On error, \c *status is set to the appropriate error
* defined below. In the case where the action already exists, \c status will
* be set to \c MTAPI_ERR_ACTION_EXISTS and the handle returned will not be a
* valid handle.
* <table>
* <tr>
* <th>Error code</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_JOB_INVALID</td>
* <td>The \c job_id is not a valid job ID, i.e., no action was created for
* that ID or the action has been deleted.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_ACTION_EXISTS</td>
* <td>This action is already created.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_ACTION_LIMIT</td>
* <td>Exceeded maximum number of actions allowed.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_NODE_NOTINIT</td>
* <td>The calling node is not initialized.</td>
* </tr>
* </table>
*
* \see mtapi_action_delete(), mtapi_finalize()
*
* \returns Handle to newly created plugin action, invalid handle on error
* \threadsafe
* \ingroup C_MTAPI_EXT
*/
mtapi_action_hndl_t mtapi_ext_plugin_action_create(
MTAPI_IN mtapi_job_id_t job_id,
MTAPI_IN mtapi_ext_plugin_task_start_function_t task_start_function,
MTAPI_IN mtapi_ext_plugin_task_cancel_function_t task_cancel_function,
MTAPI_IN mtapi_ext_plugin_action_finalize_function_t action_finalize_function,
MTAPI_IN void* plugin_data,
MTAPI_IN void* node_local_data,
MTAPI_IN mtapi_size_t node_local_data_size,
MTAPI_IN mtapi_action_attributes_t* attributes,
MTAPI_OUT mtapi_status_t* status
);
#ifdef __cplusplus
}
#endif
#endif // EMBB_MTAPI_C_MTAPI_EXT_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_EXT_H_
#define MTAPI_EXT_H_
// Just includes the actual MTAPI extension header for standard conformity
#include <embb/mtapi/c/mtapi_ext.h>
#endif // MTAPI_EXT_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb/mtapi/c/mtapi_ext.h>
#include <embb_mtapi_action_t.h>
#include <embb_mtapi_node_t.h>
#include <embb_mtapi_job_t.h>
#include <embb_mtapi_log.h>
#include <mtapi_status_t.h>
mtapi_action_hndl_t mtapi_ext_plugin_action_create(
MTAPI_IN mtapi_job_id_t job_id,
MTAPI_IN mtapi_ext_plugin_task_start_function_t task_start_function,
MTAPI_IN mtapi_ext_plugin_task_cancel_function_t task_cancel_function,
MTAPI_IN mtapi_ext_plugin_action_finalize_function_t
action_finalize_function,
MTAPI_IN void* plugin_data,
MTAPI_IN void* node_local_data,
MTAPI_IN mtapi_size_t node_local_data_size,
MTAPI_IN mtapi_action_attributes_t* attributes,
MTAPI_OUT mtapi_status_t* status) {
mtapi_status_t local_status = MTAPI_ERR_UNKNOWN;
mtapi_action_hndl_t action_handle = { 0, EMBB_MTAPI_IDPOOL_INVALID_ID };
embb_mtapi_log_trace("mtapi_ext_plugin_action_create() called\n");
if (embb_mtapi_node_is_initialized()) {
embb_mtapi_node_t* node = embb_mtapi_node_get_instance();
/* check if job is valid */
if (embb_mtapi_job_is_id_valid(node, job_id)) {
embb_mtapi_job_t* job = embb_mtapi_job_get_storage_for_id(node, job_id);
embb_mtapi_action_t* new_action =
embb_mtapi_action_pool_allocate(node->action_pool);
if (MTAPI_NULL != new_action) {
new_action->domain_id = node->domain_id;
new_action->node_id = node->node_id;
new_action->job_id = job_id;
new_action->node_local_data = node_local_data;
new_action->node_local_data_size = node_local_data_size;
new_action->enabled = MTAPI_TRUE;
new_action->is_plugin_action = MTAPI_TRUE;
embb_atomic_store_int(&new_action->num_tasks, 0);
new_action->plugin_task_start_function = task_start_function;
new_action->plugin_task_cancel_function = task_cancel_function;
new_action->plugin_action_finalize_function = action_finalize_function;
new_action->plugin_data = (void*)plugin_data;
/* set defaults if no attributes were given */
if (MTAPI_NULL != attributes) {
new_action->attributes = *attributes;
local_status = MTAPI_SUCCESS;
} else {
/* use the default */
mtapi_actionattr_init(&new_action->attributes, &local_status);
}
/* check if affinity is sane */
if (0 == new_action->attributes.affinity) {
local_status = MTAPI_ERR_PARAMETER;
}
if (MTAPI_SUCCESS == local_status) {
action_handle = new_action->handle;
embb_mtapi_job_add_action(job, new_action);
} else {
embb_mtapi_action_pool_deallocate(node->action_pool, new_action);
}
} else {
/* no more space left in action pool */
local_status = MTAPI_ERR_ACTION_LIMIT;
}
} else {
local_status = MTAPI_ERR_JOB_INVALID;
}
} else {
embb_mtapi_log_error("mtapi not initialized\n");
local_status = MTAPI_ERR_NODE_NOTINIT;
}
mtapi_status_set(status, local_status);
return action_handle;
}
......@@ -56,10 +56,15 @@ void embb_mtapi_action_initialize(embb_mtapi_action_t* that) {
that->enabled = MTAPI_FALSE;
that->node_local_data = NULL;
that->node_local_data_size = 0;
that->plugin_data = MTAPI_NULL;
embb_atomic_store_int(&that->num_tasks, 0);
}
void embb_mtapi_action_finalize(embb_mtapi_action_t* that) {
if (that->is_plugin_action) {
// TODO(mw): check status
that->plugin_action_finalize_function(that->handle, NULL);
}
embb_mtapi_action_initialize(that);
}
......@@ -131,12 +136,14 @@ mtapi_action_hndl_t mtapi_action_create(
new_action->domain_id = node->domain_id;
new_action->node_id = node->node_id;
new_action->job_id = job_id;
new_action->action_function = action_function;
new_action->node_local_data = node_local_data;
new_action->node_local_data_size = node_local_data_size;
new_action->enabled = MTAPI_TRUE;
new_action->is_plugin_action = MTAPI_FALSE;
embb_atomic_store_int(&new_action->num_tasks, 0);
new_action->action_function = action_function;
/* set defaults if no attributes were given */
if (MTAPI_NULL != attributes) {
new_action->attributes = *attributes;
......@@ -322,7 +329,8 @@ void mtapi_action_delete(
node, local_action->job_id);
embb_mtapi_job_remove_action(local_job, local_action);
}
embb_mtapi_action_finalize(local_action);
/* this is done by pool deallocate:
embb_mtapi_action_finalize(local_action); */
embb_mtapi_action_pool_deallocate(node->action_pool, local_action);
} else {
local_status = MTAPI_ERR_ACTION_INVALID;
......
......@@ -27,7 +27,7 @@
#ifndef MTAPI_C_SRC_EMBB_MTAPI_ACTION_T_H_
#define MTAPI_C_SRC_EMBB_MTAPI_ACTION_T_H_
#include <embb/mtapi/c/mtapi.h>
#include <embb/mtapi/c/mtapi_ext.h>
#include <embb/base/c/atomic.h>
#include <embb_mtapi_pool_template.h>
......@@ -57,6 +57,12 @@ struct embb_mtapi_action_struct {
mtapi_action_attributes_t attributes;
mtapi_boolean_t enabled;
mtapi_boolean_t is_plugin_action;
void* plugin_data;
mtapi_ext_plugin_task_start_function_t plugin_task_start_function;
mtapi_ext_plugin_task_cancel_function_t plugin_task_cancel_function;
mtapi_ext_plugin_action_finalize_function_t plugin_action_finalize_function;
embb_atomic_int num_tasks;
};
......
......@@ -131,6 +131,11 @@ void mtapi_initialize(
/* initialization succeeded, tell workers to start working */
embb_atomic_store_int(&node->is_scheduler_running, MTAPI_TRUE);
if (MTAPI_SUCCESS != local_status) {
mtapi_finalize(MTAPI_NULL);
local_status = MTAPI_ERR_NODE_INITFAILED;
}
} else {
mtapi_finalize(MTAPI_NULL);
local_status = MTAPI_ERR_NODE_INITFAILED;
......
......@@ -350,6 +350,11 @@ int embb_mtapi_scheduler_worker(void * arg) {
/* do nothing, although this is an error */
break;
}
/* issue task complete callback if set */
if (MTAPI_NULL != task->attributes.complete_func) {
task->attributes.complete_func(task->handle, MTAPI_NULL);
}
} else if (counter < 1024) {
/* spin and yield for a while before going to sleep */
embb_thread_yield();
......
......@@ -227,9 +227,23 @@ static mtapi_task_hndl_t embb_mtapi_task_start(
task->queue.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
}
/* load balancing is unsupported right now,
so always choose action 0 */
/* load balancing: choose action with minimum tasks */
action_index = 0;
for (mtapi_uint_t ii = 0; ii < local_job->num_actions; ii++) {
if (embb_mtapi_action_pool_is_handle_valid(
node->action_pool, local_job->actions[ii])) {
embb_mtapi_action_t * act_m =
embb_mtapi_action_pool_get_storage_for_handle(
node->action_pool, local_job->actions[action_index]);
embb_mtapi_action_t * act_i =
embb_mtapi_action_pool_get_storage_for_handle(
node->action_pool, local_job->actions[ii]);
if (embb_atomic_load_int(&act_m->num_tasks) >
embb_atomic_load_int(&act_i->num_tasks)) {
action_index = ii;
}
}
}
if (embb_mtapi_action_pool_is_handle_valid(
node->action_pool, local_job->actions[action_index])) {
task->action = local_job->actions[action_index];
......@@ -248,14 +262,28 @@ static mtapi_task_hndl_t embb_mtapi_task_start(
if (MTAPI_SUCCESS == local_status) {
embb_mtapi_scheduler_t * scheduler = node->scheduler;
mtapi_boolean_t was_scheduled;
embb_mtapi_action_t * local_action =
embb_mtapi_action_pool_get_storage_for_handle(
node->action_pool, task->action);
embb_mtapi_task_set_state(task, MTAPI_TASK_SCHEDULED);
was_scheduled = MTAPI_TRUE;
if (local_action->is_plugin_action) {
/* schedule plugin task */
mtapi_status_t plugin_status = MTAPI_ERR_UNKNOWN;
local_action->plugin_task_start_function(
task_hndl, &plugin_status);
was_scheduled = (MTAPI_SUCCESS == plugin_status) ?
MTAPI_TRUE : MTAPI_FALSE;
} else {
/* schedule local task */
was_scheduled = MTAPI_TRUE;
for (mtapi_uint_t kk = 0; kk < task->attributes.num_instances; kk++) {
was_scheduled = was_scheduled &
embb_mtapi_scheduler_schedule_task(scheduler, task, kk);
for (mtapi_uint_t kk = 0; kk < task->attributes.num_instances;
kk++) {
was_scheduled = was_scheduled &
embb_mtapi_scheduler_schedule_task(scheduler, task, kk);
}
}
if (was_scheduled) {
......@@ -474,7 +502,19 @@ void mtapi_task_cancel(
embb_mtapi_task_t* local_task =
embb_mtapi_task_pool_get_storage_for_handle(node->task_pool, task);
embb_mtapi_task_set_state(local_task, MTAPI_TASK_CANCELLED);
local_status = MTAPI_SUCCESS;
/* call plugin action cancel function */
if (embb_mtapi_action_pool_is_handle_valid(
node->action_pool, local_task->action)) {
embb_mtapi_action_t* local_action =
embb_mtapi_action_pool_get_storage_for_handle(
node->action_pool, local_task->action);
if (local_action->is_plugin_action) {
local_action->plugin_task_cancel_function(task, &local_status);
}
} else {
local_status = MTAPI_SUCCESS;
}
} else {
local_status = MTAPI_ERR_TASK_INVALID;
}
......
......@@ -25,6 +25,7 @@
*/
#include <assert.h>
#include <string.h>
#include <embb/mtapi/c/mtapi.h>
......@@ -46,6 +47,7 @@ void mtapi_taskattr_init(
attributes->num_instances = 1;
attributes->is_detached = MTAPI_FALSE;
attributes->priority = 0;
attributes->complete_func = MTAPI_NULL;
mtapi_affinity_init(&attributes->affinity, MTAPI_TRUE, &local_status);
} else {
local_status = MTAPI_ERR_PARAMETER;
......@@ -90,6 +92,16 @@ void mtapi_taskattr_set(
&attributes->affinity, attribute, attribute_size);
break;
case MTAPI_TASK_USER_DATA:
attributes->user_data = (void*)attribute;
local_status = MTAPI_SUCCESS;
break;
case MTAPI_TASK_COMPLETE_FUNCTION:
memcpy(&attributes->complete_func, &attribute, sizeof(void*));
local_status = MTAPI_SUCCESS;
break;
default:
/* attribute unknown */
local_status = MTAPI_ERR_ATTR_NUM;
......
......@@ -29,6 +29,7 @@
#include <partest/partest.h>
#include <embb/mtapi/c/mtapi.h>
#include <embb/mtapi/c/mtapi_ext.h>
#include <embb_mtapi_log.h>
......
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb_mtapi_test_config.h>
#include <embb_mtapi_test_plugin.h>
#include <embb_mtapi_task_t.h>
#include <embb_mtapi_action_t.h>
#include <embb_mtapi_node_t.h>
#include <mtapi_status_t.h>
#include <embb/base/c/memory_allocation.h>
#include <embb/base/c/thread.h>
#include <embb/base/c/atomic.h>
#include <embb/base/c/internal/unused.h>
#define PLUGIN_JOB_ID 2
embb_thread_t plugin_thread;
embb_atomic_int plugin_running;
mtapi_task_hndl_t plugin_task;
embb_atomic_int plugin_task_available;
int plugin_thread_function(void * args) {
EMBB_UNUSED(args);
while (embb_atomic_load_int(&plugin_running)) {
/* wait for incoming task */
while (embb_atomic_load_int(&plugin_running) &&
!embb_atomic_load_int(&plugin_task_available))
embb_thread_yield();
if (embb_atomic_load_int(&plugin_running)) {
if (embb_mtapi_node_is_initialized()) {
embb_mtapi_node_t * node = embb_mtapi_node_get_instance();
if (embb_mtapi_task_pool_is_handle_valid(
node->task_pool, plugin_task)) {
embb_mtapi_task_t * local_task =
embb_mtapi_task_pool_get_storage_for_handle(
node->task_pool, plugin_task);
embb_mtapi_task_set_state(local_task, MTAPI_TASK_COMPLETED);
}
}
embb_atomic_store_int(&plugin_task_available, 0);
}
}
return 0;
}
void plugin_initialize(
MTAPI_IN mtapi_domain_t domain_id,
MTAPI_IN mtapi_node_t node_id,
MTAPI_OUT mtapi_status_t* status
) {
EMBB_UNUSED(domain_id);
EMBB_UNUSED(node_id);
mtapi_status_t local_status = MTAPI_ERR_UNKNOWN;
int err;
plugin_task.id = 0;
plugin_task.tag = 0;
embb_atomic_store_int(&plugin_running, 1);
embb_atomic_store_int(&plugin_task_available, 0);
err = embb_thread_create(&plugin_thread, NULL, plugin_thread_function, NULL);
if (EMBB_SUCCESS == err) {
local_status = MTAPI_SUCCESS;
}
mtapi_status_set(status, local_status);
}
void plugin_finalize(
MTAPI_OUT mtapi_status_t* status
) {
mtapi_status_t local_status = MTAPI_ERR_UNKNOWN;
int result = 0;
int err;
embb_atomic_store_int(&plugin_running, 0);
err = embb_thread_join(&plugin_thread, &result);
if (EMBB_SUCCESS == err) {
local_status = MTAPI_SUCCESS;
}
mtapi_status_set(status, local_status);
}
void plugin_task_start(
MTAPI_IN mtapi_task_hndl_t task,
MTAPI_OUT mtapi_status_t* status) {
mtapi_status_t local_status = MTAPI_ERR_UNKNOWN;
if (embb_mtapi_node_is_initialized()) {
embb_mtapi_node_t * node = embb_mtapi_node_get_instance();
if (embb_mtapi_task_pool_is_handle_valid(node->task_pool, task)) {
embb_mtapi_task_t * local_task =
embb_mtapi_task_pool_get_storage_for_handle(node->task_pool, task);
embb_mtapi_task_set_state(local_task, MTAPI_TASK_RUNNING);
plugin_task = task;
embb_atomic_store_int(&plugin_task_available, 1);
}
}
local_status = MTAPI_SUCCESS;
mtapi_status_set(status, local_status);
}
void plugin_task_cancel(
MTAPI_IN mtapi_task_hndl_t task,
MTAPI_OUT mtapi_status_t* status
) {
EMBB_UNUSED(task);
mtapi_status_t local_status = MTAPI_ERR_UNKNOWN;
mtapi_status_set(status, local_status);
}
void plugin_action_finalize(
MTAPI_IN mtapi_action_hndl_t action,
MTAPI_OUT mtapi_status_t* status
) {
EMBB_UNUSED(action);
mtapi_status_set(status, MTAPI_SUCCESS);
}
PluginTest::PluginTest() {
CreateUnit("mtapi plugin test").
Add(&PluginTest::TestBasic, this);
}
void PluginTest::TestBasic() {
embb_mtapi_log_info("running plugin test...\n");
mtapi_node_attributes_t node_attr;
mtapi_info_t info;
mtapi_status_t status;
mtapi_job_hndl_t job;
mtapi_action_hndl_t action;
mtapi_task_hndl_t task;
status = MTAPI_ERR_UNKNOWN;
mtapi_nodeattr_init(&node_attr, &status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
mtapi_nodeattr_set(&node_attr,
MTAPI_NODE_TYPE,
MTAPI_ATTRIBUTE_VALUE(MTAPI_NODE_TYPE_SMP),
MTAPI_ATTRIBUTE_POINTER_AS_VALUE,
&status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
mtapi_initialize(
THIS_DOMAIN_ID,
THIS_NODE_ID,
&node_attr,
&info,
&status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
plugin_initialize(THIS_DOMAIN_ID, THIS_NODE_ID, &status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
action = mtapi_ext_plugin_action_create(
PLUGIN_JOB_ID,
plugin_task_start,
plugin_task_cancel,
plugin_action_finalize,
MTAPI_NULL,
MTAPI_NULL,
0,
MTAPI_DEFAULT_ACTION_ATTRIBUTES,
&status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
job = mtapi_job_get(
PLUGIN_JOB_ID,
THIS_DOMAIN_ID,
&status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
task = mtapi_task_start(
MTAPI_TASK_ID_NONE,
job,
MTAPI_NULL, 0,
MTAPI_NULL, 0,
MTAPI_DEFAULT_TASK_ATTRIBUTES,
MTAPI_GROUP_NONE,
&status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
mtapi_task_wait(task, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
plugin_finalize(&status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
mtapi_finalize(&status);
MTAPI_CHECK_STATUS(status);
PT_EXPECT_EQ(embb_get_bytes_allocated(), 0u);
embb_mtapi_log_info("...done\n\n");
}
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_C_TEST_EMBB_MTAPI_TEST_PLUGIN_H_
#define MTAPI_C_TEST_EMBB_MTAPI_TEST_PLUGIN_H_
#include <partest/partest.h>
class PluginTest : public partest::TestCase {
public:
PluginTest();
private:
void TestBasic();
};
#endif // MTAPI_C_TEST_EMBB_MTAPI_TEST_PLUGIN_H_
......@@ -218,11 +218,11 @@ void TaskTest::TestBasic() {
mtapi_taskattr_init(&task_attr, &status);
MTAPI_CHECK_STATUS(status);
const int kTaskInstances = 5;
const mtapi_uint_t kTaskInstances = 5;
status = MTAPI_ERR_UNKNOWN;
mtapi_taskattr_set(&task_attr, MTAPI_TASK_INSTANCES,
MTAPI_ATTRIBUTE_VALUE(kTaskInstances), MTAPI_ATTRIBUTE_POINTER_AS_VALUE,
&kTaskInstances, sizeof(mtapi_uint_t),
&status);
MTAPI_CHECK_STATUS(status);
......
......@@ -31,6 +31,7 @@
#include <embb_mtapi_log.h>
#include <embb_mtapi_test_plugin.h>
#include <embb_mtapi_test_init_finalize.h>
#include <embb_mtapi_test_task.h>
#include <embb_mtapi_test_group.h>
......@@ -42,6 +43,7 @@ PT_MAIN("MTAPI C") {
embb_thread_set_max_count(1024);
PT_RUN(TaskTest);
PT_RUN(PluginTest);
PT_RUN(ErrorTest);
PT_RUN(InitFinalizeTest);
PT_RUN(GroupTest);
......
project (project_embb_mtapi_network_c)
file(GLOB_RECURSE EMBB_MTAPI_NETWORK_C_SOURCES "src/*.c" "src/*.h")
file(GLOB_RECURSE EMBB_MTAPI_NETWORK_C_HEADERS "include/*.h")
file(GLOB_RECURSE EMBB_MTAPI_NETWORK_TEST_SOURCES "test/*.cc" "test/*.h")
IF(MSVC8 OR MSVC9 OR MSVC10 OR MSVC11)
FOREACH(src_tmp ${EMBB_MTAPI_NETWORK_TEST_SOURCES})
SET_PROPERTY(SOURCE ${src_tmp} PROPERTY LANGUAGE CXX)
ENDFOREACH(src_tmp)
FOREACH(src_tmp ${EMBB_MTAPI_NETWORK_C_SOURCES})
SET_PROPERTY(SOURCE ${src_tmp} PROPERTY LANGUAGE CXX)
ENDFOREACH(src_tmp)
ENDIF()
IF(MSVC)
set (EMBB_MTAPI_NETWORK_C_LIBS ws2_32)
ENDIF()
# Execute the GroupSources macro
include(${CMAKE_SOURCE_DIR}/CMakeCommon/GroupSourcesMSVC.cmake)
GroupSourcesMSVC(include)
GroupSourcesMSVC(src)
GroupSourcesMSVC(test)
set (EMBB_MTAPI_NETWORK_INCLUDE_DIRS "include" "src" "test")
include_directories(${EMBB_MTAPI_NETWORK_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../base_c/include
${CMAKE_CURRENT_BINARY_DIR}/../base_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../mtapi_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../mtapi_c/src
)
add_library(embb_mtapi_network_c ${EMBB_MTAPI_NETWORK_C_SOURCES} ${EMBB_MTAPI_NETWORK_C_HEADERS})
target_link_libraries(embb_mtapi_network_c embb_mtapi_c embb_base_c)
if (BUILD_TESTS STREQUAL ON)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../partest/include)
add_executable (embb_mtapi_network_c_test ${EMBB_MTAPI_NETWORK_TEST_SOURCES})
target_link_libraries(embb_mtapi_network_c_test embb_mtapi_network_c embb_mtapi_c partest embb_base_c ${compiler_libs} ${EMBB_MTAPI_NETWORK_C_LIBS})
CopyBin(BIN embb_mtapi_network_c_test DEST ${local_install_dir})
endif()
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION include FILES_MATCHING PATTERN "*.h")
install(TARGETS embb_mtapi_network_c DESTINATION lib)
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef EMBB_MTAPI_C_MTAPI_NETWORK_H_
#define EMBB_MTAPI_C_MTAPI_NETWORK_H_
#include <embb/mtapi/c/mtapi_ext.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup C_MTAPI_NETWORK MTAPI Network Plugin
*
* \ingroup C_MTAPI_EXT
*
* Provides functionality to distribute tasks across nodes in a TCP/IP network.
*/
/**
* Initializes the MTAPI network environment on a previously initialized MTAPI
* node.
*
* It must be called on all nodes using the MTAPI network plugin.
*
* Application software using MTAPI network must call
* mtapi_network_plugin_initialize() once per node. It is an error to call
* mtapi_network_plugin_initialize() multiple times
* from a given node, unless mtapi_network_plugin_finalize() is called in
* between.
*
* On success, \c *status is set to \c MTAPI_SUCCESS. On error, \c *status is
* set to the appropriate error defined below.
* Error code | Description
* --------------------------- | ----------------------------------------------
* \c MTAPI_ERR_UNKNOWN | MTAPI network couldn't be initialized.
*
* \see mtapi_network_plugin_finalize()
*
* \notthreadsafe
* \ingroup C_MTAPI_NETWORK
*/
void mtapi_network_plugin_initialize(
MTAPI_IN char * host, /**< [in] The interface to listen on, if
MTAPI_NULL is given the plugin will
listen on all available
interfaces. */
MTAPI_IN mtapi_uint16_t port, /**< [in] The port to listen on. */
MTAPI_IN mtapi_uint16_t max_connections,
/**< [in] Maximum concurrent connections
accepted by the plugin. */
MTAPI_IN mtapi_size_t buffer_size, /**< [in] Capacity of the transfer
buffers, this should be chosen big
enough to hold argument and result
buffers.*/
MTAPI_OUT mtapi_status_t* status /**< [out] Pointer to error code,
may be \c MTAPI_NULL */
);
/**
* Finalizes the MTAPI network environment on the local MTAPI node.
*
* It has to be called by each node using MTAPI network. It is an error to call
* mtapi_network_plugin_finalize() without first calling
* mtapi_network_plugin_initialize(). An MTAPI node can call
* mtapi_network_plugin_finalize() once for each call to
* mtapi_network_plugin_initialize(), but it is an error to call
* mtapi_network_plugin_finalize() multiple times from a given node
* unless mtapi_network_plugin_initialize() has been called prior to each
* mtapi_network_plugin_finalize() call.
*
* All network tasks that have not completed and that have been started on the
* node where mtapi_network_plugin_finalize() is called will be canceled
* (see mtapi_task_cancel()). mtapi_network_plugin_finalize() blocks until all
* tasks that have been started on the same node return. Tasks that execute
* actions on the node where mtapi_network_plugin_finalize() is called, also
* block finalization of the MTAPI network system on that node.
*
* On success, \c *status is set to \c MTAPI_SUCCESS. On error, \c *status is
* set to the appropriate error defined below.
* Error code | Description
* ----------------------------- | --------------------------------------------
* \c MTAPI_ERR_UNKNOWN | MTAPI network couldn't be finalized.
*
* \see mtapi_network_plugin_initialize(), mtapi_task_cancel()
*
* \notthreadsafe
* \ingroup C_MTAPI_NETWORK
*/
void mtapi_network_plugin_finalize(
MTAPI_OUT mtapi_status_t* status /**< [out] Pointer to error code,
may be \c MTAPI_NULL */
);
/**
* This function creates a network action.
*
* It is called on the node where the user wants to execute an action on a
* remote node where the actual action is implemented. A network action
* contains a reference to a local job, a remote job and a remote domain as
* well as a host and port to connect to.
* After a network action is created, it is referenced by the application using
* a node-local handle of type \c mtapi_action_hndl_t, or indirectly through a
* node-local job handle of type \c mtapi_job_hndl_t. A network action's
* life-cycle begins with mtapi_network_action_create(), and ends when
* mtapi_action_delete() or mtapi_finalize() is called.
*
* To create an action, the application must supply the domain-wide job ID of
* the job associated with the action. Job IDs must be predefined in the
* application and runtime, of type \c mtapi_job_id_t, which is an
* implementation-defined type. The job ID is unique in the sense that it is
* unique for the job implemented by the action. However several actions may
* implement the same job for load balancing purposes.
*
* A network action defines no node local data, instead the node local data of
* the remote action is used. The user has to make sure that the remote node
* local data matches what he expects the remote action to use if invoked
* through the network.
*
* On success, an action handle is returned and \c *status is set to
* \c MTAPI_SUCCESS. On error, \c *status is set to the appropriate error
* defined below. In the case where the action already exists, \c status will
* be set to \c MTAPI_ERR_ACTION_EXISTS and the handle returned will not be a
* valid handle.
* <table>
* <tr>
* <th>Error code</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_JOB_INVALID</td>
* <td>The \c job_id is not a valid job ID, i.e., no action was created for
* that ID or the action has been deleted.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_ACTION_EXISTS</td>
* <td>This action is already created.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_ACTION_LIMIT</td>
* <td>Exceeded maximum number of actions allowed.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_NODE_NOTINIT</td>
* <td>The calling node is not initialized.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_UNKNOWN</td>
* <td>The remote node could not be reached or there was no local
* interface available.</td>
* </tr>
* </table>
*
* \see mtapi_action_delete(), mtapi_finalize()
*
* \returns Handle to newly created network action, invalid handle on error
* \threadsafe
* \ingroup C_MTAPI_NETWORK
*/
mtapi_action_hndl_t mtapi_network_action_create(
MTAPI_IN mtapi_domain_t domain_id, /**< [in] The domain the action is
associated with */
MTAPI_IN mtapi_job_id_t local_job_id,
/**< [in] The ID of the local job */
MTAPI_IN mtapi_job_id_t remote_job_id,
/**< [in] The ID of the remote job */
MTAPI_IN char * host, /**< [in] The host to connect to */
MTAPI_IN mtapi_uint16_t port, /**< [in] The port the host is listening
on */
MTAPI_OUT mtapi_status_t* status /**< [out] Pointer to error code,
may be \c MTAPI_NULL */
);
#ifdef __cplusplus
}
#endif
#endif // EMBB_MTAPI_C_MTAPI_NETWORK_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_NETWORK_C_SRC_EMBB_MTAPI_NETWORK_H_
#define MTAPI_NETWORK_C_SRC_EMBB_MTAPI_NETWORK_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
int embb_mtapi_network_initialize();
void embb_mtapi_network_finalize();
#ifdef __cplusplus
}
#endif
#endif // MTAPI_NETWORK_C_SRC_EMBB_MTAPI_NETWORK_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb_mtapi_network_buffer.h>
#include <embb/base/c/memory_allocation.h>
#include <string.h>
void embb_mtapi_network_buffer_initialize(
embb_mtapi_network_buffer_t * that,
int capacity) {
that->position = 0;
that->size = 0;
that->data = (char*)embb_alloc((size_t)capacity);
if (NULL != that->data) {
that->capacity = capacity;
} else {
that->capacity = 0;
}
}
void embb_mtapi_network_buffer_finalize(
embb_mtapi_network_buffer_t * that) {
that->position = 0;
that->size = 0;
that->capacity = 0;
if (NULL != that->data) {
embb_free(that->data);
that->data = NULL;
}
}
void embb_mtapi_network_buffer_clear(
embb_mtapi_network_buffer_t * that) {
that->position = 0;
that->size = 0;
}
int embb_mtapi_network_buffer_push_back_int8(
embb_mtapi_network_buffer_t * that,
int8_t value) {
if (that->size + 1 > that->capacity) {
return 0;
}
memcpy(that->data + that->size, &value, 1);
that->size += 1;
return 1;
}
int embb_mtapi_network_buffer_push_back_int16(
embb_mtapi_network_buffer_t * that,
int16_t value) {
if (that->size + 2 > that->capacity) {
return 0;
}
memcpy(that->data + that->size, &value, 2);
that->size += 2;
return 2;
}
int embb_mtapi_network_buffer_push_back_int32(
embb_mtapi_network_buffer_t * that,
int32_t value) {
if (that->size + 4 > that->capacity) {
return 0;
}
memcpy(that->data + that->size, &value, 4);
that->size += 4;
return 4;
}
int embb_mtapi_network_buffer_push_back_rawdata(
embb_mtapi_network_buffer_t * that,
int32_t size,
void const * rawdata) {
if (that->size + size > that->capacity) {
return 0;
}
memcpy(that->data + that->size, rawdata, (size_t)size);
that->size += size;
return size;
}
int embb_mtapi_network_buffer_pop_front_int8(
embb_mtapi_network_buffer_t * that,
int8_t * value) {
if (that->position + 1 > that->size) {
return 0;
}
memcpy(value, that->data + that->position, 1);
that->position += 1;
return 1;
}
int embb_mtapi_network_buffer_pop_front_int16(
embb_mtapi_network_buffer_t * that,
int16_t * value) {
if (that->position + 2 > that->size) {
return 0;
}
memcpy(value, that->data + that->position, 2);
that->position += 2;
return 2;
}
int embb_mtapi_network_buffer_pop_front_int32(
embb_mtapi_network_buffer_t * that,
int32_t * value) {
if (that->position + 4 > that->size) {
return 0;
}
memcpy(value, that->data + that->position, 4);
that->position += 4;
return 4;
}
int embb_mtapi_network_buffer_pop_front_rawdata(
embb_mtapi_network_buffer_t * that,
int32_t size,
void * rawdata) {
if (that->position + size > that->size) {
return 0;
}
memcpy(rawdata, that->data + that->position, (size_t)size);
that->position += size;
return size;
}
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_NETWORK_C_SRC_EMBB_MTAPI_NETWORK_BUFFER_H_
#define MTAPI_NETWORK_C_SRC_EMBB_MTAPI_NETWORK_BUFFER_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct embb_mtapi_network_buffer_struct {
int position;
int size;
int capacity;
char * data;
};
typedef struct embb_mtapi_network_buffer_struct embb_mtapi_network_buffer_t;
void embb_mtapi_network_buffer_initialize(
embb_mtapi_network_buffer_t * that,
int capacity
);
void embb_mtapi_network_buffer_finalize(
embb_mtapi_network_buffer_t * that
);
void embb_mtapi_network_buffer_clear(
embb_mtapi_network_buffer_t * that
);
int embb_mtapi_network_buffer_push_back_int8(
embb_mtapi_network_buffer_t * that,
int8_t value
);
int embb_mtapi_network_buffer_push_back_int16(
embb_mtapi_network_buffer_t * that,
int16_t value
);
int embb_mtapi_network_buffer_push_back_int32(
embb_mtapi_network_buffer_t * that,
int32_t value
);
int embb_mtapi_network_buffer_push_back_rawdata(
embb_mtapi_network_buffer_t * that,
int32_t size,
void const * rawdata
);
int embb_mtapi_network_buffer_pop_front_int8(
embb_mtapi_network_buffer_t * that,
int8_t * value
);
int embb_mtapi_network_buffer_pop_front_int16(
embb_mtapi_network_buffer_t * that,
int16_t * value
);
int embb_mtapi_network_buffer_pop_front_int32(
embb_mtapi_network_buffer_t * that,
int32_t * value
);
int embb_mtapi_network_buffer_pop_front_rawdata(
embb_mtapi_network_buffer_t * that,
int32_t size,
void * rawdata
);
#ifdef __cplusplus
}
#endif
#endif // MTAPI_NETWORK_C_SRC_EMBB_MTAPI_NETWORK_BUFFER_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <embb_mtapi_network_socket.h>
#include <embb/base/c/internal/config.h>
#include <string.h>
#ifdef _WIN32
#include <WinSock2.h>
#else
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#endif
int embb_mtapi_network_socket_initialize(
embb_mtapi_network_socket_t * that) {
that->handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == that->handle) {
return 0;
} else {
return 1;
}
}
void embb_mtapi_network_socket_finalize(
embb_mtapi_network_socket_t * that) {
if (INVALID_SOCKET != that->handle) {
#ifdef _WIN32
closesocket(that->handle);
#else
close(that->handle);
#endif
that->handle = INVALID_SOCKET;
}
}
int embb_mtapi_network_socket_bind_and_listen(
embb_mtapi_network_socket_t * that,
char const * host,
uint16_t port,
uint16_t max_connections) {
struct sockaddr_in in_addr;
int reuseaddr_on = 1;
// addr reuse
if (SOCKET_ERROR == setsockopt(that->handle, SOL_SOCKET, SO_REUSEADDR,
(const char *)&reuseaddr_on, sizeof(reuseaddr_on))) {
return 0;
}
// bind & listen
memset(&in_addr, 0, sizeof(in_addr));
in_addr.sin_family = AF_INET;
in_addr.sin_addr.s_addr = (NULL == host) ?
htonl(INADDR_ANY) : inet_addr(host);
in_addr.sin_port = htons(port);
if (SOCKET_ERROR == bind(that->handle, (struct sockaddr *) &in_addr,
sizeof(in_addr))) {
return 0;
}
if (SOCKET_ERROR == listen(that->handle, max_connections)) {
return 0;
}
return 1;
}
int embb_mtapi_network_socket_accept(
embb_mtapi_network_socket_t * that,
embb_mtapi_network_socket_t * sock) {
sock->handle = accept(that->handle, NULL, NULL);
if (INVALID_SOCKET == sock->handle) {
return 0;
} else {
return 1;
}
}
int embb_mtapi_network_socket_connect(
embb_mtapi_network_socket_t * that,
const char * host,
uint16_t port) {
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(host);
addr.sin_port = htons(port);
if (SOCKET_ERROR == connect(that->handle, (struct sockaddr *)&addr,
sizeof(addr))) {
#ifdef _WIN32
if (WSAEWOULDBLOCK != WSAGetLastError())
#else
if (EAGAIN != errno)
#endif
return 0;
}
return 1;
}
int embb_mtapi_network_socket_select(
embb_mtapi_network_socket_t * sockets,
int count,
int timeout
) {
fd_set read_set;
embb_mtapi_network_socket_t max_fd = { 0 };
int err;
int ii;
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = timeout % 1000;
FD_ZERO(&read_set);
for (ii = 0; ii < count; ii++) {
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(push)
#pragma warning(disable: 4548)
#endif
FD_SET(sockets[ii].handle, &read_set);
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(pop)
#endif
if (sockets[ii].handle > max_fd.handle)
max_fd.handle = sockets[ii].handle;
}
if (timeout >= 0) {
err = select((int)max_fd.handle + 1, &read_set, NULL, NULL, &tv);
} else {
err = select((int)max_fd.handle + 1, &read_set, NULL, NULL, NULL);
}
if (0 == err) {
// timeout
return -1;
}
if (SOCKET_ERROR == err) {
return -1;
}
for (ii = 0; ii < count; ii++) {
if (FD_ISSET(sockets[ii].handle, &read_set)) {
return ii;
}
}
return -1;
}
int embb_mtapi_network_socket_sendbuffer(
embb_mtapi_network_socket_t * that,
embb_mtapi_network_buffer_t * buffer) {
char * buf = (char*)(buffer->data);
int cnt = 0;
int result = send(that->handle, buf, buffer->size, 0);
while (result > 0) {
buf += result;
cnt += result;
if (cnt == buffer->size)
break;
result = send(that->handle, buf, buffer->size - cnt, 0);
}
if (cnt == buffer->size) {
return buffer->size;
} else {
return 0;
}
}
int embb_mtapi_network_socket_recvbuffer_sized(
embb_mtapi_network_socket_t * that,
embb_mtapi_network_buffer_t * buffer,
int size) {
int err;
/*
#ifdef _WIN32
u_long bytes_available = 0;
if (0 != ioctlsocket(that->handle, FIONREAD, &bytes_available))
#else
int bytes_available = 0;
if (0 != ioctl(that->handle, FIONREAD, &bytes_available))
#endif
return 0;
*/
if (buffer->capacity < size)
return 0;
/*
if (size > (int)bytes_available)
return 0;
*/
if (0 < size) {
char * buf = (char*)(buffer->data);
int cnt = 0;
err = recv(that->handle, buf, size, 0);
while (err > 0) {
cnt += err;
if (cnt == size)
break;
buf += err;
err = recv(that->handle, buf, size - cnt, 0);
}
if (err > 0)
err = cnt;
} else {
err = 0;
}
if (err != size)
return 0;
buffer->size = size;
return buffer->size;
}
int embb_mtapi_network_socket_recvbuffer(
embb_mtapi_network_socket_t * that,
embb_mtapi_network_buffer_t * buffer) {
return
embb_mtapi_network_socket_recvbuffer_sized(that, buffer, buffer->capacity);
}
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_NETWORK_C_SRC_EMBB_MTAPI_NETWORK_SOCKET_H_
#define MTAPI_NETWORK_C_SRC_EMBB_MTAPI_NETWORK_SOCKET_H_
#include <stdint.h>
#include <embb_mtapi_network_buffer.h>
#ifdef __cplusplus
extern "C" {
#endif
struct embb_mtapi_network_socket_struct {
#ifdef _WIN32
# ifdef _WIN64
uint64_t handle;
# else
uint32_t handle;
# endif
#else
int handle;
#endif
};
typedef struct embb_mtapi_network_socket_struct embb_mtapi_network_socket_t;
int embb_mtapi_network_socket_initialize(
embb_mtapi_network_socket_t * that
);
void embb_mtapi_network_socket_finalize(
embb_mtapi_network_socket_t * that
);
int embb_mtapi_network_socket_bind_and_listen(
embb_mtapi_network_socket_t * that,
char const * host,
uint16_t port,
uint16_t max_connections
);
int embb_mtapi_network_socket_accept(
embb_mtapi_network_socket_t * that,
embb_mtapi_network_socket_t * sock
);
int embb_mtapi_network_socket_connect(
embb_mtapi_network_socket_t * that,
const char * host,
uint16_t port
);
int embb_mtapi_network_socket_select(
embb_mtapi_network_socket_t * sockets,
int count,
int timeout
);
int embb_mtapi_network_socket_sendbuffer(
embb_mtapi_network_socket_t * that,
embb_mtapi_network_buffer_t * buffer
);
int embb_mtapi_network_socket_recvbuffer(
embb_mtapi_network_socket_t * that,
embb_mtapi_network_buffer_t * buffer
);
int embb_mtapi_network_socket_recvbuffer_sized(
embb_mtapi_network_socket_t * that,
embb_mtapi_network_buffer_t * buffer,
int size
);
#ifdef __cplusplus
}
#endif
#endif // MTAPI_NETWORK_C_SRC_EMBB_MTAPI_NETWORK_SOCKET_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb_mtapi_network_test_buffer.h>
#include <embb_mtapi_network_buffer.h>
#include <embb/base/c/memory_allocation.h>
NetworkBufferTest::NetworkBufferTest() {
CreateUnit("mtapi network buffer test").Add(
&NetworkBufferTest::TestBasic, this);
}
void NetworkBufferTest::TestBasic() {
embb_mtapi_network_buffer_t buffer;
int err;
embb_mtapi_network_buffer_initialize(&buffer, 1024);
err = embb_mtapi_network_buffer_push_back_int8(&buffer, -1);
PT_EXPECT(err == 1);
err = embb_mtapi_network_buffer_push_back_int16(&buffer, -2);
PT_EXPECT(err == 2);
int8_t val8 = 0;
err = embb_mtapi_network_buffer_pop_front_int8(&buffer, &val8);
PT_EXPECT(err == 1);
PT_EXPECT(val8 == -1);
int32_t val32 = 0;
err = embb_mtapi_network_buffer_pop_front_int32(&buffer, &val32);
PT_EXPECT(err == 0);
PT_EXPECT(val32 == 0);
int16_t val16 = 0;
err = embb_mtapi_network_buffer_pop_front_int16(&buffer, &val16);
PT_EXPECT(err == 2);
PT_EXPECT(val16 == -2);
embb_mtapi_network_buffer_finalize(&buffer);
PT_EXPECT(embb_get_bytes_allocated() == 0);
}
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_NETWORK_C_TEST_EMBB_MTAPI_NETWORK_TEST_BUFFER_H_
#define MTAPI_NETWORK_C_TEST_EMBB_MTAPI_NETWORK_TEST_BUFFER_H_
#include <partest/partest.h>
class NetworkBufferTest : public partest::TestCase {
public:
NetworkBufferTest();
private:
void TestBasic();
};
#endif // MTAPI_NETWORK_C_TEST_EMBB_MTAPI_NETWORK_TEST_BUFFER_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb_mtapi_network_test_socket.h>
#include <embb_mtapi_network.h>
#include <embb_mtapi_network_socket.h>
#include <embb/base/c/memory_allocation.h>
NetworkSocketTest::NetworkSocketTest() {
CreateUnit("mtapi network socket test").Add(
&NetworkSocketTest::TestBasic, this);
}
void NetworkSocketTest::TestBasic() {
int err;
embb_mtapi_network_socket_t server_sock;
embb_mtapi_network_socket_t accept_sock;
embb_mtapi_network_socket_t client_sock;
embb_mtapi_network_buffer_t send_buffer;
embb_mtapi_network_buffer_t recv_buffer;
embb_mtapi_network_buffer_initialize(&send_buffer, 4);
embb_mtapi_network_buffer_initialize(&recv_buffer, 4);
err = embb_mtapi_network_initialize();
PT_EXPECT(err != 0);
err = embb_mtapi_network_socket_initialize(&server_sock);
PT_EXPECT(err != 0);
err = embb_mtapi_network_socket_bind_and_listen(
&server_sock, "127.0.0.1", 4711, 5);
PT_EXPECT(err != 0);
err = embb_mtapi_network_socket_select(&server_sock, 1, 1);
PT_EXPECT(err == -1);
err = embb_mtapi_network_socket_initialize(&client_sock);
PT_EXPECT(err != 0);
err = embb_mtapi_network_socket_connect(&client_sock, "127.0.0.1", 4711);
PT_EXPECT(err != 0);
err = embb_mtapi_network_socket_select(&server_sock, 1, -1);
PT_EXPECT(err == 0);
err = embb_mtapi_network_socket_accept(&server_sock, &accept_sock);
PT_EXPECT(err != 0);
err = embb_mtapi_network_socket_select(&accept_sock, 1, 1);
PT_EXPECT(err == -1);
err = embb_mtapi_network_buffer_push_back_int32(&send_buffer, 0x12345678);
PT_EXPECT(err == 4);
err = embb_mtapi_network_socket_sendbuffer(&client_sock, &send_buffer);
PT_EXPECT(err == 4);
err = embb_mtapi_network_socket_select(&accept_sock, 1, -1);
PT_EXPECT(err == 0);
err = embb_mtapi_network_socket_recvbuffer(&accept_sock, &recv_buffer);
PT_EXPECT(err == 4);
int32_t result = 0;
err = embb_mtapi_network_buffer_pop_front_int32(&recv_buffer, &result);
PT_EXPECT(err == 4);
PT_EXPECT(result == 0x12345678);
embb_mtapi_network_socket_finalize(&accept_sock);
embb_mtapi_network_socket_finalize(&client_sock);
embb_mtapi_network_socket_finalize(&server_sock);
embb_mtapi_network_buffer_finalize(&recv_buffer);
embb_mtapi_network_buffer_finalize(&send_buffer);
embb_mtapi_network_finalize();
PT_EXPECT(embb_get_bytes_allocated() == 0);
}
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_NETWORK_C_TEST_EMBB_MTAPI_NETWORK_TEST_SOCKET_H_
#define MTAPI_NETWORK_C_TEST_EMBB_MTAPI_NETWORK_TEST_SOCKET_H_
#include <partest/partest.h>
class NetworkSocketTest : public partest::TestCase {
public:
NetworkSocketTest();
private:
void TestBasic();
};
#endif // MTAPI_NETWORK_C_TEST_EMBB_MTAPI_NETWORK_TEST_SOCKET_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb_mtapi_network_test_task.h>
#include <embb/mtapi/c/mtapi_ext.h>
#include <embb/mtapi/c/mtapi_network.h>
#include <embb/base/c/internal/unused.h>
#define MTAPI_CHECK_STATUS(status) PT_ASSERT(MTAPI_SUCCESS == status)
#define NETWORK_DOMAIN 1
#define NETWORK_LOCAL_NODE 3
#define NETWORK_LOCAL_JOB 3
#define NETWORK_REMOTE_NODE 3
#define NETWORK_REMOTE_JOB 4
static void test(
void const * arguments,
mtapi_size_t arguments_size,
void * result_buffer,
mtapi_size_t result_buffer_size,
void const * node_local_data,
mtapi_size_t node_local_data_size,
mtapi_task_context_t * context) {
EMBB_UNUSED(context);
EMBB_UNUSED(result_buffer_size);
EMBB_UNUSED(node_local_data_size);
int elements = static_cast<int>(arguments_size / sizeof(float) / 2);
float const * a = reinterpret_cast<float const *>(arguments);
float const * b = reinterpret_cast<float const *>(arguments)+elements;
float * c = reinterpret_cast<float*>(result_buffer);
float const * d = reinterpret_cast<float const *>(node_local_data);
for (int ii = 0; ii < elements; ii++) {
c[ii] = a[ii] + b[ii] + d[0];
}
}
NetworkTaskTest::NetworkTaskTest() {
CreateUnit("mtapi network task test").Add(&NetworkTaskTest::TestBasic, this);
}
void NetworkTaskTest::TestBasic() {
mtapi_status_t status;
mtapi_job_hndl_t job;
mtapi_task_hndl_t task;
mtapi_action_hndl_t network_action, local_action;
const int kElements = 64;
float arguments[kElements * 2];
float results[kElements];
for (int ii = 0; ii < kElements; ii++) {
arguments[ii] = static_cast<float>(ii);
arguments[ii + kElements] = static_cast<float>(ii);
}
mtapi_initialize(
NETWORK_DOMAIN,
NETWORK_LOCAL_NODE,
MTAPI_NULL,
MTAPI_NULL,
&status);
MTAPI_CHECK_STATUS(status);
mtapi_network_plugin_initialize("127.0.0.1", 12345, 5,
kElements * 4 * 3 + 32, &status);
MTAPI_CHECK_STATUS(status);
float node_remote = 1.0f;
local_action = mtapi_action_create(
NETWORK_REMOTE_JOB,
test,
&node_remote, sizeof(float),
MTAPI_DEFAULT_ACTION_ATTRIBUTES,
&status);
MTAPI_CHECK_STATUS(status);
network_action = mtapi_network_action_create(
NETWORK_DOMAIN,
NETWORK_LOCAL_JOB,
NETWORK_REMOTE_JOB,
"127.0.0.1", 12345,
&status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
job = mtapi_job_get(NETWORK_LOCAL_JOB, NETWORK_DOMAIN, &status);
MTAPI_CHECK_STATUS(status);
task = mtapi_task_start(
MTAPI_TASK_ID_NONE,
job,
arguments, kElements * 2 * sizeof(float),
results, kElements*sizeof(float),
MTAPI_DEFAULT_TASK_ATTRIBUTES,
MTAPI_GROUP_NONE,
&status);
MTAPI_CHECK_STATUS(status);
mtapi_task_wait(task, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
for (int ii = 0; ii < kElements; ii++) {
PT_EXPECT_EQ(results[ii], ii * 2 + 1);
}
mtapi_action_delete(network_action, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
mtapi_action_delete(local_action, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
mtapi_network_plugin_finalize(&status);
MTAPI_CHECK_STATUS(status);
mtapi_finalize(&status);
MTAPI_CHECK_STATUS(status);
}
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_NETWORK_C_TEST_EMBB_MTAPI_NETWORK_TEST_TASK_H_
#define MTAPI_NETWORK_C_TEST_EMBB_MTAPI_NETWORK_TEST_TASK_H_
#include <partest/partest.h>
class NetworkTaskTest : public partest::TestCase {
public:
NetworkTaskTest();
private:
void TestBasic();
};
#endif // MTAPI_NETWORK_C_TEST_EMBB_MTAPI_NETWORK_TEST_TASK_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <partest/partest.h>
#include <embb_mtapi_network_test_buffer.h>
#include <embb_mtapi_network_test_socket.h>
#include <embb_mtapi_network_test_task.h>
PT_MAIN("MTAPI NETWORK") {
PT_RUN(NetworkBufferTest);
PT_RUN(NetworkSocketTest);
PT_RUN(NetworkTaskTest);
}
project (project_embb_mtapi_opencl_c)
file(GLOB_RECURSE EMBB_MTAPI_OPENCL_C_SOURCES "src/*.c" "src/*.h")
file(GLOB_RECURSE EMBB_MTAPI_OPENCL_C_HEADERS "include/*.h")
file(GLOB_RECURSE EMBB_MTAPI_OPENCL_TEST_SOURCES "test/*.cc" "test/*.h")
IF(MSVC8 OR MSVC9 OR MSVC10 OR MSVC11)
FOREACH(src_tmp ${EMBB_MTAPI_OPENCL_TEST_SOURCES})
SET_PROPERTY(SOURCE ${src_tmp} PROPERTY LANGUAGE CXX)
ENDFOREACH(src_tmp)
FOREACH(src_tmp ${EMBB_MTAPI_OPENCL_C_SOURCES})
SET_PROPERTY(SOURCE ${src_tmp} PROPERTY LANGUAGE CXX)
ENDFOREACH(src_tmp)
ENDIF()
IF(CMAKE_COMPILER_IS_GNUCC)
set (EMBB_MTAPI_OPENCL_C_LIBS dl)
ENDIF()
# Execute the GroupSources macro
include(${CMAKE_SOURCE_DIR}/CMakeCommon/GroupSourcesMSVC.cmake)
GroupSourcesMSVC(include)
GroupSourcesMSVC(src)
GroupSourcesMSVC(test)
set (EMBB_MTAPI_OPENCL_INCLUDE_DIRS "include" "src" "test")
include_directories(${EMBB_MTAPI_OPENCL_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../base_c/include
${CMAKE_CURRENT_BINARY_DIR}/../base_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../mtapi_c/include
${CMAKE_CURRENT_SOURCE_DIR}/../mtapi_c/src
)
add_library(embb_mtapi_opencl_c ${EMBB_MTAPI_OPENCL_C_SOURCES} ${EMBB_MTAPI_OPENCL_C_HEADERS})
target_link_libraries(embb_mtapi_opencl_c embb_mtapi_c embb_base_c)
if (BUILD_TESTS STREQUAL ON)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../partest/include)
add_executable (embb_mtapi_opencl_c_test ${EMBB_MTAPI_OPENCL_TEST_SOURCES})
target_link_libraries(embb_mtapi_opencl_c_test embb_mtapi_opencl_c embb_mtapi_c partest embb_base_c ${compiler_libs} ${EMBB_MTAPI_OPENCL_C_LIBS})
CopyBin(BIN embb_mtapi_opencl_c_test DEST ${local_install_dir})
endif()
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION include FILES_MATCHING PATTERN "*.h")
install(TARGETS embb_mtapi_opencl_c DESTINATION lib)
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef EMBB_MTAPI_C_MTAPI_OPENCL_H_
#define EMBB_MTAPI_C_MTAPI_OPENCL_H_
#include <embb/mtapi/c/mtapi_ext.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup C_MTAPI_OPENCL MTAPI OpenCL Plugin
*
* \ingroup C_MTAPI_EXT
*
* Provides functionality to execute tasks on OpenCL devices.
*/
/**
* Initializes the MTAPI OpenCL environment on a previously initialized MTAPI
* node.
*
* It must be called on all nodes using the MTAPI OpenCL plugin.
*
* Application software using MTAPI network must call
* mtapi_opencl_plugin_initialize() once per node. It is an error to call
* mtapi_opencl_plugin_initialize() multiple times
* from a given node, unless mtapi_opencl_plugin_finalize() is called in
* between.
*
* On success, \c *status is set to \c MTAPI_SUCCESS. On error, \c *status is
* set to the appropriate error defined below.
* Error code | Description
* --------------------------- | ----------------------------------------------
* \c MTAPI_ERR_UNKNOWN | MTAPI OpenCL couldn't be initialized.
*
* \see mtapi_opencl_plugin_finalize()
*
* \notthreadsafe
* \ingroup C_MTAPI_OPENCL
*/
void mtapi_opencl_plugin_initialize(
MTAPI_OUT mtapi_status_t* status /**< [out] Pointer to error code,
may be \c MTAPI_NULL */
);
/**
* Finalizes the MTAPI OpenCL environment on the local MTAPI node.
*
* It has to be called by each node using MTAPI OpenCL. It is an error to call
* mtapi_opencl_plugin_finalize() without first calling
* mtapi_opencl_plugin_initialize(). An MTAPI node can call
* mtapi_opencl_plugin_finalize() once for each call to
* mtapi_opencl_plugin_initialize(), but it is an error to call
* mtapi_opencl_plugin_finalize() multiple times from a given node
* unless mtapi_opencl_plugin_initialize() has been called prior to each
* mtapi_opencl_plugin_finalize() call.
*
* All network tasks that have not completed and that have been started on the
* node where mtapi_opencl_plugin_finalize() is called will be canceled
* (see mtapi_task_cancel()). mtapi_opencl_plugin_finalize() blocks until all
* tasks that have been started on the same node return. Tasks that execute
* actions on the node where mtapi_opencl_plugin_finalize() is called, also
* block finalization of the MTAPI OpenCL system on that node.
*
* On success, \c *status is set to \c MTAPI_SUCCESS. On error, \c *status is
* set to the appropriate error defined below.
* Error code | Description
* ----------------------------- | --------------------------------------------
* \c MTAPI_ERR_UNKNOWN | MTAPI OpenCL couldn't be finalized.
*
* \see mtapi_opencl_plugin_initialize(), mtapi_task_cancel()
*
* \notthreadsafe
* \ingroup C_MTAPI_OPENCL
*/
void mtapi_opencl_plugin_finalize(
MTAPI_OUT mtapi_status_t* status /**< [out] Pointer to error code,
may be \c MTAPI_NULL */
);
/**
* This function creates an OpenCL action.
*
* It is called on the node where the user wants to execute an action on an
* OpenCL device. An OpenCL action contains a reference to a local job, the
* kernel source to compile and execute on the OpenCL device, the name of the
* kernel function, a local work size (see OpenCL specification for details)
* and the size of one element in the result buffer.
* After an OpenCL action is created, it is referenced by the application using
* a node-local handle of type \c mtapi_action_hndl_t, or indirectly through a
* node-local job handle of type \c mtapi_job_hndl_t. An OpenCL action's
* life-cycle begins with mtapi_opencl_action_create(), and ends when
* mtapi_action_delete() or mtapi_finalize() is called.
*
* To create an action, the application must supply the domain-wide job ID of
* the job associated with the action. Job IDs must be predefined in the
* application and runtime, of type \c mtapi_job_id_t, which is an
* implementation-defined type. The job ID is unique in the sense that it is
* unique for the job implemented by the action. However several actions may
* implement the same job for load balancing purposes.
*
* If \c node_local_data_size is not zero, \c node_local_data specifies the
* start of node local data shared by kernel functions executed on the same
* node. \c node_local_data_size can be used by the runtime for cache coherency
* operations.
*
* On success, an action handle is returned and \c *status is set to
* \c MTAPI_SUCCESS. On error, \c *status is set to the appropriate error
* defined below. In the case where the action already exists, \c status will
* be set to \c MTAPI_ERR_ACTION_EXISTS and the handle returned will not be a
* valid handle.
* <table>
* <tr>
* <th>Error code</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_JOB_INVALID</td>
* <td>The \c job_id is not a valid job ID, i.e., no action was created for
* that ID or the action has been deleted.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_ACTION_EXISTS</td>
* <td>This action is already created.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_ACTION_LIMIT</td>
* <td>Exceeded maximum number of actions allowed.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_NODE_NOTINIT</td>
* <td>The calling node is not initialized.</td>
* </tr>
* <tr>
* <td>\c MTAPI_ERR_UNKNOWN</td>
* <td>The kernel could not be compiled or no OpenCL device was
* available.</td>
* </tr>
* </table>
*
* \see mtapi_action_delete(), mtapi_finalize()
*
* \returns Handle to newly created OpenCL action, invalid handle on error
* \threadsafe
* \ingroup C_MTAPI_OPENCL
*/
mtapi_action_hndl_t mtapi_opencl_action_create(
MTAPI_IN mtapi_job_id_t job_id, /**< [in] Job id */
MTAPI_IN char* kernel_source, /**< [in] Pointer to kernel source */
MTAPI_IN char* kernel_name, /**< [in] Name of the kernel function */
MTAPI_IN mtapi_size_t local_work_size,
/**< [in] Size of local work group */
MTAPI_IN mtapi_size_t element_size, /**< [in] Size of one element in the
result buffer */
MTAPI_IN void* node_local_data, /**< [in] Data shared across tasks */
MTAPI_IN mtapi_size_t node_local_data_size,
/**< [in] Size of shared data */
MTAPI_OUT mtapi_status_t* status /**< [out] Pointer to error code,
may be \c MTAPI_NULL */
);
#ifdef __cplusplus
}
#endif
#endif // EMBB_MTAPI_C_MTAPI_OPENCL_H_
/*******************************************************************************
* Copyright (c) 2008-2010 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and/or associated documentation files (the
* "Materials"), to deal in the Materials without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Materials, and to
* permit persons to whom the Materials are furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
******************************************************************************/
/* $Revision: 11687 $ on $Date: 2010-06-12 03:47:22 +0530 (Sat, 12 Jun 2010) $ */
/* cl_ext.h contains OpenCL extensions which don't have external */
/* (OpenGL, D3D) dependencies. */
#ifndef __CL_EXT_H
#define __CL_EXT_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __APPLE__
#include <OpenCL/cl.h>
#include <AvailabilityMacros.h>
#else
#include <CL/cl.h>
#endif
/* cl_khr_fp64 extension - no extension #define since it has no functions */
#define CL_DEVICE_DOUBLE_FP_CONFIG 0x1032
/* cl_khr_fp16 extension - no extension #define since it has no functions */
#define CL_DEVICE_HALF_FP_CONFIG 0x1033
/* Memory object destruction
*
* Apple extension for use to manage externally allocated buffers used with cl_mem objects with CL_MEM_USE_HOST_PTR
*
* Registers a user callback function that will be called when the memory object is deleted and its resources
* freed. Each call to clSetMemObjectCallbackFn registers the specified user callback function on a callback
* stack associated with memobj. The registered user callback functions are called in the reverse order in
* which they were registered. The user callback functions are called and then the memory object is deleted
* and its resources freed. This provides a mechanism for the application (and libraries) using memobj to be
* notified when the memory referenced by host_ptr, specified when the memory object is created and used as
* the storage bits for the memory object, can be reused or freed.
*
* The application may not call CL api's with the cl_mem object passed to the pfn_notify.
*
* Please check for the "cl_APPLE_SetMemObjectDestructor" extension using clGetDeviceInfo(CL_DEVICE_EXTENSIONS)
* before using.
*/
#define cl_APPLE_SetMemObjectDestructor 1
cl_int CL_API_ENTRY clSetMemObjectDestructorAPPLE( cl_mem /* memobj */,
void (* /*pfn_notify*/)( cl_mem /* memobj */, void* /*user_data*/),
void * /*user_data */ ) CL_EXT_SUFFIX__VERSION_1_0;
/* Context Logging Functions
*
* The next three convenience functions are intended to be used as the pfn_notify parameter to clCreateContext().
* Please check for the "cl_APPLE_ContextLoggingFunctions" extension using clGetDeviceInfo(CL_DEVICE_EXTENSIONS)
* before using.
*
* clLogMessagesToSystemLog fowards on all log messages to the Apple System Logger
*/
#define cl_APPLE_ContextLoggingFunctions 1
extern void CL_API_ENTRY clLogMessagesToSystemLogAPPLE( const char * /* errstr */,
const void * /* private_info */,
size_t /* cb */,
void * /* user_data */ ) CL_EXT_SUFFIX__VERSION_1_0;
/* clLogMessagesToStdout sends all log messages to the file descriptor stdout */
extern void CL_API_ENTRY clLogMessagesToStdoutAPPLE( const char * /* errstr */,
const void * /* private_info */,
size_t /* cb */,
void * /* user_data */ ) CL_EXT_SUFFIX__VERSION_1_0;
/* clLogMessagesToStderr sends all log messages to the file descriptor stderr */
extern void CL_API_ENTRY clLogMessagesToStderrAPPLE( const char * /* errstr */,
const void * /* private_info */,
size_t /* cb */,
void * /* user_data */ ) CL_EXT_SUFFIX__VERSION_1_0;
/************************
* cl_khr_icd extension *
************************/
#define cl_khr_icd 1
/* cl_platform_info */
#define CL_PLATFORM_ICD_SUFFIX_KHR 0x0920
/* Additional Error Codes */
#define CL_PLATFORM_NOT_FOUND_KHR -1001
extern CL_API_ENTRY cl_int CL_API_CALL
clIcdGetPlatformIDsKHR(cl_uint /* num_entries */,
cl_platform_id * /* platforms */,
cl_uint * /* num_platforms */);
typedef CL_API_ENTRY cl_int (CL_API_CALL *clIcdGetPlatformIDsKHR_fn)(
cl_uint /* num_entries */,
cl_platform_id * /* platforms */,
cl_uint * /* num_platforms */);
/******************************************
* cl_nv_device_attribute_query extension *
******************************************/
/* cl_nv_device_attribute_query extension - no extension #define since it has no functions */
#define CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 0x4000
#define CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 0x4001
#define CL_DEVICE_REGISTERS_PER_BLOCK_NV 0x4002
#define CL_DEVICE_WARP_SIZE_NV 0x4003
#define CL_DEVICE_GPU_OVERLAP_NV 0x4004
#define CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 0x4005
#define CL_DEVICE_INTEGRATED_MEMORY_NV 0x4006
/*********************************
* cl_amd_device_attribute_query *
*********************************/
#define CL_DEVICE_PROFILING_TIMER_OFFSET_AMD 0x4036
#ifdef CL_VERSION_1_1
/***********************************
* cl_ext_device_fission extension *
***********************************/
#define cl_ext_device_fission 1
extern CL_API_ENTRY cl_int CL_API_CALL
clReleaseDeviceEXT( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1;
typedef CL_API_ENTRY cl_int
(CL_API_CALL *clReleaseDeviceEXT_fn)( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1;
extern CL_API_ENTRY cl_int CL_API_CALL
clRetainDeviceEXT( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1;
typedef CL_API_ENTRY cl_int
(CL_API_CALL *clRetainDeviceEXT_fn)( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1;
typedef cl_ulong cl_device_partition_property_ext;
extern CL_API_ENTRY cl_int CL_API_CALL
clCreateSubDevicesEXT( cl_device_id /*in_device*/,
const cl_device_partition_property_ext * /* properties */,
cl_uint /*num_entries*/,
cl_device_id * /*out_devices*/,
cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1;
extern CL_API_ENTRY cl_int
( CL_API_CALL * clCreateSubDevicesEXT_fn)( cl_device_id /*in_device*/,
const cl_device_partition_property_ext * /* properties */,
cl_uint /*num_entries*/,
cl_device_id * /*out_devices*/,
cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1;
/* cl_device_partition_property_ext */
#define CL_DEVICE_PARTITION_EQUALLY_EXT 0x4050
#define CL_DEVICE_PARTITION_BY_COUNTS_EXT 0x4051
#define CL_DEVICE_PARTITION_BY_NAMES_EXT 0x4052
#define CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN_EXT 0x4053
/* clDeviceGetInfo selectors */
#define CL_DEVICE_PARENT_DEVICE_EXT 0x4054
#define CL_DEVICE_PARTITION_TYPES_EXT 0x4055
#define CL_DEVICE_AFFINITY_DOMAINS_EXT 0x4056
#define CL_DEVICE_REFERENCE_COUNT_EXT 0x4057
#define CL_DEVICE_PARTITION_STYLE_EXT 0x4058
/* error codes */
#define CL_DEVICE_PARTITION_FAILED_EXT -1057
#define CL_INVALID_PARTITION_COUNT_EXT -1058
#define CL_INVALID_PARTITION_NAME_EXT -1059
/* CL_AFFINITY_DOMAINs */
#define CL_AFFINITY_DOMAIN_L1_CACHE_EXT 0x1
#define CL_AFFINITY_DOMAIN_L2_CACHE_EXT 0x2
#define CL_AFFINITY_DOMAIN_L3_CACHE_EXT 0x3
#define CL_AFFINITY_DOMAIN_L4_CACHE_EXT 0x4
#define CL_AFFINITY_DOMAIN_NUMA_EXT 0x10
#define CL_AFFINITY_DOMAIN_NEXT_FISSIONABLE_EXT 0x100
/* cl_device_partition_property_ext list terminators */
#define CL_PROPERTIES_LIST_END_EXT ((cl_device_partition_property_ext) 0)
#define CL_PARTITION_BY_COUNTS_LIST_END_EXT ((cl_device_partition_property_ext) 0)
#define CL_PARTITION_BY_NAMES_LIST_END_EXT ((cl_device_partition_property_ext) 0 - 1)
#endif /* CL_VERSION_1_1 */
#ifdef __cplusplus
}
#endif
#endif /* __CL_EXT_H */
/**********************************************************************************
* Copyright (c) 2008-2010 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and/or associated documentation files (the
* "Materials"), to deal in the Materials without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Materials, and to
* permit persons to whom the Materials are furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
**********************************************************************************/
/* $Revision: 11708 $ on $Date: 2010-06-14 12:06:24 +0530 (Mon, 14 Jun 2010) $ */
/*
* cl_gl.h contains Khronos-approved (KHR) OpenCL extensions which have
* OpenGL dependencies. The application is responsible for #including
* OpenGL or OpenGL ES headers before #including cl_gl.h.
*/
#ifndef __OPENCL_CL_GL_H
#define __OPENCL_CL_GL_H
#ifdef __APPLE__
#include <OpenCL/cl.h>
#include <OpenGL/CGLDevice.h>
#else
#include <CL/cl.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef cl_uint cl_gl_object_type;
typedef cl_uint cl_gl_texture_info;
typedef cl_uint cl_gl_platform_info;
typedef struct __GLsync *cl_GLsync;
/* cl_gl_object_type */
#define CL_GL_OBJECT_BUFFER 0x2000
#define CL_GL_OBJECT_TEXTURE2D 0x2001
#define CL_GL_OBJECT_TEXTURE3D 0x2002
#define CL_GL_OBJECT_RENDERBUFFER 0x2003
/* cl_gl_texture_info */
#define CL_GL_TEXTURE_TARGET 0x2004
#define CL_GL_MIPMAP_LEVEL 0x2005
extern CL_API_ENTRY cl_mem CL_API_CALL
clCreateFromGLBuffer(cl_context /* context */,
cl_mem_flags /* flags */,
cl_GLuint /* bufobj */,
int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
extern CL_API_ENTRY cl_mem CL_API_CALL
clCreateFromGLTexture2D(cl_context /* context */,
cl_mem_flags /* flags */,
cl_GLenum /* target */,
cl_GLint /* miplevel */,
cl_GLuint /* texture */,
cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
extern CL_API_ENTRY cl_mem CL_API_CALL
clCreateFromGLTexture3D(cl_context /* context */,
cl_mem_flags /* flags */,
cl_GLenum /* target */,
cl_GLint /* miplevel */,
cl_GLuint /* texture */,
cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
extern CL_API_ENTRY cl_mem CL_API_CALL
clCreateFromGLRenderbuffer(cl_context /* context */,
cl_mem_flags /* flags */,
cl_GLuint /* renderbuffer */,
cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
extern CL_API_ENTRY cl_int CL_API_CALL
clGetGLObjectInfo(cl_mem /* memobj */,
cl_gl_object_type * /* gl_object_type */,
cl_GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0;
extern CL_API_ENTRY cl_int CL_API_CALL
clGetGLTextureInfo(cl_mem /* memobj */,
cl_gl_texture_info /* param_name */,
size_t /* param_value_size */,
void * /* param_value */,
size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
extern CL_API_ENTRY cl_int CL_API_CALL
clEnqueueAcquireGLObjects(cl_command_queue /* command_queue */,
cl_uint /* num_objects */,
const cl_mem * /* mem_objects */,
cl_uint /* num_events_in_wait_list */,
const cl_event * /* event_wait_list */,
cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
extern CL_API_ENTRY cl_int CL_API_CALL
clEnqueueReleaseGLObjects(cl_command_queue /* command_queue */,
cl_uint /* num_objects */,
const cl_mem * /* mem_objects */,
cl_uint /* num_events_in_wait_list */,
const cl_event * /* event_wait_list */,
cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
/* cl_khr_gl_sharing extension */
#define cl_khr_gl_sharing 1
typedef cl_uint cl_gl_context_info;
/* Additional Error Codes */
#define CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000
/* cl_gl_context_info */
#define CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x2006
#define CL_DEVICES_FOR_GL_CONTEXT_KHR 0x2007
/* Additional cl_context_properties */
#define CL_GL_CONTEXT_KHR 0x2008
#define CL_EGL_DISPLAY_KHR 0x2009
#define CL_GLX_DISPLAY_KHR 0x200A
#define CL_WGL_HDC_KHR 0x200B
#define CL_CGL_SHAREGROUP_KHR 0x200C
extern CL_API_ENTRY cl_int CL_API_CALL
clGetGLContextInfoKHR(const cl_context_properties * /* properties */,
cl_gl_context_info /* param_name */,
size_t /* param_value_size */,
void * /* param_value */,
size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)(
const cl_context_properties * properties,
cl_gl_context_info param_name,
size_t param_value_size,
void * param_value,
size_t * param_value_size_ret);
#ifdef __cplusplus
}
#endif
#endif /* __OPENCL_CL_GL_H */
/**********************************************************************************
* Copyright (c) 2008-2010 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and/or associated documentation files (the
* "Materials"), to deal in the Materials without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Materials, and to
* permit persons to whom the Materials are furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
**********************************************************************************/
/* $Revision: 11708 $ on $Date: 2010-06-14 12:06:24 +0530 (Mon, 14 Jun 2010) $ */
/* cl_gl_ext.h contains vendor (non-KHR) OpenCL extensions which have */
/* OpenGL dependencies. */
#ifndef __OPENCL_CL_GL_EXT_H
#define __OPENCL_CL_GL_EXT_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __APPLE__
#include <OpenCL/cl_gl.h>
#else
#include <CL/cl_gl.h>
#endif
/*
* For each extension, follow this template
* /* cl_VEN_extname extension */
/* #define cl_VEN_extname 1
* ... define new types, if any
* ... define new tokens, if any
* ... define new APIs, if any
*
* If you need GLtypes here, mirror them with a cl_GLtype, rather than including a GL header
* This allows us to avoid having to decide whether to include GL headers or GLES here.
*/
/*
* cl_khr_gl_event extension
* See section 9.9 in the OpenCL 1.1 spec for more information
*/
#define CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR 0x200D
extern CL_API_ENTRY cl_event CL_API_CALL
clCreateEventFromGLsyncKHR(cl_context /* context */,
cl_GLsync /* cl_GLsync */,
cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1;
#ifdef __cplusplus
}
#endif
#endif /* __OPENCL_CL_GL_EXT_H */
/*******************************************************************************
* Copyright (c) 2008-2010 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and/or associated documentation files (the
* "Materials"), to deal in the Materials without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Materials, and to
* permit persons to whom the Materials are furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
******************************************************************************/
/* $Revision: 11708 $ on $Date: 2010-06-14 12:06:24 +0530 (Mon, 14 Jun 2010) $ */
#ifndef __OPENCL_H
#define __OPENCL_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __APPLE__
#include <OpenCL/cl.h>
#include <OpenCL/cl_gl.h>
#include <OpenCL/cl_gl_ext.h>
#include <OpenCL/cl_ext.h>
#else
#include <CL/cl.h>
#include <CL/cl_gl.h>
#include <CL/cl_gl_ext.h>
#include <CL/cl_ext.h>
#endif
#ifdef __cplusplus
}
#endif
#endif /* __OPENCL_H */
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_OPENCL_C_SRC_EMBB_MTAPI_OPENCL_RUNTIMELINKER_H_
#define MTAPI_OPENCL_C_SRC_EMBB_MTAPI_OPENCL_RUNTIMELINKER_H_
#ifdef __cplusplus
extern "C" {
#endif
int embb_mtapi_opencl_link_at_runtime();
#ifdef __cplusplus
}
#endif
#endif // MTAPI_OPENCL_C_SRC_EMBB_MTAPI_OPENCL_RUNTIMELINKER_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb_mtapi_opencl_test_linker.h>
#include <embb_mtapi_opencl_runtimelinker.h>
LinkerTest::LinkerTest() {
CreateUnit("mtapi opencl linker test").Add(&LinkerTest::TestBasic, this);
}
void LinkerTest::TestBasic() {
PT_EXPECT(embb_mtapi_opencl_link_at_runtime() != 0);
}
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_OPENCL_C_TEST_EMBB_MTAPI_OPENCL_TEST_LINKER_H_
#define MTAPI_OPENCL_C_TEST_EMBB_MTAPI_OPENCL_TEST_LINKER_H_
#include <partest/partest.h>
class LinkerTest : public partest::TestCase {
public:
LinkerTest();
private:
void TestBasic();
};
#endif // MTAPI_OPENCL_C_TEST_EMBB_MTAPI_OPENCL_TEST_LINKER_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <embb_mtapi_opencl_test_task.h>
#include <embb/mtapi/c/mtapi_opencl.h>
#define MTAPI_CHECK_STATUS(status) \
PT_ASSERT(MTAPI_SUCCESS == status)
#define OPENCL_DOMAIN 1
#define OPENCL_NODE 2
#define OPENCL_JOB 2
// OpenCL Kernel Function for element by element vector addition
const char * kernel =
"__kernel void test(\n"
" __global void* arguments,\n"
" int arguments_size,\n"
" __global void* result_buffer,\n"
" int result_buffer_size,\n"
" __global void* node_local_data,\n"
" int node_local_data_size) {\n"
" int ii = get_global_id(0);\n"
" int elements = arguments_size / sizeof(float) / 2;\n"
" if (ii >= elements)"
" return;"
" __global float* a = (__global float*)arguments;\n"
" __global float* b = ((__global float*)arguments) + elements;\n"
" __global float* c = (__global float*)result_buffer;\n"
" __global float* d = (__global float*)node_local_data;\n"
" c[ii] = a[ii] + b[ii] + d[0];\n"
"}\n";
TaskTest::TaskTest() {
CreateUnit("mtapi opencl task test").Add(&TaskTest::TestBasic, this);
}
void TaskTest::TestBasic() {
mtapi_status_t status;
mtapi_job_hndl_t job;
mtapi_task_hndl_t task;
mtapi_action_hndl_t action;
const int kElements = 64;
float arguments[kElements * 2];
float results[kElements];
for (int ii = 0; ii < kElements; ii++) {
arguments[ii] = static_cast<float>(ii);
arguments[ii + kElements] = static_cast<float>(ii);
}
mtapi_opencl_plugin_initialize(&status);
MTAPI_CHECK_STATUS(status);
mtapi_initialize(
OPENCL_DOMAIN,
OPENCL_NODE,
MTAPI_NULL,
MTAPI_NULL,
&status);
MTAPI_CHECK_STATUS(status);
float node_local = 1.0f;
action = mtapi_opencl_action_create(
OPENCL_JOB,
kernel, "test", 32, 4,
&node_local, sizeof(float),
&status);
MTAPI_CHECK_STATUS(status);
status = MTAPI_ERR_UNKNOWN;
job = mtapi_job_get(OPENCL_JOB, OPENCL_DOMAIN, &status);
MTAPI_CHECK_STATUS(status);
task = mtapi_task_start(
MTAPI_TASK_ID_NONE,
job,
arguments, kElements * 2 * sizeof(float),
results, kElements*sizeof(float),
MTAPI_DEFAULT_TASK_ATTRIBUTES,
MTAPI_GROUP_NONE,
&status);
MTAPI_CHECK_STATUS(status);
mtapi_task_wait(task, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
for (int ii = 0; ii < kElements; ii++) {
PT_EXPECT_EQ(results[ii], ii * 2 + 1);
}
mtapi_action_delete(action, MTAPI_INFINITE, &status);
MTAPI_CHECK_STATUS(status);
mtapi_finalize(&status);
MTAPI_CHECK_STATUS(status);
mtapi_opencl_plugin_finalize(&status);
MTAPI_CHECK_STATUS(status);
}
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#ifndef MTAPI_OPENCL_C_TEST_EMBB_MTAPI_OPENCL_TEST_TASK_H_
#define MTAPI_OPENCL_C_TEST_EMBB_MTAPI_OPENCL_TEST_TASK_H_
#include <partest/partest.h>
class TaskTest : public partest::TestCase {
public:
TaskTest();
private:
void TestBasic();
};
#endif // MTAPI_OPENCL_C_TEST_EMBB_MTAPI_OPENCL_TEST_TASK_H_
/*
* Copyright (c) 2014, Siemens AG. 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.
*
* 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 HOLDER 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.
*/
#include <partest/partest.h>
#include <embb_mtapi_opencl_test_linker.h>
#include <embb_mtapi_opencl_test_task.h>
PT_MAIN("MTAPI OPENCL") {
PT_RUN(LinkerTest);
PT_RUN(TaskTest);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment