Compare commits

..

74 Commits

Author SHA1 Message Date
36cf3121d1 Fix implicit signed conversions
Some checks failed
CI / build:rt (push) Failing after 12s
CI / build:asan (push) Failing after 12s
CI / build:nompi (push) Successful in 59s
CI / build:debug (push) Successful in 1m50s
CI / build:local (push) Successful in 2m2s
CI / build:compilers (push) Successful in 2m27s
2024-09-09 13:44:05 +02:00
c8b95313ff Fix unaligned access to 64 bits payload 2024-09-09 13:44:05 +02:00
e5448af6d8 Rebuild ring buffer pointers after injecting events
The ring buffer pointers are no longer valid as we may have displaced
events around. The pointers of the affected region are reconstructed by
reading the events again, following their size.
2024-09-09 13:43:59 +02:00
49149e452c Check ring buffer order after injecting events
Ensure that we are not reading garbage.
2024-09-09 09:10:04 +02:00
b2d91391b3 Add sort-into-previous-region emu test 2024-09-09 09:10:04 +02:00
13f70be87b Set nOS-V version required for tests to 2.3.1
Includes the required fixes for the kernel ring buffer tests.
2024-09-09 08:51:04 +02:00
71aa33d22f Use string to set ovni.kernel_ringsize 2024-09-09 08:51:04 +02:00
4c3da12ea1 Fix typos in nOS-V kernel test 2024-09-09 08:51:04 +02:00
a47082730a Ensure that nOS-V aborts on ring overflow 2024-09-09 08:51:04 +02:00
99dc3904af Add overflow and normal kernel nOS-V tests 2024-09-09 08:51:04 +02:00
acf18c1bb4 Make nOS-V kernel overflow test configurable 2024-09-09 08:51:04 +02:00
e9788e22ad Add test kernel ring overflow test for nOS-V
There is a problem in the way we are reading the buffer in nOS-V, which
fails when the ring buffer gets full. This regression test ensures it is
fixed.

Reported-by: David Álvarez <david.alvarez@bsc.es>
2024-09-09 08:51:04 +02:00
6cb983a7c4 Update nOS-V commit 2024-09-09 08:51:04 +02:00
7496a6a866 Fix easy cases of unneeded casts 2024-09-09 08:28:08 +02:00
c8750b9dfd Enable -Wconversion and -Wsign-conversion
Prevents implicit conversions to go undetected, as they will have to be
explicit now.
2024-09-09 08:28:02 +02:00
d98ca97624 Fix unaligned load of 4 bytes for typeid
Use memcpy() to move the typeid to an aligned address.
2024-07-29 13:17:37 +02:00
61d57901b1 Enable undefined behavior sanitizer in CI 2024-07-29 13:09:41 +02:00
9c82038561 Add release link to tag 1.10.0 2024-07-26 16:20:34 +02:00
15dfa48d2d Release version 1.10.0 2024-07-26 13:25:43 +02:00
2457e50712 Use always base 10 integer formats with scanf()
The %i printf variant tries to autodetect the base, so 010 becomes 8.
2024-07-24 16:36:54 +02:00
92c36502bc Reduce heat and fibonnacci test sizes 2024-07-24 16:09:47 +02:00
439b716a71 Use int64_t printf formats for mark channels 2024-07-24 16:09:47 +02:00
97282ff051 Increase test timeout to 60 seconds 2024-07-24 16:09:47 +02:00
093c91521a Fix error format strings in mark API 2024-07-24 16:09:44 +02:00
74aa7b4ea6 Update changelog 2024-07-24 15:12:09 +02:00
3d8c84e17c Fix heap when size_t is not unsigned long long
When the width of size_t doesn't match the width of the unsigned long
long type, the number of leading zeros doesn't match, making the
heap_get_move() function return incorrect values. This is the case on
ARMv7 with 32 bits, where size_t is 32 bits but unsigned long long is 64
bits.

We check the size of size_t to select which builtin we need. The sizeof
operator cannot be used at preprocessing, so we rely on the
optimizations to only leave the proper assembly instruction.

