Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2021 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : : #include "spdk/likely.h"
8 : :
9 : : #include "spdk_internal/event.h"
10 : : #include "spdk/thread.h"
11 : :
12 : : #include "spdk/log.h"
13 : : #include "spdk/env.h"
14 : : #include "spdk/scheduler.h"
15 : :
16 : : static uint32_t g_max_threshold = 99;
17 : : static uint32_t g_adjust_threshold = 50;
18 : : static uint32_t g_min_threshold = 1;
19 : :
20 : : static int
21 : 2 : init(void)
22 : : {
23 : 2 : return spdk_governor_set("dpdk_governor");
24 : : }
25 : :
26 : : static void
27 : 2 : deinit(void)
28 : : {
29 : 2 : spdk_governor_set(NULL);
30 : 2 : }
31 : :
32 : : static uint32_t
33 : 48 : calculate_busy_pct(struct spdk_scheduler_core_info *core)
34 : : {
35 : : uint64_t total_tsc;
36 : :
37 [ # # # # : 48 : total_tsc = core->current_busy_tsc + core->current_idle_tsc;
# # # # ]
38 [ - + ]: 48 : if (total_tsc == 0) {
39 : 0 : return 0;
40 : : } else {
41 [ - + # # : 48 : return core->current_busy_tsc * 100 / total_tsc;
# # ]
42 : : }
43 : 0 : }
44 : :
45 : : struct check_sibling_ctx {
46 : : struct spdk_scheduler_core_info *cores;
47 : : uint32_t busy_pct;
48 : : };
49 : :
50 : : static void
51 : 32 : check_sibling(void *_ctx, uint32_t i)
52 : : {
53 : 32 : struct check_sibling_ctx *ctx = _ctx;
54 [ # # # # : 32 : struct spdk_scheduler_core_info *core = &ctx->cores[i];
# # ]
55 : 32 : uint32_t busy_pct = calculate_busy_pct(core);
56 : :
57 [ # # # # : 32 : ctx->busy_pct = spdk_max(ctx->busy_pct, busy_pct);
# # # # #
# # # #
# ]
58 : 32 : }
59 : :
60 : : static void
61 : 2 : balance(struct spdk_scheduler_core_info *cores, uint32_t core_count)
62 : : {
63 : : struct spdk_governor *governor;
64 : : struct spdk_scheduler_core_info *core;
65 : 0 : struct spdk_governor_capabilities capabilities;
66 : : uint32_t busy_pct;
67 : : uint32_t i;
68 : : int rc;
69 : :
70 : 2 : governor = spdk_governor_get();
71 [ - + # # ]: 2 : assert(governor != NULL);
72 : :
73 : : /* Gather active/idle statistics */
74 [ + + ]: 18 : SPDK_ENV_FOREACH_CORE(i) {
75 : 16 : struct spdk_cpuset smt_siblings = {};
76 [ # # ]: 16 : core = &cores[i];
77 : :
78 [ # # # # : 16 : rc = governor->get_core_capabilities(core->lcore, &capabilities);
# # # # #
# # # ]
79 [ - + ]: 16 : if (rc < 0) {
80 [ # # # # ]: 0 : SPDK_ERRLOG("failed to get capabilities for core: %u\n", core->lcore);
81 : 0 : return;
82 : : }
83 : :
84 : 16 : busy_pct = calculate_busy_pct(core);
85 [ + - ]: 16 : if (spdk_env_core_get_smt_cpuset(&smt_siblings, i)) {
86 : 16 : struct check_sibling_ctx ctx = {.cores = cores, .busy_pct = busy_pct};
87 : :
88 : 16 : spdk_cpuset_for_each_cpu(&smt_siblings, check_sibling, &ctx);
89 [ # # ]: 16 : busy_pct = ctx.busy_pct;
90 : 0 : }
91 : :
92 [ + + ]: 16 : if (busy_pct < g_min_threshold) {
93 [ # # # # : 12 : rc = governor->set_core_freq_min(core->lcore);
# # # # #
# # # ]
94 [ - + ]: 12 : if (rc < 0) {
95 [ # # # # ]: 0 : SPDK_ERRLOG("setting to minimal frequency for core %u failed\n", core->lcore);
96 : 0 : }
97 [ + + ]: 4 : } else if (busy_pct < g_adjust_threshold) {
98 [ # # # # : 2 : rc = governor->core_freq_down(core->lcore);
# # # # #
# # # ]
99 [ - + ]: 2 : if (rc < 0) {
100 [ # # # # ]: 0 : SPDK_ERRLOG("lowering frequency for core %u failed\n", core->lcore);
101 : 0 : }
102 [ - + ]: 2 : } else if (busy_pct >= g_max_threshold) {
103 [ # # # # : 0 : rc = governor->set_core_freq_max(core->lcore);
# # # # #
# # # ]
104 [ # # ]: 0 : if (rc < 0) {
105 [ # # # # ]: 0 : SPDK_ERRLOG("setting to maximal frequency for core %u failed\n", core->lcore);
106 : 0 : }
107 : 0 : } else {
108 [ # # # # : 2 : rc = governor->core_freq_up(core->lcore);
# # # # #
# # # ]
109 [ - + ]: 2 : if (rc < 0) {
110 [ # # # # ]: 0 : SPDK_ERRLOG("increasing frequency for core %u failed\n", core->lcore);
111 : 0 : }
112 : : }
113 : 0 : }
114 : 0 : }
115 : :
116 : : static struct spdk_scheduler gscheduler = {
117 : : .name = "gscheduler",
118 : : .init = init,
119 : : .deinit = deinit,
120 : : .balance = balance,
121 : : };
122 : :
123 : 2101 : SPDK_SCHEDULER_REGISTER(gscheduler);
|