Skip to content

Commit f31c527

Browse files
shankarsealAlan-JowettAlan Jowettdthaler
authored
Approximate time helpers (#4013) (#4067)
* Approximate time helpers * PR feedback * Update expected c files * Apply suggestions from code review * Pickup latest usersim --------- Signed-off-by: Alan Jowett <alan.jowett@microsoft.com> Co-authored-by: Alan Jowett <alanjo@microsoft.com> Co-authored-by: Alan Jowett <alan.jowett@microsoft.com> Co-authored-by: Dave Thaler <dthaler1968@gmail.com>
1 parent cfba44d commit f31c527

File tree

15 files changed

+479
-309
lines changed

15 files changed

+479
-309
lines changed

include/bpf_helper_defs.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,3 +473,25 @@ EBPF_HELPER(size_t, bpf_strnlen_s, (const char* str, size_t str_size));
473473
#define memcpy_s bpf_memcpy
474474
#define memmove_s bpf_memmove
475475
#endif
476+
477+
/**
478+
* @brief Return time elapsed since boot in milliseconds including time while suspended.
479+
* This function uses a lower resolution clock source than bpf_ktime_get_boot_ns, but is faster.
480+
*
481+
* @return Time elapsed since boot in milliseconds.
482+
*/
483+
EBPF_HELPER(uint64_t, bpf_ktime_get_boot_ms, ());
484+
#ifndef __doxygen
485+
#define bpf_ktime_get_boot_ms ((bpf_ktime_get_boot_ms_t)BPF_FUNC_ktime_get_boot_ms)
486+
#endif
487+
488+
/**
489+
* @brief Return time elapsed since boot in milliseconds excluding time while suspended.
490+
* This function uses a lower resolution clock source than bpf_ktime_get_ns, but is faster.
491+
*
492+
* @return Time elapsed since boot in milliseconds.
493+
*/
494+
EBPF_HELPER(uint64_t, bpf_ktime_get_ms, ());
495+
#ifndef __doxygen
496+
#define bpf_ktime_get_ms ((bpf_ktime_get_ms_t)BPF_FUNC_ktime_get_ms)
497+
#endif

include/ebpf_structs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ typedef enum
164164
BPF_FUNC_strncpy_s = 27, ///< \ref bpf_strncpy_s
165165
BPF_FUNC_strncat_s = 28, ///< \ref bpf_strncat_s
166166
BPF_FUNC_strnlen_s = 29, ///< \ref bpf_strnlen_s
167+
BPF_FUNC_ktime_get_boot_ms = 30, ///< \ref bpf_ktime_get_boot_ms
168+
BPF_FUNC_ktime_get_ms = 31, ///< \ref bpf_ktime_get_ms
167169
} ebpf_helper_id_t;
168170

169171
// Cross-platform BPF program types.

libs/execution_context/ebpf_core.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ _ebpf_core_memmove(
101101
_In_reads_(source_length) const void* source,
102102
size_t source_length);
103103

104+
static uint64_t
105+
_ebpf_core_get_time_since_boot_ms();
106+
107+
static uint64_t
108+
_ebpf_core_get_time_ms();
109+
104110
#define EBPF_CORE_GLOBAL_HELPER_EXTENSION_VERSION 0
105111

