1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2026 fangqiurong <fangqiurong@kylinos.cn> 4 */ 5 #include <bpf/bpf.h> 6 #include <scx/common.h> 7 #include <time.h> 8 #include <unistd.h> 9 #include "dequeue_iter.bpf.skel.h" 10 #include "scx_test.h" 11 12 #define DQ_TARGET 10 13 #define DQ_DEADLINE_MS 3000 14 15 static unsigned long long now_ms(void) 16 { 17 struct timespec ts; 18 19 clock_gettime(CLOCK_MONOTONIC, &ts); 20 21 return ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000; 22 } 23 24 static enum scx_test_status setup(void **ctx) 25 { 26 struct dequeue_iter *skel; 27 28 skel = dequeue_iter__open(); 29 SCX_FAIL_IF(!skel, "Failed to open"); 30 SCX_ENUM_INIT(skel); 31 SCX_FAIL_IF(dequeue_iter__load(skel), "Failed to load skel"); 32 33 *ctx = skel; 34 35 return SCX_TEST_PASS; 36 } 37 38 static enum scx_test_status run(void *ctx) 39 { 40 struct dequeue_iter *skel = ctx; 41 struct bpf_link *link; 42 unsigned long long end; 43 44 link = bpf_map__attach_struct_ops(skel->maps.dequeue_iter_ops); 45 SCX_FAIL_IF(!link, "Failed to attach scheduler"); 46 47 end = now_ms() + DQ_DEADLINE_MS; 48 while (skel->bss->dq_count < DQ_TARGET && !UEI_EXITED(skel, uei) && 49 now_ms() < end) 50 usleep(100); 51 52 bpf_link__destroy(link); 53 54 SCX_EQ(skel->data->uei.kind, EXIT_KIND(SCX_EXIT_UNREG)); 55 56 if (skel->bss->dq_count < DQ_TARGET) { 57 SCX_ERR("ops.dequeue() fired only %llu times", 58 (unsigned long long)skel->bss->dq_count); 59 return SCX_TEST_FAIL; 60 } 61 62 return SCX_TEST_PASS; 63 } 64 65 static void cleanup(void *ctx) 66 { 67 struct dequeue_iter *skel = ctx; 68 69 dequeue_iter__destroy(skel); 70 } 71 72 struct scx_test dequeue_iter = { 73 .name = "dequeue_iter", 74 .description = "Verify ops.dequeue() can iterate its source user DSQ", 75 .setup = setup, 76 .run = run, 77 .cleanup = cleanup, 78 }; 79 REGISTER_SCX_TEST(&dequeue_iter) 80