Fixes: https://pm.bsc.es/gitlab/rarias/ovni/-/issues/193
2024-07-24 15:12:09 +02:00
91e8367d35 Set timeout to 30 seconds for tests 2024-07-24 15:12:09 +02:00
129020e1c5 Fix format errors in printf-like functions 2024-07-24 15:12:09 +02:00
d03fe10be8 Protect printf-like calls against format errors 2024-07-24 15:12:09 +02:00
3fdbb95080 Fix remaining problems for 32 bits architectures 2024-07-24 15:12:09 +02:00
Miquel Vidal i Pinyol
3103018404 Use format macro constants for fprintf and fscanf family functions 2024-07-24 15:12:09 +02:00
Miquel Vidal i Pinyol
478ed1f5d0 Use proper format specifiers
Allows compiling for architectures with different data type sizes
2024-07-24 15:12:09 +02:00
42feb53c86 Cross compile for ARMv7, Aarch64 and RISC-V 64
Adds CI cross-compilation tests for those architectures. Requires the
host to be able to run thos binaries via binfmt.

See: https://docs.kernel.org/admin-guide/binfmt-misc.html
2024-07-24 15:12:09 +02:00
391d695144 Add mark API to the changelog 2024-07-23 10:35:08 +02:00
038b9d8564 Document usage rules for the mark API 2024-07-23 10:35:08 +02:00
5448b5c0ec Check duplicated mark channel types are the same
Ensure that two threads cannot define the same mark type with different
channel types.
2024-07-23 10:35:08 +02:00
be45235d15 Improve documentation of the mark API 2024-07-23 10:35:08 +02:00
87e4b829c5 Switch the mark tracking for threads to active
In the thread view, the values will still be visible when the thread
goes to Warming or Cooling states, instead of being removed like when
the thread enters the Paused state. The CPU view will continue to track
the running thread (only in the Running state).
2024-07-23 10:35:02 +02:00
1ab605b70d Fix calloc() argument order
Catched by a new gcc 14.1.1 warning.
2024-07-22 16:45:29 +02:00
fbb78ae22d Avoid initialization of mark channels without types
There is no need to create any channel or connect any channel to the PRV
output.
2024-07-22 16:42:23 +02:00
a21dc76d81 Use 100 as example mark type
As the types for mark timelines start at 100, it is likely that it
matches in the first try.
2024-06-21 09:45:54 +02:00
49cecb798a Don't allow zero in PRV for mark channels
As the zero value is not allowed to reach the mark channels, there is no
need to allow it in the PRV end.
2024-06-21 09:39:32 +02:00
e31f0f1ded Add fibonacci and heat RT tests for mark API 2024-06-20 17:39:42 +02:00
43792fb349 Clarify push and pop value in mark API 2024-06-20 11:48:31 +02:00
d6a83a0520 Allow duplicate values in mark channels 2024-06-20 11:41:38 +02:00
c803a7566f Prevent zero values in the mark API
These values cannot be differentiated from a null value, due to a
Paraver limitation.
2024-06-20 11:41:09 +02:00
670edb6ddc Add documentation for the mark API
Includes the runtime usage as well as how to adjust the Paraver
configuration.
2024-06-20 11:08:29 +02:00
f5d1e0a3cb Add example mark configurations 2024-06-20 11:07:49 +02:00
a58b3d194c Add CPU output for mark channels
By default they are configured to track the running thread.
2024-06-19 13:48:18 +02:00
d9180d950b Make mark thread channels show only when running
Implements support for tracking the running thread using the track API.
2024-06-19 13:15:16 +02:00
9da7234684 Pause one thread in mark API emu test.
The Paraver timeline should hide the value of the thread while it is
paused. This will require adding a tracking module with a mux.
2024-06-19 13:13:18 +02:00
610b1223d9 Update version docs for ovni model 1.1.0 2024-06-19 12:26:58 +02:00
6954f05dee Update mark test to for single and stack types 2024-06-19 12:26:35 +02:00
db57136f1b Allow the value zero in marks
When using the mark API to track a counter, it is posible that the value
zero is being emitted as it will be properly displayed using the
gradient view in Paraver.
2024-06-19 12:26:35 +02:00
2c111fd98c Add ovni_mark_set() to the API
Allows emitting a single event to change the value of the mark channel.
The mark type must be defined as single without the MARK_FLAG_STACK
flag.
2024-06-19 12:26:35 +02:00
90f8ae4188 Allow marks without labels defined
The labels are optional, so they shouldn't be required when processing
the mark types.
2024-06-19 12:26:35 +02:00
b4d445b378 Write mark PCF types for thread PVT 2024-06-19 12:26:35 +02:00
ea79c90c89 Connect mark channels to PRV
There must be one channel per thread and type.
2024-06-19 12:26:35 +02:00
1b2f72cc3a Store mark labels into a hash table
Multiple threads can define the same values as long as the labels match.
They will be combined into a single hash table by value.
2024-06-19 12:26:35 +02:00
505245d54c Implement emulator logic to parse mark metadata
The marks are parsed from the metadata definition, then merged from all
threads and a new channel for each mark type is created. The channel
type is specified using a flag when calling ovni_mark_type(), so the
channels is set to single or stack. For now, only ovni_mark_push() and
ovni_mark_pop() are implemented.
2024-06-19 12:26:35 +02:00
93ab5a5833 Add ovni_mark_* API to store custom states
In order to allow easy debugging of some programs and runtimes, it is
often neccessary to add extra information in the timeline views. The
modification of the emulator to accomodate those temporal events is time
consuming and requires knowlegde of the emulator internals.

