Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Tobias Langer
/
experiment
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
7da6d540
authored
Oct 08, 2016
by
Tobias Langer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added template for cpp file.
parent
6e9afca7
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
228 additions
and
0 deletions
+228
-0
templates/normal/experiment.cpp
+228
-0
No files found.
templates/normal/experiment.cpp
View file @
7da6d540
#include <iostream>
#include <thread>
#include <vector>
#include <sched.h>
#include <embb/mtapi/mtapi.h>
#include "defines.h"
#define UNUSED(x) ((void)(x))
#define DOMAIN_ID 1
#define NODE_ID 1
#define ACTION_ID 2
auto
gcd
(
long
long
a
,
long
long
b
)
->
long
long
{
return
b
==
0
?
a
:
gcd
(
b
,
a
%
b
);
}
auto
lcm
(
long
long
a
,
long
long
b
)
->
long
long
{
return
(
a
*
b
)
/
gcd
(
a
,
b
);
}
auto
calculate_hyperperiod
()
->
long
long
{
long
long
hyperperiod
=
taskset
[
0
].
period
;
for
(
int
i
=
1
;
i
<
taskset_length
;
i
++
)
{
hyperperiod
=
lcm
(
hyperperiod
,
taskset
[
i
].
period
);
}
return
hyperperiod
;
}
struct
timestamps
{
base_clock
::
time_point
start
;
base_clock
::
time_point
end
;
int
core_id
=
0
;
};
base_clock
::
time_point
start
;
base_clock
::
time_point
end
;
std
::
vector
<
timestamps
>
benchmark
[
taskset_length
];
void
benchmark_out
()
{
using
namespace
std
::
chrono
;
std
::
cout
<<
"benchmark results "
;
std
::
cout
<<
"start "
<<
base_clock
::
to_time_t
(
start
)
<<
" "
;
std
::
cout
<<
"end "
<<
base_clock
::
to_time_t
(
end
)
<<
std
::
endl
;
for
(
int
i
=
0
;
i
<
taskset_length
;
i
++
)
{
std
::
cout
<<
"task "
<<
i
<<
" "
;
std
::
cout
<<
"wcet "
<<
taskset
[
i
].
wcet
<<
" "
;
std
::
cout
<<
"period "
<<
taskset
[
i
].
period
<<
" "
;
std
::
cout
<<
"deadline "
<<
taskset
[
i
].
deadline
<<
" "
;
std
::
cout
<<
"executions "
<<
taskset
[
i
].
count
<<
std
::
endl
;
for
(
int
j
=
0
;
j
<
benchmark
[
i
].
size
();
j
++
)
{
auto
start
=
base_clock
::
to_time_t
(
benchmark
[
i
][
j
].
start
);
auto
end
=
base_clock
::
to_time_t
(
benchmark
[
i
][
j
].
end
);
auto
core_id
=
benchmark
[
i
][
j
].
core_id
;
std
::
cout
<<
"instance "
<<
i
<<
" "
;
std
::
cout
<<
"start "
<<
start
<<
" "
;
std
::
cout
<<
"end "
<<
end
<<
" "
;
std
::
cout
<<
"core_id "
<<
core_id
<<
std
::
endl
;
}
}
}
/******
* Task Declarations
******/
/* Workaround helper function, the base node action is not initialized if the
* node gets attributes set.
*/
static
void
ActionFunction
(
const
void
*
args
,
mtapi_size_t
/*args_size*/
,
void
*
/*result_buffer*/
,
mtapi_size_t
/*result_buffer_size*/
,
const
void
*
/*node_local_data*/
,
mtapi_size_t
/*node_local_data_size*/
,
mtapi_task_context_t
*
context
)
{
embb
::
mtapi
::
TaskContext
task_context
(
context
);
embb
::
base
::
Function
<
void
,
embb
::
mtapi
::
TaskContext
&>
*
func
=
reinterpret_cast
<
embb
::
base
::
Function
<
void
,
embb
::
mtapi
::
TaskContext
&>*>
(
const_cast
<
void
*>
(
args
));
(
*
func
)(
task_context
);
embb
::
base
::
Allocation
::
Delete
(
func
);
}
static
void
IdleTask
(
const
void
*
args
,
mtapi_size_t
,
void
*
,
mtapi_size_t
,
const
void
*
,
mtapi_size_t
,
mtapi_task_context_t
*
)
{
using
namespace
std
::
chrono
;
/* Get access to parameter data. */
auto
data
=
static_cast
<
const
std
::
pair
<
int
,
int
>*>
(
args
);
auto
task_id
=
data
->
first
;
auto
task_num
=
data
->
second
;
auto
start_time
=
base_clock
::
now
();
/* idle until task completion. */
auto
idle_time
=
cpp_time_base
(
taskset
[
task_id
].
wcet
);
std
::
this_thread
::
sleep_for
(
idle_time
);
/* Store our benchmarking data. */
auto
end_time
=
base_clock
::
now
();
int
core_id
=
sched_getcpu
();
benchmark
[
task_id
][
task_num
-
1
].
start
=
start_time
;
benchmark
[
task_id
][
task_num
-
1
].
end
=
end_time
;
benchmark
[
task_id
][
task_num
-
1
].
core_id
=
core_id
;
}
/****
* Main loop of task starter core.
****/
static
void
TaskStarter
()
{
/* Initialize task starter */
auto
&
node
=
embb
::
mtapi
::
Node
::
GetInstance
();
/* Storage for any task which is started. */
std
::
vector
<
embb
::
mtapi
::
Task
>
running
;
/* Storage for task parameters. */
std
::
vector
<
std
::
pair
<
int
,
int
>>
running_num
;
auto
hyperperiod
=
calculate_hyperperiod
();
using
namespace
std
::
chrono
;
start
=
base_clock
::
now
();
auto
cur_time
=
duration_cast
<
cpp_time_base
>
(
base_clock
::
now
()
-
start
);
std
::
cerr
<<
"Starting TaskStarter thread at: "
;
std
::
cerr
<<
base_clock
::
to_time_t
(
start
)
<<
std
::
endl
;
while
(
cur_time
.
count
()
<
hyperperiod
)
{
auto
min
=
cpp_time_base
::
max
();
/* Check for every task if it has to be executed. */
for
(
int
i
=
0
;
i
<
taskset_length
;
i
++
)
{
auto
task_period
=
cpp_time_base
(
taskset
[
i
].
period
);
/* Execute always then when a next period has started, meaning when
* cur_time / task_period is bigger than for the last check. The
* first task_period is to let the tasks start at time 0 and not at
* time task_period.
*/
auto
count
=
(
cur_time
+
task_period
)
/
task_period
;
/* Check how long to sleep next, either min(cur_time % period), or
* period if cur_time % period == 0
*/
auto
remaining
=
cur_time
%
task_period
;
remaining
=
remaining
.
count
()
==
0
?
task_period
:
remaining
;
if
(
remaining
<
min
)
{
min
=
remaining
;
}
if
(
count
>
taskset
[
i
].
count
)
{
embb
::
mtapi
::
ExecutionPolicy
deadline_policy
(
embb_time_base
(
taskset
[
i
].
deadline
));
/* Store parameters for execution.
* The count may change during the execution, therefore we have
* to make sure that all possible running tasks can access their
* parameters.
*/
running_num
.
push_back
(
std
::
make_pair
(
i
,
count
));
node
.
CreateAction
(
ACTION_ID
+
i
+
1
,
IdleTask
);
auto
job
=
node
.
GetJob
(
ACTION_ID
+
i
+
1
,
DOMAIN_ID
);
int
tmp
;
auto
t
=
node
.
Start
(
job
,
&
running_num
.
back
(),
&
tmp
);
/* Store task to wait for it. */
running
.
push_back
(
t
);
taskset
[
i
].
count
=
count
;
}
}
std
::
this_thread
::
sleep_for
(
min
);
cur_time
=
duration_cast
<
cpp_time_base
>
(
base_clock
::
now
()
-
start
);
}
/* Wait for all started tasks to be completed. */
for
(
auto
&
task
:
running
)
{
task
.
Wait
(
MTAPI_INFINITE
);
}
end
=
base_clock
::
now
();
std
::
cerr
<<
"Finishing TaskStarter thread at: "
;
std
::
cerr
<<
base_clock
::
to_time_t
(
end
)
<<
std
::
endl
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
UNUSED
(
argc
);
UNUSED
(
argv
);
/* Initialize node and set global edf as scheduling method. */
embb
::
mtapi
::
NodeAttributes
attr
;
attr
.
SetSchedulerMode
(
GLOBAL_EDF
);
embb
::
mtapi
::
Node
::
Initialize
(
DOMAIN_ID
,
NODE_ID
,
attr
);
auto
&
node
=
embb
::
mtapi
::
Node
::
GetInstance
();
/* Initialize storage for benchmarking data */
auto
hyperperiod
=
calculate_hyperperiod
();
for
(
int
i
=
0
;
i
<
taskset_length
;
i
++
)
{
auto
job_count
=
hyperperiod
/
taskset
[
i
].
period
;
benchmark
[
i
]
=
std
::
vector
<
timestamps
>
(
job_count
);
}
/* Workaround, the base node action is not initialized if the node gets
* attributes set.
*/
node
.
CreateAction
(
ACTION_ID
,
ActionFunction
);
/* Start task loop */
TaskStarter
();
/* Print experiment results. */
benchmark_out
();
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment