MEDIUM: stats-file: processes share the same clock source from shm-stats-file

The use of the "shm-stats-file" directive now implies that all processes
using the same file now share a common clock source, this is required
for consistency regarding time-related operations.

The clock source is stored in the shm stats file header.
When the directive is set, all processes share the same clock
(global_now_ms and global_now_ns both point to variables in the map),
this is required for time-based counters such as freq counters to work
consistently. Since all processes manipulate global clock with atomic
operations exclusively during runtime, and don't systematically relies
on it (thanks to local now_ms and now_ns), it is pretty much transparent.
This commit is contained in:
Aurelien DARRAGON 2025-08-27 16:14:53 +02:00
parent c91d93ed1c
commit 443e657fd6
2 changed files with 43 additions and 0 deletions

View File

@ -24,6 +24,9 @@ struct shm_stats_file_hdr {
uint8_t major;
uint8_t minor;
} version;
uint global_now_ms; /* global monotonic date (ms) common to all processes using the shm */
ullong global_now_ns; /* global monotonic date (ns) common to all processes using the shm */
llong now_offset; /* offset applied to global monotonic date on startup */
};
struct shm_stats_file_object {

View File

@ -538,10 +538,50 @@ int shm_stats_file_prepare(void)
memset(shm_stats_file_hdr, 0, sizeof(*shm_stats_file_hdr));
shm_stats_file_hdr->version.major = SHM_STATS_FILE_VER_MAJOR;
shm_stats_file_hdr->version.minor = SHM_STATS_FILE_VER_MINOR;
/* set global clock for the first time */
shm_stats_file_hdr->global_now_ms = *global_now_ms;
shm_stats_file_hdr->global_now_ns = *global_now_ns;
shm_stats_file_hdr->now_offset = clock_get_now_offset();
}
else if (!shm_stats_file_check_ver(shm_stats_file_hdr))
goto err_version;
/* from now on use the shared global time */
global_now_ms = &shm_stats_file_hdr->global_now_ms;
global_now_ns = &shm_stats_file_hdr->global_now_ns;
if (!first) {
llong adjt_offset;
/* set adjusted offset which corresponds to the corrected offset
* relative to the initial offset stored in the shared memory instead
* of our process-local one
*/
adjt_offset = -clock_get_now_offset() + shm_stats_file_hdr->now_offset;
/* we now rely on global_now_* from the shm, so the boot
* offset that was initially applied in clock_init_process_date()
* is no longer relevant. So we fix it by applying the one from the
* initial process instead
*/
now_ns = now_ns + adjt_offset;
start_time_ns = start_time_ns + adjt_offset;
clock_set_now_offset(shm_stats_file_hdr->now_offset);
/* ensure global_now_* is consistent before continuing */
clock_update_global_date();
}
/* now that global_now_ns is accurate, recompute precise now_offset
* if needed (in case it is dynamic when monotonic clock not available)
*/
if (!th_ctx->curr_mono_time)
clock_set_now_offset(HA_ATOMIC_LOAD(global_now_ns) - tv_to_ns(&date));
/* sync local and global clocks, so all clocks are consistent */
clock_update_date(0, 1);
end:
return ERR_NONE;