To improve the situation, a new set of functions are added to libovni
which allow users to define their own views. Up to 100 types of events
can be declared, where each type can have an unlimited number ov values
with an optional label attached.
2024-06-19 12:26:35 +02:00
247ea7e7c3 Add nosv.can_breakdown attribute check
The nosv.can_breakdown attribute states if enough events for the
breakdown model of nOS-V are enabled at runtime. It is used to ensure
that breakdown traces have the progress events enabled along with others
required for proper visualization of traces.

The emulator will panic when the level is not enough, instead of relying
on users to always remember to enable the correct level.
2024-06-18 12:06:42 +02:00
d1e8a62396 Add API to manage metadata in streams
The ovni_attr_* set of functions allows users to write and read metadata
stores in the thread stream. The metadata information is available to
the emulator at the beginning of the emulation.
2024-06-13 11:09:40 +02:00
2ac67cff18 Update CHANGELOG for nOS-V breakdown 2024-06-12 16:52:30 +02:00
eed2273ddf Add nOS-V docs for idle and breakdown views 2024-06-12 16:52:30 +02:00
31d6eb076c Add unknown subsystem state for nOS-V breakdown
It will appear when the emulator knows that a thread is running in the
CPU, but no subsystem has been entered yet. This is common a
instrumentation level lower than 3 in nOS-V.
2024-06-12 16:52:30 +02:00
bb5e406af3 Set a default value for empty task type labels 2024-06-12 16:52:30 +02:00
aab33ccfab Add Nodes RT tests with breakdown enabled 2024-06-12 16:52:30 +02:00
98164afc90 Update nOS-V state colors in paraver CFG 2024-06-12 16:52:30 +02:00
819e83d138 Add RT breakdown tests for nOS-V
The nOS-V version required is now 2.3.0.
2024-06-12 16:52:30 +02:00
16b9b2ba85 Update nOS-V commit for RT tests 2024-06-12 16:51:57 +02:00
9d94189165 Increase nOS-V model version to 2.2.0
The new progressing state events VP{pra} cause a minor version bump in
the nOS-V model.
2024-06-12 10:25:24 +02:00
David Alvarez
9fb53df45d nOS-V Breakdown 2024-06-12 10:15:59 +02:00
92cc779caf Make chan_pop() error more clear
Fixes: https://pm.bsc.es/gitlab/rarias/ovni/-/issues/188
2024-06-11 09:19:35 +02:00
125 changed files with 3273 additions and 450 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View 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
View 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
View 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
View 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"

View File

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -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)

View File

@ -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
View 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.

View File

@ -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;
});
}; };
}; };
} }

View File

@ -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

View File

@ -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

View File

@ -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';

View File

@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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"

View File

@ -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;
} }

View File

@ -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);

View File

@ -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");

View File

@ -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;
} }

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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;
} }

View File

@ -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];

View File

@ -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;

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;

View File

@ -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
View 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
View 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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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");

View File

@ -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
View 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
View 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 */

View File

@ -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);

View File

@ -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;
} }

View File

@ -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,

View File

@ -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], "&amp;"); j += 5; break; case '&': strcpy(&dst[j], "&amp;"); j += 5; break;
case '"': strcpy(&dst[j], "&quot;"); j += 6; break; case '"': strcpy(&dst[j], "&quot;"); 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;
} }
} }

View File

@ -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();

View File

@ -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)

View File

@ -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';
} }

View File

@ -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;

View File

@ -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:");

View File

@ -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)

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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];

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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) */

View File

@ -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);
}

View File

@ -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;

View File

@ -23,7 +23,7 @@ int64_t get_delta(void);
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); \
} }
@ -32,7 +32,7 @@ int64_t get_delta(void);
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 */

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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++) {

View File

@ -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);
} }

View File

@ -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();

View File

@ -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++) {

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
} }

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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();

View File

@ -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)

View File

@ -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