Compare commits
74 Commits
e3d72fb14e
...
36cf3121d1
Author | SHA1 | Date | |
---|---|---|---|
36cf3121d1 | |||
c8b95313ff | |||
e5448af6d8 | |||
49149e452c | |||
b2d91391b3 | |||
13f70be87b | |||
71aa33d22f | |||
4c3da12ea1 | |||
a47082730a | |||
99dc3904af | |||
acf18c1bb4 | |||
e9788e22ad | |||
6cb983a7c4 | |||
7496a6a866 | |||
c8750b9dfd | |||
d98ca97624 | |||
61d57901b1 | |||
9c82038561 | |||
15dfa48d2d | |||
2457e50712 | |||
92c36502bc | |||
439b716a71 | |||
97282ff051 | |||
093c91521a | |||
74aa7b4ea6 | |||
3d8c84e17c | |||
91e8367d35 | |||
129020e1c5 | |||
d03fe10be8 | |||
3fdbb95080 | |||
|
3103018404 | ||
|
478ed1f5d0 | ||
42feb53c86 | |||
391d695144 | |||
038b9d8564 | |||
5448b5c0ec | |||
be45235d15 | |||
87e4b829c5 | |||
1ab605b70d | |||
fbb78ae22d | |||
a21dc76d81 | |||
49cecb798a | |||
e31f0f1ded | |||
43792fb349 | |||
d6a83a0520 | |||
c803a7566f | |||
670edb6ddc | |||
f5d1e0a3cb | |||
a58b3d194c | |||
d9180d950b | |||
9da7234684 | |||
610b1223d9 | |||
6954f05dee | |||
db57136f1b | |||
2c111fd98c | |||
90f8ae4188 | |||
b4d445b378 | |||
ea79c90c89 | |||
1b2f72cc3a | |||
505245d54c | |||
93ab5a5833 | |||
247ea7e7c3 | |||
d1e8a62396 | |||
2ac67cff18 | |||
eed2273ddf | |||
31d6eb076c | |||
bb5e406af3 | |||
aab33ccfab | |||
98164afc90 | |||
819e83d138 | |||
16b9b2ba85 | |||
9d94189165 | |||
|
9fb53df45d | ||
92cc779caf |
@ -42,6 +42,13 @@ build:asan:
|
|||||||
script:
|
script:
|
||||||
- nix build -L --no-link .#ovniPackages.asan
|
- nix build -L --no-link .#ovniPackages.asan
|
||||||
|
|
||||||
|
build:ubsan:
|
||||||
|
stage: build
|
||||||
|
tags:
|
||||||
|
- nix
|
||||||
|
script:
|
||||||
|
- nix build -L --no-link .#ovniPackages.ubsan
|
||||||
|
|
||||||
build:nompi:
|
build:nompi:
|
||||||
stage: build
|
stage: build
|
||||||
tags:
|
tags:
|
||||||
@ -55,3 +62,24 @@ build:compilers:
|
|||||||
- nix
|
- nix
|
||||||
script:
|
script:
|
||||||
- nix build -L --no-link .#ovniPackages.compilers
|
- 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,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [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
|
## [1.9.1] - 2024-05-10
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
@ -246,6 +274,7 @@ are used along with some other changes.
|
|||||||
- First ovni release.
|
- First ovni release.
|
||||||
|
|
||||||
[unreleased]: https://jungle.bsc.es/git/rarias/ovni
|
[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.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.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
|
[1.8.0]: https://github.com/rodarima/ovni/releases/tag/1.8.0
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
project(OVNI LANGUAGES C VERSION 1.9.1)
|
project(OVNI LANGUAGES C VERSION 1.10.0)
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||||
|
|
||||||
add_compile_options(-Wall -Wextra -Wformat
|
add_compile_options(-Wall -Wextra -Wformat
|
||||||
-Wmissing-prototypes -Wstrict-prototypes
|
-Wmissing-prototypes -Wstrict-prototypes
|
||||||
#-Wconversion -Wsign-conversion
|
-Wconversion -Wsign-conversion
|
||||||
-Wold-style-definition -pedantic
|
-Wold-style-definition -pedantic
|
||||||
-Werror
|
-Werror
|
||||||
)
|
)
|
||||||
@ -67,7 +67,9 @@ set(CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_DEBUG} \
|
|||||||
-fno-omit-frame-pointer"
|
-fno-omit-frame-pointer"
|
||||||
CACHE STRING "Flags used by the C compiler during AddressSanitizer builds." FORCE)
|
CACHE STRING "Flags used by the C compiler during AddressSanitizer builds." FORCE)
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS_UBSAN "${CMAKE_C_FLAGS_DEBUG} -fsanitize=undefined"
|
set(CMAKE_C_FLAGS_UBSAN "${CMAKE_C_FLAGS_DEBUG} \
|
||||||
|
-fsanitize=undefined \
|
||||||
|
-fno-sanitize-recover=all"
|
||||||
CACHE STRING "Flags used by the C compiler during UndefinedBehaviorSanitizer builds." FORCE)
|
CACHE STRING "Flags used by the C compiler during UndefinedBehaviorSanitizer builds." FORCE)
|
||||||
|
|
||||||
find_program(IWYU NAMES include-what-you-use iwyu)
|
find_program(IWYU NAMES include-what-you-use iwyu)
|
||||||
|
44
cfg/cpu/nosv/breakdown.cfg
Normal file
44
cfg/cpu/nosv/breakdown.cfg
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#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"
|
||||||
|
|
44
cfg/cpu/nosv/idle.cfg
Normal file
44
cfg/cpu/nosv/idle.cfg
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#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"
|
||||||
|
|
41
cfg/cpu/ovni/mark.cfg
Normal file
41
cfg/cpu/ovni/mark.cfg
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#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"
|
41
cfg/thread/ovni/mark.cfg
Normal file
41
cfg/thread/ovni/mark.cfg
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#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
|
# Emulator events
|
||||||
|
|
||||||
This is a exhaustive list of the events recognized by the emulator.
|
This is a exhaustive list of the events recognized by the emulator.
|
||||||
Built on Mar 20 2024.
|
Built on Jun 17 2024.
|
||||||
|
|
||||||
## Model nanos6
|
## Model nanos6
|
||||||
|
|
||||||
@ -395,7 +395,7 @@ List of events for the model *mpi* with identifier **`M`** at version `1.0.0`:
|
|||||||
|
|
||||||
## Model ovni
|
## Model ovni
|
||||||
|
|
||||||
List of events for the model *ovni* with identifier **`O`** at version `1.0.0`:
|
List of events for the model *ovni* with identifier **`O`** at version `1.1.0`:
|
||||||
<dl>
|
<dl>
|
||||||
<dt><a id="OAr" href="#OAr"><pre>OAr(i32 cpu, i32 tid)</pre></a></dt>
|
<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>
|
<dd>changes the affinity of thread %{tid} to CPU %{cpu}</dd>
|
||||||
@ -427,6 +427,12 @@ List of events for the model *ovni* with identifier **`O`** at version `1.0.0`:
|
|||||||
<dd>enters unordered event region</dd>
|
<dd>enters unordered event region</dd>
|
||||||
<dt><a id="OU]" href="#OU]"><pre>OU]</pre></a></dt>
|
<dt><a id="OU]" href="#OU]"><pre>OU]</pre></a></dt>
|
||||||
<dd>leaves unordered event region</dd>
|
<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>
|
</dl>
|
||||||
|
|
||||||
## Model openmp
|
## Model openmp
|
||||||
@ -615,7 +621,7 @@ List of events for the model *tampi* with identifier **`T`** at version `1.0.0`:
|
|||||||
|
|
||||||
## Model nosv
|
## Model nosv
|
||||||
|
|
||||||
List of events for the model *nosv* with identifier **`V`** at version `2.1.0`:
|
List of events for the model *nosv* with identifier **`V`** at version `2.3.0`:
|
||||||
<dl>
|
<dl>
|
||||||
<dt><a id="VTc" href="#VTc"><pre>VTc(u32 taskid, u32 typeid)</pre></a></dt>
|
<dt><a id="VTc" href="#VTc"><pre>VTc(u32 taskid, u32 typeid)</pre></a></dt>
|
||||||
<dd>creates task %{taskid} with type %{typeid}</dd>
|
<dd>creates task %{taskid} with type %{typeid}</dd>
|
||||||
@ -721,4 +727,10 @@ List of events for the model *nosv* with identifier **`V`** at version `2.1.0`:
|
|||||||
<dd>begins execution as delegate</dd>
|
<dd>begins execution as delegate</dd>
|
||||||
<dt><a id="VHD" href="#VHD"><pre>VHD</pre></a></dt>
|
<dt><a id="VHD" href="#VHD"><pre>VHD</pre></a></dt>
|
||||||
<dd>ceases execution as delegate</dd>
|
<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>
|
</dl>
|
||||||
|
BIN
doc/user/emulation/fig/breakdown-nosv.code_legend.png
Normal file
BIN
doc/user/emulation/fig/breakdown-nosv.code_legend.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
BIN
doc/user/emulation/fig/breakdown-nosv.png
Normal file
BIN
doc/user/emulation/fig/breakdown-nosv.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
@ -61,3 +61,46 @@ For more details, see [this MR][1].
|
|||||||
The subsystem view provides a simplified view on what is the nOS-V
|
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
|
runtime doing over time. The view follows the same rules described in
|
||||||
the [subsystem view of Nanos6](../nanos6/#subsystem_view).
|
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,6 +27,8 @@ Track changes in emulator model versions.
|
|||||||
|
|
||||||
## Ovni
|
## Ovni
|
||||||
|
|
||||||
|
- ovni 1.1.0
|
||||||
|
- Add support for mark events `OM[`, `OM]` and `OM=`
|
||||||
- ovni 1.0.0: Initial version
|
- ovni 1.0.0: Initial version
|
||||||
|
|
||||||
## OpenMP
|
## OpenMP
|
||||||
@ -39,9 +41,13 @@ Track changes in emulator model versions.
|
|||||||
|
|
||||||
## nOS-V
|
## 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
|
- nosv 2.1.0
|
||||||
- Add support for `nosv_mutex_lock`, `nosv_mutex_trylock` and `nosv_mutex_unlock` events VA{lLtTuU}.
|
- 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_barrier_wait` event `VA{bB}`.
|
||||||
- nosv 2.0.0
|
- nosv 2.0.0
|
||||||
- Add support for parallel tasks, adding a new `bodyid` argument in `VT*` events.
|
- Add support for parallel tasks, adding a new `bodyid` argument in `VT*` events.
|
||||||
- Remove support for old attach events `VH{aA}`.
|
- Remove support for old attach events `VH{aA}`.
|
||||||
|
156
doc/user/runtime/mark.md
Normal file
156
doc/user/runtime/mark.md
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
# 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 {
|
nosv = prev.nosv.override {
|
||||||
useGit = true;
|
useGit = true;
|
||||||
gitBranch = "master";
|
gitBranch = "master";
|
||||||
gitCommit = "c698c16c0518e6afc68fb32ee6f1a0f65ca69327";
|
gitCommit = "3286ff5a788a989407519dd1dfe57c1750258d3f";
|
||||||
};
|
};
|
||||||
nanos6 = prev.nanos6.override {
|
nanos6 = prev.nanos6.override {
|
||||||
useGit = true;
|
useGit = true;
|
||||||
@ -37,7 +37,8 @@
|
|||||||
ovniFixed = prev.ovni.override {
|
ovniFixed = prev.ovni.override {
|
||||||
useGit = true;
|
useGit = true;
|
||||||
gitBranch = "master";
|
gitBranch = "master";
|
||||||
gitCommit = "68fc8b0eba299c3a7fa3833ace2c94933a26749e";
|
# Includes ovni_attr_* API
|
||||||
|
gitCommit = "d1e8a62396ae92934c0b6e248d5f6ff921bef56f";
|
||||||
};
|
};
|
||||||
# Build with the current source
|
# Build with the current source
|
||||||
ovniLocal = prev.ovni.overrideAttrs (old: rec {
|
ovniLocal = prev.ovni.overrideAttrs (old: rec {
|
||||||
@ -134,6 +135,38 @@
|
|||||||
export ASAN_OPTIONS=detect_leaks=0
|
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-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: MIT */
|
* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
#ifndef OVNI_H
|
#ifndef OVNI_H
|
||||||
@ -130,6 +130,28 @@ void ovni_ev_jumbo_emit(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize
|
|||||||
|
|
||||||
void ovni_flush(void);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,6 +27,7 @@ nav:
|
|||||||
- user/installation.md
|
- user/installation.md
|
||||||
- 'Runtime':
|
- 'Runtime':
|
||||||
- user/runtime/tracing.md
|
- user/runtime/tracing.md
|
||||||
|
- user/runtime/mark.md
|
||||||
- user/runtime/distributed.md
|
- user/runtime/distributed.md
|
||||||
- user/runtime/kernel.md
|
- user/runtime/kernel.md
|
||||||
- user/runtime/trace_spec.md
|
- user/runtime/trace_spec.md
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: MIT */
|
* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -45,7 +45,7 @@ vaerr(const char *prefix, const char *func, const char *errstr, va_list ap)
|
|||||||
|
|
||||||
vfprintf(stderr, errstr, ap);
|
vfprintf(stderr, errstr, ap);
|
||||||
|
|
||||||
int len = strlen(errstr);
|
int len = (int) strlen(errstr);
|
||||||
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
char last = errstr[len - 1];
|
char last = errstr[len - 1];
|
||||||
@ -103,7 +103,7 @@ mkpath(const char *path, mode_t mode, int is_dir)
|
|||||||
char *copypath = strdup(path);
|
char *copypath = strdup(path);
|
||||||
|
|
||||||
/* Remove trailing slash */
|
/* Remove trailing slash */
|
||||||
int last = strlen(path) - 1;
|
int last = (int) strlen(path) - 1;
|
||||||
while (last > 0 && copypath[last] == '/')
|
while (last > 0 && copypath[last] == '/')
|
||||||
copypath[last--] = '\0';
|
copypath[last--] = '\0';
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
extern int is_debug_enabled;
|
extern int is_debug_enabled;
|
||||||
|
|
||||||
@ -18,8 +19,8 @@ int mkpath(const char *path, mode_t mode, int is_dir);
|
|||||||
void progname_set(char *name);
|
void progname_set(char *name);
|
||||||
const char *progname_get(void);
|
const char *progname_get(void);
|
||||||
void enable_debug(void);
|
void enable_debug(void);
|
||||||
void verr(const char *prefix, const char *func, const char *errstr, ...);
|
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, ...);
|
void vdie(const char *prefix, const char *func, const char *errstr, ...) __attribute__((format(printf, 3, 4)));
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
|
@ -49,9 +49,11 @@ add_library(emu STATIC
|
|||||||
value.c
|
value.c
|
||||||
ovni/event.c
|
ovni/event.c
|
||||||
ovni/setup.c
|
ovni/setup.c
|
||||||
|
ovni/mark.c
|
||||||
nanos6/setup.c
|
nanos6/setup.c
|
||||||
nanos6/event.c
|
nanos6/event.c
|
||||||
nanos6/breakdown.c
|
nanos6/breakdown.c
|
||||||
|
nosv/breakdown.c
|
||||||
nosv/setup.c
|
nosv/setup.c
|
||||||
nosv/event.c
|
nosv/event.c
|
||||||
nodes/setup.c
|
nodes/setup.c
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "bay.h"
|
#include "bay.h"
|
||||||
@ -106,7 +106,7 @@ bay_add_cb(struct bay *bay, enum bay_cb_type type,
|
|||||||
cb->func = func;
|
cb->func = func;
|
||||||
cb->arg = arg;
|
cb->arg = arg;
|
||||||
cb->bchan = bchan;
|
cb->bchan = bchan;
|
||||||
cb->type = type;
|
cb->type = (int) type;
|
||||||
cb->enabled = 0;
|
cb->enabled = 0;
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
@ -168,7 +168,7 @@ propagate_chan(struct bay_chan *bchan, enum bay_cb_type type)
|
|||||||
struct bay_cb *cur = NULL;
|
struct bay_cb *cur = NULL;
|
||||||
/* New callbacks cannot be added while propagating a bay_chan */
|
/* New callbacks cannot be added while propagating a bay_chan */
|
||||||
DL_FOREACH(bchan->cb[type], cur) {
|
DL_FOREACH(bchan->cb[type], cur) {
|
||||||
dbg("calling cb %p", cur->func);
|
dbg("calling cb %"PRIxPTR, (uintptr_t) cur->func);
|
||||||
if (cur->func(bchan->chan, cur->arg) != 0) {
|
if (cur->func(bchan->chan, cur->arg) != 0) {
|
||||||
err("callback failed for %s", bchan->chan->name);
|
err("callback failed for %s", bchan->chan->name);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "body.h"
|
#include "body.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "chan.h"
|
#include "chan.h"
|
||||||
@ -15,9 +15,11 @@ chan_init(struct chan *chan, enum chan_type type, const char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
|
||||||
int n = ARRAYLEN(chan->name);
|
size_t n = ARRAYLEN(chan->name);
|
||||||
int ret = vsnprintf(chan->name, n, fmt, ap);
|
int ret = vsnprintf(chan->name, n, fmt, ap);
|
||||||
if (ret >= n)
|
if (ret < 0)
|
||||||
|
die("vsnprintf failed");
|
||||||
|
else if ((size_t) ret >= n)
|
||||||
die("channel name too long");
|
die("channel name too long");
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
@ -155,7 +157,7 @@ chan_push(struct chan *chan, struct value value)
|
|||||||
/** Remove one value from the stack. Fails if the top of the stack
|
/** Remove one value from the stack. Fails if the top of the stack
|
||||||
* doesn't match the expected value.
|
* doesn't match the expected value.
|
||||||
*
|
*
|
||||||
* @param expected The expected value on the top of the stack.
|
* @param evalue The expected value on the top of the stack.
|
||||||
*
|
*
|
||||||
* @return On success returns 0, otherwise returns -1.
|
* @return On success returns 0, otherwise returns -1.
|
||||||
*/
|
*/
|
||||||
@ -182,10 +184,10 @@ chan_pop(struct chan *chan, struct value evalue)
|
|||||||
struct value *value = &stack->values[stack->n - 1];
|
struct value *value = &stack->values[stack->n - 1];
|
||||||
|
|
||||||
if (!value_is_equal(value, &evalue)) {
|
if (!value_is_equal(value, &evalue)) {
|
||||||
err("%s: unexpected value %s (expected %s)",
|
err("%s: expected value %s different from top of stack %s",
|
||||||
chan->name,
|
chan->name,
|
||||||
value_str(*value),
|
value_str(evalue),
|
||||||
value_str(evalue));
|
value_str(*value));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#ifndef CHAN_H
|
#ifndef CHAN_H
|
||||||
@ -70,7 +70,7 @@ chan_read(struct chan *chan, struct value *value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void chan_init(struct chan *chan, enum chan_type type, const char *fmt, ...);
|
void chan_init(struct chan *chan, enum chan_type type, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
|
||||||
USE_RET int chan_set(struct chan *chan, struct value value);
|
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_push(struct chan *chan, struct value value);
|
||||||
USE_RET int chan_pop(struct chan *chan, struct value expected);
|
USE_RET int chan_pop(struct chan *chan, struct value expected);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "clkoff.h"
|
#include "clkoff.h"
|
||||||
@ -59,7 +59,7 @@ cparse(struct clkoff *table, FILE *file)
|
|||||||
if (buf[0] == '\n')
|
if (buf[0] == '\n')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int ret = sscanf(buf, "%ld %s %lf %lf %lf",
|
int ret = sscanf(buf, "%" SCNd64 "%s %lf %lf %lf",
|
||||||
&e.index, e.name,
|
&e.index, e.name,
|
||||||
&e.median, &e.mean, &e.stdev);
|
&e.median, &e.mean, &e.stdev);
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ cindex(struct clkoff *table)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
table->index = calloc(table->nentries, sizeof(struct clkoff_entry *));
|
table->index = calloc((size_t) table->nentries, sizeof(struct clkoff_entry *));
|
||||||
|
|
||||||
if (table->index == NULL) {
|
if (table->index == NULL) {
|
||||||
err("calloc failed");
|
err("calloc failed");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
@ -17,7 +17,7 @@
|
|||||||
#include "utlist.h"
|
#include "utlist.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
|
||||||
static const char chan_fmt[] = "cpu%ld.%s";
|
static const char chan_fmt[] = "cpu%"PRIi64".%s";
|
||||||
static const char *chan_name[CPU_CHAN_MAX] = {
|
static const char *chan_name[CPU_CHAN_MAX] = {
|
||||||
[CPU_CHAN_NRUN] = "nrunning",
|
[CPU_CHAN_NRUN] = "nrunning",
|
||||||
[CPU_CHAN_PID] = "pid_running",
|
[CPU_CHAN_PID] = "pid_running",
|
||||||
@ -78,14 +78,14 @@ cpu_set_loom(struct cpu *cpu, struct loom *loom)
|
|||||||
static int
|
static int
|
||||||
set_name(struct cpu *cpu)
|
set_name(struct cpu *cpu)
|
||||||
{
|
{
|
||||||
size_t i = loom_get_gindex(cpu->loom);
|
size_t i = (size_t) loom_get_gindex(cpu->loom);
|
||||||
size_t j = cpu_get_phyid(cpu);
|
size_t j = (size_t) cpu_get_phyid(cpu);
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (cpu->is_virtual)
|
if (cpu->is_virtual)
|
||||||
n = snprintf(cpu->name, PATH_MAX, "vCPU %ld.*", i);
|
n = snprintf(cpu->name, PATH_MAX, "vCPU %zu.*", i);
|
||||||
else
|
else
|
||||||
n = snprintf(cpu->name, PATH_MAX, " CPU %ld.%ld", i, j);
|
n = snprintf(cpu->name, PATH_MAX, " CPU %zu.%zu", i, j);
|
||||||
|
|
||||||
if (n >= PATH_MAX) {
|
if (n >= PATH_MAX) {
|
||||||
err("cpu name too long");
|
err("cpu name too long");
|
||||||
@ -162,7 +162,7 @@ cpu_connect(struct cpu *cpu, struct bay *bay, struct recorder *rec)
|
|||||||
if (type < 0)
|
if (type < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
long row = cpu->gindex;
|
long row = (long) cpu->gindex;
|
||||||
long flags = prv_flags[i];
|
long flags = prv_flags[i];
|
||||||
if (prv_register(prv, row, type, bay, c, flags)) {
|
if (prv_register(prv, row, type, bay, c, flags)) {
|
||||||
err("prv_register failed");
|
err("prv_register failed");
|
||||||
@ -176,7 +176,7 @@ cpu_connect(struct cpu *cpu, struct bay *bay, struct recorder *rec)
|
|||||||
struct pcf_value *
|
struct pcf_value *
|
||||||
cpu_add_to_pcf_type(struct cpu *cpu, struct pcf_type *type)
|
cpu_add_to_pcf_type(struct cpu *cpu, struct pcf_type *type)
|
||||||
{
|
{
|
||||||
return pcf_add_value(type, cpu->gindex + 1, cpu->name);
|
return pcf_add_value(type, (int) cpu->gindex + 1, cpu->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct thread *
|
static struct thread *
|
||||||
@ -215,12 +215,12 @@ cpu_update(struct cpu *cpu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->nth_running = running;
|
cpu->nth_running = (size_t) running;
|
||||||
cpu->nth_active = active;
|
cpu->nth_active = (size_t) active;
|
||||||
|
|
||||||
/* Only virtual cpus can be oversubscribed */
|
/* Only virtual cpus can be oversubscribed */
|
||||||
if (cpu->nth_running > 1 && !cpu->is_virtual) {
|
if (cpu->nth_running > 1 && !cpu->is_virtual) {
|
||||||
err("physical cpu %s has %d threads running at the same time",
|
err("physical cpu %s has %zd threads running at the same time",
|
||||||
cpu->name, cpu->nth_running);
|
cpu->name, cpu->nth_running);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -248,7 +248,7 @@ cpu_update(struct cpu *cpu)
|
|||||||
err("chan_set pid failed");
|
err("chan_set pid failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dbg("cpu%ld sets th_running to %s",
|
dbg("cpu%"PRIi64" sets th_running to %s",
|
||||||
cpu->gindex, value_str(gid_running));
|
cpu->gindex, value_str(gid_running));
|
||||||
if (chan_set(&cpu->chan[CPU_CHAN_THRUN], gid_running) != 0) {
|
if (chan_set(&cpu->chan[CPU_CHAN_THRUN], gid_running) != 0) {
|
||||||
err("chan_set gid_running failed");
|
err("chan_set gid_running failed");
|
||||||
@ -265,7 +265,7 @@ cpu_update(struct cpu *cpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update nth_running number in the channel */
|
/* Update nth_running number in the channel */
|
||||||
if (chan_set(&cpu->chan[CPU_CHAN_NRUN], value_int64(running)) != 0) {
|
if (chan_set(&cpu->chan[CPU_CHAN_NRUN], value_int64((int64_t) running)) != 0) {
|
||||||
err("chan_set nth_running failed");
|
err("chan_set nth_running failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
@ -118,18 +118,18 @@ panic(struct emu *emu)
|
|||||||
if (emu->ev != NULL) {
|
if (emu->ev != NULL) {
|
||||||
err("event: ");
|
err("event: ");
|
||||||
err(" mcv=%s", emu->ev->mcv);
|
err(" mcv=%s", emu->ev->mcv);
|
||||||
err(" rclock=%ld", emu->ev->rclock);
|
err(" rclock=%"PRIi64, emu->ev->rclock);
|
||||||
err(" sclock=%ld", emu->ev->sclock);
|
err(" sclock=%"PRIi64, emu->ev->sclock);
|
||||||
err(" dclock=%ld", emu->ev->dclock);
|
err(" dclock=%"PRIi64, emu->ev->dclock);
|
||||||
err(" payload_size=%ld", emu->ev->payload_size);
|
err(" payload_size=%zd", emu->ev->payload_size);
|
||||||
err(" is_jumbo=%d", emu->ev->is_jumbo);
|
err(" is_jumbo=%d", emu->ev->is_jumbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emu->stream != NULL) {
|
if (emu->stream != NULL) {
|
||||||
err("stream: ");
|
err("stream: ");
|
||||||
err(" relpath=%s", emu->stream->relpath);
|
err(" relpath=%s", emu->stream->relpath);
|
||||||
err(" offset=%ld", emu->stream->offset);
|
err(" offset=%"PRIi64, emu->stream->offset);
|
||||||
err(" clock_offset=%ld", emu->stream->clock_offset);
|
err(" clock_offset=%"PRIi64, emu->stream->clock_offset);
|
||||||
}
|
}
|
||||||
err("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
err("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ emu_step(struct emu *emu)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("----- mvc=%s dclock=%ld -----", emu->ev->mcv, emu->ev->dclock);
|
dbg("----- mcv=%s dclock=%"PRIi64" -----", emu->ev->mcv, emu->ev->dclock);
|
||||||
|
|
||||||
emu_stat_update(&emu->stat, &emu->player);
|
emu_stat_update(&emu->stat, &emu->player);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "emu_ev.h"
|
#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->v = oev->header.value;
|
||||||
ev->mcv[3] = '\0';
|
ev->mcv[3] = '\0';
|
||||||
|
|
||||||
ev->rclock = oev->header.clock;
|
ev->rclock = (int64_t) oev->header.clock;
|
||||||
ev->sclock = sclock;
|
ev->sclock = sclock;
|
||||||
ev->dclock = dclock;
|
ev->dclock = dclock;
|
||||||
|
|
||||||
ev->payload_size = ovni_payload_size(oev);
|
ev->payload_size = (size_t) ovni_payload_size(oev);
|
||||||
|
|
||||||
if (ev->payload_size > 0) {
|
if (ev->payload_size > 0) {
|
||||||
ev->has_payload = 1;
|
ev->has_payload = 1;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#ifndef EMU_PRV_H
|
#ifndef EMU_PRV_H
|
||||||
@ -19,6 +19,8 @@ enum emu_prv_types {
|
|||||||
PRV_NOSV_SUBSYSTEM = 13,
|
PRV_NOSV_SUBSYSTEM = 13,
|
||||||
PRV_NOSV_RANK = 14,
|
PRV_NOSV_RANK = 14,
|
||||||
PRV_NOSV_BODYID = 15,
|
PRV_NOSV_BODYID = 15,
|
||||||
|
PRV_NOSV_IDLE = 16,
|
||||||
|
PRV_NOSV_BREAKDOWN = 17,
|
||||||
PRV_TAMPI_SUBSYSTEM = 20,
|
PRV_TAMPI_SUBSYSTEM = 20,
|
||||||
PRV_MPI_FUNCTION = 25,
|
PRV_MPI_FUNCTION = 25,
|
||||||
PRV_NODES_SUBSYSTEM = 30,
|
PRV_NODES_SUBSYSTEM = 30,
|
||||||
@ -31,7 +33,9 @@ enum emu_prv_types {
|
|||||||
PRV_NANOS6_BREAKDOWN = 41,
|
PRV_NANOS6_BREAKDOWN = 41,
|
||||||
PRV_KERNEL_CS = 45,
|
PRV_KERNEL_CS = 45,
|
||||||
PRV_OPENMP_SUBSYSTEM = 50,
|
PRV_OPENMP_SUBSYSTEM = 50,
|
||||||
PRV_RESERVED = 100,
|
PRV_OVNI_MARK = 100,
|
||||||
|
/* User marks [100, 200) */
|
||||||
|
PRV_RESERVED = 200,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EMU_PRV_H */
|
#endif /* EMU_PRV_H */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "emu_stat.h"
|
#include "emu_stat.h"
|
||||||
@ -54,11 +54,9 @@ emu_stat_report(struct emu_stat *stat, struct player *player, int last)
|
|||||||
double speed = stat->average ? avgspeed : instspeed;
|
double speed = stat->average ? avgspeed : instspeed;
|
||||||
|
|
||||||
if (last) {
|
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",
|
info("%5.1f%% done at avg %.0f kev/s \n",
|
||||||
progress * 100.0, avgspeed * 1e-3, tmin, tsec);
|
progress * 100.0, avgspeed * 1e-3);
|
||||||
info("processed %ld input events in %.2f s\n",
|
info("processed %"PRIi64" input events in %.2f s\n",
|
||||||
nprocessed, time_elapsed);
|
nprocessed, time_elapsed);
|
||||||
} else {
|
} else {
|
||||||
int tmin = (int) (time_left / 60.0);
|
int tmin = (int) (time_left / 60.0);
|
||||||
|
@ -104,7 +104,7 @@ parse_arg(struct ev_spec *spec, char *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Copy name */
|
/* Copy name */
|
||||||
size_t n = snprintf(argspec->name, sizeof(argspec->name), "%s", name);
|
size_t n = (size_t) snprintf(argspec->name, sizeof(argspec->name), "%s", name);
|
||||||
if (n >= sizeof(argspec->name)) {
|
if (n >= sizeof(argspec->name)) {
|
||||||
err("argument name too long: %s", name);
|
err("argument name too long: %s", name);
|
||||||
return -1;
|
return -1;
|
||||||
@ -363,8 +363,9 @@ print_arg(struct ev_arg *arg, const char *fmt, struct cursor *c, struct emu_ev *
|
|||||||
|
|
||||||
#define CASE(TYPE) \
|
#define CASE(TYPE) \
|
||||||
do { \
|
do { \
|
||||||
TYPE *data = (TYPE *) &payload[arg->offset]; \
|
TYPE data; \
|
||||||
n = snprintf(c->out, c->len, fmt, *data); \
|
memcpy(&data, &payload[arg->offset], sizeof(data)); \
|
||||||
|
n = snprintf(c->out, (size_t) c->len, fmt, data); \
|
||||||
if (n >= c->len) { \
|
if (n >= c->len) { \
|
||||||
err("no space for argument"); \
|
err("no space for argument"); \
|
||||||
return -1; \
|
return -1; \
|
||||||
@ -386,8 +387,8 @@ print_arg(struct ev_arg *arg, const char *fmt, struct cursor *c, struct emu_ev *
|
|||||||
char *data = (char *) &payload[arg->offset];
|
char *data = (char *) &payload[arg->offset];
|
||||||
/* Here we trust the input string to
|
/* Here we trust the input string to
|
||||||
* contain a nil at the end */
|
* contain a nil at the end */
|
||||||
int n = snprintf(c->out, c->len, fmt, data);
|
int n = snprintf(c->out, (size_t) c->len, fmt, data);
|
||||||
if (n >= c->len) {
|
if (n >= (int) c->len) {
|
||||||
err("no space for string argument");
|
err("no space for string argument");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#ifndef LOOM_H
|
#ifndef LOOM_H
|
||||||
@ -14,7 +14,7 @@
|
|||||||
struct proc;
|
struct proc;
|
||||||
|
|
||||||
struct loom {
|
struct loom {
|
||||||
size_t gindex;
|
int64_t gindex;
|
||||||
int is_init;
|
int is_init;
|
||||||
|
|
||||||
char name[PATH_MAX];
|
char name[PATH_MAX];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "model_cpu.h"
|
#include "model_cpu.h"
|
||||||
@ -27,7 +27,7 @@ get_model_cpu(struct cpu *cpu, int id)
|
|||||||
static int
|
static int
|
||||||
init_chan(struct model_cpu *cpu, const struct model_chan_spec *spec, int64_t gindex)
|
init_chan(struct model_cpu *cpu, const struct model_chan_spec *spec, int64_t gindex)
|
||||||
{
|
{
|
||||||
cpu->track = calloc(spec->nch, sizeof(struct track));
|
cpu->track = calloc((size_t) spec->nch, sizeof(struct track));
|
||||||
if (cpu->track == NULL) {
|
if (cpu->track == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
return -1;
|
return -1;
|
||||||
@ -40,7 +40,8 @@ init_chan(struct model_cpu *cpu, const struct model_chan_spec *spec, int64_t gin
|
|||||||
const char *ch_name = spec->ch_names[i];
|
const char *ch_name = spec->ch_names[i];
|
||||||
int track_mode = spec->track[i];
|
int track_mode = spec->track[i];
|
||||||
|
|
||||||
if (track_init(track, cpu->bay, TRACK_TYPE_TH, track_mode, "%s.cpu%ld.%s",
|
if (track_init(track, cpu->bay, TRACK_TYPE_TH, track_mode,
|
||||||
|
"%s.cpu%"PRIi64".%s",
|
||||||
name, gindex, ch_name) != 0) {
|
name, gindex, ch_name) != 0) {
|
||||||
err("track_init failed");
|
err("track_init failed");
|
||||||
return -1;
|
return -1;
|
||||||
@ -107,7 +108,7 @@ connect_cpu(struct emu *emu, struct cpu *scpu, int id)
|
|||||||
|
|
||||||
struct chan *sel = cpu_get_th_chan(scpu);
|
struct chan *sel = cpu_get_th_chan(scpu);
|
||||||
|
|
||||||
int64_t nthreads = emu->system.nthreads;
|
int64_t nthreads = (int64_t) emu->system.nthreads;
|
||||||
if (track_set_select(track, sel, NULL, nthreads) != 0) {
|
if (track_set_select(track, sel, NULL, nthreads) != 0) {
|
||||||
err("track_select failed");
|
err("track_select failed");
|
||||||
return -1;
|
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 */
|
/* Preallocate a contiguous map, as we know the size */
|
||||||
evspec->alloc = calloc(evspec->nevents, sizeof(struct ev_spec));
|
evspec->alloc = calloc((size_t) evspec->nevents, sizeof(struct ev_spec));
|
||||||
if (evspec->alloc == NULL) {
|
if (evspec->alloc == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "model_pvt.h"
|
#include "model_pvt.h"
|
||||||
@ -35,7 +35,7 @@ create_values(const struct model_pvt_spec *pvt,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (const struct pcf_value_label *p = q; p->label != NULL; p++) {
|
for (const struct pcf_value_label *p = q; p->label != NULL; p++) {
|
||||||
if (pcf_add_value(t, p->value, p->label) == NULL) {
|
if (pcf_add_value(t, (int) p->value, p->label) == NULL) {
|
||||||
err("pcf_add_value failed");
|
err("pcf_add_value failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ create_type(const struct model_pvt_spec *pvt,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pcf_type *pcftype = pcf_add_type(pcf, type, label);
|
struct pcf_type *pcftype = pcf_add_type(pcf, (int) type, label);
|
||||||
if (pcftype == NULL) {
|
if (pcftype == NULL) {
|
||||||
err("pcf_add_type failed");
|
err("pcf_add_type failed");
|
||||||
return -1;
|
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++) {
|
for (int i = 0; i < spec->nch; i++) {
|
||||||
struct chan *out = track_get_output(&cpu->track[i]);
|
struct chan *out = track_get_output(&cpu->track[i]);
|
||||||
long type = spec->pvt->type[i];
|
long type = spec->pvt->type[i];
|
||||||
long row = scpu->gindex;
|
long row = (long) scpu->gindex;
|
||||||
long flags = flags_arr ? flags_arr[i] : 0;
|
long flags = flags_arr ? flags_arr[i] : 0;
|
||||||
if (prv_register(prv, row, type, &emu->bay, out, flags)) {
|
if (prv_register(prv, row, type, &emu->bay, out, flags)) {
|
||||||
err("prv_register failed");
|
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++) {
|
for (int i = 0; i < spec->nch; i++) {
|
||||||
struct chan *out = track_get_output(&th->track[i]);
|
struct chan *out = track_get_output(&th->track[i]);
|
||||||
long type = spec->pvt->type[i];
|
long type = spec->pvt->type[i];
|
||||||
long row = sth->gindex;
|
long row = (long) sth->gindex;
|
||||||
long flags = flags_arr ? flags_arr[i] : 0;
|
long flags = flags_arr ? flags_arr[i] : 0;
|
||||||
if (prv_register(prv, row, type, &emu->bay, out, flags)) {
|
if (prv_register(prv, row, type, &emu->bay, out, flags)) {
|
||||||
err("prv_register failed");
|
err("prv_register failed");
|
||||||
@ -178,7 +178,7 @@ model_pvt_connect_thread(struct emu *emu, const struct model_thread_spec *spec)
|
|||||||
/* Get cpu PRV */
|
/* Get cpu PRV */
|
||||||
struct pvt *pvt = recorder_find_pvt(&emu->recorder, "thread");
|
struct pvt *pvt = recorder_find_pvt(&emu->recorder, "thread");
|
||||||
if (pvt == NULL) {
|
if (pvt == NULL) {
|
||||||
err("cannot find cpu pvt");
|
err("cannot find thread pvt");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "model_thread.h"
|
#include "model_thread.h"
|
||||||
@ -19,10 +19,10 @@
|
|||||||
static int
|
static int
|
||||||
init_chan(struct model_thread *th, const struct model_chan_spec *spec, int64_t gindex)
|
init_chan(struct model_thread *th, const struct model_chan_spec *spec, int64_t gindex)
|
||||||
{
|
{
|
||||||
const char *fmt = "%s.thread%ld.%s";
|
const char *fmt = "%s.thread%"PRIi64".%s";
|
||||||
const char *prefix = spec->prefix;
|
const char *prefix = spec->prefix;
|
||||||
|
|
||||||
th->ch = calloc(spec->nch, sizeof(struct chan));
|
th->ch = calloc((size_t) spec->nch, sizeof(struct chan));
|
||||||
if (th->ch == NULL) {
|
if (th->ch == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
return -1;
|
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++) {
|
for (int i = 0; i < spec->nch; i++) {
|
||||||
struct chan *c = &th->ch[i];
|
struct chan *c = &th->ch[i];
|
||||||
int type = spec->ch_stack[i];
|
enum chan_type type = spec->ch_stack[i] ? CHAN_STACK : CHAN_SINGLE;
|
||||||
const char *ch_name = spec->ch_names[i];
|
const char *ch_name = spec->ch_names[i];
|
||||||
chan_init(c, type, fmt, prefix, gindex, ch_name);
|
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(spec->nch, sizeof(struct track));
|
th->track = calloc((size_t) spec->nch, sizeof(struct track));
|
||||||
if (th->track == NULL) {
|
if (th->track == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "mux.h"
|
#include "mux.h"
|
||||||
@ -25,7 +25,7 @@ default_select(struct mux *mux,
|
|||||||
int64_t index = key.i;
|
int64_t index = key.i;
|
||||||
|
|
||||||
if (index < 0 || index >= mux->ninputs) {
|
if (index < 0 || index >= mux->ninputs) {
|
||||||
err("index out of bounds %ld", index);
|
err("index out of bounds %"PRIi64, index);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ mux_init(struct mux *mux,
|
|||||||
mux->select = select;
|
mux->select = select;
|
||||||
mux->output = output;
|
mux->output = output;
|
||||||
mux->ninputs = ninputs;
|
mux->ninputs = ninputs;
|
||||||
mux->inputs = calloc(ninputs, sizeof(struct mux_input));
|
mux->inputs = calloc((size_t) ninputs, sizeof(struct mux_input));
|
||||||
mux->def = value_null();
|
mux->def = value_null();
|
||||||
|
|
||||||
if (mux->inputs == 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];
|
struct mux_input *input = &mux->inputs[index];
|
||||||
|
|
||||||
if (input->chan != NULL) {
|
if (input->chan != NULL) {
|
||||||
err("input %d already has a channel", index);
|
err("input %"PRIi64" already has a channel", index);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ static int
|
|||||||
create_cpu(struct bay *bay, struct breakdown_cpu *bcpu, int64_t gindex)
|
create_cpu(struct bay *bay, struct breakdown_cpu *bcpu, int64_t gindex)
|
||||||
{
|
{
|
||||||
enum chan_type t = CHAN_SINGLE;
|
enum chan_type t = CHAN_SINGLE;
|
||||||
chan_init(&bcpu->tr, t, "nanos6.cpu%ld.breakdown.tr", gindex);
|
chan_init(&bcpu->tr, t, "nanos6.cpu%"PRIi64".breakdown.tr", gindex);
|
||||||
chan_init(&bcpu->tri, t, "nanos6.cpu%ld.breakdown.tri", gindex);
|
chan_init(&bcpu->tri, t, "nanos6.cpu%"PRIi64".breakdown.tri", gindex);
|
||||||
|
|
||||||
/* Register all channels in the bay */
|
/* Register all channels in the bay */
|
||||||
if (bay_register(bay, &bcpu->tr) != 0) {
|
if (bay_register(bay, &bcpu->tr) != 0) {
|
||||||
@ -59,12 +59,12 @@ model_nanos6_breakdown_create(struct emu *emu)
|
|||||||
|
|
||||||
/* Count phy cpus */
|
/* Count phy cpus */
|
||||||
struct system *sys = &emu->system;
|
struct system *sys = &emu->system;
|
||||||
int64_t nphycpus = sys->ncpus - sys->nlooms;
|
int64_t nphycpus = (int64_t) (sys->ncpus - sys->nlooms);
|
||||||
bemu->nphycpus = nphycpus;
|
bemu->nphycpus = nphycpus;
|
||||||
|
|
||||||
/* Create a new Paraver trace */
|
/* Create a new Paraver trace */
|
||||||
struct recorder *rec = &emu->recorder;
|
struct recorder *rec = &emu->recorder;
|
||||||
bemu->pvt = recorder_add_pvt(rec, "nanos6-breakdown", nphycpus);
|
bemu->pvt = recorder_add_pvt(rec, "nanos6-breakdown", (long) nphycpus);
|
||||||
if (bemu->pvt == NULL) {
|
if (bemu->pvt == NULL) {
|
||||||
err("recorder_add_pvt failed");
|
err("recorder_add_pvt failed");
|
||||||
return -1;
|
return -1;
|
||||||
@ -131,7 +131,7 @@ select_tr(struct mux *mux, struct value value, struct mux_input **input)
|
|||||||
|
|
||||||
int64_t i = in_body;
|
int64_t i = in_body;
|
||||||
char *inputs[] = { "subsystem", "task_type" };
|
char *inputs[] = { "subsystem", "task_type" };
|
||||||
dbg("selecting input %ld (%s)", i, inputs[i]);
|
dbg("selecting input %"PRIi64" (%s)", i, inputs[i]);
|
||||||
*input = mux_get_input(mux, i);
|
*input = mux_get_input(mux, i);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -245,7 +245,7 @@ model_nanos6_breakdown_connect(struct emu *emu)
|
|||||||
flags |= PRV_ZERO;
|
flags |= PRV_ZERO;
|
||||||
|
|
||||||
struct chan *out = sort_get_output(&bemu->sort, i);
|
struct chan *out = sort_get_output(&bemu->sort, i);
|
||||||
if (prv_register(prv, i, type, bay, out, flags)) {
|
if (prv_register(prv, (long) i, type, bay, out, flags)) {
|
||||||
err("prv_register failed");
|
err("prv_register failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -268,7 +268,7 @@ model_nanos6_breakdown_finish(struct emu *emu,
|
|||||||
struct pcf *pcf = pvt_get_pcf(bemu->pvt);
|
struct pcf *pcf = pvt_get_pcf(bemu->pvt);
|
||||||
long typeid = PRV_NANOS6_BREAKDOWN;
|
long typeid = PRV_NANOS6_BREAKDOWN;
|
||||||
char label[] = "CPU: Nanos6 Runtime/Idle/Task breakdown";
|
char label[] = "CPU: Nanos6 Runtime/Idle/Task breakdown";
|
||||||
struct pcf_type *pcftype = pcf_add_type(pcf, typeid, label);
|
struct pcf_type *pcftype = pcf_add_type(pcf, (int) typeid, label);
|
||||||
const struct pcf_value_label *v = NULL;
|
const struct pcf_value_label *v = NULL;
|
||||||
|
|
||||||
/* Emit subsystem values */
|
/* Emit subsystem values */
|
||||||
@ -302,12 +302,12 @@ model_nanos6_breakdown_finish(struct emu *emu,
|
|||||||
struct prf *prf = pvt_get_prf(bemu->pvt);
|
struct prf *prf = pvt_get_prf(bemu->pvt);
|
||||||
for (int64_t row = 0; row < bemu->nphycpus; row++) {
|
for (int64_t row = 0; row < bemu->nphycpus; row++) {
|
||||||
char name[128];
|
char name[128];
|
||||||
if (snprintf(name, 128, "~CPU %4ld", bemu->nphycpus - row) >= 128) {
|
if (snprintf(name, 128, "~CPU %4" PRIi64, bemu->nphycpus - row) >= 128) {
|
||||||
err("label too long");
|
err("label too long");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prf_add(prf, row, name) != 0) {
|
if (prf_add(prf, (long) row, name) != 0) {
|
||||||
err("prf_add failed for %s", name);
|
err("prf_add failed for %s", name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "nanos6_priv.h"
|
#include "nanos6_priv.h"
|
||||||
@ -299,7 +299,7 @@ update_task_state(struct emu *emu)
|
|||||||
static int
|
static int
|
||||||
expand_transition_value(struct emu *emu, int was_running, int runs_now, char *tr_p)
|
expand_transition_value(struct emu *emu, int was_running, int runs_now, char *tr_p)
|
||||||
{
|
{
|
||||||
char tr = emu->ev->v;
|
char tr = (char) emu->ev->v;
|
||||||
|
|
||||||
/* Ensure we don't clobber the value */
|
/* Ensure we don't clobber the value */
|
||||||
if (tr == 'X' || tr == 'E') {
|
if (tr == 'X' || tr == 'E') {
|
||||||
@ -419,7 +419,7 @@ update_task(struct emu *emu)
|
|||||||
struct task *next = bnext == NULL ? NULL : body_get_task(bnext);
|
struct task *next = bnext == NULL ? NULL : body_get_task(bnext);
|
||||||
|
|
||||||
/* Update the subsystem channel */
|
/* Update the subsystem channel */
|
||||||
if (update_task_ss_channel(emu, emu->ev->v) != 0) {
|
if (update_task_ss_channel(emu, (char) emu->ev->v) != 0) {
|
||||||
err("update_task_ss_channel failed");
|
err("update_task_ss_channel failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -467,7 +467,7 @@ create_task(struct emu *emu)
|
|||||||
* task, so we relax the model to allow this for now. */
|
* task, so we relax the model to allow this for now. */
|
||||||
flags |= TASK_FLAG_RELAX_NESTING;
|
flags |= TASK_FLAG_RELAX_NESTING;
|
||||||
|
|
||||||
if (task_create(info, type_id, task_id, flags) != 0) {
|
if (task_create(info, type_id, task_id, (uint32_t) flags) != 0) {
|
||||||
err("task_create failed");
|
err("task_create failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -521,7 +521,8 @@ pre_type(struct emu *emu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *data = &emu->ev->payload->jumbo.data[0];
|
const uint8_t *data = &emu->ev->payload->jumbo.data[0];
|
||||||
uint32_t typeid = *(uint32_t *) data;
|
uint32_t typeid;
|
||||||
|
memcpy(&typeid, data, 4); /* May be unaligned */
|
||||||
data += 4;
|
data += 4;
|
||||||
|
|
||||||
const char *label = (const char *) data;
|
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);
|
struct pcf *pcf = pvt_get_pcf(pvt);
|
||||||
long typeid = pvt_type[CH_TYPE];
|
long typeid = pvt_type[CH_TYPE];
|
||||||
struct pcf_type *pcftype = pcf_find_type(pcf, typeid);
|
struct pcf_type *pcftype = pcf_find_type(pcf, (int) typeid);
|
||||||
|
|
||||||
for (struct proc *p = sys->procs; p; p = p->gnext) {
|
for (struct proc *p = sys->procs; p; p = p->gnext) {
|
||||||
struct nanos6_proc *proc = EXT(p, model_id);
|
struct nanos6_proc *proc = EXT(p, model_id);
|
||||||
|
342
src/emu/nosv/breakdown.c
Normal file
342
src/emu/nosv/breakdown.c
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
/* 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;
|
||||||
|
}
|
56
src/emu/nosv/breakdown.h
Normal file
56
src/emu/nosv/breakdown.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* 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 "thread.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
|
||||||
enum { PUSH = 1, POP = 2, IGN = 3 };
|
enum { PUSH = 1, POP = 2, SET = 3, IGN = 4 };
|
||||||
|
|
||||||
#define CHSS CH_SUBSYSTEM
|
#define CHSS CH_SUBSYSTEM
|
||||||
|
|
||||||
@ -77,6 +77,11 @@ static const int ss_table[256][256][3] = {
|
|||||||
['d'] = { CHSS, PUSH, ST_DELEGATE },
|
['d'] = { CHSS, PUSH, ST_DELEGATE },
|
||||||
['D'] = { CHSS, POP, 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
|
static int
|
||||||
@ -94,6 +99,8 @@ simple(struct emu *emu)
|
|||||||
return chan_push(ch, value_int64(st));
|
return chan_push(ch, value_int64(st));
|
||||||
} else if (action == POP) {
|
} else if (action == POP) {
|
||||||
return chan_pop(ch, value_int64(st));
|
return chan_pop(ch, value_int64(st));
|
||||||
|
} else if (action == SET) {
|
||||||
|
return chan_set(ch, value_int64(st));
|
||||||
} else if (action == IGN) {
|
} else if (action == IGN) {
|
||||||
return 0; /* do nothing */
|
return 0; /* do nothing */
|
||||||
} else {
|
} else {
|
||||||
@ -317,7 +324,7 @@ update_task_state(struct emu *emu)
|
|||||||
static int
|
static int
|
||||||
expand_transition_value(struct emu *emu, int was_running, int runs_now, char *tr_p)
|
expand_transition_value(struct emu *emu, int was_running, int runs_now, char *tr_p)
|
||||||
{
|
{
|
||||||
char tr = emu->ev->v;
|
char tr = (char) emu->ev->v;
|
||||||
|
|
||||||
/* Ensure we don't clobber the value */
|
/* Ensure we don't clobber the value */
|
||||||
if (tr == 'X' || tr == 'E') {
|
if (tr == 'X' || tr == 'E') {
|
||||||
@ -434,7 +441,7 @@ update_task(struct emu *emu)
|
|||||||
struct body *next = task_get_running(stack);
|
struct body *next = task_get_running(stack);
|
||||||
|
|
||||||
/* Update the subsystem channel */
|
/* Update the subsystem channel */
|
||||||
if (update_task_ss_channel(emu, emu->ev->v) != 0) {
|
if (update_task_ss_channel(emu, (char) emu->ev->v) != 0) {
|
||||||
err("update_task_ss_channel failed");
|
err("update_task_ss_channel failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -502,7 +509,7 @@ pre_task(struct emu *emu)
|
|||||||
switch (emu->ev->v) {
|
switch (emu->ev->v) {
|
||||||
case 'C':
|
case 'C':
|
||||||
case 'c':
|
case 'c':
|
||||||
ret = create_task(emu, emu->ev->v);
|
ret = create_task(emu, (char) emu->ev->v);
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'e':
|
case 'e':
|
||||||
@ -539,7 +546,8 @@ pre_type(struct emu *emu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *data = &emu->ev->payload->jumbo.data[0];
|
const uint8_t *data = &emu->ev->payload->jumbo.data[0];
|
||||||
uint32_t typeid = *(uint32_t *) data;
|
uint32_t typeid;
|
||||||
|
memcpy(&typeid, data, 4); /* May be unaligned */
|
||||||
data += 4;
|
data += 4;
|
||||||
|
|
||||||
const char *label = (const char *) data;
|
const char *label = (const char *) data;
|
||||||
@ -574,6 +582,7 @@ process_ev(struct emu *emu)
|
|||||||
case 'M':
|
case 'M':
|
||||||
case 'H':
|
case 'H':
|
||||||
case 'A':
|
case 'A':
|
||||||
|
case 'P':
|
||||||
return simple(emu);
|
return simple(emu);
|
||||||
case 'T':
|
case 'T':
|
||||||
return pre_task(emu);
|
return pre_task(emu);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#ifndef NOSV_PRIV_H
|
#ifndef NOSV_PRIV_H
|
||||||
#define NOSV_PRIV_H
|
#define NOSV_PRIV_H
|
||||||
|
|
||||||
|
#include "breakdown.h"
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "model_cpu.h"
|
#include "model_cpu.h"
|
||||||
@ -18,10 +19,12 @@ enum nosv_chan {
|
|||||||
CH_APPID,
|
CH_APPID,
|
||||||
CH_SUBSYSTEM,
|
CH_SUBSYSTEM,
|
||||||
CH_RANK,
|
CH_RANK,
|
||||||
|
CH_IDLE,
|
||||||
CH_MAX,
|
CH_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nosv_ss_values {
|
enum nosv_ss_values {
|
||||||
|
ST_UNKNOWN_SS = 2,
|
||||||
ST_SCHED_HUNGRY = 6,
|
ST_SCHED_HUNGRY = 6,
|
||||||
ST_SCHED_SERVING,
|
ST_SCHED_SERVING,
|
||||||
ST_SCHED_SUBMITTING,
|
ST_SCHED_SUBMITTING,
|
||||||
@ -56,16 +59,36 @@ struct nosv_thread {
|
|||||||
|
|
||||||
struct nosv_cpu {
|
struct nosv_cpu {
|
||||||
struct model_cpu m;
|
struct model_cpu m;
|
||||||
|
struct nosv_breakdown_cpu breakdown;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nosv_proc {
|
struct nosv_proc {
|
||||||
struct task_info task_info;
|
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_probe(struct emu *emu);
|
||||||
int model_nosv_create(struct emu *emu);
|
int model_nosv_create(struct emu *emu);
|
||||||
int model_nosv_connect(struct emu *emu);
|
int model_nosv_connect(struct emu *emu);
|
||||||
int model_nosv_event(struct emu *emu);
|
int model_nosv_event(struct emu *emu);
|
||||||
int model_nosv_finish(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 */
|
#endif /* NOSV_PRIV_H */
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "chan.h"
|
#include "chan.h"
|
||||||
|
#include "cpu.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "emu_args.h"
|
#include "emu_args.h"
|
||||||
@ -72,12 +73,16 @@ static struct ev_decl model_evlist[] = {
|
|||||||
PAIR_B("VHw", "VHW", "execution as worker")
|
PAIR_B("VHw", "VHW", "execution as worker")
|
||||||
PAIR_B("VHd", "VHD", "execution as delegate")
|
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 },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
struct model_spec model_nosv = {
|
struct model_spec model_nosv = {
|
||||||
.name = model_name,
|
.name = model_name,
|
||||||
.version = "2.1.0",
|
.version = "2.3.0",
|
||||||
.evlist = model_evlist,
|
.evlist = model_evlist,
|
||||||
.model = model_id,
|
.model = model_id,
|
||||||
.create = model_nosv_create,
|
.create = model_nosv_create,
|
||||||
@ -96,6 +101,7 @@ static const char *chan_name[CH_MAX] = {
|
|||||||
[CH_APPID] = "appid",
|
[CH_APPID] = "appid",
|
||||||
[CH_SUBSYSTEM] = "subsystem",
|
[CH_SUBSYSTEM] = "subsystem",
|
||||||
[CH_RANK] = "rank",
|
[CH_RANK] = "rank",
|
||||||
|
[CH_IDLE] = "idle",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int chan_stack[CH_MAX] = {
|
static const int chan_stack[CH_MAX] = {
|
||||||
@ -121,6 +127,7 @@ static const int pvt_type[CH_MAX] = {
|
|||||||
[CH_APPID] = PRV_NOSV_APPID,
|
[CH_APPID] = PRV_NOSV_APPID,
|
||||||
[CH_SUBSYSTEM] = PRV_NOSV_SUBSYSTEM,
|
[CH_SUBSYSTEM] = PRV_NOSV_SUBSYSTEM,
|
||||||
[CH_RANK] = PRV_NOSV_RANK,
|
[CH_RANK] = PRV_NOSV_RANK,
|
||||||
|
[CH_IDLE] = PRV_NOSV_IDLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *pcf_prefix[CH_MAX] = {
|
static const char *pcf_prefix[CH_MAX] = {
|
||||||
@ -130,9 +137,11 @@ static const char *pcf_prefix[CH_MAX] = {
|
|||||||
[CH_APPID] = "nOS-V task AppID",
|
[CH_APPID] = "nOS-V task AppID",
|
||||||
[CH_SUBSYSTEM] = "nOS-V subsystem",
|
[CH_SUBSYSTEM] = "nOS-V subsystem",
|
||||||
[CH_RANK] = "nOS-V task MPI rank",
|
[CH_RANK] = "nOS-V task MPI rank",
|
||||||
|
[CH_IDLE] = "nOS-V idle state",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pcf_value_label nosv_ss_values[] = {
|
static const struct pcf_value_label nosv_ss_values[] = {
|
||||||
|
{ ST_UNKNOWN_SS, "Unknown subsystem" },
|
||||||
{ ST_SCHED_HUNGRY, "Scheduler: Hungry" },
|
{ ST_SCHED_HUNGRY, "Scheduler: Hungry" },
|
||||||
{ ST_SCHED_SERVING, "Scheduler: Serving" },
|
{ ST_SCHED_SERVING, "Scheduler: Serving" },
|
||||||
{ ST_SCHED_SUBMITTING, "Scheduler: Submitting" },
|
{ ST_SCHED_SUBMITTING, "Scheduler: Submitting" },
|
||||||
@ -160,8 +169,16 @@ static const struct pcf_value_label nosv_ss_values[] = {
|
|||||||
{ -1, NULL },
|
{ -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] = {
|
static const struct pcf_value_label *pcf_labels[CH_MAX] = {
|
||||||
[CH_SUBSYSTEM] = nosv_ss_values,
|
[CH_SUBSYSTEM] = nosv_ss_values,
|
||||||
|
[CH_IDLE] = nosv_worker_idle,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const long prv_flags[CH_MAX] = {
|
static const long prv_flags[CH_MAX] = {
|
||||||
@ -171,6 +188,7 @@ static const long prv_flags[CH_MAX] = {
|
|||||||
[CH_APPID] = PRV_SKIPDUPNULL, /* Switch to task of same appid */
|
[CH_APPID] = PRV_SKIPDUPNULL, /* Switch to task of same appid */
|
||||||
[CH_SUBSYSTEM] = PRV_SKIPDUPNULL,
|
[CH_SUBSYSTEM] = PRV_SKIPDUPNULL,
|
||||||
[CH_RANK] = PRV_SKIPDUPNULL, /* Switch to task of same rank */
|
[CH_RANK] = PRV_SKIPDUPNULL, /* Switch to task of same rank */
|
||||||
|
[CH_IDLE] = PRV_SKIPDUPNULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct model_pvt_spec pvt_spec = {
|
static const struct model_pvt_spec pvt_spec = {
|
||||||
@ -189,6 +207,7 @@ static const int th_track[CH_MAX] = {
|
|||||||
[CH_APPID] = TRACK_TH_RUN,
|
[CH_APPID] = TRACK_TH_RUN,
|
||||||
[CH_SUBSYSTEM] = TRACK_TH_ACT,
|
[CH_SUBSYSTEM] = TRACK_TH_ACT,
|
||||||
[CH_RANK] = TRACK_TH_RUN,
|
[CH_RANK] = TRACK_TH_RUN,
|
||||||
|
[CH_IDLE] = TRACK_TH_RUN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int cpu_track[CH_MAX] = {
|
static const int cpu_track[CH_MAX] = {
|
||||||
@ -198,6 +217,7 @@ static const int cpu_track[CH_MAX] = {
|
|||||||
[CH_APPID] = TRACK_TH_RUN,
|
[CH_APPID] = TRACK_TH_RUN,
|
||||||
[CH_SUBSYSTEM] = TRACK_TH_RUN,
|
[CH_SUBSYSTEM] = TRACK_TH_RUN,
|
||||||
[CH_RANK] = TRACK_TH_RUN,
|
[CH_RANK] = TRACK_TH_RUN,
|
||||||
|
[CH_IDLE] = TRACK_TH_RUN,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ----------------- chan_spec ------------------ */
|
/* ----------------- chan_spec ------------------ */
|
||||||
@ -279,6 +299,19 @@ 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,6 +328,28 @@ model_nosv_connect(struct emu *emu)
|
|||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,8 +396,12 @@ finish_pvt(struct emu *emu, const char *name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
struct pcf *pcf = pvt_get_pcf(pvt);
|
struct pcf *pcf = pvt_get_pcf(pvt);
|
||||||
long typeid = pvt_type[CH_TYPE];
|
int typeid = pvt_type[CH_TYPE];
|
||||||
struct pcf_type *pcftype = pcf_find_type(pcf, typeid);
|
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) {
|
for (struct proc *p = sys->procs; p; p = p->gnext) {
|
||||||
struct nosv_proc *proc = EXT(p, model_id);
|
struct nosv_proc *proc = EXT(p, model_id);
|
||||||
@ -370,6 +429,11 @@ model_nosv_finish(struct emu *emu)
|
|||||||
return -1;
|
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 */
|
/* When running in linter mode perform additional checks */
|
||||||
if (emu->args.linter_mode && end_lint(emu) != 0) {
|
if (emu->args.linter_mode && end_lint(emu) != 0) {
|
||||||
err("end_lint failed");
|
err("end_lint failed");
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
#include "mark.h"
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pre_thread_execute(struct emu *emu, struct thread *th)
|
pre_thread_execute(struct emu *emu, struct thread *th)
|
||||||
@ -228,7 +229,7 @@ pre_affinity_set(struct emu *emu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (emu->ev->payload_size != 4) {
|
if (emu->ev->payload_size != 4) {
|
||||||
err("unexpected payload size %d", emu->ev->payload_size);
|
err("unexpected payload size %zd", emu->ev->payload_size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +265,7 @@ static int
|
|||||||
pre_affinity_remote(struct emu *emu)
|
pre_affinity_remote(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (emu->ev->payload_size != 8) {
|
if (emu->ev->payload_size != 8) {
|
||||||
err("unexpected payload size %d", emu->ev->payload_size);
|
err("unexpected payload size %zd", emu->ev->payload_size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,18 +390,18 @@ pre_burst(struct emu *emu)
|
|||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
deltas[i] = th->burst_time[i + 1] - th->burst_time[i];
|
deltas[i] = th->burst_time[i + 1] - th->burst_time[i];
|
||||||
|
|
||||||
qsort(deltas, n, sizeof(int64_t), compare_int64);
|
qsort(deltas, (size_t) n, sizeof(int64_t), compare_int64);
|
||||||
|
|
||||||
double avg = 0.0;
|
double avg = 0.0;
|
||||||
double maxdelta = 0;
|
double maxdelta = 0;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
if (deltas[i] > maxdelta)
|
if ((double) deltas[i] > maxdelta)
|
||||||
maxdelta = deltas[i];
|
maxdelta = (double) deltas[i];
|
||||||
avg += deltas[i];
|
avg += (double) deltas[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
avg /= (double) n;
|
avg /= (double) n;
|
||||||
double median = deltas[n / 2];
|
double median = (double) deltas[n / 2];
|
||||||
|
|
||||||
info("%s burst stats: median/avg/max = %3.0f/%3.0f/%3.0f ns",
|
info("%s burst stats: median/avg/max = %3.0f/%3.0f/%3.0f ns",
|
||||||
emu->loom->id, median, avg, maxdelta);
|
emu->loom->id, median, avg, maxdelta);
|
||||||
@ -436,7 +437,7 @@ pre_flush(struct emu *emu)
|
|||||||
double flush_ms = (double) flush_ns * 1e-6;
|
double flush_ms = (double) flush_ns * 1e-6;
|
||||||
/* Avoid last flush warnings */
|
/* Avoid last flush warnings */
|
||||||
if (flush_ms > 10.0 && emu->thread->is_running)
|
if (flush_ms > 10.0 && emu->thread->is_running)
|
||||||
warn("large flush of %.1f ms at dclock=%ld ns in tid=%d",
|
warn("large flush of %.1f ms at dclock=%"PRIi64" ns in tid=%d",
|
||||||
flush_ms,
|
flush_ms,
|
||||||
emu->ev->dclock,
|
emu->ev->dclock,
|
||||||
emu->thread->tid);
|
emu->thread->tid);
|
||||||
@ -477,6 +478,8 @@ model_ovni_event(struct emu *emu)
|
|||||||
case 'U':
|
case 'U':
|
||||||
/* Ignore sorting events */
|
/* Ignore sorting events */
|
||||||
return 0;
|
return 0;
|
||||||
|
case 'M':
|
||||||
|
return mark_event(emu);
|
||||||
default:
|
default:
|
||||||
err("unknown ovni event category %c",
|
err("unknown ovni event category %c",
|
||||||
emu->ev->c);
|
emu->ev->c);
|
||||||
|
668
src/emu/ovni/mark.c
Normal file
668
src/emu/ovni/mark.c
Normal file
@ -0,0 +1,668 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
30
src/emu/ovni/mark.h
Normal file
30
src/emu/ovni/mark.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#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-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#ifndef OVNI_PRIV_H
|
#ifndef OVNI_PRIV_H
|
||||||
@ -10,6 +10,7 @@
|
|||||||
* execution by the kernel. */
|
* execution by the kernel. */
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
|
#include "mark.h"
|
||||||
#include "model_cpu.h"
|
#include "model_cpu.h"
|
||||||
#include "model_thread.h"
|
#include "model_thread.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -33,10 +34,17 @@ struct ovni_thread {
|
|||||||
int64_t burst_time[MAX_BURSTS];
|
int64_t burst_time[MAX_BURSTS];
|
||||||
|
|
||||||
int64_t flush_start;
|
int64_t flush_start;
|
||||||
|
|
||||||
|
struct ovni_mark_thread mark;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ovni_cpu {
|
struct ovni_cpu {
|
||||||
struct model_cpu m;
|
struct model_cpu m;
|
||||||
|
struct ovni_mark_cpu mark;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ovni_emu {
|
||||||
|
struct ovni_mark_emu mark;
|
||||||
};
|
};
|
||||||
|
|
||||||
int model_ovni_probe(struct emu *emu);
|
int model_ovni_probe(struct emu *emu);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "emu_prv.h"
|
#include "emu_prv.h"
|
||||||
#include "ev_spec.h"
|
#include "ev_spec.h"
|
||||||
|
#include "mark.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "model_chan.h"
|
#include "model_chan.h"
|
||||||
#include "model_cpu.h"
|
#include "model_cpu.h"
|
||||||
@ -37,12 +38,16 @@ static struct ev_decl model_evlist[] = {
|
|||||||
PAIR_B("OF[", "OF]", "flushing events to disk")
|
PAIR_B("OF[", "OF]", "flushing events to disk")
|
||||||
PAIR_E("OU[", "OU]", "unordered event region")
|
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 },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
struct model_spec model_ovni = {
|
struct model_spec model_ovni = {
|
||||||
.name = model_name,
|
.name = model_name,
|
||||||
.version = "1.0.0",
|
.version = "1.1.0",
|
||||||
.evlist = model_evlist,
|
.evlist = model_evlist,
|
||||||
.model = model_id,
|
.model = model_id,
|
||||||
.create = model_ovni_create,
|
.create = model_ovni_create,
|
||||||
@ -175,6 +180,19 @@ model_ovni_create(struct emu *emu)
|
|||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +209,11 @@ model_ovni_connect(struct emu *emu)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mark_connect(emu) != 0) {
|
||||||
|
err("mark_connect failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ emit(struct model *model, struct player *player)
|
|||||||
struct emu_ev *ev = player_ev(player);
|
struct emu_ev *ev = player_ev(player);
|
||||||
struct stream *stream = player_stream(player);
|
struct stream *stream = player_stream(player);
|
||||||
|
|
||||||
printf("%10ld %c%c%c %s ",
|
printf("%10" PRIi64 " %c%c%c %s ",
|
||||||
ev->rclock,
|
ev->rclock,
|
||||||
ev->m,
|
ev->m,
|
||||||
ev->c,
|
ev->c,
|
||||||
|
@ -20,7 +20,7 @@ static int
|
|||||||
html_encode(char *dst, int ndst, const char *src)
|
html_encode(char *dst, int ndst, const char *src)
|
||||||
{
|
{
|
||||||
int j = 0;
|
int j = 0;
|
||||||
int nsrc = strlen(src);
|
int nsrc = (int) strlen(src);
|
||||||
|
|
||||||
for (int i = 0; i < nsrc; i++) {
|
for (int i = 0; i < nsrc; i++) {
|
||||||
/* Simple check */
|
/* Simple check */
|
||||||
@ -29,7 +29,7 @@ html_encode(char *dst, int ndst, const char *src)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c = src[i];
|
char c = src[i];
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '&': strcpy(&dst[j], "&"); j += 5; break;
|
case '&': strcpy(&dst[j], "&"); j += 5; break;
|
||||||
case '"': strcpy(&dst[j], """); j += 6; break;
|
case '"': strcpy(&dst[j], """); j += 6; break;
|
||||||
@ -87,7 +87,7 @@ print_model(struct model_spec *spec)
|
|||||||
printf("<dl>\n");
|
printf("<dl>\n");
|
||||||
for (long j = 0; j < spec->evspec->nevents; j++) {
|
for (long j = 0; j < spec->evspec->nevents; j++) {
|
||||||
if (print_event(spec, j) != 0) {
|
if (print_event(spec, j) != 0) {
|
||||||
err("cannot print event %d", j);
|
err("cannot print event %ld", j);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
/* This program is a really bad idea. It attempts to sort streams by using a
|
/* This program is a really bad idea. It attempts to sort streams by using a
|
||||||
@ -74,6 +74,20 @@ ring_add(struct ring *r, struct ovni_ev *ev)
|
|||||||
r->head = 0;
|
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
|
static ssize_t
|
||||||
find_destination(struct ring *r, uint64_t clock)
|
find_destination(struct ring *r, uint64_t clock)
|
||||||
{
|
{
|
||||||
@ -86,7 +100,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) {
|
for (ssize_t i = start; i != end; i = i - 1 < 0 ? r->size - 1 : i - 1) {
|
||||||
last_clock = r->ev[i]->header.clock;
|
last_clock = r->ev[i]->header.clock;
|
||||||
if (last_clock < clock) {
|
if (last_clock < clock) {
|
||||||
dbg("found suitable position %ld events backwards",
|
dbg("found suitable position %zd events backwards",
|
||||||
nback);
|
nback);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -100,14 +114,14 @@ find_destination(struct ring *r, uint64_t clock)
|
|||||||
if (r->head != 0)
|
if (r->head != 0)
|
||||||
die("ring head expected to be 0");
|
die("ring head expected to be 0");
|
||||||
if (r->tail >= r->size - 1)
|
if (r->tail >= r->size - 1)
|
||||||
die("ring tail=%ld expected to be less than %ld", r->tail, r->size - 1);
|
die("ring tail=%zd expected to be less than %zd", r->tail, r->size - 1);
|
||||||
|
|
||||||
dbg("starting of ring with nback=%ld", nback);
|
dbg("starting of ring with nback=%zd", nback);
|
||||||
return r->head;
|
return r->head;
|
||||||
}
|
}
|
||||||
|
|
||||||
err("cannot find a event previous to clock %lu", clock);
|
err("cannot find a event previous to clock %"PRIu64, clock);
|
||||||
err("nback=%ld, last_clock=%lu", nback, last_clock);
|
err("nback=%zd, last_clock=%"PRIu64, nback, last_clock);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -179,11 +193,11 @@ write_events(struct ovni_ev **table, long n, uint8_t *buf)
|
|||||||
{
|
{
|
||||||
for (long i = 0; i < n; i++) {
|
for (long i = 0; i < n; i++) {
|
||||||
struct ovni_ev *ev = table[i];
|
struct ovni_ev *ev = table[i];
|
||||||
size_t size = ovni_ev_size(ev);
|
size_t size = (size_t) ovni_ev_size(ev);
|
||||||
memcpy(buf, ev, size);
|
memcpy(buf, ev, size);
|
||||||
buf += size;
|
buf += size;
|
||||||
|
|
||||||
dbg("injected event %c%c%c at %ld",
|
dbg("injected event %c%c%c at %"PRIu64,
|
||||||
ev->header.model,
|
ev->header.model,
|
||||||
ev->header.category,
|
ev->header.category,
|
||||||
ev->header.value,
|
ev->header.value,
|
||||||
@ -200,8 +214,8 @@ cmp_ev(const void *a, const void *b)
|
|||||||
struct ovni_ev *ev1 = *pev1;
|
struct ovni_ev *ev1 = *pev1;
|
||||||
struct ovni_ev *ev2 = *pev2;
|
struct ovni_ev *ev2 = *pev2;
|
||||||
|
|
||||||
int64_t clock1 = ev1->header.clock;
|
int64_t clock1 = (int64_t) ev1->header.clock;
|
||||||
int64_t clock2 = ev2->header.clock;
|
int64_t clock2 = (int64_t) ev2->header.clock;
|
||||||
|
|
||||||
if (clock1 < clock2)
|
if (clock1 < clock2)
|
||||||
return -1;
|
return -1;
|
||||||
@ -216,29 +230,29 @@ sort_buf(uint8_t *src, uint8_t *buf, int64_t bufsize)
|
|||||||
{
|
{
|
||||||
struct ovni_ev *ev = (struct ovni_ev *) src;
|
struct ovni_ev *ev = (struct ovni_ev *) src;
|
||||||
|
|
||||||
dbg("first event before sorting %c%c%c at %ld",
|
dbg("first event before sorting %c%c%c at %"PRIu64,
|
||||||
ev->header.model,
|
ev->header.model,
|
||||||
ev->header.category,
|
ev->header.category,
|
||||||
ev->header.value,
|
ev->header.value,
|
||||||
ev->header.clock);
|
ev->header.clock);
|
||||||
|
|
||||||
/* Create a copy of the array */
|
/* Create a copy of the array */
|
||||||
uint8_t *buf2 = malloc(bufsize);
|
uint8_t *buf2 = malloc((size_t) bufsize);
|
||||||
if (buf2 == NULL)
|
if (buf2 == NULL)
|
||||||
die("malloc failed:");
|
die("malloc failed:");
|
||||||
|
|
||||||
memcpy(buf2, src, bufsize);
|
memcpy(buf2, src, (size_t) bufsize);
|
||||||
|
|
||||||
long n = count_events(buf2, buf2 + bufsize);
|
long n = count_events(buf2, buf2 + bufsize);
|
||||||
struct ovni_ev **table = calloc(n, sizeof(struct ovni_ev *));
|
struct ovni_ev **table = calloc((size_t) n, sizeof(struct ovni_ev *));
|
||||||
if (table == NULL)
|
if (table == NULL)
|
||||||
die("calloc failed:");
|
die("calloc failed:");
|
||||||
|
|
||||||
index_events(table, n, buf2);
|
index_events(table, n, buf2);
|
||||||
qsort(table, n, sizeof(struct ovni_ev *), cmp_ev);
|
qsort(table, (size_t) n, sizeof(struct ovni_ev *), cmp_ev);
|
||||||
write_events(table, n, buf);
|
write_events(table, n, buf);
|
||||||
|
|
||||||
dbg("first event after sorting %c%c%c at %ld",
|
dbg("first event after sorting %c%c%c at %"PRIu64,
|
||||||
ev->header.model,
|
ev->header.model,
|
||||||
ev->header.category,
|
ev->header.category,
|
||||||
ev->header.value,
|
ev->header.value,
|
||||||
@ -254,44 +268,71 @@ static void
|
|||||||
write_stream(int fd, void *base, void *dst, const void *src, size_t size)
|
write_stream(int fd, void *base, void *dst, const void *src, size_t size)
|
||||||
{
|
{
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
off_t offset = (off_t) ((int64_t) dst - (int64_t) base);
|
off_t offset = (off_t) dst - (off_t) base;
|
||||||
ssize_t written = pwrite(fd, src, size, offset);
|
ssize_t written = pwrite(fd, src, size, offset);
|
||||||
|
|
||||||
if (written < 0)
|
if (written < 0)
|
||||||
die("pwrite failed:");
|
die("pwrite failed:");
|
||||||
|
|
||||||
size -= written;
|
size -= (size_t) written;
|
||||||
src = (void *) (((uint8_t *) src) + written);
|
src = (void *) (((uint8_t *) src) + written);
|
||||||
dst = (void *) (((uint8_t *) dst) + 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
|
static int
|
||||||
execute_sort_plan(struct sortplan *sp)
|
execute_sort_plan(struct sortplan *sp)
|
||||||
{
|
{
|
||||||
uint64_t clock0 = sp->bad0->header.clock;
|
uint64_t clock0 = sp->bad0->header.clock;
|
||||||
dbg("attempt to sort: start clock %ld", sp->bad0->header.clock);
|
dbg("attempt to sort: start clock %"PRIi64, sp->bad0->header.clock);
|
||||||
|
|
||||||
uint64_t min_clock = find_min_clock((void *) sp->bad0, (void *) sp->next);
|
uint64_t min_clock = find_min_clock((void *) sp->bad0, (void *) sp->next);
|
||||||
|
|
||||||
if (min_clock < clock0) {
|
if (min_clock < clock0) {
|
||||||
clock0 = min_clock;
|
clock0 = min_clock;
|
||||||
dbg("region not sorted, using min clock=%ld", clock0);
|
dbg("region not sorted, using min clock=%"PRIi64, clock0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cannot sort in one pass; just fail for now */
|
/* Cannot sort in one pass; just fail for now */
|
||||||
int64_t i0 = find_destination(sp->r, clock0);
|
int64_t i0 = find_destination(sp->r, clock0);
|
||||||
if (i0 < 0) {
|
if (i0 < 0) {
|
||||||
err("cannot find destination for region starting at clock %ld", clock0);
|
err("cannot find destination for region starting at clock %"PRIi64, clock0);
|
||||||
err("consider increasing the look back size with -n");
|
err("consider increasing the look back size with -n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the pointer to the first event that may be affected */
|
/* Set the pointer to the first event that may be affected */
|
||||||
struct ovni_ev *first = sp->r->ev[i0];
|
struct ovni_ev *first = sp->r->ev[i0];
|
||||||
|
long long dirty = i0;
|
||||||
|
|
||||||
/* Allocate a working buffer */
|
/* Allocate a working buffer */
|
||||||
int64_t bufsize = ((int64_t) sp->next) - ((int64_t) first);
|
uintptr_t bufsize = (uintptr_t) sp->next - (uintptr_t) first;
|
||||||
|
|
||||||
if (bufsize <= 0)
|
if (bufsize <= 0)
|
||||||
die("bufsize is non-positive");
|
die("bufsize is non-positive");
|
||||||
@ -300,12 +341,19 @@ execute_sort_plan(struct sortplan *sp)
|
|||||||
if (!buf)
|
if (!buf)
|
||||||
die("malloc failed:");
|
die("malloc failed:");
|
||||||
|
|
||||||
sort_buf((uint8_t *) first, buf, bufsize);
|
sort_buf((uint8_t *) first, buf, (int64_t) bufsize);
|
||||||
|
|
||||||
write_stream(sp->fd, sp->base, first, buf, bufsize);
|
write_stream(sp->fd, sp->base, first, buf, bufsize);
|
||||||
|
|
||||||
free(buf);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,7 +423,7 @@ stream_winsort(struct stream *stream, struct ring *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (empty_regions > 0)
|
if (empty_regions > 0)
|
||||||
warn("stream %s contains %ld empty sort regions",
|
warn("stream %s contains %zd empty sort regions",
|
||||||
stream->relpath, empty_regions);
|
stream->relpath, empty_regions);
|
||||||
|
|
||||||
if (updated && fdatasync(fd) < 0)
|
if (updated && fdatasync(fd) < 0)
|
||||||
@ -410,7 +458,7 @@ stream_check(struct stream *stream)
|
|||||||
uint64_t cur_clock = ovni_ev_get_clock(ev);
|
uint64_t cur_clock = ovni_ev_get_clock(ev);
|
||||||
|
|
||||||
if (cur_clock < last_clock) {
|
if (cur_clock < last_clock) {
|
||||||
err("backwards jump in time %ld -> %ld for stream %s",
|
err("backwards jump in time %"PRIi64" -> %"PRIi64" for stream %s",
|
||||||
last_clock, cur_clock, stream->relpath);
|
last_clock, cur_clock, stream->relpath);
|
||||||
backjump = 1;
|
backjump = 1;
|
||||||
}
|
}
|
||||||
@ -435,8 +483,8 @@ process_trace(struct trace *trace)
|
|||||||
struct ring ring;
|
struct ring ring;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
ring.size = max_look_back;
|
ring.size = (ssize_t) max_look_back;
|
||||||
ring.ev = malloc(ring.size * sizeof(struct ovni_ev *));
|
ring.ev = malloc((size_t) ring.size * sizeof(struct ovni_ev *));
|
||||||
|
|
||||||
if (ring.ev == NULL)
|
if (ring.ev == NULL)
|
||||||
die("malloc failed:");
|
die("malloc failed:");
|
||||||
@ -483,7 +531,7 @@ usage(void)
|
|||||||
rerr("Sorts the events in each stream of the trace given in\n");
|
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("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("Only the events enclosed by OU[ OU] are sorted. At most a\n");
|
||||||
rerr("total of %ld events are looked back to insert the unsorted\n",
|
rerr("total of %zd events are looked back to insert the unsorted\n",
|
||||||
max_look_back);
|
max_look_back);
|
||||||
rerr("events, so the sort procedure can fail with an error.\n");
|
rerr("events, so the sort procedure can fail with an error.\n");
|
||||||
rerr("\n");
|
rerr("\n");
|
||||||
@ -492,7 +540,7 @@ usage(void)
|
|||||||
rerr(" trace is already sorted.\n");
|
rerr(" trace is already sorted.\n");
|
||||||
rerr("\n");
|
rerr("\n");
|
||||||
rerr(" -n Set the number of events to look back.\n");
|
rerr(" -n Set the number of events to look back.\n");
|
||||||
rerr(" Defaul: %ld\n", max_look_back);
|
rerr(" Default: %zd\n", max_look_back);
|
||||||
rerr("\n");
|
rerr("\n");
|
||||||
rerr(" tracedir The trace directory generated by ovni.\n");
|
rerr(" tracedir The trace directory generated by ovni.\n");
|
||||||
rerr("\n");
|
rerr("\n");
|
||||||
@ -511,7 +559,7 @@ parse_args(int argc, char *argv[])
|
|||||||
operation_mode = CHECK;
|
operation_mode = CHECK;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
max_look_back = atol(optarg);
|
max_look_back = (size_t) atol(optarg);
|
||||||
break;
|
break;
|
||||||
default: /* '?' */
|
default: /* '?' */
|
||||||
usage();
|
usage();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -182,7 +182,7 @@ fill_offset(struct offset *offset, int nsamples)
|
|||||||
static void
|
static void
|
||||||
offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int verbose)
|
offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int verbose)
|
||||||
{
|
{
|
||||||
double *delta = malloc(sizeof(double) * nsamples);
|
double *delta = malloc(sizeof(double) * (size_t) nsamples);
|
||||||
|
|
||||||
if (delta == NULL) {
|
if (delta == NULL) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
@ -199,7 +199,7 @@ offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qsort(delta, nsamples, sizeof(double), cmp_double);
|
qsort(delta, (size_t) nsamples, sizeof(double), cmp_double);
|
||||||
|
|
||||||
cur->delta_median = delta[nsamples / 2];
|
cur->delta_median = delta[nsamples / 2];
|
||||||
cur->delta_mean = 0;
|
cur->delta_mean = 0;
|
||||||
@ -223,14 +223,14 @@ offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int v
|
|||||||
static size_t
|
static size_t
|
||||||
offset_size(int nsamples)
|
offset_size(int nsamples)
|
||||||
{
|
{
|
||||||
return sizeof(struct offset) + sizeof(double) * nsamples;
|
return sizeof(struct offset) + sizeof(double) * (size_t) nsamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct offset *
|
static struct offset *
|
||||||
table_get_offset(struct offset_table *table, int i, int nsamples)
|
table_get_offset(struct offset_table *table, int i, int nsamples)
|
||||||
{
|
{
|
||||||
char *p = (char *) table->_offset;
|
char *p = (char *) table->_offset;
|
||||||
p += i * offset_size(nsamples);
|
p += (size_t) i * offset_size(nsamples);
|
||||||
|
|
||||||
return (struct offset *) p;
|
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);
|
MPI_Comm_size(MPI_COMM_WORLD, &table->nprocs);
|
||||||
|
|
||||||
table->_offset = calloc(table->nprocs, offset_size(nsamples));
|
table->_offset = calloc((size_t) table->nprocs, offset_size(nsamples));
|
||||||
|
|
||||||
if (table->_offset == NULL) {
|
if (table->_offset == NULL) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
table->offset = malloc(sizeof(struct offset *) * table->nprocs);
|
table->offset = malloc(sizeof(struct offset *) * (size_t) table->nprocs);
|
||||||
|
|
||||||
if (table->offset == NULL) {
|
if (table->offset == NULL) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
@ -288,8 +288,8 @@ build_offset_table(int nsamples, int rank, int verbose)
|
|||||||
void *sendbuf = rank == 0 ? MPI_IN_PLACE : offset;
|
void *sendbuf = rank == 0 ? MPI_IN_PLACE : offset;
|
||||||
|
|
||||||
/* Then collect all the offsets into the rank 0 */
|
/* Then collect all the offsets into the rank 0 */
|
||||||
MPI_Gather(sendbuf, offset_size(nsamples), MPI_CHAR,
|
MPI_Gather(sendbuf, (int) offset_size(nsamples), MPI_CHAR,
|
||||||
offset, offset_size(nsamples), MPI_CHAR,
|
offset, (int) offset_size(nsamples), MPI_CHAR,
|
||||||
0, MPI_COMM_WORLD);
|
0, MPI_COMM_WORLD);
|
||||||
|
|
||||||
/* Finish the offsets by computing the deltas on rank 0 */
|
/* Finish the offsets by computing the deltas on rank 0 */
|
||||||
@ -399,7 +399,7 @@ do_work(struct options *options, int rank)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (drift_mode)
|
if (drift_mode)
|
||||||
sleep(options->drift_wait);
|
sleep((unsigned) options->drift_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rank == 0)
|
if (rank == 0)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
@ -95,7 +95,7 @@ path_keep(char *path, int n)
|
|||||||
void
|
void
|
||||||
path_remove_trailing(char *path)
|
path_remove_trailing(char *path)
|
||||||
{
|
{
|
||||||
int n = strlen(path);
|
int n = (int) strlen(path);
|
||||||
for (int i = n - 1; i >= 0 && path[i] == '/'; i--) {
|
for (int i = n - 1; i >= 0 && path[i] == '/'; i--) {
|
||||||
path[i] = '\0';
|
path[i] = '\0';
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
@ -164,7 +164,7 @@ update_clocks(struct player *player, struct stream *stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sclock < player->lastclock) {
|
if (sclock < player->lastclock) {
|
||||||
err("backwards jump in time %ld -> %ld in stream '%s'",
|
err("backwards jump in time %"PRIi64" -> %"PRIi64" in stream '%s'",
|
||||||
player->lastclock, sclock, stream->relpath);
|
player->lastclock, sclock, stream->relpath);
|
||||||
if (player->unsorted == 0)
|
if (player->unsorted == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "prf.h"
|
#include "prf.h"
|
||||||
@ -20,7 +20,7 @@ prf_open(struct prf *prf, const char *path, long nrows)
|
|||||||
}
|
}
|
||||||
|
|
||||||
prf->nrows = nrows;
|
prf->nrows = nrows;
|
||||||
prf->rows = calloc(nrows, sizeof(struct prf_row));
|
prf->rows = calloc((size_t) nrows, sizeof(struct prf_row));
|
||||||
|
|
||||||
if (prf->rows == NULL) {
|
if (prf->rows == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "prv.h"
|
#include "prv.h"
|
||||||
@ -25,7 +25,7 @@ prv_open_file(struct prv *prv, long nrows, FILE *file)
|
|||||||
prv->file = file;
|
prv->file = file;
|
||||||
|
|
||||||
/* Write fake header to allocate the space */
|
/* Write fake header to allocate the space */
|
||||||
write_header(file, 0LL, nrows);
|
write_header(file, 0LL, (int) nrows);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ prv_close(struct prv *prv)
|
|||||||
{
|
{
|
||||||
/* Fix the header with the current duration */
|
/* Fix the header with the current duration */
|
||||||
fseek(prv->file, 0, SEEK_SET);
|
fseek(prv->file, 0, SEEK_SET);
|
||||||
write_header(prv->file, prv->time, prv->nrows);
|
write_header(prv->file, prv->time, (int) prv->nrows);
|
||||||
fclose(prv->file);
|
fclose(prv->file);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -69,9 +69,9 @@ find_prv_chan(struct prv *prv, long id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_line(struct prv *prv, long row_base1, long type, long value)
|
write_line(struct prv *prv, long row_base1, int64_t type, int64_t value)
|
||||||
{
|
{
|
||||||
fprintf(prv->file, "2:0:1:1:%ld:%ld:%ld:%ld\n",
|
fprintf(prv->file, "2:0:1:1:%ld:%"PRIi64":%"PRIi64":%"PRIi64"\n",
|
||||||
row_base1, prv->time, type, value);
|
row_base1, prv->time, type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ emit(struct prv *prv, struct prv_chan *rchan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Assume null */
|
/* Assume null */
|
||||||
long val = 0;
|
int64_t val = 0;
|
||||||
if (likely(value.type == VALUE_INT64)) {
|
if (likely(value.type == VALUE_INT64)) {
|
||||||
val = value.i;
|
val = value.i;
|
||||||
if (rchan->flags & PRV_NEXT)
|
if (rchan->flags & PRV_NEXT)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "sort.h"
|
#include "sort.h"
|
||||||
@ -106,8 +106,8 @@ sort_cb_input(struct chan *in_chan, void *ptr)
|
|||||||
if (likely(sort->copied)) {
|
if (likely(sort->copied)) {
|
||||||
sort_replace(sort->sorted, sort->n, old, new);
|
sort_replace(sort->sorted, sort->n, old, new);
|
||||||
} else {
|
} else {
|
||||||
memcpy(sort->sorted, sort->values, sort->n * sizeof(int64_t));
|
memcpy(sort->sorted, sort->values, (size_t) sort->n * sizeof(int64_t));
|
||||||
qsort(sort->sorted, sort->n, sizeof(int64_t), cmp_int64);
|
qsort(sort->sorted, (size_t) sort->n, sizeof(int64_t), cmp_int64);
|
||||||
sort->copied = 1;
|
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));
|
memset(sort, 0, sizeof(struct sort));
|
||||||
sort->bay = bay;
|
sort->bay = bay;
|
||||||
sort->n = n;
|
sort->n = n;
|
||||||
sort->inputs = calloc(n, sizeof(struct sort_input));
|
sort->inputs = calloc((size_t) n, sizeof(struct sort_input));
|
||||||
if (sort->inputs == NULL) {
|
if (sort->inputs == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sort->outputs = calloc(n, sizeof(struct chan));
|
sort->outputs = calloc((size_t) n, sizeof(struct chan));
|
||||||
if (sort->outputs == NULL) {
|
if (sort->outputs == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sort->values = calloc(n, sizeof(int64_t));
|
sort->values = calloc((size_t) n, sizeof(int64_t));
|
||||||
if (sort->values == NULL) {
|
if (sort->values == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sort->sorted = calloc(n, sizeof(int64_t));
|
sort->sorted = calloc((size_t) n, sizeof(int64_t));
|
||||||
if (sort->sorted == NULL) {
|
if (sort->sorted == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
return -1;
|
return -1;
|
||||||
@ -165,7 +165,7 @@ sort_init(struct sort *sort, struct bay *bay, int64_t n, const char *name)
|
|||||||
/* Init and register outputs */
|
/* Init and register outputs */
|
||||||
for (int64_t i = 0; i < n; i++) {
|
for (int64_t i = 0; i < n; i++) {
|
||||||
struct chan *out = &sort->outputs[i];
|
struct chan *out = &sort->outputs[i];
|
||||||
chan_init(out, CHAN_SINGLE, "%s.out%ld", name, i);
|
chan_init(out, CHAN_SINGLE, "%s.out%"PRIi64, name, i);
|
||||||
|
|
||||||
/* The sort module may write multiple times to the same
|
/* The sort module may write multiple times to the same
|
||||||
* channel if we update more than one input. */
|
* 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);
|
chan_prop_set(out, CHAN_ALLOW_DUP, 1);
|
||||||
|
|
||||||
if (bay_register(bay, out) != 0) {
|
if (bay_register(bay, out) != 0) {
|
||||||
err("bay_register out%ld failed", i);
|
err("bay_register out%"PRIi64" failed", i);
|
||||||
return -1;
|
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];
|
struct sort_input *input = &sort->inputs[index];
|
||||||
|
|
||||||
if (input->chan != NULL) {
|
if (input->chan != NULL) {
|
||||||
err("input %d already has a channel", index);
|
err("input %"PRIi64" already has a channel", index);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
@ -59,7 +59,7 @@ load_stream_fd(struct stream *stream, int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int prot = PROT_READ | PROT_WRITE;
|
int prot = PROT_READ | PROT_WRITE;
|
||||||
stream->buf = mmap(NULL, st.st_size, prot, MAP_PRIVATE, fd, 0);
|
stream->buf = mmap(NULL, (size_t) st.st_size, prot, MAP_PRIVATE, fd, 0);
|
||||||
|
|
||||||
if (stream->buf == MAP_FAILED) {
|
if (stream->buf == MAP_FAILED) {
|
||||||
err("mmap 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);
|
warn("stream '%s' has zero events", stream->relpath);
|
||||||
stream->active = 0;
|
stream->active = 0;
|
||||||
} else {
|
} else {
|
||||||
err("impossible, offset %ld bigger than size %ld",
|
err("impossible, offset %"PRIi64" bigger than size %"PRIi64,
|
||||||
stream->offset, stream->size);
|
stream->offset, stream->size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ stream_step(struct stream *stream)
|
|||||||
|
|
||||||
/* It cannot pass the size, otherwise we are reading garbage */
|
/* It cannot pass the size, otherwise we are reading garbage */
|
||||||
if (stream->offset > stream->size) {
|
if (stream->offset > stream->size) {
|
||||||
err("stream offset %ld exceeds size %ld",
|
err("stream offset %"PRIi64" exceeds size %"PRIi64,
|
||||||
stream->offset, stream->size);
|
stream->offset, stream->size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -223,7 +223,7 @@ stream_step(struct stream *stream)
|
|||||||
/* Ensure the clock grows monotonically if unsorted flag not set */
|
/* Ensure the clock grows monotonically if unsorted flag not set */
|
||||||
if (stream->unsorted == 0) {
|
if (stream->unsorted == 0) {
|
||||||
if (clock < stream->lastclock) {
|
if (clock < stream->lastclock) {
|
||||||
err("clock goes backwards %ld -> %ld in stream '%s' at offset %ld",
|
err("clock goes backwards %"PRIi64" -> %"PRIi64" in stream '%s' at offset %"PRIi64,
|
||||||
stream->lastclock,
|
stream->lastclock,
|
||||||
clock,
|
clock,
|
||||||
stream->relpath,
|
stream->relpath,
|
||||||
@ -241,7 +241,7 @@ stream_step(struct stream *stream)
|
|||||||
void
|
void
|
||||||
stream_progress(struct stream *stream, int64_t *done, int64_t *total)
|
stream_progress(struct stream *stream, int64_t *done, int64_t *total)
|
||||||
{
|
{
|
||||||
*done = stream->offset - sizeof(struct ovni_stream_header);
|
*done = stream->offset - (int64_t) sizeof(struct ovni_stream_header);
|
||||||
*total = stream->usize;
|
*total = stream->usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
@ -226,7 +226,7 @@ create_system(struct system *sys, struct trace *trace)
|
|||||||
const char *dir = trace->tracedir;
|
const char *dir = trace->tracedir;
|
||||||
|
|
||||||
/* Allocate the lpt map */
|
/* Allocate the lpt map */
|
||||||
sys->lpt = calloc(trace->nstreams, sizeof(struct lpt));
|
sys->lpt = calloc((size_t) trace->nstreams, sizeof(struct lpt));
|
||||||
if (sys->lpt == NULL) {
|
if (sys->lpt == NULL) {
|
||||||
err("calloc failed:");
|
err("calloc failed:");
|
||||||
return -1;
|
return -1;
|
||||||
@ -340,28 +340,28 @@ print_system(struct system *sys)
|
|||||||
{
|
{
|
||||||
err("content of system: ");
|
err("content of system: ");
|
||||||
for (struct loom *l = sys->looms; l; l = l->next) {
|
for (struct loom *l = sys->looms; l; l = l->next) {
|
||||||
err("%s gindex=%d", l->id, l->gindex);
|
err("%s gindex=%"PRIi64, l->id, l->gindex);
|
||||||
err("+ %ld processes: ", l->nprocs);
|
err("+ %zd processes: ", l->nprocs);
|
||||||
for (struct proc *p = l->procs; p; p = p->hh.next) {
|
for (struct proc *p = l->procs; p; p = p->hh.next) {
|
||||||
err("| %s gindex=%d pid=%d",
|
err("| %s gindex=%"PRIi64" pid=%d",
|
||||||
p->id, p->gindex, p->pid);
|
p->id, p->gindex, p->pid);
|
||||||
err("| + %ld threads: ", p->nthreads);
|
err("| + %d threads: ", p->nthreads);
|
||||||
for (struct thread *t = p->threads; t; t = t->hh.next) {
|
for (struct thread *t = p->threads; t; t = t->hh.next) {
|
||||||
err("| | %s tid=%d",
|
err("| | %s tid=%d",
|
||||||
t->id, t->tid);
|
t->id, t->tid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err("+ %ld phy cpus: ", l->ncpus);
|
err("+ %zd phy cpus: ", l->ncpus);
|
||||||
for (struct cpu *cpu = l->cpus; cpu; cpu = cpu->hh.next) {
|
for (struct cpu *cpu = l->cpus; cpu; cpu = cpu->hh.next) {
|
||||||
err("| %s gindex=%ld phyid=%d",
|
err("| %s gindex=%"PRIi64" phyid=%d",
|
||||||
cpu->name,
|
cpu->name,
|
||||||
cpu->gindex,
|
cpu->gindex,
|
||||||
cpu->phyid);
|
cpu->phyid);
|
||||||
}
|
}
|
||||||
|
|
||||||
err("+ 1 virtual cpu: ", l->ncpus);
|
err("+ 1 virtual cpu: ");
|
||||||
struct cpu *cpu = &l->vcpu;
|
struct cpu *cpu = &l->vcpu;
|
||||||
err("| %s gindex=%ld phyid=%d",
|
err("| %s gindex=%"PRIi64" phyid=%d",
|
||||||
cpu->name,
|
cpu->name,
|
||||||
cpu->gindex,
|
cpu->gindex,
|
||||||
cpu->phyid);
|
cpu->phyid);
|
||||||
@ -373,20 +373,20 @@ init_global_indices(struct system *sys)
|
|||||||
{
|
{
|
||||||
size_t iloom = 0;
|
size_t iloom = 0;
|
||||||
for (struct loom *l = sys->looms; l; l = l->next)
|
for (struct loom *l = sys->looms; l; l = l->next)
|
||||||
loom_set_gindex(l, iloom++);
|
loom_set_gindex(l, (int64_t) iloom++);
|
||||||
|
|
||||||
sys->nprocs = 0;
|
sys->nprocs = 0;
|
||||||
for (struct proc *p = sys->procs; p; p = p->gnext)
|
for (struct proc *p = sys->procs; p; p = p->gnext)
|
||||||
proc_set_gindex(p, sys->nprocs++);
|
proc_set_gindex(p, (int64_t) sys->nprocs++);
|
||||||
|
|
||||||
sys->nthreads = 0;
|
sys->nthreads = 0;
|
||||||
for (struct thread *t = sys->threads; t; t = t->gnext)
|
for (struct thread *t = sys->threads; t; t = t->gnext)
|
||||||
thread_set_gindex(t, sys->nthreads++);
|
thread_set_gindex(t, (int64_t) sys->nthreads++);
|
||||||
|
|
||||||
sys->ncpus = 0;
|
sys->ncpus = 0;
|
||||||
sys->nphycpus = 0;
|
sys->nphycpus = 0;
|
||||||
for (struct cpu *c = sys->cpus; c; c = c->next) {
|
for (struct cpu *c = sys->cpus; c; c = c->next) {
|
||||||
cpu_set_gindex(c, sys->ncpus++);
|
cpu_set_gindex(c, (int64_t) sys->ncpus++);
|
||||||
if (!c->is_virtual)
|
if (!c->is_virtual)
|
||||||
sys->nphycpus++;
|
sys->nphycpus++;
|
||||||
}
|
}
|
||||||
@ -424,7 +424,7 @@ init_end_system(struct system *sys)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info("loaded %ld looms, %ld processes, %ld threads and %ld cpus",
|
info("loaded %zd looms, %zd processes, %zd threads and %zd cpus",
|
||||||
sys->nlooms, sys->nprocs, sys->nthreads, sys->nphycpus);
|
sys->nlooms, sys->nprocs, sys->nthreads, sys->nphycpus);
|
||||||
|
|
||||||
return 0;
|
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,
|
/* If we have more than one hostname and no offset table has been found,
|
||||||
* we won't be able to synchronize the clocks */
|
* we won't be able to synchronize the clocks */
|
||||||
if (n == 0 && sys->nlooms > 1) {
|
if (n == 0 && sys->nlooms > 1) {
|
||||||
warn("no clock offset file loaded with %ld looms",
|
warn("no clock offset file loaded with %zd looms",
|
||||||
sys->nlooms);
|
sys->nlooms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,13 +641,13 @@ system_connect(struct system *sys, struct bay *bay, struct recorder *rec)
|
|||||||
{
|
{
|
||||||
/* Create Paraver traces */
|
/* Create Paraver traces */
|
||||||
struct pvt *pvt_cpu = NULL;
|
struct pvt *pvt_cpu = NULL;
|
||||||
if ((pvt_cpu = recorder_add_pvt(rec, "cpu", sys->ncpus)) == NULL) {
|
if ((pvt_cpu = recorder_add_pvt(rec, "cpu", (long) sys->ncpus)) == NULL) {
|
||||||
err("recorder_add_pvt failed");
|
err("recorder_add_pvt failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pvt *pvt_th = NULL;
|
struct pvt *pvt_th = NULL;
|
||||||
if ((pvt_th = recorder_add_pvt(rec, "thread", sys->nthreads)) == NULL) {
|
if ((pvt_th = recorder_add_pvt(rec, "thread", (long) sys->nthreads)) == NULL) {
|
||||||
err("recorder_add_pvt failed");
|
err("recorder_add_pvt failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -667,7 +667,7 @@ system_connect(struct system *sys, struct bay *bay, struct recorder *rec)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prf_add(prf, th->gindex, name) != 0) {
|
if (prf_add(prf, (long) th->gindex, name) != 0) {
|
||||||
err("prf_add failed for thread '%s'", th->id);
|
err("prf_add failed for thread '%s'", th->id);
|
||||||
return -1;
|
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);
|
struct prf *prf = pvt_get_prf(pvt_cpu);
|
||||||
if (prf_add(prf, cpu->gindex, cpu->name) != 0) {
|
if (prf_add(prf, (long) cpu->gindex, cpu->name) != 0) {
|
||||||
err("prf_add failed for cpu '%s'", cpu->name);
|
err("prf_add failed for cpu '%s'", cpu->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
@ -258,13 +258,22 @@ task_type_create(struct task_info *info, uint32_t type_id, const char *label)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
type->gid = task_get_type_gid(label);
|
int n;
|
||||||
int n = snprintf(type->label, MAX_PCF_LABEL, "%s", label);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
if (n >= MAX_PCF_LABEL) {
|
if (n >= MAX_PCF_LABEL) {
|
||||||
err("task type label too long: %s", label);
|
err("task type %u label too long", type_id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type->gid = task_get_type_gid(type->label);
|
||||||
|
|
||||||
/* Add the new task type to the hash table */
|
/* Add the new task type to the hash table */
|
||||||
HASH_ADD_INT(info->types, id, type);
|
HASH_ADD_INT(info->types, id, type);
|
||||||
|
|
||||||
@ -279,7 +288,7 @@ task_create_pcf_types(struct pcf_type *pcftype, struct task_type *types)
|
|||||||
|
|
||||||
/* Emit types for all task types */
|
/* Emit types for all task types */
|
||||||
for (struct task_type *tt = types; tt != NULL; tt = tt->hh.next) {
|
for (struct task_type *tt = types; tt != NULL; tt = tt->hh.next) {
|
||||||
struct pcf_value *pcfvalue = pcf_find_value(pcftype, tt->gid);
|
struct pcf_value *pcfvalue = pcf_find_value(pcftype, (int) tt->gid);
|
||||||
if (pcfvalue != NULL) {
|
if (pcfvalue != NULL) {
|
||||||
/* Ensure the label is the same, so we know that
|
/* Ensure the label is the same, so we know that
|
||||||
* no collision occurred */
|
* no collision occurred */
|
||||||
@ -292,7 +301,7 @@ task_create_pcf_types(struct pcf_type *pcftype, struct task_type *types)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcf_add_value(pcftype, tt->gid, tt->label) == NULL) {
|
if (pcf_add_value(pcftype, (int) tt->gid, tt->label) == NULL) {
|
||||||
err("pcf_add_value failed");
|
err("pcf_add_value failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
@ -18,7 +18,6 @@
|
|||||||
#include "value.h"
|
#include "value.h"
|
||||||
struct proc;
|
struct proc;
|
||||||
|
|
||||||
static const char chan_fmt[] = "thread%lu.%s";
|
|
||||||
static const char *chan_name[TH_CHAN_MAX] = {
|
static const char *chan_name[TH_CHAN_MAX] = {
|
||||||
[TH_CHAN_CPU] = "cpu_gindex",
|
[TH_CHAN_CPU] = "cpu_gindex",
|
||||||
[TH_CHAN_TID] = "tid_active",
|
[TH_CHAN_TID] = "tid_active",
|
||||||
@ -92,7 +91,7 @@ get_tid(const char *id, int *tid)
|
|||||||
|
|
||||||
char *endptr;
|
char *endptr;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
*tid = strtol(tidstr, &endptr, 10);
|
*tid = (int) strtol(tidstr, &endptr, 10);
|
||||||
if (errno != 0) {
|
if (errno != 0) {
|
||||||
err("strtol failed for '%s':", tidstr);
|
err("strtol failed for '%s':", tidstr);
|
||||||
return -1;
|
return -1;
|
||||||
@ -159,7 +158,7 @@ thread_init_end(struct thread *th)
|
|||||||
|
|
||||||
for (int i = 0; i < TH_CHAN_MAX; i++) {
|
for (int i = 0; i < TH_CHAN_MAX; i++) {
|
||||||
chan_init(&th->chan[i], CHAN_SINGLE,
|
chan_init(&th->chan[i], CHAN_SINGLE,
|
||||||
chan_fmt, th->gindex, chan_name[i]);
|
"thread%"PRIi64".%s", th->gindex, chan_name[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The transition Running -> Cooling causes a duplicate (the thread is
|
/* The transition Running -> Cooling causes a duplicate (the thread is
|
||||||
@ -197,7 +196,7 @@ create_type(struct pcf *pcf, int i)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const char *label = pvt_name[i];
|
const char *label = pvt_name[i];
|
||||||
struct pcf_type *pcftype = pcf_add_type(pcf, type, label);
|
struct pcf_type *pcftype = pcf_add_type(pcf, (int) type, label);
|
||||||
if (pcftype == NULL) {
|
if (pcftype == NULL) {
|
||||||
err("pcf_add_type failed");
|
err("pcf_add_type failed");
|
||||||
return -1;
|
return -1;
|
||||||
@ -235,7 +234,7 @@ thread_connect(struct thread *th, struct bay *bay, struct recorder *rec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
long type = chan_type[i];
|
long type = chan_type[i];
|
||||||
long row = th->gindex;
|
long row = (long) th->gindex;
|
||||||
long flags = prv_flags[i];
|
long flags = prv_flags[i];
|
||||||
|
|
||||||
if (prv_register(prv, row, type, bay, c, flags)) {
|
if (prv_register(prv, row, type, bay, c, flags)) {
|
||||||
@ -327,7 +326,7 @@ thread_select_active(struct mux *mux,
|
|||||||
enum thread_state state = (enum thread_state) value.i;
|
enum thread_state state = (enum thread_state) value.i;
|
||||||
|
|
||||||
if (mux->ninputs != 1) {
|
if (mux->ninputs != 1) {
|
||||||
err("mux doesn't have one input but %d", mux->ninputs);
|
err("mux doesn't have one input but %"PRIi64, mux->ninputs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,7 +362,7 @@ thread_select_running(struct mux *mux,
|
|||||||
enum thread_state state = (enum thread_state) value.i;
|
enum thread_state state = (enum thread_state) value.i;
|
||||||
|
|
||||||
if (mux->ninputs != 1) {
|
if (mux->ninputs != 1) {
|
||||||
err("mux doesn't have one input but %d", mux->ninputs);
|
err("mux doesn't have one input but %"PRIi64, mux->ninputs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,7 +391,7 @@ thread_set_cpu(struct thread *th, struct cpu *cpu)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("thread%ld sets cpu%ld", th->gindex, cpu->gindex);
|
dbg("thread%"PRIi64" sets cpu%"PRIi64, th->gindex, cpu->gindex);
|
||||||
th->cpu = cpu;
|
th->cpu = cpu;
|
||||||
|
|
||||||
/* Update cpu channel */
|
/* Update cpu channel */
|
||||||
@ -413,7 +412,7 @@ thread_unset_cpu(struct thread *th)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("thread%ld unsets cpu", th->gindex);
|
dbg("thread%"PRIi64" unsets cpu", th->gindex);
|
||||||
th->cpu = NULL;
|
th->cpu = NULL;
|
||||||
|
|
||||||
struct chan *c = &th->chan[TH_CHAN_CPU];
|
struct chan *c = &th->chan[TH_CHAN_CPU];
|
||||||
@ -433,7 +432,7 @@ thread_migrate_cpu(struct thread *th, struct cpu *cpu)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("thread%ld migrates to cpu%d", th->gindex, cpu->gindex);
|
dbg("thread%"PRIi64" migrates to cpu%"PRIi64, th->gindex, cpu->gindex);
|
||||||
th->cpu = cpu;
|
th->cpu = cpu;
|
||||||
|
|
||||||
struct chan *c = &th->chan[TH_CHAN_CPU];
|
struct chan *c = &th->chan[TH_CHAN_CPU];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#define _XOPEN_SOURCE 500
|
#define _XOPEN_SOURCE 500
|
||||||
@ -36,7 +36,7 @@ load_stream(struct trace *trace, const char *path)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = strlen(trace->tracedir);
|
int offset = (int) strlen(trace->tracedir);
|
||||||
const char *relpath = path + offset;
|
const char *relpath = path + offset;
|
||||||
|
|
||||||
/* Skip begin slashes */
|
/* Skip begin slashes */
|
||||||
@ -58,14 +58,14 @@ has_suffix(const char *str, const char *suffix)
|
|||||||
if (!str || !suffix)
|
if (!str || !suffix)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int lenstr = strlen(str);
|
int lenstr = (int) strlen(str);
|
||||||
int lensuffix = strlen(suffix);
|
int lensuffix = (int) strlen(suffix);
|
||||||
|
|
||||||
if (lensuffix > lenstr)
|
if (lensuffix > lenstr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const char *p = str + lenstr - lensuffix;
|
const char *p = str + lenstr - lensuffix;
|
||||||
if (strncmp(p, suffix, lensuffix) == 0)
|
if (strncmp(p, suffix, (size_t) lensuffix) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "track.h"
|
#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_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
|
||||||
int n = ARRAYLEN(track->name);
|
int n = (int) ARRAYLEN(track->name);
|
||||||
int ret = vsnprintf(track->name, n, fmt, ap);
|
int ret = vsnprintf(track->name, (size_t) n, fmt, ap);
|
||||||
if (ret >= n) {
|
if (ret >= n) {
|
||||||
err("track name too long");
|
err("track name too long");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#ifndef TRACK_H
|
#ifndef TRACK_H
|
||||||
@ -27,12 +27,12 @@ struct track {
|
|||||||
int mode;
|
int mode;
|
||||||
char name[MAX_CHAN_NAME];
|
char name[MAX_CHAN_NAME];
|
||||||
struct bay *bay;
|
struct bay *bay;
|
||||||
struct chan ch;
|
struct chan ch; /*< Scratch channel as output when mux is used */
|
||||||
struct chan *out;
|
struct chan *out; /*< Output channel (ch or the input channel) */
|
||||||
struct mux mux;
|
struct mux mux;
|
||||||
};
|
};
|
||||||
|
|
||||||
USE_RET int track_init(struct track *track, struct bay *bay, enum track_type type, int mode, const char *fmt, ...);
|
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_set_select(struct track *track, struct chan *sel, mux_select_func_t fsel, int64_t ninputs);
|
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 int track_set_input(struct track *track, int64_t index, struct chan *inp);
|
||||||
USE_RET struct chan *track_get_output(struct track *track);
|
USE_RET struct chan *track_get_output(struct track *track);
|
||||||
|
@ -68,7 +68,7 @@ value_str(struct value a)
|
|||||||
ret = snprintf(buf, n, "{NULL}");
|
ret = snprintf(buf, n, "{NULL}");
|
||||||
break;
|
break;
|
||||||
case VALUE_INT64:
|
case VALUE_INT64:
|
||||||
ret = snprintf(buf, n, "{int64_t %ld}", a.i);
|
ret = snprintf(buf, n, "{int64_t %" PRIi64 "}", a.i);
|
||||||
break;
|
break;
|
||||||
case VALUE_DOUBLE:
|
case VALUE_DOUBLE:
|
||||||
ret = snprintf(buf, n, "{double %e}", a.d);
|
ret = snprintf(buf, n, "{double %e}", a.d);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
/* Author: David Alvarez
|
/* Author: David Alvarez
|
||||||
@ -112,6 +112,20 @@ heap_max(heap_head_t *head)
|
|||||||
return head->root;
|
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 */
|
/* Get a move to reach a leaf */
|
||||||
static inline int
|
static inline int
|
||||||
heap_get_move(size_t *node /*out*/)
|
heap_get_move(size_t *node /*out*/)
|
||||||
@ -119,8 +133,8 @@ heap_get_move(size_t *node /*out*/)
|
|||||||
size_t aux_node = *node;
|
size_t aux_node = *node;
|
||||||
|
|
||||||
// Round to previous po2
|
// Round to previous po2
|
||||||
size_t base = (1ULL) << (sizeof(size_t) * 8
|
int shift = (int) sizeof(size_t) * 8 - leading_zeros(aux_node) - 1;
|
||||||
- __builtin_clzll(aux_node) - 1);
|
size_t base = 1ULL << shift;
|
||||||
|
|
||||||
aux_node -= base / 2;
|
aux_node -= base / 2;
|
||||||
|
|
||||||
|
32
src/parson.c
32
src/parson.c
@ -316,7 +316,7 @@ read_file(const char *filename)
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
size_to_read = pos;
|
size_to_read = (size_t) pos;
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
file_contents = (char *) parson_malloc(sizeof(char) * (size_to_read + 1));
|
file_contents = (char *) parson_malloc(sizeof(char) * (size_to_read + 1));
|
||||||
if (!file_contents) {
|
if (!file_contents) {
|
||||||
@ -361,7 +361,7 @@ remove_comments(char *string, const char *start_token, const char *end_token)
|
|||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (i = 0; i < (ptr - string) + end_token_len; i++) {
|
for (i = 0; i < (size_t) (ptr - string) + end_token_len; i++) {
|
||||||
string[i] = ' ';
|
string[i] = ' ';
|
||||||
}
|
}
|
||||||
string = ptr + end_token_len - 1;
|
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) {
|
if (dot_pos == NULL) {
|
||||||
return json_object_remove_internal(object, name, free_value);
|
return json_object_remove_internal(object, name, free_value);
|
||||||
}
|
}
|
||||||
temp_value = json_object_getn_value(object, name, dot_pos - name);
|
temp_value = json_object_getn_value(object, name, (size_t) (dot_pos - name));
|
||||||
if (json_value_get_type(temp_value) != JSONObject) {
|
if (json_value_get_type(temp_value) != JSONObject) {
|
||||||
return JSONFailure;
|
return JSONFailure;
|
||||||
}
|
}
|
||||||
@ -638,13 +638,13 @@ parse_utf16(const char **unprocessed, char **processed)
|
|||||||
if (cp < 0x80) {
|
if (cp < 0x80) {
|
||||||
processed_ptr[0] = (char) cp; /* 0xxxxxxx */
|
processed_ptr[0] = (char) cp; /* 0xxxxxxx */
|
||||||
} else if (cp < 0x800) {
|
} else if (cp < 0x800) {
|
||||||
processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */
|
processed_ptr[0] = (char) (((cp >> 6) & 0x1F) | 0xC0); /* 110xxxxx */
|
||||||
processed_ptr[1] = ((cp) &0x3F) | 0x80; /* 10xxxxxx */
|
processed_ptr[1] = (char) (((cp) &0x3F) | 0x80); /* 10xxxxxx */
|
||||||
processed_ptr += 1;
|
processed_ptr += 1;
|
||||||
} else if (cp < 0xD800 || cp > 0xDFFF) {
|
} else if (cp < 0xD800 || cp > 0xDFFF) {
|
||||||
processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */
|
processed_ptr[0] = (char) (((cp >> 12) & 0x0F) | 0xE0);/* 1110xxxx */
|
||||||
processed_ptr[1] = ((cp >> 6) & 0x3F) | 0x80; /* 10xxxxxx */
|
processed_ptr[1] = (char) (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */
|
||||||
processed_ptr[2] = ((cp) &0x3F) | 0x80; /* 10xxxxxx */
|
processed_ptr[2] = (char) (((cp) &0x3F) | 0x80); /* 10xxxxxx */
|
||||||
processed_ptr += 2;
|
processed_ptr += 2;
|
||||||
} else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
|
} else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
|
||||||
lead = cp;
|
lead = cp;
|
||||||
@ -657,10 +657,10 @@ parse_utf16(const char **unprocessed, char **processed)
|
|||||||
return JSONFailure;
|
return JSONFailure;
|
||||||
}
|
}
|
||||||
cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000;
|
cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000;
|
||||||
processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
|
processed_ptr[0] = (char) (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
|
||||||
processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
|
processed_ptr[1] = (char) (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
|
||||||
processed_ptr[2] = (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */
|
processed_ptr[2] = (char) (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */
|
||||||
processed_ptr[3] = (((cp) &0x3F) | 0x80); /* 10xxxxxx */
|
processed_ptr[3] = (char) (((cp) &0x3F) | 0x80); /* 10xxxxxx */
|
||||||
processed_ptr += 3;
|
processed_ptr += 3;
|
||||||
} else { /* trail surrogate before lead surrogate */
|
} else { /* trail surrogate before lead surrogate */
|
||||||
return JSONFailure;
|
return JSONFailure;
|
||||||
@ -758,7 +758,7 @@ get_quoted_string(const char **string, size_t *output_string_len)
|
|||||||
if (status != JSONSuccess) {
|
if (status != JSONSuccess) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
input_string_len = *string - string_start - 2; /* length without quotes */
|
input_string_len = (size_t) (*string - string_start - 2); /* length without quotes */
|
||||||
return process_string(string_start + 1, input_string_len, output_string_len);
|
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)) {
|
if (errno == ERANGE && (number == -HUGE_VAL || number == HUGE_VAL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((errno && errno != ERANGE) || !is_decimal(*string, end - *string)) {
|
if ((errno && errno != ERANGE) || !is_decimal(*string, (size_t) (end - *string))) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*string = end;
|
*string = end;
|
||||||
@ -1410,7 +1410,7 @@ json_object_dotget_value(const JSON_Object *object, const char *name)
|
|||||||
if (!dot_position) {
|
if (!dot_position) {
|
||||||
return json_object_get_value(object, name);
|
return json_object_get_value(object, name);
|
||||||
}
|
}
|
||||||
object = json_value_get_object(json_object_getn_value(object, name, dot_position - name));
|
object = json_value_get_object(json_object_getn_value(object, name, (size_t) (dot_position - name)));
|
||||||
return json_object_dotget_value(object, dot_position + 1);
|
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) {
|
if (dot_pos == NULL) {
|
||||||
return json_object_set_value(object, name, value);
|
return json_object_set_value(object, name, value);
|
||||||
}
|
}
|
||||||
name_len = dot_pos - name;
|
name_len = (size_t) (dot_pos - name);
|
||||||
temp_value = json_object_getn_value(object, name, name_len);
|
temp_value = json_object_getn_value(object, name, name_len);
|
||||||
if (temp_value) {
|
if (temp_value) {
|
||||||
/* Don't overwrite existing non-object (unlike json_object_set_value, but it shouldn't be changed at this point) */
|
/* 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,8 +1,9 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: MIT */
|
* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -434,8 +435,8 @@ write_evbuf(uint8_t *buf, size_t size)
|
|||||||
if (written < 0)
|
if (written < 0)
|
||||||
die("failed to write buffer to disk:");
|
die("failed to write buffer to disk:");
|
||||||
|
|
||||||
size -= written;
|
size -= (size_t) written;
|
||||||
buf += written;
|
buf += (size_t) written;
|
||||||
} while (size > 0);
|
} while (size > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,7 +638,7 @@ clock_monotonic_now(void)
|
|||||||
if (clock_gettime(rproc.clockid, &tp))
|
if (clock_gettime(rproc.clockid, &tp))
|
||||||
die("clock_gettime() failed:");
|
die("clock_gettime() failed:");
|
||||||
|
|
||||||
return tp.tv_sec * ns + tp.tv_nsec;
|
return (uint64_t) tp.tv_sec * ns + (uint64_t) tp.tv_nsec;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
@ -665,9 +666,9 @@ ovni_ev_get_clock(const struct ovni_ev *ev)
|
|||||||
void
|
void
|
||||||
ovni_ev_set_mcv(struct ovni_ev *ev, const char *mcv)
|
ovni_ev_set_mcv(struct ovni_ev *ev, const char *mcv)
|
||||||
{
|
{
|
||||||
ev->header.model = mcv[0];
|
ev->header.model = (uint8_t) mcv[0];
|
||||||
ev->header.category = mcv[1];
|
ev->header.category = (uint8_t) mcv[1];
|
||||||
ev->header.value = mcv[2];
|
ev->header.value = (uint8_t) mcv[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
@ -680,7 +681,7 @@ int
|
|||||||
ovni_payload_size(const struct ovni_ev *ev)
|
ovni_payload_size(const struct ovni_ev *ev)
|
||||||
{
|
{
|
||||||
if (ev->header.flags & OVNI_EV_JUMBO)
|
if (ev->header.flags & OVNI_EV_JUMBO)
|
||||||
return get_jumbo_payload_size(ev);
|
return (int) get_jumbo_payload_size(ev);
|
||||||
|
|
||||||
int size = ev->header.flags & 0x0f;
|
int size = ev->header.flags & 0x0f;
|
||||||
|
|
||||||
@ -703,22 +704,23 @@ ovni_payload_add(struct ovni_ev *ev, const uint8_t *buf, int size)
|
|||||||
if (size < 2)
|
if (size < 2)
|
||||||
die("payload size %d too small", size);
|
die("payload size %d too small", size);
|
||||||
|
|
||||||
size_t payload_size = ovni_payload_size(ev);
|
size_t payload_size = (size_t) ovni_payload_size(ev);
|
||||||
|
|
||||||
/* Ensure we have room */
|
/* Ensure we have room */
|
||||||
if (payload_size + size > sizeof(ev->payload))
|
if (payload_size + (size_t) size > sizeof(ev->payload))
|
||||||
die("no space left for %d bytes", size);
|
die("no space left for %d bytes", size);
|
||||||
|
|
||||||
memcpy(&ev->payload.u8[payload_size], buf, size);
|
memcpy(&ev->payload.u8[payload_size], buf, (size_t) size);
|
||||||
payload_size += size;
|
payload_size += (size_t) size;
|
||||||
|
|
||||||
ev->header.flags = (ev->header.flags & 0xf0) | ((payload_size - 1) & 0x0f);
|
ev->header.flags = (uint8_t) ((ev->header.flags & 0xf0)
|
||||||
|
| ((payload_size - 1) & 0x0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ovni_ev_size(const struct ovni_ev *ev)
|
ovni_ev_size(const struct ovni_ev *ev)
|
||||||
{
|
{
|
||||||
return sizeof(ev->header) + ovni_payload_size(ev);
|
return (int) sizeof(ev->header) + ovni_payload_size(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -777,7 +779,7 @@ ovni_ev_add_jumbo(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize)
|
|||||||
die("the event payload must be empty");
|
die("the event payload must be empty");
|
||||||
|
|
||||||
ovni_payload_add(ev, (uint8_t *) &bufsize, sizeof(bufsize));
|
ovni_payload_add(ev, (uint8_t *) &bufsize, sizeof(bufsize));
|
||||||
size_t evsize = ovni_ev_size(ev);
|
size_t evsize = (size_t) ovni_ev_size(ev);
|
||||||
|
|
||||||
size_t totalsize = evsize + bufsize;
|
size_t totalsize = evsize + bufsize;
|
||||||
|
|
||||||
@ -817,7 +819,7 @@ ovni_ev_add(struct ovni_ev *ev)
|
|||||||
int flushed = 0;
|
int flushed = 0;
|
||||||
uint64_t t0, t1;
|
uint64_t t0, t1;
|
||||||
|
|
||||||
int size = ovni_ev_size(ev);
|
size_t size = (size_t) ovni_ev_size(ev);
|
||||||
|
|
||||||
/* Check if the event fits or flush first otherwise */
|
/* Check if the event fits or flush first otherwise */
|
||||||
if (rthread.evlen + size >= OVNI_MAX_EV_BUF) {
|
if (rthread.evlen + size >= OVNI_MAX_EV_BUF) {
|
||||||
@ -848,3 +850,368 @@ ovni_ev_emit(struct ovni_ev *ev)
|
|||||||
{
|
{
|
||||||
ovni_ev_add(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-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "instr.h"
|
#include "instr.h"
|
||||||
@ -9,7 +9,7 @@ int64_t last_clock; /* Clock from the last event */
|
|||||||
|
|
||||||
int64_t get_clock(void)
|
int64_t get_clock(void)
|
||||||
{
|
{
|
||||||
last_clock = ovni_clock_now();
|
last_clock = (int64_t) ovni_clock_now();
|
||||||
if (first_clock_set == 0) {
|
if (first_clock_set == 0) {
|
||||||
first_clock = last_clock;
|
first_clock = last_clock;
|
||||||
first_clock_set = 1;
|
first_clock_set = 1;
|
||||||
|
@ -19,20 +19,20 @@ extern int64_t last_clock;
|
|||||||
int64_t get_clock(void);
|
int64_t get_clock(void);
|
||||||
int64_t get_delta(void);
|
int64_t get_delta(void);
|
||||||
|
|
||||||
#define INSTR_0ARG(name, mcv) \
|
#define INSTR_0ARG(name, mcv) \
|
||||||
static inline void name(void) \
|
static inline void name(void) \
|
||||||
{ \
|
{ \
|
||||||
struct ovni_ev ev = {0}; \
|
struct ovni_ev ev = {0}; \
|
||||||
ovni_ev_set_clock(&ev, get_clock()); \
|
ovni_ev_set_clock(&ev, (uint64_t) get_clock()); \
|
||||||
ovni_ev_set_mcv(&ev, mcv); \
|
ovni_ev_set_mcv(&ev, mcv); \
|
||||||
ovni_ev_emit(&ev); \
|
ovni_ev_emit(&ev); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSTR_1ARG(name, mcv, ta, a) \
|
#define INSTR_1ARG(name, mcv, ta, a) \
|
||||||
static inline void name(ta a) \
|
static inline void name(ta a) \
|
||||||
{ \
|
{ \
|
||||||
struct ovni_ev ev = {0}; \
|
struct ovni_ev ev = {0}; \
|
||||||
ovni_ev_set_clock(&ev, get_clock()); \
|
ovni_ev_set_clock(&ev, (uint64_t) get_clock()); \
|
||||||
ovni_ev_set_mcv(&ev, mcv); \
|
ovni_ev_set_mcv(&ev, mcv); \
|
||||||
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
|
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
|
||||||
ovni_ev_emit(&ev); \
|
ovni_ev_emit(&ev); \
|
||||||
@ -42,7 +42,7 @@ int64_t get_delta(void);
|
|||||||
static inline void name(ta a, tb b) \
|
static inline void name(ta a, tb b) \
|
||||||
{ \
|
{ \
|
||||||
struct ovni_ev ev = {0}; \
|
struct ovni_ev ev = {0}; \
|
||||||
ovni_ev_set_clock(&ev, get_clock()); \
|
ovni_ev_set_clock(&ev, (uint64_t) get_clock()); \
|
||||||
ovni_ev_set_mcv(&ev, mcv); \
|
ovni_ev_set_mcv(&ev, mcv); \
|
||||||
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
|
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
|
||||||
ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
|
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) \
|
static inline void name(ta a, tb b, tc c) \
|
||||||
{ \
|
{ \
|
||||||
struct ovni_ev ev = {0}; \
|
struct ovni_ev ev = {0}; \
|
||||||
ovni_ev_set_clock(&ev, get_clock()); \
|
ovni_ev_set_clock(&ev, (uint64_t) get_clock()); \
|
||||||
ovni_ev_set_mcv(&ev, mcv); \
|
ovni_ev_set_mcv(&ev, mcv); \
|
||||||
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
|
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
|
||||||
ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
|
ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
|
||||||
@ -62,6 +62,8 @@ int64_t get_delta(void);
|
|||||||
}
|
}
|
||||||
|
|
||||||
INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag)
|
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)
|
INSTR_1ARG(instr_thread_affinity_set, "OAs", int32_t, cpu)
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -70,7 +72,7 @@ instr_thread_end(void)
|
|||||||
struct ovni_ev ev = {0};
|
struct ovni_ev ev = {0};
|
||||||
|
|
||||||
ovni_ev_set_mcv(&ev, "OHe");
|
ovni_ev_set_mcv(&ev, "OHe");
|
||||||
ovni_ev_set_clock(&ev, get_clock());
|
ovni_ev_set_clock(&ev, (uint64_t) get_clock());
|
||||||
ovni_ev_emit(&ev);
|
ovni_ev_emit(&ev);
|
||||||
|
|
||||||
/* Flush the events to disk before killing the thread */
|
/* Flush the events to disk before killing the thread */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -19,17 +19,17 @@ main(void)
|
|||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
uint32_t taskid = 1;
|
uint32_t taskid = 1;
|
||||||
|
|
||||||
instr_nanos6_type_create(typeid);
|
instr_nanos6_type_create((int32_t) typeid);
|
||||||
|
|
||||||
instr_nanos6_task_create_and_execute(taskid, typeid);
|
instr_nanos6_task_create_and_execute((int32_t) taskid, typeid);
|
||||||
sleep_us(us);
|
sleep_us(us);
|
||||||
instr_nanos6_block_enter();
|
instr_nanos6_block_enter();
|
||||||
instr_nanos6_task_pause(taskid);
|
instr_nanos6_task_pause((int32_t) taskid);
|
||||||
sleep_us(us);
|
sleep_us(us);
|
||||||
instr_nanos6_task_resume(taskid);
|
instr_nanos6_task_resume((int32_t) taskid);
|
||||||
instr_nanos6_block_exit();
|
instr_nanos6_block_exit();
|
||||||
sleep_us(us);
|
sleep_us(us);
|
||||||
instr_nanos6_task_end(taskid);
|
instr_nanos6_task_end((int32_t) taskid);
|
||||||
instr_nanos6_task_body_exit();
|
instr_nanos6_task_body_exit();
|
||||||
|
|
||||||
instr_end();
|
instr_end();
|
||||||
|
@ -35,13 +35,13 @@ main(void)
|
|||||||
die("fopen failed:");
|
die("fopen failed:");
|
||||||
|
|
||||||
/* Ensure non-zero for A (first event) */
|
/* Ensure non-zero for A (first event) */
|
||||||
fprintf(f, "grep ':%ld:%d:[^0][0-9]*$' ovni/nanos6-breakdown.prv\n",
|
fprintf(f, "grep ':%" PRIi64 ":%d:[^0][0-9]*$' ovni/nanos6-breakdown.prv\n",
|
||||||
get_delta(), PRV_NANOS6_BREAKDOWN);
|
get_delta(), PRV_NANOS6_BREAKDOWN);
|
||||||
|
|
||||||
instr_nanos6_worker_loop_enter();
|
instr_nanos6_worker_loop_enter();
|
||||||
|
|
||||||
/* And for B */
|
/* And for B */
|
||||||
fprintf(f, "grep ':%ld:%d:[^0][0-9]*$' ovni/nanos6-breakdown.prv\n",
|
fprintf(f, "grep ':%" PRIi64 ":%d:[^0][0-9]*$' ovni/nanos6-breakdown.prv\n",
|
||||||
get_delta(), PRV_NANOS6_BREAKDOWN);
|
get_delta(), PRV_NANOS6_BREAKDOWN);
|
||||||
|
|
||||||
instr_nanos6_worker_loop_exit();
|
instr_nanos6_worker_loop_exit();
|
||||||
|
@ -34,16 +34,16 @@ main(void)
|
|||||||
int type = PRV_NANOS6_SUBSYSTEM;
|
int type = PRV_NANOS6_SUBSYSTEM;
|
||||||
int64_t t = get_delta();
|
int64_t t = get_delta();
|
||||||
int value = ST_WORKER_LOOP;
|
int value = ST_WORKER_LOOP;
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, type, value);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, type, value);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||||
|
|
||||||
instr_nanos6_worker_loop_exit();
|
instr_nanos6_worker_loop_exit();
|
||||||
|
|
||||||
/* Also test when exitting the stacked subsystem */
|
/* Also test when exitting the stacked subsystem */
|
||||||
t = get_delta();
|
t = get_delta();
|
||||||
value = 0;
|
value = 0;
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, type, value);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, type, value);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -18,7 +18,7 @@ main(void)
|
|||||||
int ntasks = 100;
|
int ntasks = 100;
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
|
||||||
instr_nanos6_type_create(typeid);
|
instr_nanos6_type_create((int32_t) typeid);
|
||||||
|
|
||||||
/* Create and run the tasks, one nested into another */
|
/* Create and run the tasks, one nested into another */
|
||||||
for (int32_t id = 1; id <= ntasks; id++) {
|
for (int32_t id = 1; id <= ntasks; id++) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#ifndef INSTR_NANOS6_H
|
#ifndef INSTR_NANOS6_H
|
||||||
@ -20,7 +20,7 @@ instr_nanos6_type_create(int32_t typeid)
|
|||||||
struct ovni_ev ev = {0};
|
struct ovni_ev ev = {0};
|
||||||
|
|
||||||
ovni_ev_set_mcv(&ev, "6Yc");
|
ovni_ev_set_mcv(&ev, "6Yc");
|
||||||
ovni_ev_set_clock(&ev, get_clock());
|
ovni_ev_set_clock(&ev, (uint64_t) get_clock());
|
||||||
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
@ -32,7 +32,7 @@ instr_nanos6_type_create(int32_t typeid)
|
|||||||
sprintf(p, "testtype%d", typeid);
|
sprintf(p, "testtype%d", typeid);
|
||||||
nbytes += strlen(p) + 1;
|
nbytes += strlen(p) + 1;
|
||||||
|
|
||||||
ovni_ev_jumbo_emit(&ev, (uint8_t *) buf, nbytes);
|
ovni_ev_jumbo_emit(&ev, (uint8_t *) buf, (uint32_t) nbytes);
|
||||||
|
|
||||||
return task_get_type_gid(p);
|
return task_get_type_gid(p);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -12,13 +12,13 @@ main(void)
|
|||||||
instr_nanos6_init();
|
instr_nanos6_init();
|
||||||
|
|
||||||
uint32_t typeid = 666;
|
uint32_t typeid = 666;
|
||||||
instr_nanos6_type_create(typeid);
|
instr_nanos6_type_create((int32_t) typeid);
|
||||||
|
|
||||||
uint32_t taskid = 1;
|
uint32_t taskid = 1;
|
||||||
instr_nanos6_task_create_and_execute(taskid, typeid);
|
instr_nanos6_task_create_and_execute((int32_t) taskid, typeid);
|
||||||
|
|
||||||
/* Run another nested task with same id (should fail) */
|
/* Run another nested task with same id (should fail) */
|
||||||
instr_nanos6_task_execute(taskid);
|
instr_nanos6_task_execute((int32_t) taskid);
|
||||||
|
|
||||||
instr_end();
|
instr_end();
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -15,7 +15,7 @@ main(void)
|
|||||||
int ntasks = 100;
|
int ntasks = 100;
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
|
||||||
instr_nanos6_type_create(typeid);
|
instr_nanos6_type_create((int32_t) typeid);
|
||||||
|
|
||||||
/* Create and run the tasks, one nested into another */
|
/* Create and run the tasks, one nested into another */
|
||||||
for (int i = 0; i < ntasks; i++) {
|
for (int i = 0; i < ntasks; i++) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -14,15 +14,15 @@ main(void)
|
|||||||
instr_nanos6_init();
|
instr_nanos6_init();
|
||||||
|
|
||||||
uint32_t typeid = 666;
|
uint32_t typeid = 666;
|
||||||
instr_nanos6_type_create(typeid);
|
instr_nanos6_type_create((int32_t) typeid);
|
||||||
|
|
||||||
uint32_t taskid = 1;
|
uint32_t taskid = 1;
|
||||||
instr_nanos6_task_create_and_execute(taskid, typeid);
|
instr_nanos6_task_create_and_execute((int32_t) taskid, typeid);
|
||||||
instr_nanos6_task_end(taskid);
|
instr_nanos6_task_end((int32_t) taskid);
|
||||||
|
|
||||||
/* Run again the same task (should fail) */
|
/* Run again the same task (should fail) */
|
||||||
instr_nanos6_task_execute(taskid);
|
instr_nanos6_task_execute((int32_t) taskid);
|
||||||
instr_nanos6_task_end(taskid);
|
instr_nanos6_task_end((int32_t) taskid);
|
||||||
|
|
||||||
instr_end();
|
instr_end();
|
||||||
|
|
||||||
|
@ -29,21 +29,21 @@ main(void)
|
|||||||
instr_nanos6_absorbing();
|
instr_nanos6_absorbing();
|
||||||
|
|
||||||
/* Ensure the only row in breakdown is in absorbing */
|
/* Ensure the only row in breakdown is in absorbing */
|
||||||
fprintf(f, "grep '1:%ld:%d:%d$' ovni/nanos6-breakdown.prv\n",
|
fprintf(f, "grep '1:%" PRIi64 ":%d:%d$' ovni/nanos6-breakdown.prv\n",
|
||||||
get_delta(), type, ST_ABSORBING);
|
get_delta(), type, ST_ABSORBING);
|
||||||
|
|
||||||
/* Set state to Resting */
|
/* Set state to Resting */
|
||||||
instr_nanos6_resting();
|
instr_nanos6_resting();
|
||||||
|
|
||||||
/* Ensure the only row in breakdown is in Resting */
|
/* Ensure the only row in breakdown is in Resting */
|
||||||
fprintf(f, "grep '1:%ld:%d:%d$' ovni/nanos6-breakdown.prv\n",
|
fprintf(f, "grep '1:%" PRIi64 ":%d:%d$' ovni/nanos6-breakdown.prv\n",
|
||||||
get_delta(), type, ST_RESTING);
|
get_delta(), type, ST_RESTING);
|
||||||
|
|
||||||
instr_nanos6_progressing();
|
instr_nanos6_progressing();
|
||||||
|
|
||||||
/* Now the state must follow the subsystem, which should be
|
/* Now the state must follow the subsystem, which should be
|
||||||
* sponge mode */
|
* sponge mode */
|
||||||
fprintf(f, "grep '1:%ld:%d:%d$' ovni/nanos6-breakdown.prv\n",
|
fprintf(f, "grep '1:%" PRIi64 ":%d:%d$' ovni/nanos6-breakdown.prv\n",
|
||||||
get_delta(), type, ST_SPONGE);
|
get_delta(), type, ST_SPONGE);
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
@ -25,15 +25,15 @@ main(void)
|
|||||||
int type = PRV_NANOS6_SUBSYSTEM;
|
int type = PRV_NANOS6_SUBSYSTEM;
|
||||||
int64_t t = get_delta();
|
int64_t t = get_delta();
|
||||||
int value = ST_SPONGE;
|
int value = ST_SPONGE;
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, type, value);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, type, value);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||||
|
|
||||||
instr_nanos6_sponge_exit();
|
instr_nanos6_sponge_exit();
|
||||||
|
|
||||||
t = get_delta();
|
t = get_delta();
|
||||||
value = 0;
|
value = 0;
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, type, value);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, type, value);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, type, value);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, type, value);
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -19,7 +19,7 @@ main(void)
|
|||||||
instr_nanos6_init();
|
instr_nanos6_init();
|
||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
uint32_t gid = instr_nanos6_type_create(typeid);
|
uint32_t gid = instr_nanos6_type_create((int32_t) typeid);
|
||||||
|
|
||||||
/* Create two tasks of the same type */
|
/* Create two tasks of the same type */
|
||||||
instr_nanos6_task_create(1, typeid);
|
instr_nanos6_task_create(1, typeid);
|
||||||
@ -41,14 +41,14 @@ main(void)
|
|||||||
/* Check the task type */
|
/* Check the task type */
|
||||||
int prvtype = PRV_NANOS6_TYPE;
|
int prvtype = PRV_NANOS6_TYPE;
|
||||||
int64_t t = get_delta();
|
int64_t t = get_delta();
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, gid);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, gid);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, gid);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, gid);
|
||||||
|
|
||||||
/* Check the rank */
|
/* Check the rank */
|
||||||
prvtype = PRV_NANOS6_RANK;
|
prvtype = PRV_NANOS6_RANK;
|
||||||
int rank = 0 + 1; /* Starts at one */
|
int rank = 0 + 1; /* Starts at one */
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, rank);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, rank);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, rank);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, rank);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
/* Exit from tasks and subsystem */
|
/* Exit from tasks and subsystem */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -22,7 +22,7 @@ main(void)
|
|||||||
instr_nanos6_type_create(i + 1);
|
instr_nanos6_type_create(i + 1);
|
||||||
|
|
||||||
for (int i = 0; i < ntasks; i++) {
|
for (int i = 0; i < ntasks; i++) {
|
||||||
instr_nanos6_task_create_and_execute(i + 1, (i % ntypes) + 1);
|
instr_nanos6_task_create_and_execute(i + 1, (uint32_t) ((i % ntypes) + 1));
|
||||||
sleep_us(500);
|
sleep_us(500);
|
||||||
instr_nanos6_task_end(i + 1);
|
instr_nanos6_task_end(i + 1);
|
||||||
instr_nanos6_task_body_exit();
|
instr_nanos6_task_body_exit();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -17,7 +17,7 @@ main(void)
|
|||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
|
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
instr_nosv_task_create_par(1, typeid);
|
instr_nosv_task_create_par(1, typeid);
|
||||||
instr_nosv_task_create_par(2, typeid);
|
instr_nosv_task_create_par(2, typeid);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ main(void)
|
|||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
|
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
instr_nosv_task_create(1, typeid);
|
instr_nosv_task_create(1, typeid);
|
||||||
instr_nosv_task_create(2, typeid);
|
instr_nosv_task_create(2, typeid);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -19,7 +19,7 @@ main(void)
|
|||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
|
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
instr_nosv_task_create_par(1, typeid);
|
instr_nosv_task_create_par(1, typeid);
|
||||||
instr_nosv_task_create_par(2, typeid);
|
instr_nosv_task_create_par(2, typeid);
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ main(void)
|
|||||||
instr_nosv_init();
|
instr_nosv_init();
|
||||||
|
|
||||||
uint32_t typeid = 666;
|
uint32_t typeid = 666;
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
|
|
||||||
instr_nosv_task_create(1, typeid);
|
instr_nosv_task_create(1, typeid);
|
||||||
instr_nosv_task_execute(1, 0);
|
instr_nosv_task_execute(1, 0);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -19,7 +19,7 @@ main(void)
|
|||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
|
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
instr_nosv_task_create_par(1, typeid);
|
instr_nosv_task_create_par(1, typeid);
|
||||||
instr_nosv_submit_enter();
|
instr_nosv_submit_enter();
|
||||||
instr_nosv_task_execute(1, 1);
|
instr_nosv_task_execute(1, 1);
|
||||||
|
@ -12,6 +12,7 @@ static inline void
|
|||||||
instr_nosv_init(void)
|
instr_nosv_init(void)
|
||||||
{
|
{
|
||||||
instr_require("nosv");
|
instr_require("nosv");
|
||||||
|
ovni_attr_set_boolean("nosv.can_breakdown", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
@ -20,7 +21,7 @@ instr_nosv_type_create(int32_t typeid)
|
|||||||
struct ovni_ev ev = {0};
|
struct ovni_ev ev = {0};
|
||||||
|
|
||||||
ovni_ev_set_mcv(&ev, "VYc");
|
ovni_ev_set_mcv(&ev, "VYc");
|
||||||
ovni_ev_set_clock(&ev, get_clock());
|
ovni_ev_set_clock(&ev, (uint64_t) get_clock());
|
||||||
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
@ -32,7 +33,7 @@ instr_nosv_type_create(int32_t typeid)
|
|||||||
sprintf(p, "testtype%d", typeid);
|
sprintf(p, "testtype%d", typeid);
|
||||||
nbytes += strlen(p) + 1;
|
nbytes += strlen(p) + 1;
|
||||||
|
|
||||||
ovni_ev_jumbo_emit(&ev, (uint8_t *) buf, nbytes);
|
ovni_ev_jumbo_emit(&ev, (uint8_t *) buf, (uint32_t) nbytes);
|
||||||
|
|
||||||
return task_get_type_gid(p);
|
return task_get_type_gid(p);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "instr_nosv.h"
|
#include "instr_nosv.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
task(int32_t id, uint32_t typeid, int us)
|
task(uint32_t id, uint32_t typeid, int us)
|
||||||
{
|
{
|
||||||
instr_nosv_task_create(id, typeid);
|
instr_nosv_task_create(id, typeid);
|
||||||
instr_nosv_task_execute(id, 0);
|
instr_nosv_task_execute(id, 0);
|
||||||
@ -23,11 +23,11 @@ main(void)
|
|||||||
instr_start(rank, nranks);
|
instr_start(rank, nranks);
|
||||||
instr_nosv_init();
|
instr_nosv_init();
|
||||||
|
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
|
|
||||||
/* Create some fake nosv tasks */
|
/* Create some fake nosv tasks */
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
task(i + 1, typeid, 5000);
|
task((uint32_t) i + 1, typeid, 5000);
|
||||||
|
|
||||||
instr_end();
|
instr_end();
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ main(void)
|
|||||||
instr_thread_execute(lcpu, -1, 0);
|
instr_thread_execute(lcpu, -1, 0);
|
||||||
|
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
instr_nosv_task_create(1, typeid);
|
instr_nosv_task_create(1, typeid);
|
||||||
instr_nosv_task_execute(1, 0);
|
instr_nosv_task_execute(1, 0);
|
||||||
sleep_us(10000);
|
sleep_us(10000);
|
||||||
|
@ -18,7 +18,7 @@ main(void)
|
|||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
|
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
instr_nosv_task_create(1, typeid);
|
instr_nosv_task_create(1, typeid);
|
||||||
instr_nosv_task_create_par(2, typeid);
|
instr_nosv_task_create_par(2, typeid);
|
||||||
|
|
||||||
|
@ -17,21 +17,21 @@ main(void)
|
|||||||
int ntasks = 100;
|
int ntasks = 100;
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
|
|
||||||
for (int id = 1; id <= ntasks; id++)
|
for (int id = 1; id <= ntasks; id++)
|
||||||
instr_nosv_task_create(id, typeid);
|
instr_nosv_task_create((uint32_t) id, typeid);
|
||||||
|
|
||||||
for (int id = 1; id <= ntasks; id++) {
|
for (int id = 1; id <= ntasks; id++) {
|
||||||
instr_nosv_task_execute(id, 0);
|
instr_nosv_task_execute((uint32_t) id, 0);
|
||||||
instr_nosv_task_pause(id, 0);
|
instr_nosv_task_pause((uint32_t) id, 0);
|
||||||
instr_nosv_submit_enter();
|
instr_nosv_submit_enter();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int id = ntasks; id >= 1; id--) {
|
for (int id = ntasks; id >= 1; id--) {
|
||||||
instr_nosv_submit_exit();
|
instr_nosv_submit_exit();
|
||||||
instr_nosv_task_resume(id, 0);
|
instr_nosv_task_resume((uint32_t) id, 0);
|
||||||
instr_nosv_task_end(id, 0);
|
instr_nosv_task_end((uint32_t) id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
instr_end();
|
instr_end();
|
||||||
|
@ -17,7 +17,7 @@ main(void)
|
|||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
uint32_t taskid = 200;
|
uint32_t taskid = 200;
|
||||||
|
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
instr_nosv_task_create_par(taskid, typeid);
|
instr_nosv_task_create_par(taskid, typeid);
|
||||||
|
|
||||||
/* Create and run the tasks, one nested into another */
|
/* Create and run the tasks, one nested into another */
|
||||||
|
@ -18,7 +18,7 @@ main(void)
|
|||||||
int us = 500;
|
int us = 500;
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
instr_nosv_task_create(1, typeid);
|
instr_nosv_task_create(1, typeid);
|
||||||
instr_nosv_task_execute(1, 0);
|
instr_nosv_task_execute(1, 0);
|
||||||
sleep_us(us);
|
sleep_us(us);
|
||||||
|
@ -19,7 +19,7 @@ main(void)
|
|||||||
instr_nosv_init();
|
instr_nosv_init();
|
||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
uint32_t gid = instr_nosv_type_create(typeid);
|
uint32_t gid = instr_nosv_type_create((int32_t) typeid);
|
||||||
|
|
||||||
/* Create two tasks of the same type */
|
/* Create two tasks of the same type */
|
||||||
instr_nosv_task_create(1, typeid);
|
instr_nosv_task_create(1, typeid);
|
||||||
@ -39,20 +39,20 @@ main(void)
|
|||||||
/* Check the task type */
|
/* Check the task type */
|
||||||
int prvtype = PRV_NOSV_TYPE;
|
int prvtype = PRV_NOSV_TYPE;
|
||||||
int64_t t = get_delta();
|
int64_t t = get_delta();
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, gid);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, gid);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, gid);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, gid);
|
||||||
|
|
||||||
/* Check the task appid */
|
/* Check the task appid */
|
||||||
prvtype = PRV_NOSV_APPID;
|
prvtype = PRV_NOSV_APPID;
|
||||||
int appid = 1; /* Starts at one */
|
int appid = 1; /* Starts at one */
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, appid);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, appid);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, appid);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, appid);
|
||||||
|
|
||||||
/* Check the rank */
|
/* Check the rank */
|
||||||
prvtype = PRV_NOSV_RANK;
|
prvtype = PRV_NOSV_RANK;
|
||||||
int rank = 0 + 1; /* Starts at one */
|
int rank = 0 + 1; /* Starts at one */
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", t, prvtype, rank);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", t, prvtype, rank);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", t, prvtype, rank);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", t, prvtype, rank);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
/* Exit from tasks and subsystem */
|
/* Exit from tasks and subsystem */
|
||||||
|
@ -30,7 +30,7 @@ main(void)
|
|||||||
die("fopen failed:");
|
die("fopen failed:");
|
||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create((int32_t) typeid);
|
||||||
|
|
||||||
instr_nosv_task_create(1, typeid);
|
instr_nosv_task_create(1, typeid);
|
||||||
|
|
||||||
@ -40,22 +40,22 @@ main(void)
|
|||||||
* the "Task: In body" state */
|
* the "Task: In body" state */
|
||||||
int prvtype = PRV_NOSV_SUBSYSTEM;
|
int prvtype = PRV_NOSV_SUBSYSTEM;
|
||||||
int st = ST_TASK_BODY;
|
int st = ST_TASK_BODY;
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/thread.prv\n", get_delta(), prvtype, st);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/thread.prv\n", get_delta(), prvtype, st);
|
||||||
fprintf(f, "grep ':%ld:%d:%d$' ovni/cpu.prv\n", get_delta(), prvtype, st);
|
fprintf(f, "grep ':%" PRIi64 ":%d:%d$' ovni/cpu.prv\n", get_delta(), prvtype, st);
|
||||||
|
|
||||||
instr_nosv_submit_enter(); /* Blocking submit */
|
instr_nosv_submit_enter(); /* Blocking submit */
|
||||||
instr_nosv_task_pause(1, 0);
|
instr_nosv_task_pause(1, 0);
|
||||||
|
|
||||||
/* Should be left in the submit state, so no state transition in
|
/* Should be left in the submit state, so no state transition in
|
||||||
* subsystems view */
|
* subsystems view */
|
||||||
fprintf(f, "! grep ':%ld:%d:[0-9]*$' ovni/thread.prv\n", get_delta(), prvtype);
|
fprintf(f, "! grep ':%" PRIi64 ":%d:[0-9]*$' ovni/thread.prv\n", get_delta(), prvtype);
|
||||||
fprintf(f, "! grep ':%ld:%d:[0-9]*$' ovni/cpu.prv\n", get_delta(), prvtype);
|
fprintf(f, "! grep ':%" PRIi64 ":%d:[0-9]*$' ovni/cpu.prv\n", get_delta(), prvtype);
|
||||||
|
|
||||||
/* But the task state must be set to pause, so the task id
|
/* But the task state must be set to pause, so the task id
|
||||||
* must be null */
|
* must be null */
|
||||||
prvtype = PRV_NOSV_TASKID;
|
prvtype = PRV_NOSV_TASKID;
|
||||||
fprintf(f, "grep ':%ld:%d:0$' ovni/thread.prv\n", get_delta(), prvtype);
|
fprintf(f, "grep ':%" PRIi64 ":%d:0$' ovni/thread.prv\n", get_delta(), prvtype);
|
||||||
fprintf(f, "grep ':%ld:%d:0$' ovni/cpu.prv\n", get_delta(), prvtype);
|
fprintf(f, "grep ':%" PRIi64 ":%d:0$' ovni/cpu.prv\n", get_delta(), prvtype);
|
||||||
|
|
||||||
instr_nosv_submit_exit();
|
instr_nosv_submit_exit();
|
||||||
instr_nosv_task_resume(1, 0);
|
instr_nosv_task_resume(1, 0);
|
||||||
|
@ -19,13 +19,13 @@ main(void)
|
|||||||
int ntypes = 10;
|
int ntypes = 10;
|
||||||
|
|
||||||
for (int i = 0; i < ntypes; i++)
|
for (int i = 0; i < ntypes; i++)
|
||||||
instr_nosv_type_create(i + 1);
|
instr_nosv_type_create((int32_t) i + 1);
|
||||||
|
|
||||||
for (int i = 0; i < ntasks; i++) {
|
for (int i = 0; i < ntasks; i++) {
|
||||||
instr_nosv_task_create(i + 1, (i % ntypes) + 1);
|
instr_nosv_task_create((uint32_t) i + 1, (uint32_t) ((i % ntypes) + 1));
|
||||||
instr_nosv_task_execute(i + 1, 0);
|
instr_nosv_task_execute((uint32_t) i + 1, 0);
|
||||||
sleep_us(500);
|
sleep_us(500);
|
||||||
instr_nosv_task_end(i + 1, 0);
|
instr_nosv_task_end((uint32_t) i + 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
instr_end();
|
instr_end();
|
||||||
|
@ -5,6 +5,7 @@ test_emu(flush-overhead.c DISABLED)
|
|||||||
test_emu(flush.c)
|
test_emu(flush.c)
|
||||||
test_emu(sort.c SORT)
|
test_emu(sort.c SORT)
|
||||||
test_emu(sort-flush.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(empty-sort.c SORT)
|
||||||
test_emu(sort-first-and-full-ring.c SORT
|
test_emu(sort-first-and-full-ring.c SORT
|
||||||
SHOULD_FAIL REGEX "cannot find a event previous to clock")
|
SHOULD_FAIL REGEX "cannot find a event previous to clock")
|
||||||
@ -28,3 +29,5 @@ 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 "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-events" DRIVER "match-doc-events.sh")
|
||||||
test_emu(dummy.c NAME "match-doc-version" DRIVER "match-doc-version.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-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include <stdint.h>
|
#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};
|
struct ovni_ev ev = {0};
|
||||||
ovni_ev_set_mcv(&ev, "OHx");
|
ovni_ev_set_mcv(&ev, "OHx");
|
||||||
ovni_ev_set_clock(&ev, ovni_clock_now() + delta);
|
ovni_ev_set_clock(&ev, ovni_clock_now() + (uint64_t) delta);
|
||||||
ovni_payload_add(&ev, (uint8_t *) &cpu, sizeof(cpu));
|
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 *) &creator_tid, sizeof(creator_tid));
|
||||||
ovni_payload_add(&ev, (uint8_t *) &tag, sizeof(tag));
|
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)",
|
dbg("thread %d has cpu %d (ncpus=%d)",
|
||||||
get_tid(), curcpu, nranks);
|
get_tid(), curcpu, nranks);
|
||||||
|
|
||||||
delta = ((int64_t) rank) * 2LL * 3600LL * 1000LL * 1000LL * 1000LL;
|
delta = ((int64_t) rank) * (int64_t) (2LL * 3600LL * 1000LL * 1000LL * 1000LL);
|
||||||
thread_execute_delayed(curcpu, -1, 0);
|
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