106112
static ebpf_program_type_descriptor_t _ebpf_global_helper_program_descriptor = {
@@ -144,6 +150,8 @@ static const void* _ebpf_general_helpers[] = {
144150
(void*)&_ebpf_core_strncpy_s,
145151
(void*)&_ebpf_core_strncat_s,
146152
(void*)&_ebpf_core_strlen_s,
153+
(void*)&_ebpf_core_get_time_since_boot_ms,
154+
(void*)&_ebpf_core_get_time_ms,
147155
};
148156

149157
static const ebpf_helper_function_addresses_t _ebpf_global_helper_function_dispatch_table = {
@@ -2257,17 +2265,33 @@ _ebpf_core_random_uint32()
22572265
static uint64_t
22582266
_ebpf_core_get_time_since_boot_ns()
22592267
{
2260-
// ebpf_query_time_since_boot_precise returns time elapsed since
2268+
// cxplat_query_time_since_boot_precise returns time elapsed since
22612269
// boot in units of 100 ns.
2262-
return ebpf_query_time_since_boot_precise(true) * EBPF_NS_PER_FILETIME;
2270+
return cxplat_query_time_since_boot_precise(true) * EBPF_NS_PER_FILETIME;
22632271
}
22642272

22652273
static uint64_t
22662274
_ebpf_core_get_time_ns()
22672275
{
2268-
// ebpf_query_time_since_boot_precise returns time elapsed since
2276+
// cxplat_query_time_since_boot_precise returns time elapsed since
2277+
// boot in units of 100 ns.
2278+
return cxplat_query_time_since_boot_precise(false) * EBPF_NS_PER_FILETIME;
2279+
}
2280+
2281+
static uint64_t
2282+
_ebpf_core_get_time_since_boot_ms()
2283+
{
2284+
// cxplat_query_time_since_boot_approximate returns time elapsed since
2285+
// boot in units of 100 ns.
2286+
return cxplat_query_time_since_boot_approximate(true) / EBPF_FILETIME_PER_MS;
2287+
}
2288+
2289+
static uint64_t
2290+
_ebpf_core_get_time_ms()
2291+
{
2292+
// cxplat_query_time_since_boot_approximate returns time elapsed since
22692293
// boot in units of 100 ns.
2270-
return ebpf_query_time_since_boot_precise(false) * EBPF_NS_PER_FILETIME;
2294+
return cxplat_query_time_since_boot_approximate(false) / EBPF_FILETIME_PER_MS;
22712295
}
22722296

22732297
static uint64_t

libs/execution_context/ebpf_general_helpers.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@ ebpf_helper_function_prototype_t ebpf_core_helper_function_prototype_array[] = {
197197
EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM,
198198
EBPF_ARGUMENT_TYPE_CONST_SIZE_OR_ZERO,
199199
}},
200+
{EBPF_HELPER_FUNCTION_PROTOTYPE_HEADER,
201+
BPF_FUNC_ktime_get_boot_ms,
202+
"bpf_ktime_get_boot_ms",
203+
EBPF_RETURN_TYPE_INTEGER,
204+
{0}},
205+
{EBPF_HELPER_FUNCTION_PROTOTYPE_HEADER, BPF_FUNC_ktime_get_ms, "bpf_ktime_get_ms", EBPF_RETURN_TYPE_INTEGER, {0}},
200206
};
201207

202208
#ifdef __cplusplus

