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
8 years ago
by
Tobias Langer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added template for cpp file.
parent
6e9afca7
Hide 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
;
}
This diff is collapsed.
Click to expand it.
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