Compare commits
No commits in common. "36cf3121d161f07c16312bac2d63ac464775a4f8" and "e3d72fb14e1d54881ed1b5e9e77de65fbb8bc159" have entirely different histories.
36cf3121d1
...
e3d72fb14e
@ -42,13 +42,6 @@ build:asan:
|
||||
script:
|
||||
- nix build -L --no-link .#ovniPackages.asan
|
||||
|
||||
build:ubsan:
|
||||
stage: build
|
||||
tags:
|
||||
- nix
|
||||
script:
|
||||
- nix build -L --no-link .#ovniPackages.ubsan
|
||||
|
||||
build:nompi:
|
||||
stage: build
|
||||
tags:
|
||||
@ -62,24 +55,3 @@ build:compilers:
|
||||
- nix
|
||||
script:
|
||||
- nix build -L --no-link .#ovniPackages.compilers
|
||||
|
||||
build:armv7:
|
||||
stage: build
|
||||
tags:
|
||||
- nix
|
||||
script:
|
||||
- nix build -L --no-link .#ovniPackages.armv7
|
||||
|
||||
build:aarch64:
|
||||
stage: build
|
||||
tags:
|
||||
- nix
|
||||
script:
|
||||
- nix build -L --no-link .#ovniPackages.aarch64
|
||||
|
||||
build:riscv64:
|
||||
stage: build
|
||||
tags:
|
||||
- nix
|
||||
script:
|
||||
- nix build -L --no-link .#ovniPackages.riscv64
|
||||
|
29
CHANGELOG.md
29
CHANGELOG.md
@ -7,34 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
- Enable -Wconversion and -Wsign-conversion.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix bug in ovnisort when injecting events in a previously modified section.
|
||||
|
||||
## [1.10.0] - 2024-07-26
|
||||
|
||||
### Changed
|
||||
|
||||
- nOS-V model version increased to 2.3.0.
|
||||
- Prevent accidental use of nOS-V traces without required events for the
|
||||
breakdown model using the `nosv.can_breakdown` attribute.
|
||||
- Increase ovni model version to 1.1.0 for the mark events `OM*`.
|
||||
|
||||
### Added
|
||||
|
||||
- Add support for nOS-V progressing events VP{pra}.
|
||||
- Add breakdown model for nOS-V.
|
||||
- New API to manage stream metadata `ovni_attr_*()`.
|
||||
- New mark API `ovni_mark_*()` to emit user-defined events.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Cross-compilation for ARM 32 bits.
|
||||
|
||||
## [1.9.1] - 2024-05-10
|
||||
|
||||
### Fixed
|
||||
@ -274,7 +246,6 @@ are used along with some other changes.
|
||||
- First ovni release.
|
||||
|
||||
[unreleased]: https://jungle.bsc.es/git/rarias/ovni
|
||||
[1.10.0]: https://github.com/rodarima/ovni/releases/tag/1.10.0
|
||||
[1.9.1]: https://github.com/rodarima/ovni/releases/tag/1.9.1
|
||||
[1.9.0]: https://github.com/rodarima/ovni/releases/tag/1.9.0
|
||||
[1.8.0]: https://github.com/rodarima/ovni/releases/tag/1.8.0
|
||||
|
@ -3,13 +3,13 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(OVNI LANGUAGES C VERSION 1.10.0)
|
||||
project(OVNI LANGUAGES C VERSION 1.9.1)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
|
||||
add_compile_options(-Wall -Wextra -Wformat
|
||||
-Wmissing-prototypes -Wstrict-prototypes
|
||||
-Wconversion -Wsign-conversion
|
||||
#-Wconversion -Wsign-conversion
|
||||
-Wold-style-definition -pedantic
|
||||
-Werror
|
||||
)
|
||||
@ -67,9 +67,7 @@ set(CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_DEBUG} \
|
||||
-fno-omit-frame-pointer"
|
||||
CACHE STRING "Flags used by the C compiler during AddressSanitizer builds." FORCE)
|
||||
|
||||
set(CMAKE_C_FLAGS_UBSAN "${CMAKE_C_FLAGS_DEBUG} \
|
||||
-fsanitize=undefined \
|
||||
-fno-sanitize-recover=all"
|
||||
set(CMAKE_C_FLAGS_UBSAN "${CMAKE_C_FLAGS_DEBUG} -fsanitize=undefined"
|
||||
CACHE STRING "Flags used by the C compiler during UndefinedBehaviorSanitizer builds." FORCE)
|
||||
|
||||
find_program(IWYU NAMES include-what-you-use iwyu)
|
||||
|
@ -1,44 +0,0 @@
|
||||
#ParaverCFG
|
||||
ConfigFile.Version: 3.4
|
||||
ConfigFile.NumWindows: 1
|
||||
|
||||
|
||||
################################################################################
|
||||
< NEW DISPLAYING WINDOW CPU: nOS-V Runtime/Idle/Task breakdown >
|
||||
################################################################################
|
||||
window_name CPU: nOS-V Runtime/Idle/Task breakdown
|
||||
window_type single
|
||||
window_id 1
|
||||
window_position_x 0
|
||||
window_position_y 0
|
||||
window_width 600
|
||||
window_height 150
|
||||
window_comm_lines_enabled false
|
||||
window_flags_enabled false
|
||||
window_noncolor_mode true
|
||||
window_custom_color_enabled true
|
||||
window_custom_color_palette {6.000000000000:94,0,0},{7.000000000000:153,114,0},{9.000000000000:124,213,228},{10.000000000000:242,239,141},{11.000000000000:0,70,0},{19.000000000000:195,96,151},{20.000000000000:255,162,255},{21.000000000000:203,255,3},{22.000000000000:7,255,12},{23.000000000000:21,224,189},{24.000000000000:255,103,0},{25.000000000000:0,99,162},{26.000000000000:110,77,252},{100.000000000000:0,100,0},{101.000000000000:60,60,60},{102.000000000000:150,150,0}
|
||||
window_logical_filtered true
|
||||
window_physical_filtered false
|
||||
window_comm_fromto true
|
||||
window_comm_tagsize true
|
||||
window_comm_typeval true
|
||||
window_units Microseconds
|
||||
window_maximum_y 1000.0
|
||||
window_minimum_y 1.0
|
||||
window_compute_y_max true
|
||||
window_level thread
|
||||
window_scale_relative 1.000000000000
|
||||
window_end_time_relative 1.000000000000
|
||||
window_object appl { 1, { All } }
|
||||
window_begin_time_relative 0.000000000000
|
||||
window_open true
|
||||
window_drawmode draw_randnotzero
|
||||
window_drawmode_rows draw_randnotzero
|
||||
window_pixel_size 1
|
||||
window_labels_to_draw 1
|
||||
window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } }
|
||||
window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } }
|
||||
window_filter_module evt_type 1 17
|
||||
window_filter_module evt_type_label 1 "CPU: nOS-V Runtime/Idle/Task breakdown"
|
||||
|
@ -1,44 +0,0 @@
|
||||
#ParaverCFG
|
||||
ConfigFile.Version: 3.4
|
||||
ConfigFile.NumWindows: 1
|
||||
|
||||
|
||||
################################################################################
|
||||
< NEW DISPLAYING WINDOW CPU: nOS-V idle state of the RUNNING thread >
|
||||
################################################################################
|
||||
window_name CPU: nOS-V idle state of the RUNNING thread
|
||||
window_type single
|
||||
window_id 1
|
||||
window_position_x 0
|
||||
window_position_y 0
|
||||
window_width 600
|
||||
window_height 150
|
||||
window_comm_lines_enabled false
|
||||
window_flags_enabled false
|
||||
window_noncolor_mode true
|
||||
window_custom_color_enabled true
|
||||
window_custom_color_palette {100.000000000000:0,100,0},{101.000000000000:60,60,60},{102.000000000000:150,150,0}
|
||||
window_logical_filtered true
|
||||
window_physical_filtered false
|
||||
window_comm_fromto true
|
||||
window_comm_tagsize true
|
||||
window_comm_typeval true
|
||||
window_units Microseconds
|
||||
window_maximum_y 1000.0
|
||||
window_minimum_y 1.0
|
||||
window_compute_y_max true
|
||||
window_level thread
|
||||
window_scale_relative 1.000000000000
|
||||
window_end_time_relative 1.000000000000
|
||||
window_object appl { 1, { All } }
|
||||
window_begin_time_relative 0.000000000000
|
||||
window_open true
|
||||
window_drawmode draw_randnotzero
|
||||
window_drawmode_rows draw_randnotzero
|
||||
window_pixel_size 1
|
||||
window_labels_to_draw 1
|
||||
window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } }
|
||||
window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } }
|
||||
window_filter_module evt_type 1 16
|
||||
window_filter_module evt_type_label 1 "CPU: nOS-V idle state of the RUNNING thread"
|
||||
|
@ -1,41 +0,0 @@
|
||||
#ParaverCFG
|
||||
ConfigFile.Version: 3.4
|
||||
ConfigFile.NumWindows: 1
|
||||
|
||||
|
||||
################################################################################
|
||||
< NEW DISPLAYING WINDOW CPU: Mark value of the RUNNING thread >
|
||||
################################################################################
|
||||
window_name CPU: Mark value of the RUNNING thread
|
||||
window_type single
|
||||
window_id 1
|
||||
window_position_x 100
|
||||
window_position_y 100
|
||||
window_width 600
|
||||
window_height 150
|
||||
window_comm_lines_enabled true
|
||||
window_flags_enabled false
|
||||
window_noncolor_mode true
|
||||
window_logical_filtered true
|
||||
window_physical_filtered false
|
||||
window_comm_fromto true
|
||||
window_comm_tagsize true
|
||||
window_comm_typeval true
|
||||
window_units Microseconds
|
||||
window_maximum_y 1000.0
|
||||
window_minimum_y 1.0
|
||||
window_compute_y_max true
|
||||
window_level thread
|
||||
window_scale_relative 1.000000000000
|
||||
window_end_time_relative 1.000000000000
|
||||
window_object appl { 1, { All } }
|
||||
window_begin_time_relative 0.000000000000
|
||||
window_open true
|
||||
window_drawmode draw_randnotzero
|
||||
window_drawmode_rows draw_randnotzero
|
||||
window_pixel_size 1
|
||||
window_labels_to_draw 1
|
||||
window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } }
|
||||
window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } }
|
||||
window_filter_module evt_type 1 100
|
||||
window_filter_module evt_type_label 1 "CPU: Mark value of the RUNNING thread"
|
@ -1,41 +0,0 @@
|
||||
#ParaverCFG
|
||||
ConfigFile.Version: 3.4
|
||||
ConfigFile.NumWindows: 1
|
||||
|
||||
|
||||
################################################################################
|
||||
< NEW DISPLAYING WINDOW Thread: Mark value of the ACTIVE thread >
|
||||
################################################################################
|
||||
window_name Thread: Mark value of the ACTIVE thread
|
||||
window_type single
|
||||
window_id 1
|
||||
window_position_x 100
|
||||
window_position_y 100
|
||||
window_width 600
|
||||
window_height 150
|
||||
window_comm_lines_enabled true
|
||||
window_flags_enabled false
|
||||
window_noncolor_mode true
|
||||
window_logical_filtered true
|
||||
window_physical_filtered false
|
||||
window_comm_fromto true
|
||||
window_comm_tagsize true
|
||||
window_comm_typeval true
|
||||
window_units Microseconds
|
||||
window_maximum_y 1000.0
|
||||
window_minimum_y 1.0
|
||||
window_compute_y_max true
|
||||
window_level thread
|
||||
window_scale_relative 1.000000000000
|
||||
window_end_time_relative 1.000000000000
|
||||
window_object appl { 1, { All } }
|
||||
window_begin_time_relative 0.000000000000
|
||||
window_open true
|
||||
window_drawmode draw_randnotzero
|
||||
window_drawmode_rows draw_randnotzero
|
||||
window_pixel_size 1
|
||||
window_labels_to_draw 1
|
||||
window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } }
|
||||
window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } }
|
||||
window_filter_module evt_type 1 100
|
||||
window_filter_module evt_type_label 1 "Thread: Mark value of the ACTIVE thread"
|
@ -1,7 +1,7 @@
|
||||
# Emulator events
|
||||
|
||||
This is a exhaustive list of the events recognized by the emulator.
|
||||
Built on Jun 17 2024.
|
||||
Built on Mar 20 2024.
|
||||
|
||||
## Model nanos6
|
||||
|
||||
@ -395,7 +395,7 @@ List of events for the model *mpi* with identifier **`M`** at version `1.0.0`:
|
||||
|
||||
## Model ovni
|
||||
|
||||
List of events for the model *ovni* with identifier **`O`** at version `1.1.0`:
|
||||
List of events for the model *ovni* with identifier **`O`** at version `1.0.0`:
|
||||
<dl>
|
||||
<dt><a id="OAr" href="#OAr"><pre>OAr(i32 cpu, i32 tid)</pre></a></dt>
|
||||
<dd>changes the affinity of thread %{tid} to CPU %{cpu}</dd>
|
||||
@ -427,12 +427,6 @@ List of events for the model *ovni* with identifier **`O`** at version `1.1.0`:
|
||||
<dd>enters unordered event region</dd>
|
||||
<dt><a id="OU]" href="#OU]"><pre>OU]</pre></a></dt>
|
||||
<dd>leaves unordered event region</dd>
|
||||
<dt><a id="OM[" href="#OM["><pre>OM[(i64 value, i32 type)</pre></a></dt>
|
||||
<dd>push mark with value %{value} from type %{type}</dd>
|
||||
<dt><a id="OM]" href="#OM]"><pre>OM](i64 value, i32 type)</pre></a></dt>
|
||||
<dd>pop mark with value %{value} from type %{type}</dd>
|
||||
<dt><a id="OM=" href="#OM="><pre>OM=(i64 value, i32 type)</pre></a></dt>
|
||||
<dd>set mark with value %{value} from type %{type}</dd>
|
||||
</dl>
|
||||
|
||||
## Model openmp
|
||||
@ -621,7 +615,7 @@ List of events for the model *tampi* with identifier **`T`** at version `1.0.0`:
|
||||
|
||||
## Model nosv
|
||||
|
||||
List of events for the model *nosv* with identifier **`V`** at version `2.3.0`:
|
||||
List of events for the model *nosv* with identifier **`V`** at version `2.1.0`:
|
||||
<dl>
|
||||
<dt><a id="VTc" href="#VTc"><pre>VTc(u32 taskid, u32 typeid)</pre></a></dt>
|
||||
<dd>creates task %{taskid} with type %{typeid}</dd>
|
||||
@ -727,10 +721,4 @@ List of events for the model *nosv* with identifier **`V`** at version `2.3.0`:
|
||||
<dd>begins execution as delegate</dd>
|
||||
<dt><a id="VHD" href="#VHD"><pre>VHD</pre></a></dt>
|
||||
<dd>ceases execution as delegate</dd>
|
||||
<dt><a id="VPp" href="#VPp"><pre>VPp</pre></a></dt>
|
||||
<dd>sets progress state to Progressing</dd>
|
||||
<dt><a id="VPr" href="#VPr"><pre>VPr</pre></a></dt>
|
||||
<dd>sets progress state to Resting</dd>
|
||||
<dt><a id="VPa" href="#VPa"><pre>VPa</pre></a></dt>
|
||||
<dd>sets progress state to Absorbing</dd>
|
||||
</dl>
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
@ -61,46 +61,3 @@ For more details, see [this MR][1].
|
||||
The subsystem view provides a simplified view on what is the nOS-V
|
||||
runtime doing over time. The view follows the same rules described in
|
||||
the [subsystem view of Nanos6](../nanos6/#subsystem_view).
|
||||
|
||||
|
||||
## Idle view
|
||||
|
||||
The idle view shows the progress state of the running threads:
|
||||
*Progressing* and *Resting*. The *Progressing* state is shown when they
|
||||
are making useful progress and the *Resting* state when they are waiting
|
||||
for work. When workers start running, by definition, they begin in the
|
||||
Progressing state and there are some situations that make them
|
||||
transition to Resting:
|
||||
|
||||
- When workers are waiting in the delegation lock after some spins or
|
||||
when instructed to go to sleep.
|
||||
- When the server is trying to serve tasks, but there are no more tasks
|
||||
available.
|
||||
|
||||
They will go back to Progressing as soon as they receive work. The
|
||||
specific points at which they do so can be read in [nOS-V source
|
||||
code](https://gitlab.bsc.es/nos-v/nos-v) by looking at the
|
||||
`instr_worker_resting()` and `instr_worker_progressing()` trace points.
|
||||
|
||||
This view is intended to detect parts of the execution time on which the
|
||||
workers don't have work, typically because the application doesn't have
|
||||
enough parallelism or the scheduler is unable to serve work fast enough.
|
||||
|
||||
## Breakdown view
|
||||
|
||||
The breakdown view displays a summary of what is happening in all CPUs
|
||||
by mixing in a single timeline the subsystem, idle and task type views.
|
||||
Specifically, it shows how many CPUs are resting as defined by the idle
|
||||
view, how many are inside a given task by showing the task type label,
|
||||
and how many are in a particular subsystem of the runtime.
|
||||
|
||||
!!! Important
|
||||
|
||||
You must specify *ovni.level = 3* or higher in *nosv.toml* and pass
|
||||
the *-b* option to ovniemu to generate the breakdown view.
|
||||
|
||||
Notice that the vertical axis shows the **number**
|
||||
of CPUs in that state, not the physical CPUs like other views.
|
||||
Here is an example of the Heat mini-app:
|
||||
|
||||
![Breakdown example](fig/breakdown-nosv.png)
|
||||
|
@ -27,8 +27,6 @@ Track changes in emulator model versions.
|
||||
|
||||
## Ovni
|
||||
|
||||
- ovni 1.1.0
|
||||
- Add support for mark events `OM[`, `OM]` and `OM=`
|
||||
- ovni 1.0.0: Initial version
|
||||
|
||||
## OpenMP
|
||||
@ -41,13 +39,9 @@ Track changes in emulator model versions.
|
||||
|
||||
## nOS-V
|
||||
|
||||
- nosv 2.3.0
|
||||
- Add `nosv.can_breakdown` attribute to metadata for breakdown checks.
|
||||
- nosv 2.2.0
|
||||
- Add support for progress events `VP{pra}`.
|
||||
- nosv 2.1.0
|
||||
- Add support for `nosv_mutex_lock`, `nosv_mutex_trylock` and `nosv_mutex_unlock` events `VA{lLtTuU}`.
|
||||
- Add support for `nosv_barrier_wait` event `VA{bB}`.
|
||||
- Add support for `nosv_mutex_lock`, `nosv_mutex_trylock` and `nosv_mutex_unlock` events VA{lLtTuU}.
|
||||
- Add support for `nosv_barrier_wait` event VA{bB}.
|
||||
- nosv 2.0.0
|
||||
- Add support for parallel tasks, adding a new `bodyid` argument in `VT*` events.
|
||||
- Remove support for old attach events `VH{aA}`.
|
||||
|
@ -1,156 +0,0 @@
|
||||
# Mark API
|
||||
|
||||
The mark API allows you to add arbitrary events in a trace to mark regions of
|
||||
interest while debugging or developing a new program or library. The events are
|
||||
processed by the emulator to generate a timeline.
|
||||
|
||||
## Usage in runtime
|
||||
|
||||
Follow these steps to correctly use the API. Most problems will be detected in
|
||||
emulation and cause a panic if you are not careful.
|
||||
|
||||
### Create a mark type
|
||||
|
||||
You can create up to 100 types of marks, each will be shown in its own Paraver
|
||||
timeline. To create a new type, use the following call:
|
||||
|
||||
```c
|
||||
void ovni_mark_type(int32_t type, long flags, const char *title);
|
||||
```
|
||||
|
||||
The numeric value `type` must be a number between 0 and 99 (both included). The
|
||||
`title` will be used to give a name to the Paraver timeline.
|
||||
|
||||
The default with flags set to zero, is to create a channel that can hold a
|
||||
single value only (see [channels](../../dev/channels.md)). To use a stack of
|
||||
values add the `OVNI_MARK_STACK` value to the flags.
|
||||
|
||||
Only one thread among all nodes needs to define a type to be available globally,
|
||||
but the same type can be defined from multiple threads, as long as the same
|
||||
flags and title argument are used. The idea is to avoid having to check if the
|
||||
type was already defined or not.
|
||||
|
||||
### Define labels (optional)
|
||||
|
||||
The values that are written to the channel can have labels to display in the
|
||||
Paraver timeline. The labels are optional, if not given the numeric value will
|
||||
be shown in Paraver.
|
||||
|
||||
Use the following call to register a label for a value in a given type.
|
||||
|
||||
```c
|
||||
void ovni_mark_label(int32_t type, int64_t value, const char *label);
|
||||
```
|
||||
|
||||
A value can only have at most a single label associated. Multiple threads can
|
||||
call the `ovni_mark_label()` with the same type and value as long as they use
|
||||
the same label. New labels for the same type can be associated from different
|
||||
threads, as long as the values are different.
|
||||
|
||||
All value and label pairs are combined from all threads and will be available in
|
||||
the Paraver view for each type.
|
||||
|
||||
### Emit events
|
||||
|
||||
All mark channels begin with the default value *null*, which is not shown in
|
||||
Paraver and will be displayed as the usual empty space. The value of the channel
|
||||
can be changed over time with the following functions.
|
||||
|
||||
!!! warning
|
||||
|
||||
The value 0 is forbidden, as it is used by Paraver to represent the
|
||||
"empty" state.
|
||||
|
||||
If you have used a single channel (without `OVNI_MARK_STACK`), then you must use
|
||||
the following call to emit events at runtime:
|
||||
|
||||
```c
|
||||
void ovni_mark_set(int32_t type, int64_t value);
|
||||
```
|
||||
|
||||
It will update the value of the channel to the given `value`.
|
||||
|
||||
If you have used a stack channel (with `OVNI_MARK_STACK`), then you must use the
|
||||
push/pop set of calls:
|
||||
|
||||
```c
|
||||
void ovni_mark_push(int32_t type, int64_t value);
|
||||
void ovni_mark_pop(int32_t type, int64_t value);
|
||||
```
|
||||
|
||||
The value in the pop call must match the previous pushed value.
|
||||
|
||||
## Usage in Paraver
|
||||
|
||||
Each thread holds a channel for each mark type that you have defined. The
|
||||
information of the mark channels is propagated to the Paraver timeline in
|
||||
Thread and CPU views.
|
||||
|
||||
When a thread is not *running*, the value of the mark channels is not shown in
|
||||
Paraver. In the case of the CPU timeline, only the values of the running thread are
|
||||
shown. If there are no running threads, nothing is shown.
|
||||
|
||||
Follow the next steps to create a configuration to suit your needs. You only
|
||||
need to do it once, then you can save the configuration file and reuse it for
|
||||
future traces.
|
||||
|
||||
### Filtering the type
|
||||
|
||||
To see a mark type, you will have to create a Paraver configuration that matches
|
||||
the type that you have created. The mark `type` value gets converted into a PRV
|
||||
type by adding 100 (as values from 0 to 99 are reserved).
|
||||
|
||||
You can use the `cpu/ovni/mark.cfg` and `thread/ovni/mark.cfg` configurations as
|
||||
a starting point to create your own.
|
||||
|
||||
Go to "Window Properties" (the second button under "Files & Window Properties")
|
||||
and then go to Filter > Events > Event type. Set Function to `=` and click the
|
||||
Types value to display the `[...]` button, which will allow you to choose which
|
||||
type to display.
|
||||
|
||||
In the "Events Selection" window, ensure that only one type is selected, and the
|
||||
"Values" panel shows Function "All", to see all values for the selected type.
|
||||
|
||||
### Setting the title
|
||||
|
||||
In the "Window Properties" adjust the Name so it reflects what you are seeing.
|
||||
This will be shown in the saved images, so it is good to use a proper
|
||||
description.
|
||||
|
||||
### Configure the display method
|
||||
|
||||
By default, the timeline will display the values as "Code color". To switch to a
|
||||
gradient or other methods, left-click in the timeline and go to "Paint As" and
|
||||
select "Gradient" (or others).
|
||||
|
||||
You may also want to adjust the "Drawmode" which determines what happens when
|
||||
there are multiple values under a given pixel. This is specially important when
|
||||
you are viewing the trace with a large time range, before zooming into a given
|
||||
region.
|
||||
|
||||
By default, the "Random not zero" mode is selected, which will select a
|
||||
random value from the ones under each pixel, disregarding the occurrences of each
|
||||
value. This mode will give importance to rare values, so it is usually a safe
|
||||
starting point. The "Last" mode will show the last value in that pixel, which is
|
||||
more or less fair, but will often hide rare values.
|
||||
|
||||
To change in both horizontal (Time) and in vertical (Objects) directions, go to:
|
||||
left click on timeline > Drawmode > Both > Last.
|
||||
|
||||
### Ensure the range is good
|
||||
|
||||
Paraver will only display values in the timeline that are in the Semantic
|
||||
range. If you see a red triangle in the lower left corner then there are values
|
||||
outside the range that are not being displayed. You can click on this button to
|
||||
expand the range to cover all values in the current view.
|
||||
|
||||
The opposite may also happen, where the range is too big for the current values.
|
||||
You can also click on the same spot (even if the triangle is not shown) to
|
||||
shrink the range to cover the values in the view, or go to the Window Properties
|
||||
and modify the "Semantic Minimum" and "Semantic Maximum" values manually.
|
||||
|
||||
### Save the configuration
|
||||
|
||||
Once you finish configuring the timeline, save the configuration by
|
||||
left-clicking the view and then "Save > Configuration...". You can use this
|
||||
configuration in future traces to avoid doing these steps again.
|
37
flake.nix
37
flake.nix
@ -15,7 +15,7 @@
|
||||
nosv = prev.nosv.override {
|
||||
useGit = true;
|
||||
gitBranch = "master";
|
||||
gitCommit = "3286ff5a788a989407519dd1dfe57c1750258d3f";
|
||||
gitCommit = "c698c16c0518e6afc68fb32ee6f1a0f65ca69327";
|
||||
};
|
||||
nanos6 = prev.nanos6.override {
|
||||
useGit = true;
|
||||
@ -37,8 +37,7 @@
|
||||
ovniFixed = prev.ovni.override {
|
||||
useGit = true;
|
||||
gitBranch = "master";
|
||||
# Includes ovni_attr_* API
|
||||
gitCommit = "d1e8a62396ae92934c0b6e248d5f6ff921bef56f";
|
||||
gitCommit = "68fc8b0eba299c3a7fa3833ace2c94933a26749e";
|
||||
};
|
||||
# Build with the current source
|
||||
ovniLocal = prev.ovni.overrideAttrs (old: rec {
|
||||
@ -135,38 +134,6 @@
|
||||
export ASAN_OPTIONS=detect_leaks=0
|
||||
'';
|
||||
});
|
||||
|
||||
ubsan = rt.overrideAttrs (old: {
|
||||
pname = "ovni-ubsan";
|
||||
cmakeFlags = old.cmakeFlags ++ [ "-DCMAKE_BUILD_TYPE=Ubsan" ];
|
||||
});
|
||||
|
||||
armv7 = (pkgs.pkgsCross.armv7l-hf-multiplatform.ovniLocal.overrideAttrs (old: {
|
||||
pname = "ovni-armv7";
|
||||
buildInputs = [];
|
||||
nativeBuildInputs = [ pkgs.pkgsCross.armv7l-hf-multiplatform.buildPackages.cmake ];
|
||||
cmakeFlags = old.cmakeFlags ++ [ "-DUSE_MPI=OFF" ];
|
||||
})).overrideDerivation (old: {
|
||||
doCheck = true;
|
||||
});
|
||||
|
||||
aarch64 = (pkgs.pkgsCross.aarch64-multiplatform.ovniLocal.overrideAttrs (old: {
|
||||
pname = "ovni-aarch64";
|
||||
buildInputs = [];
|
||||
nativeBuildInputs = [ pkgs.pkgsCross.aarch64-multiplatform.buildPackages.cmake ];
|
||||
cmakeFlags = old.cmakeFlags ++ [ "-DUSE_MPI=OFF" ];
|
||||
})).overrideDerivation (old: {
|
||||
doCheck = true;
|
||||
});
|
||||
|
||||
riscv64 = (pkgs.pkgsCross.riscv64.ovniLocal.overrideAttrs (old: {
|
||||
pname = "ovni-riscv64";
|
||||
buildInputs = [];
|
||||
nativeBuildInputs = [ pkgs.pkgsCross.riscv64.buildPackages.cmake ];
|
||||
cmakeFlags = old.cmakeFlags ++ [ "-DUSE_MPI=OFF" ];
|
||||
})).overrideDerivation (old: {
|
||||
doCheck = true;
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef OVNI_H
|
||||
@ -130,28 +130,6 @@ void ovni_ev_jumbo_emit(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize
|
||||
|
||||
void ovni_flush(void);
|
||||
|
||||
/* Attributes */
|
||||
int ovni_attr_has(const char *key);
|
||||
void ovni_attr_set_double(const char *key, double num);
|
||||
void ovni_attr_set_boolean(const char *key, int value);
|
||||
void ovni_attr_set_str(const char *key, const char *value);
|
||||
void ovni_attr_set_json(const char *key, const char *json);
|
||||
double ovni_attr_get_double(const char *key);
|
||||
int ovni_attr_get_boolean(const char *key);
|
||||
const char *ovni_attr_get_str(const char *key);
|
||||
char *ovni_attr_get_json(const char *key);
|
||||
void ovni_attr_flush(void);
|
||||
|
||||
/* Mark */
|
||||
enum ovni_mark_flags {
|
||||
OVNI_MARK_STACK = 1, /*< Use push/pop instead of set */
|
||||
};
|
||||
void ovni_mark_type(int32_t type, long flags, const char *title);
|
||||
void ovni_mark_label(int32_t type, int64_t value, const char *label);
|
||||
void ovni_mark_push(int32_t type, int64_t value);
|
||||
void ovni_mark_pop(int32_t type, int64_t value);
|
||||
void ovni_mark_set(int32_t type, int64_t value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -27,7 +27,6 @@ nav:
|
||||
- user/installation.md
|
||||
- 'Runtime':
|
||||
- user/runtime/tracing.md
|
||||
- user/runtime/mark.md
|
||||
- user/runtime/distributed.md
|
||||
- user/runtime/kernel.md
|
||||
- user/runtime/trace_spec.md
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "common.h"
|
||||
@ -45,7 +45,7 @@ vaerr(const char *prefix, const char *func, const char *errstr, va_list ap)
|
||||
|
||||
vfprintf(stderr, errstr, ap);
|
||||
|
||||
int len = (int) strlen(errstr);
|
||||
int len = strlen(errstr);
|
||||
|
||||
if (len > 0) {
|
||||
char last = errstr[len - 1];
|
||||
@ -103,7 +103,7 @@ mkpath(const char *path, mode_t mode, int is_dir)
|
||||
char *copypath = strdup(path);
|
||||
|
||||
/* Remove trailing slash */
|
||||
int last = (int) strlen(path) - 1;
|
||||
int last = strlen(path) - 1;
|
||||
while (last > 0 && copypath[last] == '/')
|
||||
copypath[last--] = '\0';
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
extern int is_debug_enabled;
|
||||
|
||||
@ -19,8 +18,8 @@ int mkpath(const char *path, mode_t mode, int is_dir);
|
||||
void progname_set(char *name);
|
||||
const char *progname_get(void);
|
||||
void enable_debug(void);
|
||||
void verr(const char *prefix, const char *func, const char *errstr, ...) __attribute__((format(printf, 3, 4)));
|
||||
void vdie(const char *prefix, const char *func, const char *errstr, ...) __attribute__((format(printf, 3, 4)));
|
||||
void verr(const char *prefix, const char *func, const char *errstr, ...);
|
||||
void vdie(const char *prefix, const char *func, const char *errstr, ...);
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
|
@ -49,11 +49,9 @@ add_library(emu STATIC
|
||||
value.c
|
||||
ovni/event.c
|
||||
ovni/setup.c
|
||||
ovni/mark.c
|
||||
nanos6/setup.c
|
||||
nanos6/event.c
|
||||
nanos6/breakdown.c
|
||||
nosv/breakdown.c
|
||||
nosv/setup.c
|
||||
nosv/event.c
|
||||
nodes/setup.c
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "bay.h"
|
||||
@ -106,7 +106,7 @@ bay_add_cb(struct bay *bay, enum bay_cb_type type,
|
||||
cb->func = func;
|
||||
cb->arg = arg;
|
||||
cb->bchan = bchan;
|
||||
cb->type = (int) type;
|
||||
cb->type = type;
|
||||
cb->enabled = 0;
|
||||
|
||||
if (enabled)
|
||||
@ -168,7 +168,7 @@ propagate_chan(struct bay_chan *bchan, enum bay_cb_type type)
|
||||
struct bay_cb *cur = NULL;
|
||||
/* New callbacks cannot be added while propagating a bay_chan */
|
||||
DL_FOREACH(bchan->cb[type], cur) {
|
||||
dbg("calling cb %"PRIxPTR, (uintptr_t) cur->func);
|
||||
dbg("calling cb %p", cur->func);
|
||||
if (cur->func(bchan->chan, cur->arg) != 0) {
|
||||
err("callback failed for %s", bchan->chan->name);
|
||||
return -1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "body.h"
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "chan.h"
|
||||
@ -15,11 +15,9 @@ chan_init(struct chan *chan, enum chan_type type, const char *fmt, ...)
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
size_t n = ARRAYLEN(chan->name);
|
||||
int n = ARRAYLEN(chan->name);
|
||||
int ret = vsnprintf(chan->name, n, fmt, ap);
|
||||
if (ret < 0)
|
||||
die("vsnprintf failed");
|
||||
else if ((size_t) ret >= n)
|
||||
if (ret >= n)
|
||||
die("channel name too long");
|
||||
va_end(ap);
|
||||
|
||||
@ -157,7 +155,7 @@ chan_push(struct chan *chan, struct value value)
|
||||
/** Remove one value from the stack. Fails if the top of the stack
|
||||
* doesn't match the expected value.
|
||||
*
|
||||
* @param evalue The expected value on the top of the stack.
|
||||
* @param expected The expected value on the top of the stack.
|
||||
*
|
||||
* @return On success returns 0, otherwise returns -1.
|
||||
*/
|
||||
@ -184,10 +182,10 @@ chan_pop(struct chan *chan, struct value evalue)
|
||||
struct value *value = &stack->values[stack->n - 1];
|
||||
|
||||
if (!value_is_equal(value, &evalue)) {
|
||||
err("%s: expected value %s different from top of stack %s",
|
||||
err("%s: unexpected value %s (expected %s)",
|
||||
chan->name,
|
||||
value_str(evalue),
|
||||
value_str(*value));
|
||||
value_str(*value),
|
||||
value_str(evalue));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#ifndef CHAN_H
|
||||
@ -70,7 +70,7 @@ chan_read(struct chan *chan, struct value *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void chan_init(struct chan *chan, enum chan_type type, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
|
||||
void chan_init(struct chan *chan, enum chan_type type, const char *fmt, ...);
|
||||
USE_RET int chan_set(struct chan *chan, struct value value);
|
||||
USE_RET int chan_push(struct chan *chan, struct value value);
|
||||
USE_RET int chan_pop(struct chan *chan, struct value expected);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "clkoff.h"
|
||||
@ -59,7 +59,7 @@ cparse(struct clkoff *table, FILE *file)
|
||||
if (buf[0] == '\n')
|
||||
continue;
|
||||
|
||||
int ret = sscanf(buf, "%" SCNd64 "%s %lf %lf %lf",
|
||||
int ret = sscanf(buf, "%ld %s %lf %lf %lf",
|
||||
&e.index, e.name,
|
||||
&e.median, &e.mean, &e.stdev);
|
||||
|
||||
@ -95,7 +95,7 @@ cindex(struct clkoff *table)
|
||||
return -1;
|
||||
}
|
||||
|
||||
table->index = calloc((size_t) table->nentries, sizeof(struct clkoff_entry *));
|
||||
table->index = calloc(table->nentries, sizeof(struct clkoff_entry *));
|
||||
|
||||
if (table->index == NULL) {
|
||||
err("calloc failed");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "cpu.h"
|
||||
@ -17,7 +17,7 @@
|
||||
#include "utlist.h"
|
||||
#include "value.h"
|
||||
|
||||
static const char chan_fmt[] = "cpu%"PRIi64".%s";
|
||||
static const char chan_fmt[] = "cpu%ld.%s";
|
||||
static const char *chan_name[CPU_CHAN_MAX] = {
|
||||
[CPU_CHAN_NRUN] = "nrunning",
|
||||
[CPU_CHAN_PID] = "pid_running",
|
||||
@ -78,14 +78,14 @@ cpu_set_loom(struct cpu *cpu, struct loom *loom)
|
||||
static int
|
||||
set_name(struct cpu *cpu)
|
||||
{
|
||||
size_t i = (size_t) loom_get_gindex(cpu->loom);
|
||||
size_t j = (size_t) cpu_get_phyid(cpu);
|
||||
size_t i = loom_get_gindex(cpu->loom);
|
||||
size_t j = cpu_get_phyid(cpu);
|
||||
int n;
|
||||
|
||||
if (cpu->is_virtual)
|
||||
n = snprintf(cpu->name, PATH_MAX, "vCPU %zu.*", i);
|
||||
n = snprintf(cpu->name, PATH_MAX, "vCPU %ld.*", i);
|
||||
else
|
||||
n = snprintf(cpu->name, PATH_MAX, " CPU %zu.%zu", i, j);
|
||||
n = snprintf(cpu->name, PATH_MAX, " CPU %ld.%ld", i, j);
|
||||
|
||||
if (n >= PATH_MAX) {
|
||||
err("cpu name too long");
|
||||
@ -162,7 +162,7 @@ cpu_connect(struct cpu *cpu, struct bay *bay, struct recorder *rec)
|
||||
if (type < 0)
|
||||
continue;
|
||||
|
||||
long row = (long) cpu->gindex;
|
||||
long row = cpu->gindex;
|
||||
long flags = prv_flags[i];
|
||||
if (prv_register(prv, row, type, bay, c, flags)) {
|
||||
err("prv_register failed");
|
||||
@ -176,7 +176,7 @@ cpu_connect(struct cpu *cpu, struct bay *bay, struct recorder *rec)
|
||||
struct pcf_value *
|
||||
cpu_add_to_pcf_type(struct cpu *cpu, struct pcf_type *type)
|
||||
{
|
||||
return pcf_add_value(type, (int) cpu->gindex + 1, cpu->name);
|
||||
return pcf_add_value(type, cpu->gindex + 1, cpu->name);
|
||||
}
|
||||
|
||||
static struct thread *
|
||||
@ -215,12 +215,12 @@ cpu_update(struct cpu *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
cpu->nth_running = (size_t) running;
|
||||
cpu->nth_active = (size_t) active;
|
||||
cpu->nth_running = running;
|
||||
cpu->nth_active = active;
|
||||
|
||||
/* Only virtual cpus can be oversubscribed */
|
||||
if (cpu->nth_running > 1 && !cpu->is_virtual) {
|
||||
err("physical cpu %s has %zd threads running at the same time",
|
||||
err("physical cpu %s has %d threads running at the same time",
|
||||
cpu->name, cpu->nth_running);
|
||||
return -1;
|
||||
}
|
||||
@ -248,7 +248,7 @@ cpu_update(struct cpu *cpu)
|
||||
err("chan_set pid failed");
|
||||
return -1;
|
||||
}
|
||||
dbg("cpu%"PRIi64" sets th_running to %s",
|
||||
dbg("cpu%ld sets th_running to %s",
|
||||
cpu->gindex, value_str(gid_running));
|
||||
if (chan_set(&cpu->chan[CPU_CHAN_THRUN], gid_running) != 0) {
|
||||
err("chan_set gid_running failed");
|
||||
@ -265,7 +265,7 @@ cpu_update(struct cpu *cpu)
|
||||
}
|
||||
|
||||
/* Update nth_running number in the channel */
|
||||
if (chan_set(&cpu->chan[CPU_CHAN_NRUN], value_int64((int64_t) running)) != 0) {
|
||||
if (chan_set(&cpu->chan[CPU_CHAN_NRUN], value_int64(running)) != 0) {
|
||||
err("chan_set nth_running failed");
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "emu.h"
|
||||
@ -118,18 +118,18 @@ panic(struct emu *emu)
|
||||
if (emu->ev != NULL) {
|
||||
err("event: ");
|
||||
err(" mcv=%s", emu->ev->mcv);
|
||||
err(" rclock=%"PRIi64, emu->ev->rclock);
|
||||
err(" sclock=%"PRIi64, emu->ev->sclock);
|
||||
err(" dclock=%"PRIi64, emu->ev->dclock);
|
||||
err(" payload_size=%zd", emu->ev->payload_size);
|
||||
err(" rclock=%ld", emu->ev->rclock);
|
||||
err(" sclock=%ld", emu->ev->sclock);
|
||||
err(" dclock=%ld", emu->ev->dclock);
|
||||
err(" payload_size=%ld", emu->ev->payload_size);
|
||||
err(" is_jumbo=%d", emu->ev->is_jumbo);
|
||||
}
|
||||
|
||||
if (emu->stream != NULL) {
|
||||
err("stream: ");
|
||||
err(" relpath=%s", emu->stream->relpath);
|
||||
err(" offset=%"PRIi64, emu->stream->offset);
|
||||
err(" clock_offset=%"PRIi64, emu->stream->clock_offset);
|
||||
err(" offset=%ld", emu->stream->offset);
|
||||
err(" clock_offset=%ld", emu->stream->clock_offset);
|
||||
}
|
||||
err("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||
}
|
||||
@ -156,7 +156,7 @@ emu_step(struct emu *emu)
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbg("----- mcv=%s dclock=%"PRIi64" -----", emu->ev->mcv, emu->ev->dclock);
|
||||
dbg("----- mvc=%s dclock=%ld -----", emu->ev->mcv, emu->ev->dclock);
|
||||
|
||||
emu_stat_update(&emu->stat, &emu->player);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "emu_ev.h"
|
||||
@ -13,11 +13,11 @@ emu_ev(struct emu_ev *ev, const struct ovni_ev *oev,
|
||||
ev->v = oev->header.value;
|
||||
ev->mcv[3] = '\0';
|
||||
|
||||
ev->rclock = (int64_t) oev->header.clock;
|
||||
ev->rclock = oev->header.clock;
|
||||
ev->sclock = sclock;
|
||||
ev->dclock = dclock;
|
||||
|
||||
ev->payload_size = (size_t) ovni_payload_size(oev);
|
||||
ev->payload_size = ovni_payload_size(oev);
|
||||
|
||||
if (ev->payload_size > 0) {
|
||||
ev->has_payload = 1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#ifndef EMU_PRV_H
|
||||
@ -19,8 +19,6 @@ enum emu_prv_types {
|
||||
PRV_NOSV_SUBSYSTEM = 13,
|
||||
PRV_NOSV_RANK = 14,
|
||||
PRV_NOSV_BODYID = 15,
|
||||
PRV_NOSV_IDLE = 16,
|
||||
PRV_NOSV_BREAKDOWN = 17,
|
||||
PRV_TAMPI_SUBSYSTEM = 20,
|
||||
PRV_MPI_FUNCTION = 25,
|
||||
PRV_NODES_SUBSYSTEM = 30,
|
||||
@ -33,9 +31,7 @@ enum emu_prv_types {
|
||||
PRV_NANOS6_BREAKDOWN = 41,
|
||||
PRV_KERNEL_CS = 45,
|
||||
PRV_OPENMP_SUBSYSTEM = 50,
|
||||
PRV_OVNI_MARK = 100,
|
||||
/* User marks [100, 200) */
|
||||
PRV_RESERVED = 200,
|
||||
PRV_RESERVED = 100,
|
||||
};
|
||||
|
||||
#endif /* EMU_PRV_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "emu_stat.h"
|
||||
@ -54,9 +54,11 @@ emu_stat_report(struct emu_stat *stat, struct player *player, int last)
|
||||
double speed = stat->average ? avgspeed : instspeed;
|
||||
|
||||
if (last) {
|
||||
int tmin = (int) (time_elapsed / 60.0);
|
||||
int tsec = (int) ((time_elapsed / 60.0 - tmin) * 60.0);
|
||||
info("%5.1f%% done at avg %.0f kev/s \n",
|
||||
progress * 100.0, avgspeed * 1e-3);
|
||||
info("processed %"PRIi64" input events in %.2f s\n",
|
||||
progress * 100.0, avgspeed * 1e-3, tmin, tsec);
|
||||
info("processed %ld input events in %.2f s\n",
|
||||
nprocessed, time_elapsed);
|
||||
} else {
|
||||
int tmin = (int) (time_left / 60.0);
|
||||
|
@ -104,7 +104,7 @@ parse_arg(struct ev_spec *spec, char *arg)
|
||||
}
|
||||
|
||||
/* Copy name */
|
||||
size_t n = (size_t) snprintf(argspec->name, sizeof(argspec->name), "%s", name);
|
||||
size_t n = snprintf(argspec->name, sizeof(argspec->name), "%s", name);
|
||||
if (n >= sizeof(argspec->name)) {
|
||||
err("argument name too long: %s", name);
|
||||
return -1;
|
||||
@ -363,9 +363,8 @@ print_arg(struct ev_arg *arg, const char *fmt, struct cursor *c, struct emu_ev *
|
||||
|
||||
#define CASE(TYPE) \
|
||||
do { \
|
||||
TYPE data; \
|
||||
memcpy(&data, &payload[arg->offset], sizeof(data)); \
|
||||
n = snprintf(c->out, (size_t) c->len, fmt, data); \
|
||||
TYPE *data = (TYPE *) &payload[arg->offset]; \
|
||||
n = snprintf(c->out, c->len, fmt, *data); \
|
||||
if (n >= c->len) { \
|
||||
err("no space for argument"); \
|
||||
return -1; \
|
||||
@ -387,8 +386,8 @@ print_arg(struct ev_arg *arg, const char *fmt, struct cursor *c, struct emu_ev *
|
||||
char *data = (char *) &payload[arg->offset];
|
||||
/* Here we trust the input string to
|
||||
* contain a nil at the end */
|
||||
int n = snprintf(c->out, (size_t) c->len, fmt, data);
|
||||
if (n >= (int) c->len) {
|
||||
int n = snprintf(c->out, c->len, fmt, data);
|
||||
if (n >= c->len) {
|
||||
err("no space for string argument");
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#ifndef LOOM_H
|
||||
@ -14,7 +14,7 @@
|
||||
struct proc;
|
||||
|
||||
struct loom {
|
||||
int64_t gindex;
|
||||
size_t gindex;
|
||||
int is_init;
|
||||
|
||||
char name[PATH_MAX];
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "model_cpu.h"
|
||||
@ -27,7 +27,7 @@ get_model_cpu(struct cpu *cpu, int id)
|
||||
static int
|
||||
init_chan(struct model_cpu *cpu, const struct model_chan_spec *spec, int64_t gindex)
|
||||
{
|
||||
cpu->track = calloc((size_t) spec->nch, sizeof(struct track));
|
||||
cpu->track = calloc(spec->nch, sizeof(struct track));
|
||||
if (cpu->track == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
@ -40,8 +40,7 @@ init_chan(struct model_cpu *cpu, const struct model_chan_spec *spec, int64_t gin
|
||||
const char *ch_name = spec->ch_names[i];
|
||||
int track_mode = spec->track[i];
|
||||
|
||||
if (track_init(track, cpu->bay, TRACK_TYPE_TH, track_mode,
|
||||
"%s.cpu%"PRIi64".%s",
|
||||
if (track_init(track, cpu->bay, TRACK_TYPE_TH, track_mode, "%s.cpu%ld.%s",
|
||||
name, gindex, ch_name) != 0) {
|
||||
err("track_init failed");
|
||||
return -1;
|
||||
@ -108,7 +107,7 @@ connect_cpu(struct emu *emu, struct cpu *scpu, int id)
|
||||
|
||||
struct chan *sel = cpu_get_th_chan(scpu);
|
||||
|
||||
int64_t nthreads = (int64_t) emu->system.nthreads;
|
||||
int64_t nthreads = emu->system.nthreads;
|
||||
if (track_set_select(track, sel, NULL, nthreads) != 0) {
|
||||
err("track_select failed");
|
||||
return -1;
|
||||
|
@ -21,7 +21,7 @@ model_evspec_init(struct model_evspec *evspec, struct model_spec *spec)
|
||||
}
|
||||
|
||||
/* Preallocate a contiguous map, as we know the size */
|
||||
evspec->alloc = calloc((size_t) evspec->nevents, sizeof(struct ev_spec));
|
||||
evspec->alloc = calloc(evspec->nevents, sizeof(struct ev_spec));
|
||||
if (evspec->alloc == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "model_pvt.h"
|
||||
@ -35,7 +35,7 @@ create_values(const struct model_pvt_spec *pvt,
|
||||
return 0;
|
||||
|
||||
for (const struct pcf_value_label *p = q; p->label != NULL; p++) {
|
||||
if (pcf_add_value(t, (int) p->value, p->label) == NULL) {
|
||||
if (pcf_add_value(t, p->value, p->label) == NULL) {
|
||||
err("pcf_add_value failed");
|
||||
return -1;
|
||||
}
|
||||
@ -66,7 +66,7 @@ create_type(const struct model_pvt_spec *pvt,
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct pcf_type *pcftype = pcf_add_type(pcf, (int) type, label);
|
||||
struct pcf_type *pcftype = pcf_add_type(pcf, type, label);
|
||||
if (pcftype == NULL) {
|
||||
err("pcf_add_type failed");
|
||||
return -1;
|
||||
@ -106,7 +106,7 @@ connect_cpu_prv(struct emu *emu, struct cpu *scpu, struct prv *prv, int id)
|
||||
for (int i = 0; i < spec->nch; i++) {
|
||||
struct chan *out = track_get_output(&cpu->track[i]);
|
||||
long type = spec->pvt->type[i];
|
||||
long row = (long) scpu->gindex;
|
||||
long row = scpu->gindex;
|
||||
long flags = flags_arr ? flags_arr[i] : 0;
|
||||
if (prv_register(prv, row, type, &emu->bay, out, flags)) {
|
||||
err("prv_register failed");
|
||||
@ -158,7 +158,7 @@ connect_thread_prv(struct emu *emu, struct thread *sth, struct prv *prv, int id)
|
||||
for (int i = 0; i < spec->nch; i++) {
|
||||
struct chan *out = track_get_output(&th->track[i]);
|
||||
long type = spec->pvt->type[i];
|
||||
long row = (long) sth->gindex;
|
||||
long row = sth->gindex;
|
||||
long flags = flags_arr ? flags_arr[i] : 0;
|
||||
if (prv_register(prv, row, type, &emu->bay, out, flags)) {
|
||||
err("prv_register failed");
|
||||
@ -178,7 +178,7 @@ model_pvt_connect_thread(struct emu *emu, const struct model_thread_spec *spec)
|
||||
/* Get cpu PRV */
|
||||
struct pvt *pvt = recorder_find_pvt(&emu->recorder, "thread");
|
||||
if (pvt == NULL) {
|
||||
err("cannot find thread pvt");
|
||||
err("cannot find cpu pvt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "model_thread.h"
|
||||
@ -19,10 +19,10 @@
|
||||
static int
|
||||
init_chan(struct model_thread *th, const struct model_chan_spec *spec, int64_t gindex)
|
||||
{
|
||||
const char *fmt = "%s.thread%"PRIi64".%s";
|
||||
const char *fmt = "%s.thread%ld.%s";
|
||||
const char *prefix = spec->prefix;
|
||||
|
||||
th->ch = calloc((size_t) spec->nch, sizeof(struct chan));
|
||||
th->ch = calloc(spec->nch, sizeof(struct chan));
|
||||
if (th->ch == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
@ -30,7 +30,7 @@ init_chan(struct model_thread *th, const struct model_chan_spec *spec, int64_t g
|
||||
|
||||
for (int i = 0; i < spec->nch; i++) {
|
||||
struct chan *c = &th->ch[i];
|
||||
enum chan_type type = spec->ch_stack[i] ? CHAN_STACK : CHAN_SINGLE;
|
||||
int type = spec->ch_stack[i];
|
||||
const char *ch_name = spec->ch_names[i];
|
||||
chan_init(c, type, fmt, prefix, gindex, ch_name);
|
||||
|
||||
@ -45,7 +45,7 @@ init_chan(struct model_thread *th, const struct model_chan_spec *spec, int64_t g
|
||||
}
|
||||
}
|
||||
|
||||
th->track = calloc((size_t) spec->nch, sizeof(struct track));
|
||||
th->track = calloc(spec->nch, sizeof(struct track));
|
||||
if (th->track == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "mux.h"
|
||||
@ -25,7 +25,7 @@ default_select(struct mux *mux,
|
||||
int64_t index = key.i;
|
||||
|
||||
if (index < 0 || index >= mux->ninputs) {
|
||||
err("index out of bounds %"PRIi64, index);
|
||||
err("index out of bounds %ld", index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ mux_init(struct mux *mux,
|
||||
mux->select = select;
|
||||
mux->output = output;
|
||||
mux->ninputs = ninputs;
|
||||
mux->inputs = calloc((size_t) ninputs, sizeof(struct mux_input));
|
||||
mux->inputs = calloc(ninputs, sizeof(struct mux_input));
|
||||
mux->def = value_null();
|
||||
|
||||
if (mux->inputs == NULL) {
|
||||
@ -214,7 +214,7 @@ mux_set_input(struct mux *mux, int64_t index, struct chan *chan)
|
||||
struct mux_input *input = &mux->inputs[index];
|
||||
|
||||
if (input->chan != NULL) {
|
||||
err("input %"PRIi64" already has a channel", index);
|
||||
err("input %d already has a channel", index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -32,8 +32,8 @@ static int
|
||||
create_cpu(struct bay *bay, struct breakdown_cpu *bcpu, int64_t gindex)
|
||||
{
|
||||
enum chan_type t = CHAN_SINGLE;
|
||||
chan_init(&bcpu->tr, t, "nanos6.cpu%"PRIi64".breakdown.tr", gindex);
|
||||
chan_init(&bcpu->tri, t, "nanos6.cpu%"PRIi64".breakdown.tri", gindex);
|
||||
chan_init(&bcpu->tr, t, "nanos6.cpu%ld.breakdown.tr", gindex);
|
||||
chan_init(&bcpu->tri, t, "nanos6.cpu%ld.breakdown.tri", gindex);
|
||||
|
||||
/* Register all channels in the bay */
|
||||
if (bay_register(bay, &bcpu->tr) != 0) {
|
||||
@ -59,12 +59,12 @@ model_nanos6_breakdown_create(struct emu *emu)
|
||||
|
||||
/* Count phy cpus */
|
||||
struct system *sys = &emu->system;
|
||||
int64_t nphycpus = (int64_t) (sys->ncpus - sys->nlooms);
|
||||
int64_t nphycpus = sys->ncpus - sys->nlooms;
|
||||
bemu->nphycpus = nphycpus;
|
||||
|
||||
/* Create a new Paraver trace */
|
||||
struct recorder *rec = &emu->recorder;
|
||||
bemu->pvt = recorder_add_pvt(rec, "nanos6-breakdown", (long) nphycpus);
|
||||
bemu->pvt = recorder_add_pvt(rec, "nanos6-breakdown", nphycpus);
|
||||
if (bemu->pvt == NULL) {
|
||||
err("recorder_add_pvt failed");
|
||||
return -1;
|
||||
@ -131,7 +131,7 @@ select_tr(struct mux *mux, struct value value, struct mux_input **input)
|
||||
|
||||
int64_t i = in_body;
|
||||
char *inputs[] = { "subsystem", "task_type" };
|
||||
dbg("selecting input %"PRIi64" (%s)", i, inputs[i]);
|
||||
dbg("selecting input %ld (%s)", i, inputs[i]);
|
||||
*input = mux_get_input(mux, i);
|
||||
|
||||
return 0;
|
||||
@ -245,7 +245,7 @@ model_nanos6_breakdown_connect(struct emu *emu)
|
||||
flags |= PRV_ZERO;
|
||||
|
||||
struct chan *out = sort_get_output(&bemu->sort, i);
|
||||
if (prv_register(prv, (long) i, type, bay, out, flags)) {
|
||||
if (prv_register(prv, i, type, bay, out, flags)) {
|
||||
err("prv_register failed");
|
||||
return -1;
|
||||
}
|
||||
@ -268,7 +268,7 @@ model_nanos6_breakdown_finish(struct emu *emu,
|
||||
struct pcf *pcf = pvt_get_pcf(bemu->pvt);
|
||||
long typeid = PRV_NANOS6_BREAKDOWN;
|
||||
char label[] = "CPU: Nanos6 Runtime/Idle/Task breakdown";
|
||||
struct pcf_type *pcftype = pcf_add_type(pcf, (int) typeid, label);
|
||||
struct pcf_type *pcftype = pcf_add_type(pcf, typeid, label);
|
||||
const struct pcf_value_label *v = NULL;
|
||||
|
||||
/* Emit subsystem values */
|
||||
@ -302,12 +302,12 @@ model_nanos6_breakdown_finish(struct emu *emu,
|
||||
struct prf *prf = pvt_get_prf(bemu->pvt);
|
||||
for (int64_t row = 0; row < bemu->nphycpus; row++) {
|
||||
char name[128];
|
||||
if (snprintf(name, 128, "~CPU %4" PRIi64, bemu->nphycpus - row) >= 128) {
|
||||
if (snprintf(name, 128, "~CPU %4ld", bemu->nphycpus - row) >= 128) {
|
||||
err("label too long");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (prf_add(prf, (long) row, name) != 0) {
|
||||
if (prf_add(prf, row, name) != 0) {
|
||||
err("prf_add failed for %s", name);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "nanos6_priv.h"
|
||||
@ -299,7 +299,7 @@ update_task_state(struct emu *emu)
|
||||
static int
|
||||
expand_transition_value(struct emu *emu, int was_running, int runs_now, char *tr_p)
|
||||
{
|
||||
char tr = (char) emu->ev->v;
|
||||
char tr = emu->ev->v;
|
||||
|
||||
/* Ensure we don't clobber the value */
|
||||
if (tr == 'X' || tr == 'E') {
|
||||
@ -419,7 +419,7 @@ update_task(struct emu *emu)
|
||||
struct task *next = bnext == NULL ? NULL : body_get_task(bnext);
|
||||
|
||||
/* Update the subsystem channel */
|
||||
if (update_task_ss_channel(emu, (char) emu->ev->v) != 0) {
|
||||
if (update_task_ss_channel(emu, emu->ev->v) != 0) {
|
||||
err("update_task_ss_channel failed");
|
||||
return -1;
|
||||
}
|
||||
@ -467,7 +467,7 @@ create_task(struct emu *emu)
|
||||
* task, so we relax the model to allow this for now. */
|
||||
flags |= TASK_FLAG_RELAX_NESTING;
|
||||
|
||||
if (task_create(info, type_id, task_id, (uint32_t) flags) != 0) {
|
||||
if (task_create(info, type_id, task_id, flags) != 0) {
|
||||
err("task_create failed");
|
||||
return -1;
|
||||
}
|
||||
@ -521,8 +521,7 @@ pre_type(struct emu *emu)
|
||||
}
|
||||
|
||||
const uint8_t *data = &emu->ev->payload->jumbo.data[0];
|
||||
uint32_t typeid;
|
||||
memcpy(&typeid, data, 4); /* May be unaligned */
|
||||
uint32_t typeid = *(uint32_t *) data;
|
||||
data += 4;
|
||||
|
||||
const char *label = (const char *) data;
|
||||
|
@ -402,7 +402,7 @@ finish_pvt(struct emu *emu, const char *name)
|
||||
}
|
||||
struct pcf *pcf = pvt_get_pcf(pvt);
|
||||
long typeid = pvt_type[CH_TYPE];
|
||||
struct pcf_type *pcftype = pcf_find_type(pcf, (int) typeid);
|
||||
struct pcf_type *pcftype = pcf_find_type(pcf, typeid);
|
||||
|
||||
for (struct proc *p = sys->procs; p; p = p->gnext) {
|
||||
struct nanos6_proc *proc = EXT(p, model_id);
|
||||
|
@ -1,342 +0,0 @@
|
||||
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "breakdown.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "bay.h"
|
||||
#include "chan.h"
|
||||
#include "common.h"
|
||||
#include "cpu.h"
|
||||
#include "emu.h"
|
||||
#include "emu_args.h"
|
||||
#include "emu_prv.h"
|
||||
#include "extend.h"
|
||||
#include "model_cpu.h"
|
||||
#include "mux.h"
|
||||
#include "nosv_priv.h"
|
||||
#include "proc.h"
|
||||
#include "pv/pcf.h"
|
||||
#include "pv/prf.h"
|
||||
#include "pv/prv.h"
|
||||
#include "pv/pvt.h"
|
||||
#include "recorder.h"
|
||||
#include "sort.h"
|
||||
#include "system.h"
|
||||
#include "thread.h"
|
||||
#include "task.h"
|
||||
#include "track.h"
|
||||
#include "value.h"
|
||||
|
||||
|
||||
static int
|
||||
create_cpu(struct bay *bay, struct nosv_breakdown_cpu *bcpu, int64_t gindex)
|
||||
{
|
||||
enum chan_type t = CHAN_SINGLE;
|
||||
chan_init(&bcpu->tr, t, "nosv.cpu%"PRIi64".breakdown.tr", gindex);
|
||||
chan_init(&bcpu->tri, t, "nosv.cpu%"PRIi64".breakdown.tri", gindex);
|
||||
|
||||
/* Register all channels in the bay */
|
||||
if (bay_register(bay, &bcpu->tr) != 0) {
|
||||
err("bay_register tr failed");
|
||||
return -1;
|
||||
}
|
||||
if (bay_register(bay, &bcpu->tri) != 0) {
|
||||
err("bay_register tri failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
check_thread_metadata(struct thread *th)
|
||||
{
|
||||
if (th->meta == NULL) {
|
||||
err("thread has no metadata");
|
||||
return -1;
|
||||
}
|
||||
|
||||
JSON_Value *val = json_object_dotget_value(th->meta, "nosv.can_breakdown");
|
||||
if (val == NULL) {
|
||||
err("missing nosv.can_breakdown attribute");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!json_value_get_boolean(val)) {
|
||||
err("nosv.can_breakdown is false, missing events to enable breakdown");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
model_nosv_breakdown_create(struct emu *emu)
|
||||
{
|
||||
if (emu->args.breakdown == 0)
|
||||
return 0;
|
||||
|
||||
struct nosv_emu *memu = EXT(emu, 'V');
|
||||
struct nosv_breakdown_emu *bemu = &memu->breakdown;
|
||||
|
||||
/* Count phy cpus */
|
||||
struct system *sys = &emu->system;
|
||||
int64_t nphycpus = (int64_t) (sys->ncpus - sys->nlooms);
|
||||
bemu->nphycpus = nphycpus;
|
||||
|
||||
/* Create a new Paraver trace */
|
||||
struct recorder *rec = &emu->recorder;
|
||||
bemu->pvt = recorder_add_pvt(rec, "nosv-breakdown", (long) nphycpus);
|
||||
if (bemu->pvt == NULL) {
|
||||
err("recorder_add_pvt failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sort_init(&bemu->sort, &emu->bay, nphycpus, "nosv.breakdown.sort") != 0) {
|
||||
err("sort_init failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) {
|
||||
if (cpu->is_virtual)
|
||||
continue;
|
||||
|
||||
struct nosv_cpu *mcpu = EXT(cpu, 'V');
|
||||
struct nosv_breakdown_cpu *bcpu = &mcpu->breakdown;
|
||||
|
||||
if (create_cpu(&emu->bay, bcpu, cpu->gindex) != 0) {
|
||||
err("create_cpu failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (struct thread *th = emu->system.threads; th; th = th->gnext) {
|
||||
if (check_thread_metadata(th) != 0) {
|
||||
err("bad nosv metadata in thread: %s", th->id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
select_tr(struct mux *mux, struct value value, struct mux_input **input)
|
||||
{
|
||||
/* Only select the task if we are in ST_TASK_BODY and the task_type has
|
||||
* a non-null value */
|
||||
|
||||
int64_t in_body = (value.type == VALUE_INT64 && value.i == ST_TASK_BODY);
|
||||
|
||||
if (in_body) {
|
||||
struct value tt;
|
||||
struct mux_input *ttinput = mux_get_input(mux, 1);
|
||||
if (chan_read(ttinput->chan, &tt) != 0) {
|
||||
err("chan_read failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Only show task type if we have a task */
|
||||
if (tt.type == VALUE_NULL)
|
||||
in_body = 0;
|
||||
}
|
||||
|
||||
if (!in_body) {
|
||||
/* Only select ss if not NULL */
|
||||
struct value ss;
|
||||
struct mux_input *ssinput = mux_get_input(mux, 0);
|
||||
if (chan_read(ssinput->chan, &ss) != 0) {
|
||||
err("chan_read failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Don't select anything, so the default output is shown */
|
||||
if (ss.type == VALUE_NULL) {
|
||||
dbg("not selecting anything");
|
||||
*input = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t i = in_body;
|
||||
char *inputs[] = { "subsystem", "task_type" };
|
||||
dbg("selecting input %"PRIi64" (%s)", i, inputs[i]);
|
||||
*input = mux_get_input(mux, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
select_idle(struct mux *mux, struct value value, struct mux_input **input)
|
||||
{
|
||||
dbg("selecting tri output for value %s", value_str(value));
|
||||
|
||||
if (value.type == VALUE_INT64 && value.i == ST_PROGRESSING) {
|
||||
dbg("selecting input 0 (tr)");
|
||||
*input = mux_get_input(mux, 0);
|
||||
} else {
|
||||
dbg("selecting input 1 (idle)");
|
||||
*input = mux_get_input(mux, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
connect_cpu(struct bay *bay, struct nosv_cpu *mcpu)
|
||||
{
|
||||
struct nosv_breakdown_cpu *bcpu = &mcpu->breakdown;
|
||||
|
||||
/* Channel aliases */
|
||||
struct chan *ss = &mcpu->m.track[CH_SUBSYSTEM].ch;
|
||||
struct chan *tt = &mcpu->m.track[CH_TYPE].ch;
|
||||
struct chan *idle = &mcpu->m.track[CH_IDLE].ch;
|
||||
struct chan *tr = &bcpu->tr;
|
||||
struct chan *tri = &bcpu->tri;
|
||||
|
||||
/* Connect mux0 using ss as select */
|
||||
if (mux_init(&bcpu->mux0, bay, ss, tr, select_tr, 2) != 0) {
|
||||
err("mux_init failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mux_set_input(&bcpu->mux0, 0, ss) != 0) {
|
||||
err("mux_set_input ss failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mux_set_input(&bcpu->mux0, 1, tt) != 0) {
|
||||
err("mux_set_input tt failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Emit unknown subsystem on NULL */
|
||||
mux_set_default(&bcpu->mux0, value_int64(ST_UNKNOWN_SS));
|
||||
|
||||
/* Connect mux 1 using idle as select */
|
||||
if (mux_init(&bcpu->mux1, bay, idle, tri, select_idle, 2) != 0) {
|
||||
err("mux_init failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mux_set_input(&bcpu->mux1, 0, tr) != 0) {
|
||||
err("mux_set_input tr failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mux_set_input(&bcpu->mux1, 1, idle) != 0) {
|
||||
err("mux_set_input idle failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
model_nosv_breakdown_connect(struct emu *emu)
|
||||
{
|
||||
if (emu->args.breakdown == 0)
|
||||
return 0;
|
||||
|
||||
struct nosv_emu *memu = EXT(emu, 'V');
|
||||
struct nosv_breakdown_emu *bemu = &memu->breakdown;
|
||||
struct bay *bay = &emu->bay;
|
||||
struct system *sys = &emu->system;
|
||||
|
||||
int64_t i = 0;
|
||||
for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) {
|
||||
if (cpu->is_virtual)
|
||||
continue;
|
||||
|
||||
struct nosv_cpu *mcpu = EXT(cpu, 'V');
|
||||
struct nosv_breakdown_cpu *bcpu = &mcpu->breakdown;
|
||||
|
||||
/* Connect tr and tri channels and muxes */
|
||||
if (connect_cpu(bay, mcpu) != 0) {
|
||||
err("connect_cpu failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Connect tri to sort */
|
||||
if (sort_set_input(&bemu->sort, i, &bcpu->tri) != 0) {
|
||||
err("sort_set_input failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Connect out to PRV */
|
||||
struct prv *prv = pvt_get_prv(bemu->pvt);
|
||||
long type = PRV_NOSV_BREAKDOWN;
|
||||
long flags = PRV_SKIPDUP | PRV_ZERO;
|
||||
|
||||
struct chan *out = sort_get_output(&bemu->sort, i);
|
||||
if (prv_register(prv, (long) i, type, bay, out, flags)) {
|
||||
err("prv_register failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
model_nosv_breakdown_finish(struct emu *emu,
|
||||
const struct pcf_value_label **labels)
|
||||
{
|
||||
if (emu->args.breakdown == 0)
|
||||
return 0;
|
||||
|
||||
struct nosv_emu *memu = EXT(emu, 'V');
|
||||
struct nosv_breakdown_emu *bemu = &memu->breakdown;
|
||||
struct pcf *pcf = pvt_get_pcf(bemu->pvt);
|
||||
long typeid = PRV_NOSV_BREAKDOWN;
|
||||
char label[] = "CPU: nOS-V Runtime/Idle/Task breakdown";
|
||||
struct pcf_type *pcftype = pcf_add_type(pcf, (int) typeid, label);
|
||||
const struct pcf_value_label *v = NULL;
|
||||
|
||||
/* Emit subsystem values */
|
||||
for (v = labels[CH_SUBSYSTEM]; v->label; v++) {
|
||||
if (pcf_add_value(pcftype, v->value, v->label) == NULL) {
|
||||
err("pcf_add_value ss failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit idle values */
|
||||
for (v = labels[CH_IDLE]; v->label; v++) {
|
||||
if (pcf_add_value(pcftype, v->value, v->label) == NULL) {
|
||||
err("pcf_add_value idle failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit task_type values */
|
||||
struct system *sys = &emu->system;
|
||||
for (struct proc *p = sys->procs; p; p = p->gnext) {
|
||||
struct nosv_proc *proc = EXT(p, 'V');
|
||||
struct task_info *info = &proc->task_info;
|
||||
if (task_create_pcf_types(pcftype, info->types) != 0) {
|
||||
err("task_create_pcf_types failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Also populate the row labels */
|
||||
struct prf *prf = pvt_get_prf(bemu->pvt);
|
||||
for (int64_t row = 0; row < bemu->nphycpus; row++) {
|
||||
char name[128];
|
||||
if (snprintf(name, 128, "~CPU %4"PRIi64, bemu->nphycpus - row) >= 128) {
|
||||
err("label too long");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (prf_add(prf, (long) row, name) != 0) {
|
||||
err("prf_add failed for %s", name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#ifndef BREAKDOWN_H
|
||||
#define BREAKDOWN_H
|
||||
|
||||
/*
|
||||
* The breakdown model is implemented on top of the CPU subsystem, task_type and
|
||||
* idle channels. The first mux0 selects the task type when the subsystem
|
||||
* matches "Task body" otherwise forwards the subsystem as-is to tr. The second
|
||||
* mux1 selects tr only when the CPU is not Idle, otherwise sets the output tri
|
||||
* as Idle.
|
||||
*
|
||||
* +--------+
|
||||
* | |
|
||||
* | v
|
||||
* | +------+
|
||||
* subsystem -+-->--| |
|
||||
* | mux0 | +------+
|
||||
* task_type ---->--| |-->-- tr -->--| |
|
||||
* +------+ | mux1 |-->-- tri
|
||||
* idle --------->-------------------+->--| |
|
||||
* | +------+
|
||||
* | ^
|
||||
* | |
|
||||
* +--------+
|
||||
*
|
||||
* Then the sort module takes the output tri of each CPU and sorts the values
|
||||
* which are propagated to the PRV directly.
|
||||
*
|
||||
* +------+ +-----+
|
||||
* cpu0.tri --->---| |--->---| |
|
||||
* ... | sort | ... | PRV |
|
||||
* cpuN.tri --->---| |--->---| |
|
||||
* +------+ +-----+
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "chan.h"
|
||||
#include "mux.h"
|
||||
#include "sort.h"
|
||||
|
||||
struct nosv_breakdown_cpu {
|
||||
struct mux mux0;
|
||||
struct chan tr;
|
||||
struct mux mux1;
|
||||
struct chan tri;
|
||||
};
|
||||
|
||||
struct nosv_breakdown_emu {
|
||||
int64_t nphycpus;
|
||||
struct sort sort;
|
||||
struct pvt *pvt;
|
||||
};
|
||||
|
||||
#endif /* BREAKDOWN_H */
|
@ -16,7 +16,7 @@
|
||||
#include "thread.h"
|
||||
#include "value.h"
|
||||
|
||||
enum { PUSH = 1, POP = 2, SET = 3, IGN = 4 };
|
||||
enum { PUSH = 1, POP = 2, IGN = 3 };
|
||||
|
||||
#define CHSS CH_SUBSYSTEM
|
||||
|
||||
@ -77,11 +77,6 @@ static const int ss_table[256][256][3] = {
|
||||
['d'] = { CHSS, PUSH, ST_DELEGATE },
|
||||
['D'] = { CHSS, POP, ST_DELEGATE },
|
||||
},
|
||||
['P'] = {
|
||||
['p'] = { CH_IDLE, SET, ST_PROGRESSING },
|
||||
['r'] = { CH_IDLE, SET, ST_RESTING },
|
||||
['a'] = { CH_IDLE, SET, ST_ABSORBING },
|
||||
},
|
||||
};
|
||||
|
||||
static int
|
||||
@ -99,8 +94,6 @@ simple(struct emu *emu)
|
||||
return chan_push(ch, value_int64(st));
|
||||
} else if (action == POP) {
|
||||
return chan_pop(ch, value_int64(st));
|
||||
} else if (action == SET) {
|
||||
return chan_set(ch, value_int64(st));
|
||||
} else if (action == IGN) {
|
||||
return 0; /* do nothing */
|
||||
} else {
|
||||
@ -324,7 +317,7 @@ update_task_state(struct emu *emu)
|
||||
static int
|
||||
expand_transition_value(struct emu *emu, int was_running, int runs_now, char *tr_p)
|
||||
{
|
||||
char tr = (char) emu->ev->v;
|
||||
char tr = emu->ev->v;
|
||||
|
||||
/* Ensure we don't clobber the value */
|
||||
if (tr == 'X' || tr == 'E') {
|
||||
@ -441,7 +434,7 @@ update_task(struct emu *emu)
|
||||
struct body *next = task_get_running(stack);
|
||||
|
||||
/* Update the subsystem channel */
|
||||
if (update_task_ss_channel(emu, (char) emu->ev->v) != 0) {
|
||||
if (update_task_ss_channel(emu, emu->ev->v) != 0) {
|
||||
err("update_task_ss_channel failed");
|
||||
return -1;
|
||||
}
|
||||
@ -509,7 +502,7 @@ pre_task(struct emu *emu)
|
||||
switch (emu->ev->v) {
|
||||
case 'C':
|
||||
case 'c':
|
||||
ret = create_task(emu, (char) emu->ev->v);
|
||||
ret = create_task(emu, emu->ev->v);
|
||||
break;
|
||||
case 'x':
|
||||
case 'e':
|
||||
@ -546,8 +539,7 @@ pre_type(struct emu *emu)
|
||||
}
|
||||
|
||||
const uint8_t *data = &emu->ev->payload->jumbo.data[0];
|
||||
uint32_t typeid;
|
||||
memcpy(&typeid, data, 4); /* May be unaligned */
|
||||
uint32_t typeid = *(uint32_t *) data;
|
||||
data += 4;
|
||||
|
||||
const char *label = (const char *) data;
|
||||
@ -582,7 +574,6 @@ process_ev(struct emu *emu)
|
||||
case 'M':
|
||||
case 'H':
|
||||
case 'A':
|
||||
case 'P':
|
||||
return simple(emu);
|
||||
case 'T':
|
||||
return pre_task(emu);
|
||||
|
@ -4,7 +4,6 @@
|
||||
#ifndef NOSV_PRIV_H
|
||||
#define NOSV_PRIV_H
|
||||
|
||||
#include "breakdown.h"
|
||||
#include "emu.h"
|
||||
#include "task.h"
|
||||
#include "model_cpu.h"
|
||||
@ -19,12 +18,10 @@ enum nosv_chan {
|
||||
CH_APPID,
|
||||
CH_SUBSYSTEM,
|
||||
CH_RANK,
|
||||
CH_IDLE,
|
||||
CH_MAX,
|
||||
};
|
||||
|
||||
enum nosv_ss_values {
|
||||
ST_UNKNOWN_SS = 2,
|
||||
ST_SCHED_HUNGRY = 6,
|
||||
ST_SCHED_SERVING,
|
||||
ST_SCHED_SUBMITTING,
|
||||
@ -59,36 +56,16 @@ struct nosv_thread {
|
||||
|
||||
struct nosv_cpu {
|
||||
struct model_cpu m;
|
||||
struct nosv_breakdown_cpu breakdown;
|
||||
};
|
||||
|
||||
struct nosv_proc {
|
||||
struct task_info task_info;
|
||||
};
|
||||
|
||||
struct nosv_emu {
|
||||
int connected;
|
||||
int event;
|
||||
struct nosv_breakdown_emu breakdown;
|
||||
};
|
||||
|
||||
enum nosv_progress {
|
||||
/* Can mix with subsystem values */
|
||||
ST_PROGRESSING = 100,
|
||||
ST_RESTING,
|
||||
ST_ABSORBING,
|
||||
};
|
||||
|
||||
int model_nosv_probe(struct emu *emu);
|
||||
int model_nosv_create(struct emu *emu);
|
||||
int model_nosv_connect(struct emu *emu);
|
||||
int model_nosv_event(struct emu *emu);
|
||||
int model_nosv_finish(struct emu *emu);
|
||||
|
||||
int model_nosv_breakdown_create(struct emu *emu);
|
||||
int model_nosv_breakdown_connect(struct emu *emu);
|
||||
int model_nosv_breakdown_finish(struct emu *emu,
|
||||
const struct pcf_value_label **labels);
|
||||
|
||||
|
||||
#endif /* NOSV_PRIV_H */
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "chan.h"
|
||||
#include "cpu.h"
|
||||
#include "common.h"
|
||||
#include "emu.h"
|
||||
#include "emu_args.h"
|
||||
@ -73,16 +72,12 @@ static struct ev_decl model_evlist[] = {
|
||||
PAIR_B("VHw", "VHW", "execution as worker")
|
||||
PAIR_B("VHd", "VHD", "execution as delegate")
|
||||
|
||||
{ "VPp", "sets progress state to Progressing" },
|
||||
{ "VPr", "sets progress state to Resting" },
|
||||
{ "VPa", "sets progress state to Absorbing" },
|
||||
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
struct model_spec model_nosv = {
|
||||
.name = model_name,
|
||||
.version = "2.3.0",
|
||||
.version = "2.1.0",
|
||||
.evlist = model_evlist,
|
||||
.model = model_id,
|
||||
.create = model_nosv_create,
|
||||
@ -101,7 +96,6 @@ static const char *chan_name[CH_MAX] = {
|
||||
[CH_APPID] = "appid",
|
||||
[CH_SUBSYSTEM] = "subsystem",
|
||||
[CH_RANK] = "rank",
|
||||
[CH_IDLE] = "idle",
|
||||
};
|
||||
|
||||
static const int chan_stack[CH_MAX] = {
|
||||
@ -127,7 +121,6 @@ static const int pvt_type[CH_MAX] = {
|
||||
[CH_APPID] = PRV_NOSV_APPID,
|
||||
[CH_SUBSYSTEM] = PRV_NOSV_SUBSYSTEM,
|
||||
[CH_RANK] = PRV_NOSV_RANK,
|
||||
[CH_IDLE] = PRV_NOSV_IDLE,
|
||||
};
|
||||
|
||||
static const char *pcf_prefix[CH_MAX] = {
|
||||
@ -137,11 +130,9 @@ static const char *pcf_prefix[CH_MAX] = {
|
||||
[CH_APPID] = "nOS-V task AppID",
|
||||
[CH_SUBSYSTEM] = "nOS-V subsystem",
|
||||
[CH_RANK] = "nOS-V task MPI rank",
|
||||
[CH_IDLE] = "nOS-V idle state",
|
||||
};
|
||||
|
||||
static const struct pcf_value_label nosv_ss_values[] = {
|
||||
{ ST_UNKNOWN_SS, "Unknown subsystem" },
|
||||
{ ST_SCHED_HUNGRY, "Scheduler: Hungry" },
|
||||
{ ST_SCHED_SERVING, "Scheduler: Serving" },
|
||||
{ ST_SCHED_SUBMITTING, "Scheduler: Submitting" },
|
||||
@ -169,16 +160,8 @@ static const struct pcf_value_label nosv_ss_values[] = {
|
||||
{ -1, NULL },
|
||||
};
|
||||
|
||||
static const struct pcf_value_label nosv_worker_idle[] = {
|
||||
{ ST_PROGRESSING, "Progressing" },
|
||||
{ ST_RESTING, "Resting" },
|
||||
{ ST_ABSORBING, "Absorbing noise" },
|
||||
{ -1, NULL },
|
||||
};
|
||||
|
||||
static const struct pcf_value_label *pcf_labels[CH_MAX] = {
|
||||
[CH_SUBSYSTEM] = nosv_ss_values,
|
||||
[CH_IDLE] = nosv_worker_idle,
|
||||
};
|
||||
|
||||
static const long prv_flags[CH_MAX] = {
|
||||
@ -188,7 +171,6 @@ static const long prv_flags[CH_MAX] = {
|
||||
[CH_APPID] = PRV_SKIPDUPNULL, /* Switch to task of same appid */
|
||||
[CH_SUBSYSTEM] = PRV_SKIPDUPNULL,
|
||||
[CH_RANK] = PRV_SKIPDUPNULL, /* Switch to task of same rank */
|
||||
[CH_IDLE] = PRV_SKIPDUPNULL,
|
||||
};
|
||||
|
||||
static const struct model_pvt_spec pvt_spec = {
|
||||
@ -207,7 +189,6 @@ static const int th_track[CH_MAX] = {
|
||||
[CH_APPID] = TRACK_TH_RUN,
|
||||
[CH_SUBSYSTEM] = TRACK_TH_ACT,
|
||||
[CH_RANK] = TRACK_TH_RUN,
|
||||
[CH_IDLE] = TRACK_TH_RUN,
|
||||
};
|
||||
|
||||
static const int cpu_track[CH_MAX] = {
|
||||
@ -217,7 +198,6 @@ static const int cpu_track[CH_MAX] = {
|
||||
[CH_APPID] = TRACK_TH_RUN,
|
||||
[CH_SUBSYSTEM] = TRACK_TH_RUN,
|
||||
[CH_RANK] = TRACK_TH_RUN,
|
||||
[CH_IDLE] = TRACK_TH_RUN,
|
||||
};
|
||||
|
||||
/* ----------------- chan_spec ------------------ */
|
||||
@ -299,19 +279,6 @@ model_nosv_create(struct emu *emu)
|
||||
}
|
||||
}
|
||||
|
||||
struct nosv_emu *e = calloc(1, sizeof(struct nosv_emu));
|
||||
if (e == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
}
|
||||
|
||||
extend_set(&emu->ext, model_id, e);
|
||||
|
||||
if (model_nosv_breakdown_create(emu) != 0) {
|
||||
err("model_nosv_breakdown_create failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -328,28 +295,6 @@ model_nosv_connect(struct emu *emu)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (emu->args.breakdown && model_nosv_breakdown_connect(emu) != 0) {
|
||||
err("model_nosv_breakdown_connect failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (struct thread *th = emu->system.threads; th; th = th->gnext) {
|
||||
struct nosv_thread *mth = EXT(th, model_id);
|
||||
struct chan *idle = &mth->m.ch[CH_IDLE];
|
||||
/* By default set all threads as Progressing */
|
||||
if (chan_set(idle, value_int64(ST_PROGRESSING)) != 0) {
|
||||
err("chan_push idle failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (struct cpu *cpu = emu->system.cpus; cpu; cpu = cpu->next) {
|
||||
struct nosv_cpu *mcpu = EXT(cpu, model_id);
|
||||
struct mux *mux = &mcpu->m.track[CH_IDLE].mux;
|
||||
/* Emit Resting when a CPU has no running threads */
|
||||
mux_set_default(mux, value_int64(ST_RESTING));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -396,12 +341,8 @@ finish_pvt(struct emu *emu, const char *name)
|
||||
return -1;
|
||||
}
|
||||
struct pcf *pcf = pvt_get_pcf(pvt);
|
||||
int typeid = pvt_type[CH_TYPE];
|
||||
long typeid = pvt_type[CH_TYPE];
|
||||
struct pcf_type *pcftype = pcf_find_type(pcf, typeid);
|
||||
if (pcftype == NULL) {
|
||||
err("cannot find %s pcf type %d", name, typeid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (struct proc *p = sys->procs; p; p = p->gnext) {
|
||||
struct nosv_proc *proc = EXT(p, model_id);
|
||||
@ -429,11 +370,6 @@ model_nosv_finish(struct emu *emu)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (model_nosv_breakdown_finish(emu, pcf_labels) != 0) {
|
||||
err("model_nosv_breakdown_finish failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* When running in linter mode perform additional checks */
|
||||
if (emu->args.linter_mode && end_lint(emu) != 0) {
|
||||
err("end_lint failed");
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "proc.h"
|
||||
#include "thread.h"
|
||||
#include "value.h"
|
||||
#include "mark.h"
|
||||
|
||||
static int
|
||||
pre_thread_execute(struct emu *emu, struct thread *th)
|
||||
@ -229,7 +228,7 @@ pre_affinity_set(struct emu *emu)
|
||||
}
|
||||
|
||||
if (emu->ev->payload_size != 4) {
|
||||
err("unexpected payload size %zd", emu->ev->payload_size);
|
||||
err("unexpected payload size %d", emu->ev->payload_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -265,7 +264,7 @@ static int
|
||||
pre_affinity_remote(struct emu *emu)
|
||||
{
|
||||
if (emu->ev->payload_size != 8) {
|
||||
err("unexpected payload size %zd", emu->ev->payload_size);
|
||||
err("unexpected payload size %d", emu->ev->payload_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -390,18 +389,18 @@ pre_burst(struct emu *emu)
|
||||
for (int i = 0; i < n; i++)
|
||||
deltas[i] = th->burst_time[i + 1] - th->burst_time[i];
|
||||
|
||||
qsort(deltas, (size_t) n, sizeof(int64_t), compare_int64);
|
||||
qsort(deltas, n, sizeof(int64_t), compare_int64);
|
||||
|
||||
double avg = 0.0;
|
||||
double maxdelta = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
if ((double) deltas[i] > maxdelta)
|
||||
maxdelta = (double) deltas[i];
|
||||
avg += (double) deltas[i];
|
||||
if (deltas[i] > maxdelta)
|
||||
maxdelta = deltas[i];
|
||||
avg += deltas[i];
|
||||
}
|
||||
|
||||
avg /= (double) n;
|
||||
double median = (double) deltas[n / 2];
|
||||
double median = deltas[n / 2];
|
||||
|
||||
info("%s burst stats: median/avg/max = %3.0f/%3.0f/%3.0f ns",
|
||||
emu->loom->id, median, avg, maxdelta);
|
||||
@ -437,7 +436,7 @@ pre_flush(struct emu *emu)
|
||||
double flush_ms = (double) flush_ns * 1e-6;
|
||||
/* Avoid last flush warnings */
|
||||
if (flush_ms > 10.0 && emu->thread->is_running)
|
||||
warn("large flush of %.1f ms at dclock=%"PRIi64" ns in tid=%d",
|
||||
warn("large flush of %.1f ms at dclock=%ld ns in tid=%d",
|
||||
flush_ms,
|
||||
emu->ev->dclock,
|
||||
emu->thread->tid);
|
||||
@ -478,8 +477,6 @@ model_ovni_event(struct emu *emu)
|
||||
case 'U':
|
||||
/* Ignore sorting events */
|
||||
return 0;
|
||||
case 'M':
|
||||
return mark_event(emu);
|
||||
default:
|
||||
err("unknown ovni event category %c",
|
||||
emu->ev->c);
|
||||
|
@ -1,668 +0,0 @@
|
||||
#include "mark.h"
|
||||
|
||||
#include "chan.h"
|
||||
#include "cpu.h"
|
||||
#include "emu.h"
|
||||
#include "emu_ev.h"
|
||||
#include "emu_prv.h"
|
||||
#include "inttypes.h"
|
||||
#include "ovni.h"
|
||||
#include "ovni_priv.h"
|
||||
#include "parson.h"
|
||||
#include "pv/pcf.h"
|
||||
#include "pv/prv.h"
|
||||
#include "pv/pvt.h"
|
||||
#include "thread.h"
|
||||
#include "track.h"
|
||||
#include "uthash.h"
|
||||
#include <errno.h>
|
||||
|
||||
struct mark_label {
|
||||
int64_t value;
|
||||
char label[MAX_PCF_LABEL];
|
||||
UT_hash_handle hh; /* Indexed by value */
|
||||
};
|
||||
|
||||
struct mark_type {
|
||||
long type;
|
||||
long prvtype;
|
||||
long index; /* From 0 to ntypes - 1 */
|
||||
enum chan_type ctype;
|
||||
struct mark_label *labels; /* Hash table of labels */
|
||||
char title[MAX_PCF_LABEL];
|
||||
UT_hash_handle hh; /* Indexed by type */
|
||||
};
|
||||
|
||||
static int
|
||||
parse_number(const char *str, int64_t *result)
|
||||
{
|
||||
errno = 0;
|
||||
char *endptr = NULL;
|
||||
int64_t n = strtoll(str, &endptr, 10);
|
||||
|
||||
if (errno != 0 || endptr == str || endptr[0] != '\0') {
|
||||
err("failed to parse number: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*result = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mark_label *
|
||||
find_label(struct mark_type *t, int64_t value)
|
||||
{
|
||||
struct mark_label *l;
|
||||
HASH_FIND(hh, t->labels, &value, sizeof(value), l);
|
||||
return l;
|
||||
}
|
||||
|
||||
static int
|
||||
add_label(struct mark_type *t, int64_t value, const char *label)
|
||||
{
|
||||
struct mark_label *l = find_label(t, value);
|
||||
|
||||
if (l != NULL) {
|
||||
if (strcmp(l->label, label) == 0) {
|
||||
/* Already exists with the same label, all good */
|
||||
return 0;
|
||||
} else {
|
||||
err("mark value %" PRIi64 " already defined with label %s", value, l->label);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
l = calloc(1, sizeof(*l));
|
||||
if (l == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
}
|
||||
|
||||
l->value = value;
|
||||
|
||||
int len = snprintf(l->label, MAX_PCF_LABEL, "%s", label);
|
||||
if (len >= MAX_PCF_LABEL) {
|
||||
err("mark label too long: %s", label);
|
||||
return -1;
|
||||
}
|
||||
|
||||
HASH_ADD(hh, t->labels, value, sizeof(value), l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_labels(struct mark_type *t, JSON_Object *labels)
|
||||
{
|
||||
/* It may happen that we call this function several times with
|
||||
* overlapping subsets of values. The only restriction is that we don't
|
||||
* define two values with different label. */
|
||||
|
||||
size_t n = json_object_get_count(labels);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
const char *valuestr = json_object_get_name(labels, i);
|
||||
if (valuestr == NULL) {
|
||||
err("json_object_get_name failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t value;
|
||||
if (parse_number(valuestr, &value) != 0) {
|
||||
err("parse_number failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
JSON_Value *labelval = json_object_get_value_at(labels, i);
|
||||
if (labelval == NULL) {
|
||||
err("json_object_get_value_at failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *label = json_value_get_string(labelval);
|
||||
if (label == NULL) {
|
||||
err("json_value_get_string() for label failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (add_label(t, value, label) != 0) {
|
||||
err("add_label() failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mark_type *
|
||||
find_mark_type(struct ovni_mark_emu *m, long type)
|
||||
{
|
||||
struct mark_type *t;
|
||||
HASH_FIND_LONG(m->types, &type, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
static struct mark_type *
|
||||
create_mark_type(struct ovni_mark_emu *m, long type, enum chan_type ctype, const char *title)
|
||||
{
|
||||
struct mark_type *t = find_mark_type(m, type);
|
||||
|
||||
if (t != NULL) {
|
||||
err("mark type %ld already defined", type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t = calloc(1, sizeof(*t));
|
||||
if (t == NULL) {
|
||||
err("calloc failed:");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t->type = type;
|
||||
t->ctype = ctype;
|
||||
t->prvtype = type + PRV_OVNI_MARK;
|
||||
t->index = m->ntypes;
|
||||
|
||||
int len = snprintf(t->title, MAX_PCF_LABEL, "%s", title);
|
||||
if (len >= MAX_PCF_LABEL) {
|
||||
err("mark title too long: %s", title);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HASH_ADD_LONG(m->types, type, t);
|
||||
m->ntypes++;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_mark(struct ovni_mark_emu *m, const char *typestr, JSON_Value *markval)
|
||||
{
|
||||
errno = 0;
|
||||
char *endptr = NULL;
|
||||
long type = strtol(typestr, &endptr, 10);
|
||||
|
||||
if (errno != 0 || endptr == typestr || endptr[0] != '\0') {
|
||||
err("failed to parse type number: %s", typestr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (type < 0 || type >= 100) {
|
||||
err("mark type should be in [0, 100) range: %ld", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
JSON_Object *mark = json_value_get_object(markval);
|
||||
if (mark == NULL) {
|
||||
err("json_value_get_object() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *title = json_object_get_string(mark, "title");
|
||||
if (title == NULL) {
|
||||
err("json_object_get_string() for title failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *chan_type = json_object_get_string(mark, "chan_type");
|
||||
if (chan_type == NULL) {
|
||||
err("json_object_get_string() for chan_type failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
enum chan_type ctype;
|
||||
if (strcmp(chan_type, "single") == 0) {
|
||||
ctype = CHAN_SINGLE;
|
||||
} else if (strcmp(chan_type, "stack") == 0) {
|
||||
ctype = CHAN_STACK;
|
||||
} else {
|
||||
err("chan_type %s not understood", chan_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct mark_type *t = find_mark_type(m, type);
|
||||
if (t == NULL) {
|
||||
t = create_mark_type(m, type, ctype, title);
|
||||
if (t == NULL) {
|
||||
err("cannot create mark type");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* It may already exist as defined by other threads, so ensure
|
||||
* they have the same title. */
|
||||
if (strcmp(t->title, title) != 0) {
|
||||
err("mark with type %ld already registered with another title", type);
|
||||
err(" old: %s", t->title);
|
||||
err(" new: %s", title);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* And also the same channel type */
|
||||
if (t->ctype != ctype) {
|
||||
err("mark with type %ld already registered with another channel type", type);
|
||||
err(" old: %s", t->ctype == CHAN_SINGLE ? "single" : "stack");
|
||||
err(" new: %s", ctype == CHAN_SINGLE ? "single" : "stack");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* The labels are optional */
|
||||
if (json_object_has_value(mark, "labels")) {
|
||||
|
||||
JSON_Object *labels = json_object_get_object(mark, "labels");
|
||||
if (labels == NULL) {
|
||||
err("json_object_get_object() for labels failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now populate the mark type with all value labels */
|
||||
|
||||
if (parse_labels(t, labels) != 0) {
|
||||
err("cannot parse labels");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
scan_thread(struct ovni_mark_emu *memu, struct thread *t)
|
||||
{
|
||||
JSON_Object *obj = json_object_dotget_object(t->meta, "ovni.mark");
|
||||
|
||||
/* No marks in this thread */
|
||||
if (obj == NULL)
|
||||
return 0;
|
||||
|
||||
size_t n = json_object_get_count(obj);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
const char *typestr = json_object_get_name(obj, i);
|
||||
if (typestr == NULL) {
|
||||
err("json_object_get_name failed");
|
||||
return -1;
|
||||
}
|
||||
JSON_Value *markval = json_object_get_value_at(obj, i);
|
||||
if (markval == NULL) {
|
||||
err("json_object_get_value_at failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parse_mark(memu, typestr, markval) != 0) {
|
||||
err("cannot parse mark");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_thread_chan(struct ovni_mark_emu *m, struct bay *bay, struct thread *th)
|
||||
{
|
||||
struct ovni_thread *oth = EXT(th, 'O');
|
||||
struct ovni_mark_thread *t = &oth->mark;
|
||||
|
||||
/* Create as many channels as required */
|
||||
t->channels = calloc((size_t) m->ntypes, sizeof(struct chan));
|
||||
if (t->channels == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
}
|
||||
|
||||
t->nchannels = m->ntypes;
|
||||
|
||||
struct mark_type *type;
|
||||
for (type = m->types; type; type = type->hh.next) {
|
||||
/* TODO: We may use a vector of thread channels in every type to
|
||||
* avoid the double hash access in events */
|
||||
long i = type->index;
|
||||
struct chan *ch = &t->channels[i];
|
||||
chan_init(ch, type->ctype, "thread%"PRIi64".mark%ld",
|
||||
th->gindex, type->type);
|
||||
|
||||
/* Allow duplicates */
|
||||
chan_prop_set(ch, CHAN_ALLOW_DUP, 1);
|
||||
|
||||
if (bay_register(bay, ch) != 0) {
|
||||
err("bay_register failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup tracking */
|
||||
t->track = calloc((size_t) m->ntypes, sizeof(struct track));
|
||||
if (t->track == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (type = m->types; type; type = type->hh.next) {
|
||||
long i = type->index;
|
||||
struct track *track = &t->track[i];
|
||||
/* For now only tracking to active thread is supported */
|
||||
if (track_init(track, bay, TRACK_TYPE_TH, TRACK_TH_ACT,
|
||||
"thread%"PRIi64".mark%ld",
|
||||
th->gindex, type->type) != 0) {
|
||||
err("track_init failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
init_cpu(struct ovni_mark_emu *m, struct bay *bay, struct cpu *cpu)
|
||||
{
|
||||
struct ovni_cpu *ocpu = EXT(cpu, 'O');
|
||||
struct ovni_mark_cpu *c = &ocpu->mark;
|
||||
|
||||
/* Setup tracking */
|
||||
c->track = calloc((size_t) m->ntypes, sizeof(struct track));
|
||||
if (c->track == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct mark_type *type;
|
||||
for (type = m->types; type; type = type->hh.next) {
|
||||
long i = type->index;
|
||||
struct track *track = &c->track[i];
|
||||
/* For now only tracking to running thread is supported */
|
||||
if (track_init(track, bay, TRACK_TYPE_TH, TRACK_TH_RUN,
|
||||
"cpu%"PRIi64".mark%ld",
|
||||
cpu->gindex, type->type) != 0) {
|
||||
err("track_init failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Scans streams for marks and creates the mark channels */
|
||||
int
|
||||
mark_create(struct emu *emu)
|
||||
{
|
||||
struct ovni_emu *oemu = EXT(emu, 'O');
|
||||
struct ovni_mark_emu *memu = &oemu->mark;
|
||||
|
||||
memset(memu, 0, sizeof(*memu));
|
||||
|
||||
for (struct thread *th = emu->system.threads; th; th = th->gnext) {
|
||||
if (scan_thread(memu, th) != 0) {
|
||||
err("scan_thread failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (memu->ntypes == 0)
|
||||
return 0;
|
||||
|
||||
for (struct thread *th = emu->system.threads; th; th = th->gnext) {
|
||||
if (create_thread_chan(memu, &emu->bay, th) != 0) {
|
||||
err("create_thread_chan failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (struct cpu *cpu = emu->system.cpus; cpu; cpu = cpu->next) {
|
||||
if (init_cpu(memu, &emu->bay, cpu) != 0) {
|
||||
err("init_cpu failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
connect_thread_prv(struct emu *emu, struct thread *sth, struct prv *prv)
|
||||
{
|
||||
struct ovni_emu *oemu = EXT(emu, 'O');
|
||||
struct ovni_mark_emu *memu = &oemu->mark;
|
||||
struct ovni_thread *oth = EXT(sth, 'O');
|
||||
struct ovni_mark_thread *mth = &oth->mark;
|
||||
|
||||
|
||||
for (struct mark_type *type = memu->types; type; type = type->hh.next) {
|
||||
/* TODO: We may use a vector of thread channels in every type to
|
||||
* avoid the double hash access in events */
|
||||
long i = type->index;
|
||||
struct chan *ch = &mth->channels[i];
|
||||
struct track *track = &mth->track[i];
|
||||
struct chan *sel = &sth->chan[TH_CHAN_STATE];
|
||||
|
||||
/* Connect the input and sel channel to the mux */
|
||||
if (track_connect_thread(track, ch, sel, 1) != 0) {
|
||||
err("track_connect_thread failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Then connect the output of the tracking module to the prv
|
||||
* trace for the current thread */
|
||||
struct chan *out = track_get_output(track);
|
||||
long row = (long) sth->gindex;
|
||||
long flags = PRV_SKIPDUPNULL;
|
||||
long prvtype = type->prvtype;
|
||||
if (prv_register(prv, row, prvtype, &emu->bay, out, flags)) {
|
||||
err("prv_register failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_type(struct pcf *pcf, struct mark_type *type)
|
||||
{
|
||||
struct pcf_type *pcftype = pcf_add_type(pcf, (int) type->prvtype, type->title);
|
||||
if (pcftype == NULL) {
|
||||
err("pcf_add_type failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (struct mark_label *l = type->labels; l; l = l->hh.next) {
|
||||
if (pcf_add_value(pcftype, (int) l->value, l->label) == NULL) {
|
||||
err("pcf_add_value failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
init_pcf(struct emu *emu, struct pcf *pcf)
|
||||
{
|
||||
struct ovni_emu *oemu = EXT(emu, 'O');
|
||||
struct ovni_mark_emu *m = &oemu->mark;
|
||||
|
||||
for (struct mark_type *type = m->types; type; type = type->hh.next) {
|
||||
if (create_type(pcf, type) != 0) {
|
||||
err("create_type failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
connect_thread(struct emu *emu)
|
||||
{
|
||||
/* Get cpu PRV */
|
||||
struct pvt *pvt = recorder_find_pvt(&emu->recorder, "thread");
|
||||
if (pvt == NULL) {
|
||||
err("cannot find thread pvt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Connect thread channels to PRV */
|
||||
struct prv *prv = pvt_get_prv(pvt);
|
||||
for (struct thread *t = emu->system.threads; t; t = t->gnext) {
|
||||
if (connect_thread_prv(emu, t, prv) != 0) {
|
||||
err("connect_thread_prv failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init thread PCF */
|
||||
struct pcf *pcf = pvt_get_pcf(pvt);
|
||||
if (init_pcf(emu, pcf) != 0) {
|
||||
err("init_pcf failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
connect_cpu_prv(struct emu *emu, struct cpu *scpu, struct prv *prv)
|
||||
{
|
||||
struct ovni_emu *oemu = EXT(emu, 'O');
|
||||
struct ovni_mark_emu *memu = &oemu->mark;
|
||||
struct ovni_cpu *ocpu = EXT(scpu, 'O');
|
||||
struct ovni_mark_cpu *mcpu = &ocpu->mark;
|
||||
|
||||
|
||||
for (struct mark_type *type = memu->types; type; type = type->hh.next) {
|
||||
/* NOTE: We may use a vector of thread channels in every type to
|
||||
* avoid the double hash access in events */
|
||||
long i = type->index;
|
||||
struct track *track = &mcpu->track[i];
|
||||
struct chan *sel = cpu_get_th_chan(scpu);
|
||||
|
||||
int64_t nthreads = (int64_t) emu->system.nthreads;
|
||||
if (track_set_select(track, sel, NULL, nthreads) != 0) {
|
||||
err("track_select failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add each thread as input */
|
||||
for (struct thread *t = emu->system.threads; t; t = t->gnext) {
|
||||
struct ovni_thread *oth = EXT(t, 'O');
|
||||
struct ovni_mark_thread *mth = &oth->mark;
|
||||
|
||||
/* Use the input thread directly */
|
||||
struct chan *inp = &mth->channels[i];
|
||||
|
||||
if (track_set_input(track, t->gindex, inp) != 0) {
|
||||
err("track_add_input failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then connect the output of the tracking module to the prv
|
||||
* trace for the current thread */
|
||||
struct chan *out = track_get_output(track);
|
||||
long row = (long) scpu->gindex;
|
||||
long flags = PRV_SKIPDUPNULL;
|
||||
long prvtype = type->prvtype;
|
||||
if (prv_register(prv, row, prvtype, &emu->bay, out, flags)) {
|
||||
err("prv_register failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
connect_cpu(struct emu *emu)
|
||||
{
|
||||
/* Get cpu PRV */
|
||||
struct pvt *pvt = recorder_find_pvt(&emu->recorder, "cpu");
|
||||
if (pvt == NULL) {
|
||||
err("cannot find thread pvt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Connect cpu channels to PRV */
|
||||
struct prv *prv = pvt_get_prv(pvt);
|
||||
for (struct cpu *cpu = emu->system.cpus; cpu; cpu = cpu->next) {
|
||||
if (connect_cpu_prv(emu, cpu, prv) != 0) {
|
||||
err("connect_cpu_prv failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init thread PCF */
|
||||
struct pcf *pcf = pvt_get_pcf(pvt);
|
||||
if (init_pcf(emu, pcf) != 0) {
|
||||
err("init_pcf failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Connect the channels to the output PVTs */
|
||||
int
|
||||
mark_connect(struct emu *emu)
|
||||
{
|
||||
struct ovni_emu *oemu = EXT(emu, 'O');
|
||||
struct ovni_mark_emu *memu = &oemu->mark;
|
||||
|
||||
if (memu->ntypes == 0)
|
||||
return 0;
|
||||
|
||||
if (connect_thread(emu) != 0) {
|
||||
err("connect_thread() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect_cpu(emu) != 0) {
|
||||
err("connect_cpu() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mark_event(struct emu *emu)
|
||||
{
|
||||
if (emu->ev->payload_size != 8 + 4) {
|
||||
err("unexpected payload size %zd", emu->ev->payload_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ovni_emu *oemu = EXT(emu, 'O');
|
||||
struct ovni_mark_emu *memu = &oemu->mark;
|
||||
|
||||
int64_t value = emu->ev->payload->i64[0];
|
||||
long type = (long) emu->ev->payload->i32[2]; /* always fits */
|
||||
|
||||
struct mark_type *mc = find_mark_type(memu, type);
|
||||
|
||||
if (mc == NULL) {
|
||||
err("cannot find mark with type %ld", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (value == 0) {
|
||||
err("mark value cannot be zero, type %ld", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long index = mc->index;
|
||||
struct ovni_thread *oth = EXT(emu->thread, 'O');
|
||||
struct ovni_mark_thread *mth = &oth->mark;
|
||||
|
||||
struct chan *ch = &mth->channels[index];
|
||||
|
||||
switch (emu->ev->v) {
|
||||
case '[':
|
||||
return chan_push(ch, value_int64(value));
|
||||
case ']':
|
||||
return chan_pop(ch, value_int64(value));
|
||||
case '=':
|
||||
return chan_set(ch, value_int64(value));
|
||||
default:
|
||||
err("unknown mark event value %c", emu->ev->v);
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#ifndef MARK_H
|
||||
#define MARK_H
|
||||
|
||||
#include "common.h"
|
||||
#include "chan.h"
|
||||
|
||||
struct emu;
|
||||
struct mark_chan;
|
||||
|
||||
struct ovni_mark_emu {
|
||||
/* Hash table of types of marks */
|
||||
struct mark_type *types;
|
||||
long ntypes;
|
||||
};
|
||||
|
||||
struct ovni_mark_thread {
|
||||
struct track *track;
|
||||
struct chan *channels;
|
||||
long nchannels;
|
||||
};
|
||||
|
||||
struct ovni_mark_cpu {
|
||||
struct track *track;
|
||||
};
|
||||
|
||||
USE_RET int mark_create(struct emu *emu);
|
||||
USE_RET int mark_connect(struct emu *emu);
|
||||
USE_RET int mark_event(struct emu *emu);
|
||||
|
||||
#endif /* MARK_H */
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#ifndef OVNI_PRIV_H
|
||||
@ -10,7 +10,6 @@
|
||||
* execution by the kernel. */
|
||||
|
||||
#include "emu.h"
|
||||
#include "mark.h"
|
||||
#include "model_cpu.h"
|
||||
#include "model_thread.h"
|
||||
#include <stdint.h>
|
||||
@ -34,17 +33,10 @@ struct ovni_thread {
|
||||
int64_t burst_time[MAX_BURSTS];
|
||||
|
||||
int64_t flush_start;
|
||||
|
||||
struct ovni_mark_thread mark;
|
||||
};
|
||||
|
||||
struct ovni_cpu {
|
||||
struct model_cpu m;
|
||||
struct ovni_mark_cpu mark;
|
||||
};
|
||||
|
||||
struct ovni_emu {
|
||||
struct ovni_mark_emu mark;
|
||||
};
|
||||
|
||||
int model_ovni_probe(struct emu *emu);
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "emu.h"
|
||||
#include "emu_prv.h"
|
||||
#include "ev_spec.h"
|
||||
#include "mark.h"
|
||||
#include "model.h"
|
||||
#include "model_chan.h"
|
||||
#include "model_cpu.h"
|
||||
@ -38,16 +37,12 @@ static struct ev_decl model_evlist[] = {
|
||||
PAIR_B("OF[", "OF]", "flushing events to disk")
|
||||
PAIR_E("OU[", "OU]", "unordered event region")
|
||||
|
||||
{ "OM[(i64 value, i32 type)", "push mark with value %{value} from type %{type}" },
|
||||
{ "OM](i64 value, i32 type)", "pop mark with value %{value} from type %{type}" },
|
||||
{ "OM=(i64 value, i32 type)", "set mark with value %{value} from type %{type}" },
|
||||
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
struct model_spec model_ovni = {
|
||||
.name = model_name,
|
||||
.version = "1.1.0",
|
||||
.version = "1.0.0",
|
||||
.evlist = model_evlist,
|
||||
.model = model_id,
|
||||
.create = model_ovni_create,
|
||||
@ -180,19 +175,6 @@ model_ovni_create(struct emu *emu)
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ovni_emu *oemu = calloc(1, sizeof(*oemu));
|
||||
if (oemu == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
}
|
||||
|
||||
extend_set(&emu->ext, 'O', oemu);
|
||||
|
||||
if (mark_create(emu) != 0) {
|
||||
err("mark_create failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -209,11 +191,6 @@ model_ovni_connect(struct emu *emu)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mark_connect(emu) != 0) {
|
||||
err("mark_connect failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ emit(struct model *model, struct player *player)
|
||||
struct emu_ev *ev = player_ev(player);
|
||||
struct stream *stream = player_stream(player);
|
||||
|
||||
printf("%10" PRIi64 " %c%c%c %s ",
|
||||
printf("%10ld %c%c%c %s ",
|
||||
ev->rclock,
|
||||
ev->m,
|
||||
ev->c,
|
||||
|
@ -20,7 +20,7 @@ static int
|
||||
html_encode(char *dst, int ndst, const char *src)
|
||||
{
|
||||
int j = 0;
|
||||
int nsrc = (int) strlen(src);
|
||||
int nsrc = strlen(src);
|
||||
|
||||
for (int i = 0; i < nsrc; i++) {
|
||||
/* Simple check */
|
||||
@ -29,7 +29,7 @@ html_encode(char *dst, int ndst, const char *src)
|
||||
return -1;
|
||||
}
|
||||
|
||||
char c = src[i];
|
||||
int c = src[i];
|
||||
switch (c) {
|
||||
case '&': strcpy(&dst[j], "&"); j += 5; break;
|
||||
case '"': strcpy(&dst[j], """); j += 6; break;
|
||||
@ -87,7 +87,7 @@ print_model(struct model_spec *spec)
|
||||
printf("<dl>\n");
|
||||
for (long j = 0; j < spec->evspec->nevents; j++) {
|
||||
if (print_event(spec, j) != 0) {
|
||||
err("cannot print event %ld", j);
|
||||
err("cannot print event %d", j);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
/* This program is a really bad idea. It attempts to sort streams by using a
|
||||
@ -74,20 +74,6 @@ ring_add(struct ring *r, struct ovni_ev *ev)
|
||||
r->head = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ring_check(struct ring *r, long long start)
|
||||
{
|
||||
uint64_t last_clock = 0;
|
||||
for (long long i = start; i != r->tail; i = (i + 1) % r->size) {
|
||||
uint64_t clock = r->ev[i]->header.clock;
|
||||
if (clock < last_clock) {
|
||||
die("ring not sorted at i=%lld, last_clock=%"PRIu64" clock=%"PRIu64 ,
|
||||
i, last_clock, clock);
|
||||
}
|
||||
last_clock = clock;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
find_destination(struct ring *r, uint64_t clock)
|
||||
{
|
||||
@ -100,7 +86,7 @@ find_destination(struct ring *r, uint64_t clock)
|
||||
for (ssize_t i = start; i != end; i = i - 1 < 0 ? r->size - 1 : i - 1) {
|
||||
last_clock = r->ev[i]->header.clock;
|
||||
if (last_clock < clock) {
|
||||
dbg("found suitable position %zd events backwards",
|
||||
dbg("found suitable position %ld events backwards",
|
||||
nback);
|
||||
return i;
|
||||
}
|
||||
@ -114,14 +100,14 @@ find_destination(struct ring *r, uint64_t clock)
|
||||
if (r->head != 0)
|
||||
die("ring head expected to be 0");
|
||||
if (r->tail >= r->size - 1)
|
||||
die("ring tail=%zd expected to be less than %zd", r->tail, r->size - 1);
|
||||
die("ring tail=%ld expected to be less than %ld", r->tail, r->size - 1);
|
||||
|
||||
dbg("starting of ring with nback=%zd", nback);
|
||||
dbg("starting of ring with nback=%ld", nback);
|
||||
return r->head;
|
||||
}
|
||||
|
||||
err("cannot find a event previous to clock %"PRIu64, clock);
|
||||
err("nback=%zd, last_clock=%"PRIu64, nback, last_clock);
|
||||
err("cannot find a event previous to clock %lu", clock);
|
||||
err("nback=%ld, last_clock=%lu", nback, last_clock);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -193,11 +179,11 @@ write_events(struct ovni_ev **table, long n, uint8_t *buf)
|
||||
{
|
||||
for (long i = 0; i < n; i++) {
|
||||
struct ovni_ev *ev = table[i];
|
||||
size_t size = (size_t) ovni_ev_size(ev);
|
||||
size_t size = ovni_ev_size(ev);
|
||||
memcpy(buf, ev, size);
|
||||
buf += size;
|
||||
|
||||
dbg("injected event %c%c%c at %"PRIu64,
|
||||
dbg("injected event %c%c%c at %ld",
|
||||
ev->header.model,
|
||||
ev->header.category,
|
||||
ev->header.value,
|
||||
@ -214,8 +200,8 @@ cmp_ev(const void *a, const void *b)
|
||||
struct ovni_ev *ev1 = *pev1;
|
||||
struct ovni_ev *ev2 = *pev2;
|
||||
|
||||
int64_t clock1 = (int64_t) ev1->header.clock;
|
||||
int64_t clock2 = (int64_t) ev2->header.clock;
|
||||
int64_t clock1 = ev1->header.clock;
|
||||
int64_t clock2 = ev2->header.clock;
|
||||
|
||||
if (clock1 < clock2)
|
||||
return -1;
|
||||
@ -230,29 +216,29 @@ sort_buf(uint8_t *src, uint8_t *buf, int64_t bufsize)
|
||||
{
|
||||
struct ovni_ev *ev = (struct ovni_ev *) src;
|
||||
|
||||
dbg("first event before sorting %c%c%c at %"PRIu64,
|
||||
dbg("first event before sorting %c%c%c at %ld",
|
||||
ev->header.model,
|
||||
ev->header.category,
|
||||
ev->header.value,
|
||||
ev->header.clock);
|
||||
|
||||
/* Create a copy of the array */
|
||||
uint8_t *buf2 = malloc((size_t) bufsize);
|
||||
uint8_t *buf2 = malloc(bufsize);
|
||||
if (buf2 == NULL)
|
||||
die("malloc failed:");
|
||||
|
||||
memcpy(buf2, src, (size_t) bufsize);
|
||||
memcpy(buf2, src, bufsize);
|
||||
|
||||
long n = count_events(buf2, buf2 + bufsize);
|
||||
struct ovni_ev **table = calloc((size_t) n, sizeof(struct ovni_ev *));
|
||||
struct ovni_ev **table = calloc(n, sizeof(struct ovni_ev *));
|
||||
if (table == NULL)
|
||||
die("calloc failed:");
|
||||
|
||||
index_events(table, n, buf2);
|
||||
qsort(table, (size_t) n, sizeof(struct ovni_ev *), cmp_ev);
|
||||
qsort(table, n, sizeof(struct ovni_ev *), cmp_ev);
|
||||
write_events(table, n, buf);
|
||||
|
||||
dbg("first event after sorting %c%c%c at %"PRIu64,
|
||||
dbg("first event after sorting %c%c%c at %ld",
|
||||
ev->header.model,
|
||||
ev->header.category,
|
||||
ev->header.value,
|
||||
@ -268,71 +254,44 @@ static void
|
||||
write_stream(int fd, void *base, void *dst, const void *src, size_t size)
|
||||
{
|
||||
while (size > 0) {
|
||||
off_t offset = (off_t) dst - (off_t) base;
|
||||
off_t offset = (off_t) ((int64_t) dst - (int64_t) base);
|
||||
ssize_t written = pwrite(fd, src, size, offset);
|
||||
|
||||
if (written < 0)
|
||||
die("pwrite failed:");
|
||||
|
||||
size -= (size_t) written;
|
||||
size -= written;
|
||||
src = (void *) (((uint8_t *) src) + written);
|
||||
dst = (void *) (((uint8_t *) dst) + written);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rebuild_ring(struct ring *r, long long start, struct ovni_ev *first, struct ovni_ev *last)
|
||||
{
|
||||
long long nbad = 0;
|
||||
long long n = 0;
|
||||
struct ovni_ev *ev = first;
|
||||
|
||||
for (long long i = start; i != r->tail; i = i + 1 >= r->size ? 0 : i + 1) {
|
||||
n++;
|
||||
if (ev != r->ev[i])
|
||||
nbad++;
|
||||
|
||||
if (ev >= last)
|
||||
die("exceeding last pointer");
|
||||
|
||||
r->ev[i] = ev;
|
||||
size_t size = (size_t) ovni_ev_size(ev);
|
||||
ev = (struct ovni_ev *) (((uint8_t *) ev) + size);
|
||||
}
|
||||
|
||||
if (ev != last)
|
||||
die("inconsistency: ev != last");
|
||||
|
||||
dbg("rebuilt ring with %lld / %lld misplaced events", nbad, n);
|
||||
}
|
||||
|
||||
static int
|
||||
execute_sort_plan(struct sortplan *sp)
|
||||
{
|
||||
uint64_t clock0 = sp->bad0->header.clock;
|
||||
dbg("attempt to sort: start clock %"PRIi64, sp->bad0->header.clock);
|
||||
dbg("attempt to sort: start clock %ld", sp->bad0->header.clock);
|
||||
|
||||
uint64_t min_clock = find_min_clock((void *) sp->bad0, (void *) sp->next);
|
||||
|
||||
if (min_clock < clock0) {
|
||||
clock0 = min_clock;
|
||||
dbg("region not sorted, using min clock=%"PRIi64, clock0);
|
||||
dbg("region not sorted, using min clock=%ld", clock0);
|
||||
}
|
||||
|
||||
/* Cannot sort in one pass; just fail for now */
|
||||
int64_t i0 = find_destination(sp->r, clock0);
|
||||
if (i0 < 0) {
|
||||
err("cannot find destination for region starting at clock %"PRIi64, clock0);
|
||||
err("cannot find destination for region starting at clock %ld", clock0);
|
||||
err("consider increasing the look back size with -n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the pointer to the first event that may be affected */
|
||||
struct ovni_ev *first = sp->r->ev[i0];
|
||||
long long dirty = i0;
|
||||
|
||||
/* Allocate a working buffer */
|
||||
uintptr_t bufsize = (uintptr_t) sp->next - (uintptr_t) first;
|
||||
int64_t bufsize = ((int64_t) sp->next) - ((int64_t) first);
|
||||
|
||||
if (bufsize <= 0)
|
||||
die("bufsize is non-positive");
|
||||
@ -341,19 +300,12 @@ execute_sort_plan(struct sortplan *sp)
|
||||
if (!buf)
|
||||
die("malloc failed:");
|
||||
|
||||
sort_buf((uint8_t *) first, buf, (int64_t) bufsize);
|
||||
sort_buf((uint8_t *) first, buf, bufsize);
|
||||
|
||||
write_stream(sp->fd, sp->base, first, buf, bufsize);
|
||||
|
||||
free(buf);
|
||||
|
||||
/* Pointers from the ring buffer are invalid now, rebuild them */
|
||||
rebuild_ring(sp->r, dirty, first, sp->next);
|
||||
|
||||
/* Invariant: The ring buffer is always sorted here. Check from the
|
||||
* dirty position onwards, so we avoid scanning all events. */
|
||||
ring_check(sp->r, dirty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -423,7 +375,7 @@ stream_winsort(struct stream *stream, struct ring *r)
|
||||
}
|
||||
|
||||
if (empty_regions > 0)
|
||||
warn("stream %s contains %zd empty sort regions",
|
||||
warn("stream %s contains %ld empty sort regions",
|
||||
stream->relpath, empty_regions);
|
||||
|
||||
if (updated && fdatasync(fd) < 0)
|
||||
@ -458,7 +410,7 @@ stream_check(struct stream *stream)
|
||||
uint64_t cur_clock = ovni_ev_get_clock(ev);
|
||||
|
||||
if (cur_clock < last_clock) {
|
||||
err("backwards jump in time %"PRIi64" -> %"PRIi64" for stream %s",
|
||||
err("backwards jump in time %ld -> %ld for stream %s",
|
||||
last_clock, cur_clock, stream->relpath);
|
||||
backjump = 1;
|
||||
}
|
||||
@ -483,8 +435,8 @@ process_trace(struct trace *trace)
|
||||
struct ring ring;
|
||||
int ret = 0;
|
||||
|
||||
ring.size = (ssize_t) max_look_back;
|
||||
ring.ev = malloc((size_t) ring.size * sizeof(struct ovni_ev *));
|
||||
ring.size = max_look_back;
|
||||
ring.ev = malloc(ring.size * sizeof(struct ovni_ev *));
|
||||
|
||||
if (ring.ev == NULL)
|
||||
die("malloc failed:");
|
||||
@ -531,7 +483,7 @@ usage(void)
|
||||
rerr("Sorts the events in each stream of the trace given in\n");
|
||||
rerr("tracedir, so they are suitable for the emulator ovniemu.\n");
|
||||
rerr("Only the events enclosed by OU[ OU] are sorted. At most a\n");
|
||||
rerr("total of %zd events are looked back to insert the unsorted\n",
|
||||
rerr("total of %ld events are looked back to insert the unsorted\n",
|
||||
max_look_back);
|
||||
rerr("events, so the sort procedure can fail with an error.\n");
|
||||
rerr("\n");
|
||||
@ -540,7 +492,7 @@ usage(void)
|
||||
rerr(" trace is already sorted.\n");
|
||||
rerr("\n");
|
||||
rerr(" -n Set the number of events to look back.\n");
|
||||
rerr(" Default: %zd\n", max_look_back);
|
||||
rerr(" Defaul: %ld\n", max_look_back);
|
||||
rerr("\n");
|
||||
rerr(" tracedir The trace directory generated by ovni.\n");
|
||||
rerr("\n");
|
||||
@ -559,7 +511,7 @@ parse_args(int argc, char *argv[])
|
||||
operation_mode = CHECK;
|
||||
break;
|
||||
case 'n':
|
||||
max_look_back = (size_t) atol(optarg);
|
||||
max_look_back = atol(optarg);
|
||||
break;
|
||||
default: /* '?' */
|
||||
usage();
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <errno.h>
|
||||
@ -182,7 +182,7 @@ fill_offset(struct offset *offset, int nsamples)
|
||||
static void
|
||||
offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int verbose)
|
||||
{
|
||||
double *delta = malloc(sizeof(double) * (size_t) nsamples);
|
||||
double *delta = malloc(sizeof(double) * nsamples);
|
||||
|
||||
if (delta == NULL) {
|
||||
perror("malloc");
|
||||
@ -199,7 +199,7 @@ offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int v
|
||||
}
|
||||
}
|
||||
|
||||
qsort(delta, (size_t) nsamples, sizeof(double), cmp_double);
|
||||
qsort(delta, nsamples, sizeof(double), cmp_double);
|
||||
|
||||
cur->delta_median = delta[nsamples / 2];
|
||||
cur->delta_mean = 0;
|
||||
@ -223,14 +223,14 @@ offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int v
|
||||
static size_t
|
||||
offset_size(int nsamples)
|
||||
{
|
||||
return sizeof(struct offset) + sizeof(double) * (size_t) nsamples;
|
||||
return sizeof(struct offset) + sizeof(double) * nsamples;
|
||||
}
|
||||
|
||||
static struct offset *
|
||||
table_get_offset(struct offset_table *table, int i, int nsamples)
|
||||
{
|
||||
char *p = (char *) table->_offset;
|
||||
p += (size_t) i * offset_size(nsamples);
|
||||
p += i * offset_size(nsamples);
|
||||
|
||||
return (struct offset *) p;
|
||||
}
|
||||
@ -252,14 +252,14 @@ build_offset_table(int nsamples, int rank, int verbose)
|
||||
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &table->nprocs);
|
||||
|
||||
table->_offset = calloc((size_t) table->nprocs, offset_size(nsamples));
|
||||
table->_offset = calloc(table->nprocs, offset_size(nsamples));
|
||||
|
||||
if (table->_offset == NULL) {
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
table->offset = malloc(sizeof(struct offset *) * (size_t) table->nprocs);
|
||||
table->offset = malloc(sizeof(struct offset *) * table->nprocs);
|
||||
|
||||
if (table->offset == NULL) {
|
||||
perror("malloc");
|
||||
@ -288,8 +288,8 @@ build_offset_table(int nsamples, int rank, int verbose)
|
||||
void *sendbuf = rank == 0 ? MPI_IN_PLACE : offset;
|
||||
|
||||
/* Then collect all the offsets into the rank 0 */
|
||||
MPI_Gather(sendbuf, (int) offset_size(nsamples), MPI_CHAR,
|
||||
offset, (int) offset_size(nsamples), MPI_CHAR,
|
||||
MPI_Gather(sendbuf, offset_size(nsamples), MPI_CHAR,
|
||||
offset, offset_size(nsamples), MPI_CHAR,
|
||||
0, MPI_COMM_WORLD);
|
||||
|
||||
/* Finish the offsets by computing the deltas on rank 0 */
|
||||
@ -399,7 +399,7 @@ do_work(struct options *options, int rank)
|
||||
}
|
||||
|
||||
if (drift_mode)
|
||||
sleep((unsigned) options->drift_wait);
|
||||
sleep(options->drift_wait);
|
||||
}
|
||||
|
||||
if (rank == 0)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "path.h"
|
||||
@ -95,7 +95,7 @@ path_keep(char *path, int n)
|
||||
void
|
||||
path_remove_trailing(char *path)
|
||||
{
|
||||
int n = (int) strlen(path);
|
||||
int n = strlen(path);
|
||||
for (int i = n - 1; i >= 0 && path[i] == '/'; i--) {
|
||||
path[i] = '\0';
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "player.h"
|
||||
@ -164,7 +164,7 @@ update_clocks(struct player *player, struct stream *stream)
|
||||
}
|
||||
|
||||
if (sclock < player->lastclock) {
|
||||
err("backwards jump in time %"PRIi64" -> %"PRIi64" in stream '%s'",
|
||||
err("backwards jump in time %ld -> %ld in stream '%s'",
|
||||
player->lastclock, sclock, stream->relpath);
|
||||
if (player->unsorted == 0)
|
||||
return -1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "prf.h"
|
||||
@ -20,7 +20,7 @@ prf_open(struct prf *prf, const char *path, long nrows)
|
||||
}
|
||||
|
||||
prf->nrows = nrows;
|
||||
prf->rows = calloc((size_t) nrows, sizeof(struct prf_row));
|
||||
prf->rows = calloc(nrows, sizeof(struct prf_row));
|
||||
|
||||
if (prf->rows == NULL) {
|
||||
err("calloc failed:");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "prv.h"
|
||||
@ -25,7 +25,7 @@ prv_open_file(struct prv *prv, long nrows, FILE *file)
|
||||
prv->file = file;
|
||||
|
||||
/* Write fake header to allocate the space */
|
||||
write_header(file, 0LL, (int) nrows);
|
||||
write_header(file, 0LL, nrows);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -48,7 +48,7 @@ prv_close(struct prv *prv)
|
||||
{
|
||||
/* Fix the header with the current duration */
|
||||
fseek(prv->file, 0, SEEK_SET);
|
||||
write_header(prv->file, prv->time, (int) prv->nrows);
|
||||
write_header(prv->file, prv->time, prv->nrows);
|
||||
fclose(prv->file);
|
||||
return 0;
|
||||
}
|
||||
@ -69,9 +69,9 @@ find_prv_chan(struct prv *prv, long id)
|
||||
}
|
||||
|
||||
static void
|
||||
write_line(struct prv *prv, long row_base1, int64_t type, int64_t value)
|
||||
write_line(struct prv *prv, long row_base1, long type, long value)
|
||||
{
|
||||
fprintf(prv->file, "2:0:1:1:%ld:%"PRIi64":%"PRIi64":%"PRIi64"\n",
|
||||
fprintf(prv->file, "2:0:1:1:%ld:%ld:%ld:%ld\n",
|
||||
row_base1, prv->time, type, value);
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ emit(struct prv *prv, struct prv_chan *rchan)
|
||||
}
|
||||
|
||||
/* Assume null */
|
||||
int64_t val = 0;
|
||||
long val = 0;
|
||||
if (likely(value.type == VALUE_INT64)) {
|
||||
val = value.i;
|
||||
if (rchan->flags & PRV_NEXT)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "sort.h"
|
||||
@ -106,8 +106,8 @@ sort_cb_input(struct chan *in_chan, void *ptr)
|
||||
if (likely(sort->copied)) {
|
||||
sort_replace(sort->sorted, sort->n, old, new);
|
||||
} else {
|
||||
memcpy(sort->sorted, sort->values, (size_t) sort->n * sizeof(int64_t));
|
||||
qsort(sort->sorted, (size_t) sort->n, sizeof(int64_t), cmp_int64);
|
||||
memcpy(sort->sorted, sort->values, sort->n * sizeof(int64_t));
|
||||
qsort(sort->sorted, sort->n, sizeof(int64_t), cmp_int64);
|
||||
sort->copied = 1;
|
||||
}
|
||||
|
||||
@ -141,22 +141,22 @@ sort_init(struct sort *sort, struct bay *bay, int64_t n, const char *name)
|
||||
memset(sort, 0, sizeof(struct sort));
|
||||
sort->bay = bay;
|
||||
sort->n = n;
|
||||
sort->inputs = calloc((size_t) n, sizeof(struct sort_input));
|
||||
sort->inputs = calloc(n, sizeof(struct sort_input));
|
||||
if (sort->inputs == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
}
|
||||
sort->outputs = calloc((size_t) n, sizeof(struct chan));
|
||||
sort->outputs = calloc(n, sizeof(struct chan));
|
||||
if (sort->outputs == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
}
|
||||
sort->values = calloc((size_t) n, sizeof(int64_t));
|
||||
sort->values = calloc(n, sizeof(int64_t));
|
||||
if (sort->values == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
}
|
||||
sort->sorted = calloc((size_t) n, sizeof(int64_t));
|
||||
sort->sorted = calloc(n, sizeof(int64_t));
|
||||
if (sort->sorted == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
@ -165,7 +165,7 @@ sort_init(struct sort *sort, struct bay *bay, int64_t n, const char *name)
|
||||
/* Init and register outputs */
|
||||
for (int64_t i = 0; i < n; i++) {
|
||||
struct chan *out = &sort->outputs[i];
|
||||
chan_init(out, CHAN_SINGLE, "%s.out%"PRIi64, name, i);
|
||||
chan_init(out, CHAN_SINGLE, "%s.out%ld", name, i);
|
||||
|
||||
/* The sort module may write multiple times to the same
|
||||
* channel if we update more than one input. */
|
||||
@ -176,7 +176,7 @@ sort_init(struct sort *sort, struct bay *bay, int64_t n, const char *name)
|
||||
chan_prop_set(out, CHAN_ALLOW_DUP, 1);
|
||||
|
||||
if (bay_register(bay, out) != 0) {
|
||||
err("bay_register out%"PRIi64" failed", i);
|
||||
err("bay_register out%ld failed", i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -190,7 +190,7 @@ sort_set_input(struct sort *sort, int64_t index, struct chan *chan)
|
||||
struct sort_input *input = &sort->inputs[index];
|
||||
|
||||
if (input->chan != NULL) {
|
||||
err("input %"PRIi64" already has a channel", index);
|
||||
err("input %d already has a channel", index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "stream.h"
|
||||
@ -59,7 +59,7 @@ load_stream_fd(struct stream *stream, int fd)
|
||||
}
|
||||
|
||||
int prot = PROT_READ | PROT_WRITE;
|
||||
stream->buf = mmap(NULL, (size_t) st.st_size, prot, MAP_PRIVATE, fd, 0);
|
||||
stream->buf = mmap(NULL, st.st_size, prot, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (stream->buf == MAP_FAILED) {
|
||||
err("mmap failed:");
|
||||
@ -118,7 +118,7 @@ stream_load(struct stream *stream, const char *tracedir, const char *relpath)
|
||||
warn("stream '%s' has zero events", stream->relpath);
|
||||
stream->active = 0;
|
||||
} else {
|
||||
err("impossible, offset %"PRIi64" bigger than size %"PRIi64,
|
||||
err("impossible, offset %ld bigger than size %ld",
|
||||
stream->offset, stream->size);
|
||||
return -1;
|
||||
}
|
||||
@ -196,7 +196,7 @@ stream_step(struct stream *stream)
|
||||
|
||||
/* It cannot pass the size, otherwise we are reading garbage */
|
||||
if (stream->offset > stream->size) {
|
||||
err("stream offset %"PRIi64" exceeds size %"PRIi64,
|
||||
err("stream offset %ld exceeds size %ld",
|
||||
stream->offset, stream->size);
|
||||
return -1;
|
||||
}
|
||||
@ -223,7 +223,7 @@ stream_step(struct stream *stream)
|
||||
/* Ensure the clock grows monotonically if unsorted flag not set */
|
||||
if (stream->unsorted == 0) {
|
||||
if (clock < stream->lastclock) {
|
||||
err("clock goes backwards %"PRIi64" -> %"PRIi64" in stream '%s' at offset %"PRIi64,
|
||||
err("clock goes backwards %ld -> %ld in stream '%s' at offset %ld",
|
||||
stream->lastclock,
|
||||
clock,
|
||||
stream->relpath,
|
||||
@ -241,7 +241,7 @@ stream_step(struct stream *stream)
|
||||
void
|
||||
stream_progress(struct stream *stream, int64_t *done, int64_t *total)
|
||||
{
|
||||
*done = stream->offset - (int64_t) sizeof(struct ovni_stream_header);
|
||||
*done = stream->offset - sizeof(struct ovni_stream_header);
|
||||
*total = stream->usize;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "system.h"
|
||||
@ -226,7 +226,7 @@ create_system(struct system *sys, struct trace *trace)
|
||||
const char *dir = trace->tracedir;
|
||||
|
||||
/* Allocate the lpt map */
|
||||
sys->lpt = calloc((size_t) trace->nstreams, sizeof(struct lpt));
|
||||
sys->lpt = calloc(trace->nstreams, sizeof(struct lpt));
|
||||
if (sys->lpt == NULL) {
|
||||
err("calloc failed:");
|
||||
return -1;
|
||||
@ -340,28 +340,28 @@ print_system(struct system *sys)
|
||||
{
|
||||
err("content of system: ");
|
||||
for (struct loom *l = sys->looms; l; l = l->next) {
|
||||
err("%s gindex=%"PRIi64, l->id, l->gindex);
|
||||
err("+ %zd processes: ", l->nprocs);
|
||||
err("%s gindex=%d", l->id, l->gindex);
|
||||
err("+ %ld processes: ", l->nprocs);
|
||||
for (struct proc *p = l->procs; p; p = p->hh.next) {
|
||||
err("| %s gindex=%"PRIi64" pid=%d",
|
||||
err("| %s gindex=%d pid=%d",
|
||||
p->id, p->gindex, p->pid);
|
||||
err("| + %d threads: ", p->nthreads);
|
||||
err("| + %ld threads: ", p->nthreads);
|
||||
for (struct thread *t = p->threads; t; t = t->hh.next) {
|
||||
err("| | %s tid=%d",
|
||||
t->id, t->tid);
|
||||
}
|
||||
}
|
||||
err("+ %zd phy cpus: ", l->ncpus);
|
||||
err("+ %ld phy cpus: ", l->ncpus);
|
||||
for (struct cpu *cpu = l->cpus; cpu; cpu = cpu->hh.next) {
|
||||
err("| %s gindex=%"PRIi64" phyid=%d",
|
||||
err("| %s gindex=%ld phyid=%d",
|
||||
cpu->name,
|
||||
cpu->gindex,
|
||||
cpu->phyid);
|
||||
}
|
||||
|
||||
err("+ 1 virtual cpu: ");
|
||||
err("+ 1 virtual cpu: ", l->ncpus);
|
||||
struct cpu *cpu = &l->vcpu;
|
||||
err("| %s gindex=%"PRIi64" phyid=%d",
|
||||
err("| %s gindex=%ld phyid=%d",
|
||||
cpu->name,
|
||||
cpu->gindex,
|
||||
cpu->phyid);
|
||||
@ -373,20 +373,20 @@ init_global_indices(struct system *sys)
|
||||
{
|
||||
size_t iloom = 0;
|
||||
for (struct loom *l = sys->looms; l; l = l->next)
|
||||
loom_set_gindex(l, (int64_t) iloom++);
|
||||
loom_set_gindex(l, iloom++);
|
||||
|
||||
sys->nprocs = 0;
|
||||
for (struct proc *p = sys->procs; p; p = p->gnext)
|
||||
proc_set_gindex(p, (int64_t) sys->nprocs++);
|
||||
proc_set_gindex(p, sys->nprocs++);
|
||||
|
||||
sys->nthreads = 0;
|
||||
for (struct thread *t = sys->threads; t; t = t->gnext)
|
||||
thread_set_gindex(t, (int64_t) sys->nthreads++);
|
||||
thread_set_gindex(t, sys->nthreads++);
|
||||
|
||||
sys->ncpus = 0;
|
||||
sys->nphycpus = 0;
|
||||
for (struct cpu *c = sys->cpus; c; c = c->next) {
|
||||
cpu_set_gindex(c, (int64_t) sys->ncpus++);
|
||||
cpu_set_gindex(c, sys->ncpus++);
|
||||
if (!c->is_virtual)
|
||||
sys->nphycpus++;
|
||||
}
|
||||
@ -424,7 +424,7 @@ init_end_system(struct system *sys)
|
||||
}
|
||||
}
|
||||
|
||||
info("loaded %zd looms, %zd processes, %zd threads and %zd cpus",
|
||||
info("loaded %ld looms, %ld processes, %ld threads and %ld cpus",
|
||||
sys->nlooms, sys->nprocs, sys->nthreads, sys->nphycpus);
|
||||
|
||||
return 0;
|
||||
@ -518,7 +518,7 @@ init_offsets(struct system *sys, struct trace *trace)
|
||||
/* If we have more than one hostname and no offset table has been found,
|
||||
* we won't be able to synchronize the clocks */
|
||||
if (n == 0 && sys->nlooms > 1) {
|
||||
warn("no clock offset file loaded with %zd looms",
|
||||
warn("no clock offset file loaded with %ld looms",
|
||||
sys->nlooms);
|
||||
}
|
||||
|
||||
@ -641,13 +641,13 @@ system_connect(struct system *sys, struct bay *bay, struct recorder *rec)
|
||||
{
|
||||
/* Create Paraver traces */
|
||||
struct pvt *pvt_cpu = NULL;
|
||||
if ((pvt_cpu = recorder_add_pvt(rec, "cpu", (long) sys->ncpus)) == NULL) {
|
||||
if ((pvt_cpu = recorder_add_pvt(rec, "cpu", sys->ncpus)) == NULL) {
|
||||
err("recorder_add_pvt failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct pvt *pvt_th = NULL;
|
||||
if ((pvt_th = recorder_add_pvt(rec, "thread", (long) sys->nthreads)) == NULL) {
|
||||
if ((pvt_th = recorder_add_pvt(rec, "thread", sys->nthreads)) == NULL) {
|
||||
err("recorder_add_pvt failed");
|
||||
return -1;
|
||||
}
|
||||
@ -667,7 +667,7 @@ system_connect(struct system *sys, struct bay *bay, struct recorder *rec)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (prf_add(prf, (long) th->gindex, name) != 0) {
|
||||
if (prf_add(prf, th->gindex, name) != 0) {
|
||||
err("prf_add failed for thread '%s'", th->id);
|
||||
return -1;
|
||||
}
|
||||
@ -688,7 +688,7 @@ system_connect(struct system *sys, struct bay *bay, struct recorder *rec)
|
||||
}
|
||||
|
||||
struct prf *prf = pvt_get_prf(pvt_cpu);
|
||||
if (prf_add(prf, (long) cpu->gindex, cpu->name) != 0) {
|
||||
if (prf_add(prf, cpu->gindex, cpu->name) != 0) {
|
||||
err("prf_add failed for cpu '%s'", cpu->name);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "task.h"
|
||||
@ -258,22 +258,13 @@ task_type_create(struct task_info *info, uint32_t type_id, const char *label)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int n;
|
||||
if (label[0] == '\0') {
|
||||
/* Give a name if empty */
|
||||
n = snprintf(type->label, MAX_PCF_LABEL,
|
||||
"(unlabeled task type %u)", type_id);
|
||||
} else {
|
||||
n = snprintf(type->label, MAX_PCF_LABEL, "%s", label);
|
||||
}
|
||||
|
||||
type->gid = task_get_type_gid(label);
|
||||
int n = snprintf(type->label, MAX_PCF_LABEL, "%s", label);
|
||||
if (n >= MAX_PCF_LABEL) {
|
||||
err("task type %u label too long", type_id);
|
||||
err("task type label too long: %s", label);
|
||||
return -1;
|
||||
}
|
||||
|
||||
type->gid = task_get_type_gid(type->label);
|
||||
|
||||
/* Add the new task type to the hash table */
|
||||
HASH_ADD_INT(info->types, id, type);
|
||||
|
||||
@ -288,7 +279,7 @@ task_create_pcf_types(struct pcf_type *pcftype, struct task_type *types)
|
||||
|
||||
/* Emit types for all task types */
|
||||
for (struct task_type *tt = types; tt != NULL; tt = tt->hh.next) {
|
||||
struct pcf_value *pcfvalue = pcf_find_value(pcftype, (int) tt->gid);
|
||||
struct pcf_value *pcfvalue = pcf_find_value(pcftype, tt->gid);
|
||||
if (pcfvalue != NULL) {
|
||||
/* Ensure the label is the same, so we know that
|
||||
* no collision occurred */
|
||||
@ -301,7 +292,7 @@ task_create_pcf_types(struct pcf_type *pcftype, struct task_type *types)
|
||||
}
|
||||
}
|
||||
|
||||
if (pcf_add_value(pcftype, (int) tt->gid, tt->label) == NULL) {
|
||||
if (pcf_add_value(pcftype, tt->gid, tt->label) == NULL) {
|
||||
err("pcf_add_value failed");
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "thread.h"
|
||||
@ -18,6 +18,7 @@
|
||||
#include "value.h"
|
||||
struct proc;
|
||||
|
||||
static const char chan_fmt[] = "thread%lu.%s";
|
||||
static const char *chan_name[TH_CHAN_MAX] = {
|
||||
[TH_CHAN_CPU] = "cpu_gindex",
|
||||
[TH_CHAN_TID] = "tid_active",
|
||||
@ -91,7 +92,7 @@ get_tid(const char *id, int *tid)
|
||||
|
||||
char *endptr;
|
||||
errno = 0;
|
||||
*tid = (int) strtol(tidstr, &endptr, 10);
|
||||
*tid = strtol(tidstr, &endptr, 10);
|
||||
if (errno != 0) {
|
||||
err("strtol failed for '%s':", tidstr);
|
||||
return -1;
|
||||
@ -158,7 +159,7 @@ thread_init_end(struct thread *th)
|
||||
|
||||
for (int i = 0; i < TH_CHAN_MAX; i++) {
|
||||
chan_init(&th->chan[i], CHAN_SINGLE,
|
||||
"thread%"PRIi64".%s", th->gindex, chan_name[i]);
|
||||
chan_fmt, th->gindex, chan_name[i]);
|
||||
}
|
||||
|
||||
/* The transition Running -> Cooling causes a duplicate (the thread is
|
||||
@ -196,7 +197,7 @@ create_type(struct pcf *pcf, int i)
|
||||
return 0;
|
||||
|
||||
const char *label = pvt_name[i];
|
||||
struct pcf_type *pcftype = pcf_add_type(pcf, (int) type, label);
|
||||
struct pcf_type *pcftype = pcf_add_type(pcf, type, label);
|
||||
if (pcftype == NULL) {
|
||||
err("pcf_add_type failed");
|
||||
return -1;
|
||||
@ -234,7 +235,7 @@ thread_connect(struct thread *th, struct bay *bay, struct recorder *rec)
|
||||
}
|
||||
|
||||
long type = chan_type[i];
|
||||
long row = (long) th->gindex;
|
||||
long row = th->gindex;
|
||||
long flags = prv_flags[i];
|
||||
|
||||
if (prv_register(prv, row, type, bay, c, flags)) {
|
||||
@ -326,7 +327,7 @@ thread_select_active(struct mux *mux,
|
||||
enum thread_state state = (enum thread_state) value.i;
|
||||
|
||||
if (mux->ninputs != 1) {
|
||||
err("mux doesn't have one input but %"PRIi64, mux->ninputs);
|
||||
err("mux doesn't have one input but %d", mux->ninputs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -362,7 +363,7 @@ thread_select_running(struct mux *mux,
|
||||
enum thread_state state = (enum thread_state) value.i;
|
||||
|
||||
if (mux->ninputs != 1) {
|
||||
err("mux doesn't have one input but %"PRIi64, mux->ninputs);
|
||||
err("mux doesn't have one input but %d", mux->ninputs);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -391,7 +392,7 @@ thread_set_cpu(struct thread *th, struct cpu *cpu)
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbg("thread%"PRIi64" sets cpu%"PRIi64, th->gindex, cpu->gindex);
|
||||
dbg("thread%ld sets cpu%ld", th->gindex, cpu->gindex);
|
||||
th->cpu = cpu;
|
||||
|
||||
/* Update cpu channel */
|
||||
@ -412,7 +413,7 @@ thread_unset_cpu(struct thread *th)
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbg("thread%"PRIi64" unsets cpu", th->gindex);
|
||||
dbg("thread%ld unsets cpu", th->gindex);
|
||||
th->cpu = NULL;
|
||||
|
||||
struct chan *c = &th->chan[TH_CHAN_CPU];
|
||||
@ -432,7 +433,7 @@ thread_migrate_cpu(struct thread *th, struct cpu *cpu)
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbg("thread%"PRIi64" migrates to cpu%"PRIi64, th->gindex, cpu->gindex);
|
||||
dbg("thread%ld migrates to cpu%d", th->gindex, cpu->gindex);
|
||||
th->cpu = cpu;
|
||||
|
||||
struct chan *c = &th->chan[TH_CHAN_CPU];
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#define _XOPEN_SOURCE 500
|
||||
@ -36,7 +36,7 @@ load_stream(struct trace *trace, const char *path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int offset = (int) strlen(trace->tracedir);
|
||||
int offset = strlen(trace->tracedir);
|
||||
const char *relpath = path + offset;
|
||||
|
||||
/* Skip begin slashes */
|
||||
@ -58,14 +58,14 @@ has_suffix(const char *str, const char *suffix)
|
||||
if (!str || !suffix)
|
||||
return 0;
|
||||
|
||||
int lenstr = (int) strlen(str);
|
||||
int lensuffix = (int) strlen(suffix);
|
||||
int lenstr = strlen(str);
|
||||
int lensuffix = strlen(suffix);
|
||||
|
||||
if (lensuffix > lenstr)
|
||||
return 0;
|
||||
|
||||
const char *p = str + lenstr - lensuffix;
|
||||
if (strncmp(p, suffix, (size_t) lensuffix) == 0)
|
||||
if (strncmp(p, suffix, lensuffix) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "track.h"
|
||||
@ -23,8 +23,8 @@ track_init(struct track *track, struct bay *bay, enum track_type type, int mode,
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
int n = (int) ARRAYLEN(track->name);
|
||||
int ret = vsnprintf(track->name, (size_t) n, fmt, ap);
|
||||
int n = ARRAYLEN(track->name);
|
||||
int ret = vsnprintf(track->name, n, fmt, ap);
|
||||
if (ret >= n) {
|
||||
err("track name too long");
|
||||
return -1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#ifndef TRACK_H
|
||||
@ -27,12 +27,12 @@ struct track {
|
||||
int mode;
|
||||
char name[MAX_CHAN_NAME];
|
||||
struct bay *bay;
|
||||
struct chan ch; /*< Scratch channel as output when mux is used */
|
||||
struct chan *out; /*< Output channel (ch or the input channel) */
|
||||
struct chan ch;
|
||||
struct chan *out;
|
||||
struct mux mux;
|
||||
};
|
||||
|
||||
USE_RET int track_init(struct track *track, struct bay *bay, enum track_type type, int mode, const char *fmt, ...) __attribute__((format(printf, 5, 6)));
|
||||
USE_RET int track_init(struct track *track, struct bay *bay, enum track_type type, int mode, const char *fmt, ...);
|
||||
USE_RET int track_set_select(struct track *track, struct chan *sel, mux_select_func_t fsel, int64_t ninputs);
|
||||
USE_RET int track_set_input(struct track *track, int64_t index, struct chan *inp);
|
||||
USE_RET struct chan *track_get_output(struct track *track);
|
||||
|
@ -68,7 +68,7 @@ value_str(struct value a)
|
||||
ret = snprintf(buf, n, "{NULL}");
|
||||
break;
|
||||
case VALUE_INT64:
|
||||
ret = snprintf(buf, n, "{int64_t %" PRIi64 "}", a.i);
|
||||
ret = snprintf(buf, n, "{int64_t %ld}", a.i);
|
||||
break;
|
||||
case VALUE_DOUBLE:
|
||||
ret = snprintf(buf, n, "{double %e}", a.d);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
/* Author: David Alvarez
|
||||
@ -112,20 +112,6 @@ heap_max(heap_head_t *head)
|
||||
return head->root;
|
||||
}
|
||||
|
||||
static inline int
|
||||
leading_zeros(size_t x)
|
||||
{
|
||||
/* Call and if()'s optimized by the compiler with -O2 */
|
||||
if (sizeof(size_t) == sizeof(unsigned int))
|
||||
return __builtin_clz((unsigned int) x);
|
||||
else if (sizeof(size_t) == sizeof(unsigned long))
|
||||
return __builtin_clzl((unsigned long) x);
|
||||
else if (sizeof(size_t) == sizeof(unsigned long long))
|
||||
return __builtin_clzll((unsigned long long) x);
|
||||
else
|
||||
die("cannot find suitable size for __builtin_clz*");
|
||||
}
|
||||
|
||||
/* Get a move to reach a leaf */
|
||||
static inline int
|
||||
heap_get_move(size_t *node /*out*/)
|
||||
@ -133,8 +119,8 @@ heap_get_move(size_t *node /*out*/)
|
||||
size_t aux_node = *node;
|
||||
|
||||
// Round to previous po2
|
||||
int shift = (int) sizeof(size_t) * 8 - leading_zeros(aux_node) - 1;
|
||||
size_t base = 1ULL << shift;
|
||||
size_t base = (1ULL) << (sizeof(size_t) * 8
|
||||
- __builtin_clzll(aux_node) - 1);
|
||||
|
||||
aux_node -= base / 2;
|
||||
|
||||
|
32
src/parson.c
32
src/parson.c
@ -316,7 +316,7 @@ read_file(const char *filename)
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
size_to_read = (size_t) pos;
|
||||
size_to_read = pos;
|
||||
rewind(fp);
|
||||
file_contents = (char *) parson_malloc(sizeof(char) * (size_to_read + 1));
|
||||
if (!file_contents) {
|
||||
@ -361,7 +361,7 @@ remove_comments(char *string, const char *start_token, const char *end_token)
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < (size_t) (ptr - string) + end_token_len; i++) {
|
||||
for (i = 0; i < (ptr - string) + end_token_len; i++) {
|
||||
string[i] = ' ';
|
||||
}
|
||||
string = ptr + end_token_len - 1;
|
||||
@ -503,7 +503,7 @@ json_object_dotremove_internal(JSON_Object *object, const char *name, int free_v
|
||||
if (dot_pos == NULL) {
|
||||
return json_object_remove_internal(object, name, free_value);
|
||||
}
|
||||
temp_value = json_object_getn_value(object, name, (size_t) (dot_pos - name));
|
||||
temp_value = json_object_getn_value(object, name, dot_pos - name);
|
||||
if (json_value_get_type(temp_value) != JSONObject) {
|
||||
return JSONFailure;
|
||||
}
|
||||
@ -638,13 +638,13 @@ parse_utf16(const char **unprocessed, char **processed)
|
||||
if (cp < 0x80) {
|
||||
processed_ptr[0] = (char) cp; /* 0xxxxxxx */
|
||||
} else if (cp < 0x800) {
|
||||
processed_ptr[0] = (char) (((cp >> 6) & 0x1F) | 0xC0); /* 110xxxxx */
|
||||
processed_ptr[1] = (char) (((cp) &0x3F) | 0x80); /* 10xxxxxx */
|
||||
processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */
|
||||
processed_ptr[1] = ((cp) &0x3F) | 0x80; /* 10xxxxxx */
|
||||
processed_ptr += 1;
|
||||
} else if (cp < 0xD800 || cp > 0xDFFF) {
|
||||
processed_ptr[0] = (char) (((cp >> 12) & 0x0F) | 0xE0);/* 1110xxxx */
|
||||
processed_ptr[1] = (char) (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */
|
||||
processed_ptr[2] = (char) (((cp) &0x3F) | 0x80); /* 10xxxxxx */
|
||||
processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */
|
||||
processed_ptr[1] = ((cp >> 6) & 0x3F) | 0x80; /* 10xxxxxx */
|
||||
processed_ptr[2] = ((cp) &0x3F) | 0x80; /* 10xxxxxx */
|
||||
processed_ptr += 2;
|
||||
} else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
|
||||
lead = cp;
|
||||
@ -657,10 +657,10 @@ parse_utf16(const char **unprocessed, char **processed)
|
||||
return JSONFailure;
|
||||
}
|
||||
cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000;
|
||||
processed_ptr[0] = (char) (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
|
||||
processed_ptr[1] = (char) (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
|
||||
processed_ptr[2] = (char) (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */
|
||||
processed_ptr[3] = (char) (((cp) &0x3F) | 0x80); /* 10xxxxxx */
|
||||
processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
|
||||
processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
|
||||
processed_ptr[2] = (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */
|
||||
processed_ptr[3] = (((cp) &0x3F) | 0x80); /* 10xxxxxx */
|
||||
processed_ptr += 3;
|
||||
} else { /* trail surrogate before lead surrogate */
|
||||
return JSONFailure;
|
||||
@ -758,7 +758,7 @@ get_quoted_string(const char **string, size_t *output_string_len)
|
||||
if (status != JSONSuccess) {
|
||||
return NULL;
|
||||
}
|
||||
input_string_len = (size_t) (*string - string_start - 2); /* length without quotes */
|
||||
input_string_len = *string - string_start - 2; /* length without quotes */
|
||||
return process_string(string_start + 1, input_string_len, output_string_len);
|
||||
}
|
||||
|
||||
@ -957,7 +957,7 @@ parse_number_value(const char **string)
|
||||
if (errno == ERANGE && (number == -HUGE_VAL || number == HUGE_VAL)) {
|
||||
return NULL;
|
||||
}
|
||||
if ((errno && errno != ERANGE) || !is_decimal(*string, (size_t) (end - *string))) {
|
||||
if ((errno && errno != ERANGE) || !is_decimal(*string, end - *string)) {
|
||||
return NULL;
|
||||
}
|
||||
*string = end;
|
||||
@ -1410,7 +1410,7 @@ json_object_dotget_value(const JSON_Object *object, const char *name)
|
||||
if (!dot_position) {
|
||||
return json_object_get_value(object, name);
|
||||
}
|
||||
object = json_value_get_object(json_object_getn_value(object, name, (size_t) (dot_position - name)));
|
||||
object = json_value_get_object(json_object_getn_value(object, name, dot_position - name));
|
||||
return json_object_dotget_value(object, dot_position + 1);
|
||||
}
|
||||
|
||||
@ -2253,7 +2253,7 @@ json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *valu
|
||||
if (dot_pos == NULL) {
|
||||
return json_object_set_value(object, name, value);
|
||||
}
|
||||
name_len = (size_t) (dot_pos - name);
|
||||
name_len = dot_pos - name;
|
||||
temp_value = json_object_getn_value(object, name, name_len);
|
||||
if (temp_value) {
|
||||
/* Don't overwrite existing non-object (unlike json_object_set_value, but it shouldn't be changed at this point) */
|
||||
|
399
src/rt/ovni.c
399
src/rt/ovni.c
@ -1,9 +1,8 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@ -435,8 +434,8 @@ write_evbuf(uint8_t *buf, size_t size)
|
||||
if (written < 0)
|
||||
die("failed to write buffer to disk:");
|
||||
|
||||
size -= (size_t) written;
|
||||
buf += (size_t) written;
|
||||
size -= written;
|
||||
buf += written;
|
||||
} while (size > 0);
|
||||
}
|
||||
|
||||
@ -638,7 +637,7 @@ clock_monotonic_now(void)
|
||||
if (clock_gettime(rproc.clockid, &tp))
|
||||
die("clock_gettime() failed:");
|
||||
|
||||
return (uint64_t) tp.tv_sec * ns + (uint64_t) tp.tv_nsec;
|
||||
return tp.tv_sec * ns + tp.tv_nsec;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
@ -666,9 +665,9 @@ ovni_ev_get_clock(const struct ovni_ev *ev)
|
||||
void
|
||||
ovni_ev_set_mcv(struct ovni_ev *ev, const char *mcv)
|
||||
{
|
||||
ev->header.model = (uint8_t) mcv[0];
|
||||
ev->header.category = (uint8_t) mcv[1];
|
||||
ev->header.value = (uint8_t) mcv[2];
|
||||
ev->header.model = mcv[0];
|
||||
ev->header.category = mcv[1];
|
||||
ev->header.value = mcv[2];
|
||||
}
|
||||
|
||||
static size_t
|
||||
@ -681,7 +680,7 @@ int
|
||||
ovni_payload_size(const struct ovni_ev *ev)
|
||||
{
|
||||
if (ev->header.flags & OVNI_EV_JUMBO)
|
||||
return (int) get_jumbo_payload_size(ev);
|
||||
return get_jumbo_payload_size(ev);
|
||||
|
||||
int size = ev->header.flags & 0x0f;
|
||||
|
||||
@ -704,23 +703,22 @@ ovni_payload_add(struct ovni_ev *ev, const uint8_t *buf, int size)
|
||||
if (size < 2)
|
||||
die("payload size %d too small", size);
|
||||
|
||||
size_t payload_size = (size_t) ovni_payload_size(ev);
|
||||
size_t payload_size = ovni_payload_size(ev);
|
||||
|
||||
/* Ensure we have room */
|
||||
if (payload_size + (size_t) size > sizeof(ev->payload))
|
||||
if (payload_size + size > sizeof(ev->payload))
|
||||
die("no space left for %d bytes", size);
|
||||
|
||||
memcpy(&ev->payload.u8[payload_size], buf, (size_t) size);
|
||||
payload_size += (size_t) size;
|
||||
memcpy(&ev->payload.u8[payload_size], buf, size);
|
||||
payload_size += size;
|
||||
|
||||
ev->header.flags = (uint8_t) ((ev->header.flags & 0xf0)
|
||||
| ((payload_size - 1) & 0x0f));
|
||||
ev->header.flags = (ev->header.flags & 0xf0) | ((payload_size - 1) & 0x0f);
|
||||
}
|
||||
|
||||
int
|
||||
ovni_ev_size(const struct ovni_ev *ev)
|
||||
{
|
||||
return (int) sizeof(ev->header) + ovni_payload_size(ev);
|
||||
return sizeof(ev->header) + ovni_payload_size(ev);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -779,7 +777,7 @@ ovni_ev_add_jumbo(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize)
|
||||
die("the event payload must be empty");
|
||||
|
||||
ovni_payload_add(ev, (uint8_t *) &bufsize, sizeof(bufsize));
|
||||
size_t evsize = (size_t) ovni_ev_size(ev);
|
||||
size_t evsize = ovni_ev_size(ev);
|
||||
|
||||
size_t totalsize = evsize + bufsize;
|
||||
|
||||
@ -819,7 +817,7 @@ ovni_ev_add(struct ovni_ev *ev)
|
||||
int flushed = 0;
|
||||
uint64_t t0, t1;
|
||||
|
||||
size_t size = (size_t) ovni_ev_size(ev);
|
||||
int size = ovni_ev_size(ev);
|
||||
|
||||
/* Check if the event fits or flush first otherwise */
|
||||
if (rthread.evlen + size >= OVNI_MAX_EV_BUF) {
|
||||
@ -850,368 +848,3 @@ ovni_ev_emit(struct ovni_ev *ev)
|
||||
{
|
||||
ovni_ev_add(ev);
|
||||
}
|
||||
|
||||
/* Attributes */
|
||||
|
||||
static JSON_Object *
|
||||
get_thread_metadata(void)
|
||||
{
|
||||
if (rthread.finished)
|
||||
die("thread already finished");
|
||||
|
||||
if (!rthread.ready)
|
||||
die("thread not initialized");
|
||||
|
||||
JSON_Object *meta = json_value_get_object(rthread.meta);
|
||||
|
||||
if (meta == NULL)
|
||||
die("json_value_get_object failed");
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the key exists in the metadata.
|
||||
*
|
||||
* @returns 1 if the key exists, 0 otherwise.
|
||||
*/
|
||||
int
|
||||
ovni_attr_has(const char *key)
|
||||
{
|
||||
JSON_Object *obj = get_thread_metadata();
|
||||
JSON_Value *val = json_object_dotget_value(obj, key);
|
||||
|
||||
if (val == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a double attribute.
|
||||
*
|
||||
* @param key The key of the attribute as a dot path.
|
||||
* @param num The double value to be stored.
|
||||
*/
|
||||
void
|
||||
ovni_attr_set_double(const char *key, double num)
|
||||
{
|
||||
JSON_Object *obj = get_thread_metadata();
|
||||
|
||||
if (json_object_dotset_number(obj, key, num) != 0)
|
||||
die("json_object_dotset_number() failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a double attribute.
|
||||
*
|
||||
* @param key The key of the attribute as a dot path.
|
||||
*
|
||||
* @return The double on the key. If there is any problem it aborts.
|
||||
*/
|
||||
double
|
||||
ovni_attr_get_double(const char *key)
|
||||
{
|
||||
JSON_Object *obj = get_thread_metadata();
|
||||
JSON_Value *val = json_object_dotget_value(obj, key);
|
||||
if (val == NULL)
|
||||
die("key not found: %s", key);
|
||||
|
||||
if (json_value_get_type(val) != JSONNumber)
|
||||
die("value with key '%s' is not a number", key);
|
||||
|
||||
return json_value_get_number(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a boolean attribute.
|
||||
*
|
||||
* @param key The key of the attribute as a dot path.
|
||||
*
|
||||
* @return The boolean on the key. If there is any problem it aborts.
|
||||
*/
|
||||
int
|
||||
ovni_attr_get_boolean(const char *key)
|
||||
{
|
||||
JSON_Object *obj = get_thread_metadata();
|
||||
JSON_Value *val = json_object_dotget_value(obj, key);
|
||||
if (val == NULL)
|
||||
die("key not found: %s", key);
|
||||
|
||||
if (json_value_get_type(val) != JSONBoolean)
|
||||
die("value with key '%s' is not a boolean", key);
|
||||
|
||||
return json_value_get_boolean(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a boolean attribute.
|
||||
*
|
||||
* @param key The key of the attribute as a dot path.
|
||||
* @param num The boolean value to be stored.
|
||||
*/
|
||||
void
|
||||
ovni_attr_set_boolean(const char *key, int value)
|
||||
{
|
||||
JSON_Object *obj = get_thread_metadata();
|
||||
|
||||
if (json_object_dotset_boolean(obj, key, value) != 0)
|
||||
die("json_object_dotset_boolean() failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a string attribute.
|
||||
*
|
||||
* @param key The key of the attribute as a dot path.
|
||||
* @param str The string value to be stored. It will be internally duplicated,
|
||||
* so it can be free on return.
|
||||
*/
|
||||
void
|
||||
ovni_attr_set_str(const char *key, const char *value)
|
||||
{
|
||||
JSON_Object *obj = get_thread_metadata();
|
||||
|
||||
if (json_object_dotset_string(obj, key, value) != 0)
|
||||
die("json_object_dotset_string() failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a string attribute from a key.
|
||||
* If not found or if there is any problem it aborts before returning.
|
||||
*
|
||||
* @param key The key of the attribute as a dot path.
|
||||
*
|
||||
* @return A pointer to a not-NULL read-only string value for the given key.
|
||||
*/
|
||||
const char *
|
||||
ovni_attr_get_str(const char *key)
|
||||
{
|
||||
JSON_Object *obj = get_thread_metadata();
|
||||
JSON_Value *val = json_object_dotget_value(obj, key);
|
||||
if (val == NULL)
|
||||
die("key not found: %s", key);
|
||||
|
||||
if (json_value_get_type(val) != JSONString)
|
||||
die("value with key '%s' is not a string", key);
|
||||
|
||||
return json_value_get_string(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a JSON value into an attribute.
|
||||
*
|
||||
* @param key The key of the attribute as a dot path.
|
||||
* @param json The JSON value to be stored.
|
||||
*
|
||||
* The value specified as a JSON string can be of any type (dictionary, array,
|
||||
* string, double...) as long as it is valid JSON. Any errors in parsing the
|
||||
* JSON string or in storing the resulting value will abort the program.
|
||||
*/
|
||||
void
|
||||
ovni_attr_set_json(const char *key, const char *json)
|
||||
{
|
||||
JSON_Object *obj = get_thread_metadata();
|
||||
JSON_Value *val = json_parse_string(json);
|
||||
if (val == NULL)
|
||||
die("cannot parse json: %s", json);
|
||||
|
||||
if (json_object_dotset_value(obj, key, val) != 0)
|
||||
die("json_object_dotset_value() failed");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a JSON value into a string.
|
||||
*
|
||||
* @param key The key of the attribute as a dot path.
|
||||
*
|
||||
* @resurn A zero-terminated string containing the serialized JSON
|
||||
* representation of the provided key. This string is allocated with malloc()
|
||||
* and it is reponsability of the user to liberate the memory with free().
|
||||
*
|
||||
* Any errors will abort the program.
|
||||
*/
|
||||
char *
|
||||
ovni_attr_get_json(const char *key)
|
||||
{
|
||||
JSON_Object *obj = get_thread_metadata();
|
||||
JSON_Value *val = json_object_dotget_value(obj, key);
|
||||
if (val == NULL)
|
||||
die("key not found: %s", key);
|
||||
|
||||
char *str = json_serialize_to_string(val);
|
||||
if (str == NULL)
|
||||
die("json_serialize_to_string() failed");
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes the metadata attributes to disk.
|
||||
* Only used to ensure they are not lost in a crash. They are already written in
|
||||
* ovni_thread_free().
|
||||
*/
|
||||
void
|
||||
ovni_attr_flush(void)
|
||||
{
|
||||
if (rthread.finished)
|
||||
die("thread already finished");
|
||||
|
||||
if (!rthread.ready)
|
||||
die("thread not initialized");
|
||||
|
||||
thread_metadata_store();
|
||||
}
|
||||
|
||||
/* Mark API */
|
||||
|
||||
/**
|
||||
* Creates a new mark type.
|
||||
*
|
||||
* @param type The mark type that must be in the range 0 to 99, both included.
|
||||
* @param flags An OR of OVNI_MARK_* flags.
|
||||
* @param title The title that will be displayed in Paraver.
|
||||
*
|
||||
* It can be called from multiple threads as long as they all use the same
|
||||
* arguments. Only one thread in all nodes needs to call it to define a type.
|
||||
*/
|
||||
void
|
||||
ovni_mark_type(int32_t type, long flags, const char *title)
|
||||
{
|
||||
if (type < 0 || type >= 100)
|
||||
die("type must be in [0,100) range");
|
||||
|
||||
if (!title || title[0] == '\0')
|
||||
die("bad title");
|
||||
|
||||
JSON_Object *meta = get_thread_metadata();
|
||||
|
||||
char key[128];
|
||||
if (snprintf(key, 128, "ovni.mark.%"PRId32, type) >= 128)
|
||||
die("type key too long");
|
||||
|
||||
JSON_Value *val = json_object_dotget_value(meta, key);
|
||||
if (val != NULL)
|
||||
die("type %"PRId32" already defined", type);
|
||||
|
||||
if (snprintf(key, 128, "ovni.mark.%"PRId32".title", type) >= 128)
|
||||
die("title key too long");
|
||||
|
||||
if (json_object_dotset_string(meta, key, title) != 0)
|
||||
die("json_object_dotset_string() failed for title");
|
||||
|
||||
const char *chan_type = flags & OVNI_MARK_STACK ? "stack" : "single";
|
||||
if (snprintf(key, 128, "ovni.mark.%"PRId32".chan_type", type) >= 128)
|
||||
die("chan_type key too long");
|
||||
|
||||
if (json_object_dotset_string(meta, key, chan_type) != 0)
|
||||
die("json_object_dotset_string() failed for chan_type");
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a label for the given value.
|
||||
*
|
||||
* @param type The mark type.
|
||||
* @param type The numeric value to which assign a label. The value 0 is
|
||||
* forbidden.
|
||||
* @param label The label that will be displayed in Paraver.
|
||||
*
|
||||
* It only needs to be called once from a thread to globally assign a label to a
|
||||
* given value. It can be called from multiple threads as long as the value for
|
||||
* a given type has only one unique label. Multiple calls with the same
|
||||
* arguments are valid, but with only a distinct label are not.
|
||||
*/
|
||||
void
|
||||
ovni_mark_label(int32_t type, int64_t value, const char *label)
|
||||
{
|
||||
if (type < 0 || type >= 100)
|
||||
die("type must be in [0,100) range");
|
||||
|
||||
if (value <= 0)
|
||||
die("value must be >0");
|
||||
|
||||
if (!label || label[0] == '\0')
|
||||
die("bad label");
|
||||
|
||||
JSON_Object *meta = get_thread_metadata();
|
||||
|
||||
char key[128];
|
||||
if (snprintf(key, 128, "ovni.mark.%"PRId32, type) >= 128)
|
||||
die("type key too long");
|
||||
|
||||
JSON_Value *valtype = json_object_dotget_value(meta, key);
|
||||
if (valtype == NULL)
|
||||
die("type %"PRId32" not defined", type);
|
||||
|
||||
if (snprintf(key, 128, "ovni.mark.%"PRId32".labels.%"PRId64, type, value) >= 128)
|
||||
die("value key too long");
|
||||
|
||||
JSON_Value *val = json_object_dotget_value(meta, key);
|
||||
if (val != NULL)
|
||||
die("label '%s' already defined", label);
|
||||
|
||||
if (json_object_dotset_string(meta, key, label) != 0)
|
||||
die("json_object_dotset_string() failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a value into a stacked mark channel.
|
||||
*
|
||||
* @param type The mark type which must be defined with the OVNI_MARK_STACK flag.
|
||||
* @param value The value to be pushed, The value 0 is forbidden.
|
||||
*/
|
||||
void
|
||||
ovni_mark_push(int32_t type, int64_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
die("value cannot be 0, type %ld", (long) type);
|
||||
|
||||
struct ovni_ev ev = {0};
|
||||
ovni_ev_set_clock(&ev, ovni_clock_now());
|
||||
ovni_ev_set_mcv(&ev, "OM[");
|
||||
ovni_payload_add(&ev, (uint8_t *) &value, sizeof(value));
|
||||
ovni_payload_add(&ev, (uint8_t *) &type, sizeof(type));
|
||||
ovni_ev_add(&ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops a value from a stacked mark channel.
|
||||
*
|
||||
* @param type The mark type which must be defined with the OVNI_MARK_STACK flag.
|
||||
* @param value The value to be popped, which must match the current value. The
|
||||
* value 0 is forbidden.
|
||||
*/
|
||||
void
|
||||
ovni_mark_pop(int32_t type, int64_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
die("value cannot be 0, type %ld", (long) type);
|
||||
|
||||
struct ovni_ev ev = {0};
|
||||
ovni_ev_set_clock(&ev, ovni_clock_now());
|
||||
ovni_ev_set_mcv(&ev, "OM]");
|
||||
ovni_payload_add(&ev, (uint8_t *) &value, sizeof(value));
|
||||
ovni_payload_add(&ev, (uint8_t *) &type, sizeof(type));
|
||||
ovni_ev_add(&ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value to a normal mark channel.
|
||||
*
|
||||
* @param type The mark type which must be defined without the OVNI_MARK_STACK flag.
|
||||
* @param value The value to be set. The value 0 is forbidden.
|
||||
*/
|
||||
void
|
||||
ovni_mark_set(int32_t type, int64_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
die("value cannot be 0, type %ld", (long) type);
|
||||
|
||||
struct ovni_ev ev = {0};
|
||||
ovni_ev_set_clock(&ev, ovni_clock_now());
|
||||
ovni_ev_set_mcv(&ev, "OM=");
|
||||
ovni_payload_add(&ev, (uint8_t *) &value, sizeof(value));
|
||||
ovni_payload_add(&ev, (uint8_t *) &type, sizeof(type));
|
||||
ovni_ev_add(&ev);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "instr.h"
|
||||
@ -9,7 +9,7 @@ int64_t last_clock; /* Clock from the last event */
|
||||
|
||||
int64_t get_clock(void)
|
||||
{
|
||||
last_clock = (int64_t) ovni_clock_now();
|
||||
last_clock = ovni_clock_now();
|
||||
if (first_clock_set == 0) {
|
||||
first_clock = last_clock;
|
||||
first_clock_set = 1;
|
||||
|
@ -23,7 +23,7 @@ int64_t get_delta(void);
|
||||
static inline void name(void) \
|
||||
{ \
|
||||
struct ovni_ev ev = {0}; \
|
||||
ovni_ev_set_clock(&ev, (uint64_t) get_clock()); \
|
||||
ovni_ev_set_clock(&ev, get_clock()); \
|
||||
ovni_ev_set_mcv(&ev, mcv); \
|
||||
ovni_ev_emit(&ev); \
|
||||
}
|
||||
@ -32,7 +32,7 @@ int64_t get_delta(void);
|
||||
static inline void name(ta a) \
|
||||
{ \
|
||||
struct ovni_ev ev = {0}; \
|
||||
ovni_ev_set_clock(&ev, (uint64_t) get_clock()); \
|
||||
ovni_ev_set_clock(&ev, get_clock()); \
|
||||
ovni_ev_set_mcv(&ev, mcv); \
|
||||
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
|
||||
ovni_ev_emit(&ev); \
|
||||
@ -42,7 +42,7 @@ int64_t get_delta(void);
|
||||
static inline void name(ta a, tb b) \
|
||||
{ \
|
||||
struct ovni_ev ev = {0}; \
|
||||
ovni_ev_set_clock(&ev, (uint64_t) get_clock()); \
|
||||
ovni_ev_set_clock(&ev, get_clock()); \
|
||||
ovni_ev_set_mcv(&ev, mcv); \
|
||||
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
|
||||
ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
|
||||
@ -53,7 +53,7 @@ int64_t get_delta(void);
|
||||
static inline void name(ta a, tb b, tc c) \
|
||||
{ \
|
||||
struct ovni_ev ev = {0}; \
|
||||
ovni_ev_set_clock(&ev, (uint64_t) get_clock()); \
|
||||
ovni_ev_set_clock(&ev, get_clock()); \
|
||||
ovni_ev_set_mcv(&ev, mcv); \
|
||||
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
|
||||
ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
|
||||
@ -62,8 +62,6 @@ int64_t get_delta(void);
|
||||
}
|
||||
|
||||
INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag)
|
||||
INSTR_0ARG(instr_thread_pause, "OHp")
|
||||
INSTR_0ARG(instr_thread_resume, "OHr")
|
||||
INSTR_1ARG(instr_thread_affinity_set, "OAs", int32_t, cpu)
|
||||
|
||||
static inline void
|
||||
@ -72,7 +70,7 @@ instr_thread_end(void)
|
||||
struct ovni_ev ev = {0};
|
||||
|
||||
ovni_ev_set_mcv(&ev, "OHe");
|
||||
ovni_ev_set_clock(&ev, (uint64_t) get_clock());
|
||||
ovni_ev_set_clock(&ev, get_clock());
|
||||
ovni_ev_emit(&ev);
|
||||
|
||||
/* Flush the events to disk before killing the thread */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -19,17 +19,17 @@ main(void)
|
||||
uint32_t typeid = 1;
|
||||
uint32_t taskid = 1;
|
||||
|
||||
instr_nanos6_type_create((int32_t) typeid);
|
||||
instr_nanos6_type_create(typeid);
|
||||
|
||||
instr_nanos6_task_create_and_execute((int32_t) taskid, typeid);
|
||||
instr_nanos6_task_create_and_execute(taskid, typeid);
|
||||
sleep_us(us);
|
||||
instr_nanos6_block_enter();
|
||||
instr_nanos6_task_pause((int32_t) taskid);
|
||||
instr_nanos6_task_pause(taskid);
|
||||
sleep_us(us);
|
||||
instr_nanos6_task_resume((int32_t) taskid);
|
||||
instr_nanos6_task_resume(taskid);
|
||||
instr_nanos6_block_exit();
|
||||
sleep_us(us);
|
||||
instr_nanos6_task_end((int32_t) taskid);
|
||||
instr_nanos6_task_end(taskid);
|
||||
instr_nanos6_task_body_exit();
|
||||
|
||||
instr_end();
|
||||
|
@ -35,13 +35,13 @@ main(void)
|
||||
die("fopen failed:");
|
||||
|
||||
/* Ensure non-zero for A (first event) */
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:[^0][0-9]*$' ovni/nanos6-breakdown.prv\n",
|
||||
fprintf(f, "grep ':%ld:%d:[^0][0-9]*$' ovni/nanos6-breakdown.prv\n",
|
||||
get_delta(), PRV_NANOS6_BREAKDOWN);
|
||||
|
||||
instr_nanos6_worker_loop_enter();
|
||||
|
||||
/* And for B */
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:[^0][0-9]*$' ovni/nanos6-breakdown.prv\n",
|
||||
fprintf(f, "grep ':%ld:%d:[^0][0-9]*$' ovni/nanos6-breakdown.prv\n",
|
||||
get_delta(), PRV_NANOS6_BREAKDOWN);
|
||||
|
||||
instr_nanos6_worker_loop_exit();
|
||||
|
@ -34,16 +34,16 @@ main(void)
|
||||
int type = PRV_NANOS6_SUBSYSTEM;
|
||||
int64_t t = get_delta();
|
||||
int value = ST_WORKER_LOOP;
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||
|
||||
instr_nanos6_worker_loop_exit();
|
||||
|
||||
/* Also test when exitting the stacked subsystem */
|
||||
t = get_delta();
|
||||
value = 0;
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||
|
||||
fclose(f);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -18,7 +18,7 @@ main(void)
|
||||
int ntasks = 100;
|
||||
uint32_t typeid = 1;
|
||||
|
||||
instr_nanos6_type_create((int32_t) typeid);
|
||||
instr_nanos6_type_create(typeid);
|
||||
|
||||
/* Create and run the tasks, one nested into another */
|
||||
for (int32_t id = 1; id <= ntasks; id++) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#ifndef INSTR_NANOS6_H
|
||||
@ -20,7 +20,7 @@ instr_nanos6_type_create(int32_t typeid)
|
||||
struct ovni_ev ev = {0};
|
||||
|
||||
ovni_ev_set_mcv(&ev, "6Yc");
|
||||
ovni_ev_set_clock(&ev, (uint64_t) get_clock());
|
||||
ovni_ev_set_clock(&ev, get_clock());
|
||||
|
||||
char buf[256];
|
||||
char *p = buf;
|
||||
@ -32,7 +32,7 @@ instr_nanos6_type_create(int32_t typeid)
|
||||
sprintf(p, "testtype%d", typeid);
|
||||
nbytes += strlen(p) + 1;
|
||||
|
||||
ovni_ev_jumbo_emit(&ev, (uint8_t *) buf, (uint32_t) nbytes);
|
||||
ovni_ev_jumbo_emit(&ev, (uint8_t *) buf, nbytes);
|
||||
|
||||
return task_get_type_gid(p);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -12,13 +12,13 @@ main(void)
|
||||
instr_nanos6_init();
|
||||
|
||||
uint32_t typeid = 666;
|
||||
instr_nanos6_type_create((int32_t) typeid);
|
||||
instr_nanos6_type_create(typeid);
|
||||
|
||||
uint32_t taskid = 1;
|
||||
instr_nanos6_task_create_and_execute((int32_t) taskid, typeid);
|
||||
instr_nanos6_task_create_and_execute(taskid, typeid);
|
||||
|
||||
/* Run another nested task with same id (should fail) */
|
||||
instr_nanos6_task_execute((int32_t) taskid);
|
||||
instr_nanos6_task_execute(taskid);
|
||||
|
||||
instr_end();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -15,7 +15,7 @@ main(void)
|
||||
int ntasks = 100;
|
||||
uint32_t typeid = 1;
|
||||
|
||||
instr_nanos6_type_create((int32_t) typeid);
|
||||
instr_nanos6_type_create(typeid);
|
||||
|
||||
/* Create and run the tasks, one nested into another */
|
||||
for (int i = 0; i < ntasks; i++) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -14,15 +14,15 @@ main(void)
|
||||
instr_nanos6_init();
|
||||
|
||||
uint32_t typeid = 666;
|
||||
instr_nanos6_type_create((int32_t) typeid);
|
||||
instr_nanos6_type_create(typeid);
|
||||
|
||||
uint32_t taskid = 1;
|
||||
instr_nanos6_task_create_and_execute((int32_t) taskid, typeid);
|
||||
instr_nanos6_task_end((int32_t) taskid);
|
||||
instr_nanos6_task_create_and_execute(taskid, typeid);
|
||||
instr_nanos6_task_end(taskid);
|
||||
|
||||
/* Run again the same task (should fail) */
|
||||
instr_nanos6_task_execute((int32_t) taskid);
|
||||
instr_nanos6_task_end((int32_t) taskid);
|
||||
instr_nanos6_task_execute(taskid);
|
||||
instr_nanos6_task_end(taskid);
|
||||
|
||||
instr_end();
|
||||
|
||||
|
@ -29,21 +29,21 @@ main(void)
|
||||
instr_nanos6_absorbing();
|
||||
|
||||
/* Ensure the only row in breakdown is in absorbing */
|
||||
fprintf(f, "grep '1:%" PRIi64 ":%d:%d$' ovni/nanos6-breakdown.prv\n",
|
||||
fprintf(f, "grep '1:%ld:%d:%d$' ovni/nanos6-breakdown.prv\n",
|
||||
get_delta(), type, ST_ABSORBING);
|
||||
|
||||
/* Set state to Resting */
|
||||
instr_nanos6_resting();
|
||||
|
||||
/* Ensure the only row in breakdown is in Resting */
|
||||
fprintf(f, "grep '1:%" PRIi64 ":%d:%d$' ovni/nanos6-breakdown.prv\n",
|
||||
fprintf(f, "grep '1:%ld:%d:%d$' ovni/nanos6-breakdown.prv\n",
|
||||
get_delta(), type, ST_RESTING);
|
||||
|
||||
instr_nanos6_progressing();
|
||||
|
||||
/* Now the state must follow the subsystem, which should be
|
||||
* sponge mode */
|
||||
fprintf(f, "grep '1:%" PRIi64 ":%d:%d$' ovni/nanos6-breakdown.prv\n",
|
||||
fprintf(f, "grep '1:%ld:%d:%d$' ovni/nanos6-breakdown.prv\n",
|
||||
get_delta(), type, ST_SPONGE);
|
||||
|
||||
fclose(f);
|
||||
|
@ -25,15 +25,15 @@ main(void)
|
||||
int type = PRV_NANOS6_SUBSYSTEM;
|
||||
int64_t t = get_delta();
|
||||
int value = ST_SPONGE;
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||
|
||||
instr_nanos6_sponge_exit();
|
||||
|
||||
t = get_delta();
|
||||
value = 0;
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||
|
||||
fclose(f);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -19,7 +19,7 @@ main(void)
|
||||
instr_nanos6_init();
|
||||
|
||||
uint32_t typeid = 100;
|
||||
uint32_t gid = instr_nanos6_type_create((int32_t) typeid);
|
||||
uint32_t gid = instr_nanos6_type_create(typeid);
|
||||
|
||||
/* Create two tasks of the same type */
|
||||
instr_nanos6_task_create(1, typeid);
|
||||
@ -41,14 +41,14 @@ main(void)
|
||||
/* Check the task type */
|
||||
int prvtype = PRV_NANOS6_TYPE;
|
||||
int64_t t = get_delta();
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, gid);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, gid);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, gid);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, gid);
|
||||
|
||||
/* Check the rank */
|
||||
prvtype = PRV_NANOS6_RANK;
|
||||
int rank = 0 + 1; /* Starts at one */
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, rank);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, rank);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, rank);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, rank);
|
||||
fclose(f);
|
||||
|
||||
/* Exit from tasks and subsystem */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -22,7 +22,7 @@ main(void)
|
||||
instr_nanos6_type_create(i + 1);
|
||||
|
||||
for (int i = 0; i < ntasks; i++) {
|
||||
instr_nanos6_task_create_and_execute(i + 1, (uint32_t) ((i % ntypes) + 1));
|
||||
instr_nanos6_task_create_and_execute(i + 1, (i % ntypes) + 1);
|
||||
sleep_us(500);
|
||||
instr_nanos6_task_end(i + 1);
|
||||
instr_nanos6_task_body_exit();
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -17,7 +17,7 @@ main(void)
|
||||
|
||||
uint32_t typeid = 100;
|
||||
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
instr_nosv_task_create_par(1, typeid);
|
||||
instr_nosv_task_create_par(2, typeid);
|
||||
|
||||
|
@ -17,7 +17,7 @@ main(void)
|
||||
|
||||
uint32_t typeid = 100;
|
||||
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
instr_nosv_task_create(1, typeid);
|
||||
instr_nosv_task_create(2, typeid);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -19,7 +19,7 @@ main(void)
|
||||
|
||||
uint32_t typeid = 100;
|
||||
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
instr_nosv_task_create_par(1, typeid);
|
||||
instr_nosv_task_create_par(2, typeid);
|
||||
|
||||
|
@ -12,7 +12,7 @@ main(void)
|
||||
instr_nosv_init();
|
||||
|
||||
uint32_t typeid = 666;
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
|
||||
instr_nosv_task_create(1, typeid);
|
||||
instr_nosv_task_execute(1, 0);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -19,7 +19,7 @@ main(void)
|
||||
|
||||
uint32_t typeid = 100;
|
||||
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
instr_nosv_task_create_par(1, typeid);
|
||||
instr_nosv_submit_enter();
|
||||
instr_nosv_task_execute(1, 1);
|
||||
|
@ -12,7 +12,6 @@ static inline void
|
||||
instr_nosv_init(void)
|
||||
{
|
||||
instr_require("nosv");
|
||||
ovni_attr_set_boolean("nosv.can_breakdown", 1);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
@ -21,7 +20,7 @@ instr_nosv_type_create(int32_t typeid)
|
||||
struct ovni_ev ev = {0};
|
||||
|
||||
ovni_ev_set_mcv(&ev, "VYc");
|
||||
ovni_ev_set_clock(&ev, (uint64_t) get_clock());
|
||||
ovni_ev_set_clock(&ev, get_clock());
|
||||
|
||||
char buf[256];
|
||||
char *p = buf;
|
||||
@ -33,7 +32,7 @@ instr_nosv_type_create(int32_t typeid)
|
||||
sprintf(p, "testtype%d", typeid);
|
||||
nbytes += strlen(p) + 1;
|
||||
|
||||
ovni_ev_jumbo_emit(&ev, (uint8_t *) buf, (uint32_t) nbytes);
|
||||
ovni_ev_jumbo_emit(&ev, (uint8_t *) buf, nbytes);
|
||||
|
||||
return task_get_type_gid(p);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "instr_nosv.h"
|
||||
|
||||
static void
|
||||
task(uint32_t id, uint32_t typeid, int us)
|
||||
task(int32_t id, uint32_t typeid, int us)
|
||||
{
|
||||
instr_nosv_task_create(id, typeid);
|
||||
instr_nosv_task_execute(id, 0);
|
||||
@ -23,11 +23,11 @@ main(void)
|
||||
instr_start(rank, nranks);
|
||||
instr_nosv_init();
|
||||
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
|
||||
/* Create some fake nosv tasks */
|
||||
for (int i = 0; i < 10; i++)
|
||||
task((uint32_t) i + 1, typeid, 5000);
|
||||
task(i + 1, typeid, 5000);
|
||||
|
||||
instr_end();
|
||||
|
||||
|
@ -51,7 +51,7 @@ main(void)
|
||||
instr_thread_execute(lcpu, -1, 0);
|
||||
|
||||
uint32_t typeid = 1;
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
instr_nosv_task_create(1, typeid);
|
||||
instr_nosv_task_execute(1, 0);
|
||||
sleep_us(10000);
|
||||
|
@ -18,7 +18,7 @@ main(void)
|
||||
|
||||
uint32_t typeid = 100;
|
||||
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
instr_nosv_task_create(1, typeid);
|
||||
instr_nosv_task_create_par(2, typeid);
|
||||
|
||||
|
@ -17,21 +17,21 @@ main(void)
|
||||
int ntasks = 100;
|
||||
uint32_t typeid = 1;
|
||||
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
|
||||
for (int id = 1; id <= ntasks; id++)
|
||||
instr_nosv_task_create((uint32_t) id, typeid);
|
||||
instr_nosv_task_create(id, typeid);
|
||||
|
||||
for (int id = 1; id <= ntasks; id++) {
|
||||
instr_nosv_task_execute((uint32_t) id, 0);
|
||||
instr_nosv_task_pause((uint32_t) id, 0);
|
||||
instr_nosv_task_execute(id, 0);
|
||||
instr_nosv_task_pause(id, 0);
|
||||
instr_nosv_submit_enter();
|
||||
}
|
||||
|
||||
for (int id = ntasks; id >= 1; id--) {
|
||||
instr_nosv_submit_exit();
|
||||
instr_nosv_task_resume((uint32_t) id, 0);
|
||||
instr_nosv_task_end((uint32_t) id, 0);
|
||||
instr_nosv_task_resume(id, 0);
|
||||
instr_nosv_task_end(id, 0);
|
||||
}
|
||||
|
||||
instr_end();
|
||||
|
@ -17,7 +17,7 @@ main(void)
|
||||
uint32_t typeid = 100;
|
||||
uint32_t taskid = 200;
|
||||
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
instr_nosv_task_create_par(taskid, typeid);
|
||||
|
||||
/* Create and run the tasks, one nested into another */
|
||||
|
@ -18,7 +18,7 @@ main(void)
|
||||
int us = 500;
|
||||
uint32_t typeid = 1;
|
||||
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
instr_nosv_task_create(1, typeid);
|
||||
instr_nosv_task_execute(1, 0);
|
||||
sleep_us(us);
|
||||
|
@ -19,7 +19,7 @@ main(void)
|
||||
instr_nosv_init();
|
||||
|
||||
uint32_t typeid = 100;
|
||||
uint32_t gid = instr_nosv_type_create((int32_t) typeid);
|
||||
uint32_t gid = instr_nosv_type_create(typeid);
|
||||
|
||||
/* Create two tasks of the same type */
|
||||
instr_nosv_task_create(1, typeid);
|
||||
@ -39,20 +39,20 @@ main(void)
|
||||
/* Check the task type */
|
||||
int prvtype = PRV_NOSV_TYPE;
|
||||
int64_t t = get_delta();
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, gid);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, gid);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, gid);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, gid);
|
||||
|
||||
/* Check the task appid */
|
||||
prvtype = PRV_NOSV_APPID;
|
||||
int appid = 1; /* Starts at one */
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, appid);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, appid);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, appid);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, appid);
|
||||
|
||||
/* Check the rank */
|
||||
prvtype = PRV_NOSV_RANK;
|
||||
int rank = 0 + 1; /* Starts at one */
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, rank);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, rank);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, rank);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, rank);
|
||||
fclose(f);
|
||||
|
||||
/* Exit from tasks and subsystem */
|
||||
|
@ -30,7 +30,7 @@ main(void)
|
||||
die("fopen failed:");
|
||||
|
||||
uint32_t typeid = 100;
|
||||
instr_nosv_type_create((int32_t) typeid);
|
||||
instr_nosv_type_create(typeid);
|
||||
|
||||
instr_nosv_task_create(1, typeid);
|
||||
|
||||
@ -40,22 +40,22 @@ main(void)
|
||||
* the "Task: In body" state */
|
||||
int prvtype = PRV_NOSV_SUBSYSTEM;
|
||||
int st = ST_TASK_BODY;
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", get_delta(), prvtype, st);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", get_delta(), prvtype, st);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", get_delta(), prvtype, st);
|
||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", get_delta(), prvtype, st);
|
||||
|
||||
instr_nosv_submit_enter(); /* Blocking submit */
|
||||
instr_nosv_task_pause(1, 0);
|
||||
|
||||
/* Should be left in the submit state, so no state transition in
|
||||
* subsystems view */
|
||||
fprintf(f, "! grep ':%" PRIi64 ":%d:[0-9]*$' ovni/thread.prv\n", get_delta(), prvtype);
|
||||
fprintf(f, "! grep ':%" PRIi64 ":%d:[0-9]*$' ovni/cpu.prv\n", get_delta(), prvtype);
|
||||
fprintf(f, "! grep ':%ld:%d:[0-9]*$' ovni/thread.prv\n", get_delta(), prvtype);
|
||||
fprintf(f, "! grep ':%ld:%d:[0-9]*$' ovni/cpu.prv\n", get_delta(), prvtype);
|
||||
|
||||
/* But the task state must be set to pause, so the task id
|
||||
* must be null */
|
||||
prvtype = PRV_NOSV_TASKID;
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:0$' ovni/thread.prv\n", get_delta(), prvtype);
|
||||
fprintf(f, "grep ':%" PRIi64 ":%d:0$' ovni/cpu.prv\n", get_delta(), prvtype);
|
||||
fprintf(f, "grep ':%ld:%d:0$' ovni/thread.prv\n", get_delta(), prvtype);
|
||||
fprintf(f, "grep ':%ld:%d:0$' ovni/cpu.prv\n", get_delta(), prvtype);
|
||||
|
||||
instr_nosv_submit_exit();
|
||||
instr_nosv_task_resume(1, 0);
|
||||
|
@ -19,13 +19,13 @@ main(void)
|
||||
int ntypes = 10;
|
||||
|
||||
for (int i = 0; i < ntypes; i++)
|
||||
instr_nosv_type_create((int32_t) i + 1);
|
||||
instr_nosv_type_create(i + 1);
|
||||
|
||||
for (int i = 0; i < ntasks; i++) {
|
||||
instr_nosv_task_create((uint32_t) i + 1, (uint32_t) ((i % ntypes) + 1));
|
||||
instr_nosv_task_execute((uint32_t) i + 1, 0);
|
||||
instr_nosv_task_create(i + 1, (i % ntypes) + 1);
|
||||
instr_nosv_task_execute(i + 1, 0);
|
||||
sleep_us(500);
|
||||
instr_nosv_task_end((uint32_t) i + 1, 0);
|
||||
instr_nosv_task_end(i + 1, 0);
|
||||
}
|
||||
|
||||
instr_end();
|
||||
|
@ -5,7 +5,6 @@ test_emu(flush-overhead.c DISABLED)
|
||||
test_emu(flush.c)
|
||||
test_emu(sort.c SORT)
|
||||
test_emu(sort-flush.c SORT)
|
||||
test_emu(sort-into-previous-region.c SORT DRIVER "sort-into-previous-region.driver.sh")
|
||||
test_emu(empty-sort.c SORT)
|
||||
test_emu(sort-first-and-full-ring.c SORT
|
||||
SHOULD_FAIL REGEX "cannot find a event previous to clock")
|
||||
@ -29,5 +28,3 @@ test_emu(tmpdir-metadata.c MP DRIVER "tmpdir-metadata.driver.sh")
|
||||
test_emu(dummy.c NAME "ovniver" DRIVER "ovniver.driver.sh")
|
||||
test_emu(dummy.c NAME "match-doc-events" DRIVER "match-doc-events.sh")
|
||||
test_emu(dummy.c NAME "match-doc-version" DRIVER "match-doc-version.sh")
|
||||
test_emu(libovni-attr.c)
|
||||
test_emu(libovni-mark.c MP)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <stdint.h>
|
||||
@ -17,7 +17,7 @@ thread_execute_delayed(int32_t cpu, int32_t creator_tid, uint64_t tag)
|
||||
{
|
||||
struct ovni_ev ev = {0};
|
||||
ovni_ev_set_mcv(&ev, "OHx");
|
||||
ovni_ev_set_clock(&ev, ovni_clock_now() + (uint64_t) delta);
|
||||
ovni_ev_set_clock(&ev, ovni_clock_now() + delta);
|
||||
ovni_payload_add(&ev, (uint8_t *) &cpu, sizeof(cpu));
|
||||
ovni_payload_add(&ev, (uint8_t *) &creator_tid, sizeof(creator_tid));
|
||||
ovni_payload_add(&ev, (uint8_t *) &tag, sizeof(tag));
|
||||
@ -50,7 +50,7 @@ start_delayed(int rank, int nranks)
|
||||
dbg("thread %d has cpu %d (ncpus=%d)",
|
||||
get_tid(), curcpu, nranks);
|
||||
|
||||
delta = ((int64_t) rank) * (int64_t) (2LL * 3600LL * 1000LL * 1000LL * 1000LL);
|
||||
delta = ((int64_t) rank) * 2LL * 3600LL * 1000LL * 1000LL * 1000LL;
|
||||
thread_execute_delayed(curcpu, -1, 0);
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user