libs/execution_context/ebpf_maps.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,15 +1224,15 @@ _insert_into_hot_list(_Inout_ ebpf_core_lru_map_t* map, size_t partition, _Inout
12241224
switch (key_state) {
12251225
case EBPF_LRU_KEY_UNINITIALIZED:
12261226
EBPF_LRU_ENTRY_GENERATION_PTR(map, entry)[partition] = map->partitions[partition].current_generation;
1227-
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = ebpf_query_time_since_boot_approximate(false);
1227+
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = cxplat_query_time_since_boot_approximate(false);
12281228
ebpf_list_insert_tail(
12291229
&map->partitions[partition].hot_list, &EBPF_LRU_ENTRY_LIST_ENTRY_PTR(map, entry)[partition]);
12301230
map->partitions[partition].hot_list_size++;
12311231
break;
12321232
case EBPF_LRU_KEY_COLD:
12331233
// Remove from cold list.
12341234
EBPF_LRU_ENTRY_GENERATION_PTR(map, entry)[partition] = map->partitions[partition].current_generation;
1235-
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = ebpf_query_time_since_boot_approximate(false);
1235+
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = cxplat_query_time_since_boot_approximate(false);
12361236
ebpf_list_remove_entry(&EBPF_LRU_ENTRY_LIST_ENTRY_PTR(map, entry)[partition]);
12371237
ebpf_list_insert_tail(
12381238
&map->partitions[partition].hot_list, &EBPF_LRU_ENTRY_LIST_ENTRY_PTR(map, entry)[partition]);
@@ -1271,7 +1271,7 @@ _initialize_lru_entry(
12711271
// Only insert into the current partition's hot list.
12721272
ebpf_lock_state_t state = ebpf_lock_lock(&map->partitions[partition].lock);
12731273
EBPF_LRU_ENTRY_GENERATION_PTR(map, entry)[partition] = map->partitions[partition].current_generation;
1274-
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = ebpf_query_time_since_boot_approximate(false);
1274+
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = cxplat_query_time_since_boot_approximate(false);
12751275
ebpf_list_insert_tail(&map->partitions[partition].hot_list, &EBPF_LRU_ENTRY_LIST_ENTRY_PTR(map, entry)[partition]);
12761276
map->partitions[partition].hot_list_size++;
12771277

libs/execution_context/ebpf_program.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2454,7 +2454,7 @@ _ebpf_program_test_run_work_item(_In_ cxplat_preemptible_work_item_t* work_item,
24542454
state_stored = true;
24552455
}
24562456

2457-
uint64_t start_time = ebpf_query_time_since_boot_precise(false);
2457+
uint64_t start_time = cxplat_query_time_since_boot_precise(false);
24582458
// Use a counter instead of performing a modulus operation to determine when to start a new epoch.
24592459
// This is because the modulus operation is expensive and we want to minimize the overhead of
24602460
// the test run.
@@ -2467,7 +2467,7 @@ _ebpf_program_test_run_work_item(_In_ cxplat_preemptible_work_item_t* work_item,
24672467
ebpf_epoch_exit(&epoch_state);
24682468
if (ebpf_should_yield_processor()) {
24692469
// Compute the elapsed time since the last yield.
2470-
end_time = ebpf_query_time_since_boot_precise(false);
2470+
end_time = cxplat_query_time_since_boot_precise(false);
24712471

24722472
// Add the elapsed time to the cumulative time.
24732473
cumulative_time += end_time - start_time;
@@ -2479,7 +2479,7 @@ _ebpf_program_test_run_work_item(_In_ cxplat_preemptible_work_item_t* work_item,
24792479
old_irql = ebpf_raise_irql(context->required_irql);
24802480

24812481
// Reset the start time.
2482-
start_time = ebpf_query_time_since_boot_precise(false);
2482+
start_time = cxplat_query_time_since_boot_precise(false);
24832483
}
24842484
ebpf_epoch_enter(&epoch_state);
24852485
}
@@ -2489,7 +2489,7 @@ _ebpf_program_test_run_work_item(_In_ cxplat_preemptible_work_item_t* work_item,
24892489
break;
24902490
}
24912491
}
2492-
end_time = ebpf_query_time_since_boot_precise(false);
2492+
end_time = cxplat_query_time_since_boot_precise(false);
24932493

24942494
cumulative_time += end_time - start_time;
24952495

libs/runtime/ebpf_platform.c

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -222,34 +222,6 @@ ebpf_allocate_process_state()
222222
return state;
223223
}
224224

225-
uint64_t
226-
ebpf_query_time_since_boot_precise(bool include_suspended_time)
227-
{
228-
uint64_t qpc_time;
229-
if (include_suspended_time) {
230-
// KeQueryUnbiasedInterruptTimePrecise returns the current interrupt-time count in 100-nanosecond units.
231-
// Unbiased Interrupt time is the total time since boot including time spent suspended.
232-
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-kequeryunbiasedinterrupttimeprecise
233-
return KeQueryUnbiasedInterruptTimePrecise(&qpc_time);
234-
} else {
235-
// KeQueryInterruptTimePrecise returns the current interrupt-time count in 100-nanosecond units.
236-
// (Biased) Interrupt time is the total time since boot excluding time spent suspended. //
237-
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-kequeryinterrupttimeprecise
238-
return KeQueryInterruptTimePrecise(&qpc_time);
239-
}
240-
}
241-
242-
uint64_t
243-
ebpf_query_time_since_boot_approximate(bool include_suspend_time)
244-
{
245-
if (include_suspend_time) {
246-
ebpf_assert(!"Include suspend time not supported on this platform.");
247-
return 0;
248-
} else {
249-
return KeQueryInterruptTime();
250-
}
251-
}
252-
253225
MDL*
254226
ebpf_map_memory(size_t length)
255227
{

libs/runtime/ebpf_platform.h

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern "C"
3939
}
4040

4141
#define EBPF_NS_PER_FILETIME 100
42+
#define EBPF_FILETIME_PER_MS 10000
4243

4344
typedef enum _ebpf_code_integrity_state
4445
{
@@ -632,29 +633,6 @@ extern "C"
632633
ebpf_validate_security_descriptor(
633634
_In_ const ebpf_security_descriptor_t* security_descriptor, size_t security_descriptor_length);
634635

635-
/**
636-
* @brief Return time elapsed since boot in units of 100 nanoseconds.
637-
*
638-
* @param[in] include_suspended_time Include time the system spent in a suspended state.
639-
* @return Time elapsed since boot in 100 nanosecond units.
640-
*/
641-
EBPF_INLINE_HINT
642-
uint64_t
643-
ebpf_query_time_since_boot_precise(bool include_suspended_time);
644-
645-
/**
646-
* @brief Return time elapsed since boot in units of 100 nanoseconds.
647-
* This function is faster than ebpf_query_time_since_boot_precise() but may not
648-
* be as accurate.
649-
*
650-
* @param[in] include_suspended_time Include time the system spent in a suspended state.
651-
*
652-
* @return Time elapsed since boot in 100 nanosecond units.
653-
*/
654-
EBPF_INLINE_HINT
655-
uint64_t
656-
ebpf_query_time_since_boot_approximate(bool include_suspended_time);
657-
658636
/**
659637
* @brief Affinitize the current thread to a specific CPU by index and return the old affinity.
660638
*

0 commit comments

Comments
 (0)