Now the uadk scheduler will search the nearest node when call session_sched_init(). But this is a repetitive work because session_sched_init() is called by wd_xxx_create_sess().
So we can build an cpu-device numa node map. Update the map when a new numa node has been enabled with a device. And then, session_sched_init() can quick get the right device id from a certain cpu.
Yang Shen (2): uadk/sched - adjust some functions location and rename for tag uadk/sched - add mapping from cpus to devices
wd_sched.c | 312 ++++++++++++++++++++++++++++------------------------- 1 file changed, 163 insertions(+), 149 deletions(-)
-- 2.24.0
1. Adjust some functions location to make code review clearly. 2. Add suffix for sched policy interface.
Signed-off-by: Yang Shen shenyang39@huawei.com --- wd_sched.c | 318 ++++++++++++++++++++++++++--------------------------- 1 file changed, 156 insertions(+), 162 deletions(-)
diff --git a/wd_sched.c b/wd_sched.c index d9a33fc..bef5f74 100644 --- a/wd_sched.c +++ b/wd_sched.c @@ -80,12 +80,51 @@ struct wd_sched_ctx { struct wd_sched_info sched_info[0]; };
+static bool sched_key_valid(struct wd_sched_ctx *sched_ctx, + const struct sched_key *key) +{ + if (key->numa_id >= sched_ctx->numa_num || + key->mode >= SCHED_MODE_BUTT || + key->type >= sched_ctx->type_num) { + WD_ERR("invalid: sched key's numa: %d, mode: %u, type: %u!\n", + key->numa_id, key->mode, key->type); + return false; + } + + return true; +} + +/** + * sched_get_ctx_range - Get ctx range from ctx_map by the wd comp arg + */ +static struct sched_ctx_region *sched_get_ctx_range(struct wd_sched_ctx *sched_ctx, + const struct sched_key *key) +{ + struct wd_sched_info *sched_info; + int numa_id; + int type; + + sched_info = sched_ctx->sched_info; + if (key->numa_id >= 0 && + sched_info[key->numa_id].ctx_region[key->mode][key->type].valid) + return &sched_info[key->numa_id].ctx_region[key->mode][key->type]; + + /* If the key->numa_id is not exist, we should scan for a region */ + for (numa_id = 0; numa_id < sched_ctx->numa_num; numa_id++) { + for (type = 0; type < sched_ctx->type_num; type++) { + if (sched_info[numa_id].ctx_region[key->mode][type].valid) + return &sched_info[numa_id].ctx_region[key->mode][type]; + } + } + + return NULL; +} + /** * sched_get_next_pos_rr - Get next resource pos by RR schedule. * The second para is reserved for future. */ -static __u32 sched_get_next_pos_rr(struct sched_ctx_region *region, - void *para) +static __u32 sched_get_next_pos_rr(struct sched_ctx_region *region, void *para) { __u32 pos;
@@ -104,46 +143,116 @@ static __u32 sched_get_next_pos_rr(struct sched_ctx_region *region, }
/** - * sched_get_ctx_range - Get ctx range from ctx_map by the wd comp arg + * session_sched_init_ctx - Get one ctx from ctxs by the sched_ctx and arg. + * @sched_ctx: Schedule ctx, reference the struct sample_sched_ctx. + * @sched_key: The key of schedule region. + * @sched_mode: The sched async/sync mode. + * + * The user must init the schedule info through wd_sched_rr_instance */ -static struct sched_ctx_region *sched_get_ctx_range(struct wd_sched_ctx *ctx, - const struct sched_key *key) +static __u32 session_sched_init_ctx(handle_t h_sched_ctx, void *sched_key, const int sched_mode) { - struct wd_sched_info *sched_info; - int numa_id; - int type; + struct wd_sched_ctx *sched_ctx = (struct wd_sched_ctx *)h_sched_ctx; + struct sched_key *key = (struct sched_key *)sched_key; + struct sched_ctx_region *region = NULL; + bool ret;
- sched_info = ctx->sched_info; - if (key->numa_id >= 0 && - sched_info[key->numa_id].ctx_region[key->mode][key->type].valid) - return &sched_info[key->numa_id].ctx_region[key->mode][key->type]; + if (!sched_ctx || !key) { + WD_ERR("invalid: sched ctx or key is NULL!\n"); + return INVALID_POS; + }
- /* If the key->numa_id is not exist, we should scan for a region */ - for (numa_id = 0; numa_id < ctx->numa_num; numa_id++) { - for (type = 0; type < ctx->type_num; type++) { - if (sched_info[numa_id].ctx_region[key->mode][type].valid) - return &sched_info[numa_id].ctx_region[key->mode][type]; + key->mode = sched_mode; + ret = sched_key_valid(sched_ctx, key); + if (!ret) + return INVALID_POS; + + region = sched_get_ctx_range(sched_ctx, key); + if (!region) + return INVALID_POS; + + return sched_get_next_pos_rr(region, NULL); +} + +static int get_nearby_numa_id(handle_t h_sched_ctx) +{ +#define MAX_NUMA_DISTANCE 1024 + struct wd_sched_ctx *sched_ctx = (struct wd_sched_ctx *)h_sched_ctx; + struct wd_sched_info *sched_info = sched_ctx->sched_info; + int cpu = sched_getcpu(); + int node = numa_node_of_cpu(cpu); + int dis = MAX_NUMA_DISTANCE; + int i, tmp, valid_id = -1; + + for (i = 0; i < sched_ctx->numa_num; i++) { + if (sched_info[i].valid) { + tmp = numa_distance(node, i); + if (dis > tmp) { + valid_id = i; + dis = tmp; + } } }
- return NULL; + return valid_id; }
-static bool sched_key_valid(struct wd_sched_ctx *ctx, - const struct sched_key *key) +static handle_t session_sched_init_rr(handle_t h_sched_ctx, void *sched_param) { - if (key->numa_id >= ctx->numa_num || key->mode >= SCHED_MODE_BUTT || - key->type >= ctx->type_num) { - WD_ERR("invalid: sched key's numa: %d, mode: %u, type: %u!\n", - key->numa_id, key->mode, key->type); - return false; + struct sched_params *param = (struct sched_params *)sched_param; + struct sched_key *skey; + + skey = malloc(sizeof(struct sched_key)); + if (!skey) { + WD_ERR("failed to alloc memory for session sched key!\n"); + return (handle_t)(-WD_ENOMEM); }
- return true; + if (!param || param->numa_id < 0) { + memset(skey, 0, sizeof(struct sched_key)); + skey->numa_id = get_nearby_numa_id(h_sched_ctx); + if (skey->numa_id < 0) { + WD_ERR("failed to get valid sched numa region!\n"); + free(skey); + return (handle_t)(-WD_ENOMEM); + } + } else { + skey->type = param->type; + skey->numa_id = param->numa_id; + } + + skey->sync_ctxid = session_sched_init_ctx(h_sched_ctx, skey, CTX_MODE_SYNC); + skey->async_ctxid = session_sched_init_ctx(h_sched_ctx, skey, CTX_MODE_ASYNC); + + return (handle_t)skey; }
-static int session_poll_region(struct wd_sched_ctx *ctx, __u32 begin, - __u32 end, __u32 expect, __u32 *count) +/** + * session_pick_next_ctx - Get one ctx from ctxs by the sched_ctx and arg. + * @sched_ctx: Schedule ctx, reference the struct sample_sched_ctx. + * @sched_key: The key of schedule region. + * @sched_mode: The sched async/sync mode. + * + * The user must init the schedule info through session_sched_init + */ +static __u32 session_sched_pick_next_ctx_rr(handle_t h_sched_ctx, void *sched_key, + const int sched_mode) +{ + struct sched_key *key = (struct sched_key *)sched_key; + + if (unlikely(!h_sched_ctx || !key)) { + WD_ERR("invalid: sched ctx or key is NULL!\n"); + return INVALID_POS; + } + + /* return in do task */ + if (sched_mode == CTX_MODE_SYNC) + return key->sync_ctxid; + return key->async_ctxid; +} + +static int session_poll_region(struct wd_sched_ctx *sched_ctx, __u32 begin, + __u32 end, __u32 expect, __u32 *count) { __u32 poll_num = 0; __u32 i; @@ -155,7 +264,7 @@ static int session_poll_region(struct wd_sched_ctx *ctx, __u32 begin, * RR schedule, one time poll one package, * poll_num is always not more than one here. */ - ret = ctx->poll_func(i, 1, &poll_num); + ret = sched_ctx->poll_func(i, 1, &poll_num); if ((ret < 0) && (ret != -EAGAIN)) return ret; else if (ret == -EAGAIN) @@ -168,22 +277,22 @@ static int session_poll_region(struct wd_sched_ctx *ctx, __u32 begin, return 0; }
-static int session_poll_policy_rr(struct wd_sched_ctx *ctx, int numa_id, - __u32 expect, __u32 *count) +static int session_poll_policy_rr(struct wd_sched_ctx *sched_ctx, int numa_id, + __u32 expect, __u32 *count) { struct sched_ctx_region **region = - ctx->sched_info[numa_id].ctx_region; + sched_ctx->sched_info[numa_id].ctx_region; __u32 begin, end; __u32 i; int ret;
- for (i = 0; i < ctx->type_num; i++) { + for (i = 0; i < sched_ctx->type_num; i++) { if (!region[SCHED_MODE_ASYNC][i].valid) continue;
begin = region[SCHED_MODE_ASYNC][i].begin; end = region[SCHED_MODE_ASYNC][i].end; - ret = session_poll_region(ctx, begin, end, expect, + ret = session_poll_region(sched_ctx, begin, end, expect, count); if (unlikely(ret)) return ret; @@ -202,27 +311,26 @@ static int session_poll_policy_rr(struct wd_sched_ctx *ctx, int numa_id, * The user must init the schedule info through wd_sched_rr_instance, the * func interval will not check the valid, becouse it will affect performance. */ -static int session_sched_poll_policy(handle_t sched_ctx, - __u32 expect, __u32 *count) +static int session_sched_poll_policy_rr(handle_t h_sched_ctx, __u32 expect, __u32 *count) { - struct wd_sched_ctx *ctx = (struct wd_sched_ctx *)sched_ctx; + struct wd_sched_ctx *sched_ctx = (struct wd_sched_ctx *)h_sched_ctx; struct wd_sched_info *sched_info; __u32 loop_time = 0; __u32 last_count = 0; __u16 i; int ret;
- if (unlikely(!count || !ctx)) { + if (unlikely(!count || !sched_ctx)) { WD_ERR("invalid: sched ctx is NULL or count is zero!\n"); return -WD_EINVAL; }
- if (unlikely(ctx->numa_num > NUMA_NUM_NODES)) { - WD_ERR("invalid: ctx's numa number is %u!\n", ctx->numa_num); + if (unlikely(sched_ctx->numa_num > NUMA_NUM_NODES)) { + WD_ERR("invalid: ctx's numa number is %u!\n", sched_ctx->numa_num); return -WD_EINVAL; }
- sched_info = ctx->sched_info; + sched_info = sched_ctx->sched_info;
/* * Try different numa's ctx if we can't receive any @@ -230,7 +338,7 @@ static int session_sched_poll_policy(handle_t sched_ctx, * bad situation, poll ends after MAX_POLL_TIMES loop. */ while (++loop_time < MAX_POLL_TIMES) { - for (i = 0; i < ctx->numa_num;) { + for (i = 0; i < sched_ctx->numa_num;) { /* If current numa is not valid, find next. */ if (!sched_info[i].valid) { i++; @@ -238,7 +346,7 @@ static int session_sched_poll_policy(handle_t sched_ctx, }
last_count = *count; - ret = session_poll_policy_rr(ctx, i, expect, count); + ret = session_poll_policy_rr(sched_ctx, i, expect, count); if (unlikely(ret)) return ret;
@@ -257,130 +365,17 @@ static int session_sched_poll_policy(handle_t sched_ctx, return 0; }
-/** - * session_sched_init_ctx - Get one ctx from ctxs by the sched_ctx and arg. - * @sched_ctx: Schedule ctx, reference the struct sample_sched_ctx. - * @sched_key: The key of schedule region. - * @sched_mode: The sched async/sync mode. - * - * The user must init the schedule info through wd_sched_rr_instance - */ -static __u32 session_sched_init_ctx(handle_t sched_ctx, - void *sched_key, const int sched_mode) -{ - struct wd_sched_ctx *ctx = (struct wd_sched_ctx *)sched_ctx; - struct sched_key *key = (struct sched_key *)sched_key; - struct sched_ctx_region *region = NULL; - bool ret; - - if (!ctx || !key) { - WD_ERR("invalid: sched ctx or key is NULL!\n"); - return INVALID_POS; - } - - key->mode = sched_mode; - ret = sched_key_valid(ctx, key); - if (!ret) - return INVALID_POS; - - region = sched_get_ctx_range(ctx, key); - if (!region) - return INVALID_POS; - - return sched_get_next_pos_rr(region, NULL); -} - -static int get_nearby_numa_id(handle_t sched_ctx) -{ -#define MAX_NUMA_DISTANCE 1024 - struct wd_sched_ctx *ctx = (struct wd_sched_ctx *)sched_ctx; - struct wd_sched_info *sched_info = ctx->sched_info; - int cpu = sched_getcpu(); - int node = numa_node_of_cpu(cpu); - int dis = MAX_NUMA_DISTANCE; - int i, tmp, valid_id = -1; - - for (i = 0; i < ctx->numa_num; i++) { - if (sched_info[i].valid) { - tmp = numa_distance(node, i); - if (dis > tmp) { - valid_id = i; - dis = tmp; - } - } - } - - return valid_id; -} - -handle_t session_sched_init(handle_t h_sched_ctx, void *sched_param) -{ - struct sched_params *param = (struct sched_params *)sched_param; - struct sched_key *skey; - - skey = malloc(sizeof(struct sched_key)); - if (!skey) { - WD_ERR("failed to alloc memory for session sched key!\n"); - return (handle_t)(-WD_ENOMEM); - } - - if (!param || param->numa_id < 0) { - memset(skey, 0, sizeof(struct sched_key)); - skey->numa_id = get_nearby_numa_id(h_sched_ctx); - if (skey->numa_id < 0) { - WD_ERR("failed to get valid sched numa region!\n"); - free(skey); - return (handle_t)(-WD_ENOMEM); - } - } else { - skey->type = param->type; - skey->numa_id = param->numa_id; - } - - skey->sync_ctxid = session_sched_init_ctx(h_sched_ctx, - skey, CTX_MODE_SYNC); - skey->async_ctxid = session_sched_init_ctx(h_sched_ctx, - skey, CTX_MODE_ASYNC); - - return (handle_t)skey; -} - -/** - * session_pick_next_ctx - Get one ctx from ctxs by the sched_ctx and arg. - * @sched_ctx: Schedule ctx, reference the struct sample_sched_ctx. - * @sched_key: The key of schedule region. - * @sched_mode: The sched async/sync mode. - * - * The user must init the schedule info through session_sched_init - */ -static __u32 session_sched_pick_next_ctx(handle_t sched_ctx, - void *sched_key, const int sched_mode) -{ - struct sched_key *key = (struct sched_key *)sched_key; - - if (unlikely(!sched_ctx || !key)) { - WD_ERR("invalid: sched ctx or key is NULL!\n"); - return INVALID_POS; - } - - /* return in do task */ - if (sched_mode == CTX_MODE_SYNC) - return key->sync_ctxid; - return key->async_ctxid; -} - static struct wd_sched sched_table[SCHED_POLICY_BUTT] = { { .name = "RR scheduler", .sched_policy = SCHED_POLICY_RR, - .sched_init = session_sched_init, - .pick_next_ctx = session_sched_pick_next_ctx, - .poll_policy = session_sched_poll_policy, + .sched_init = session_sched_init_rr, + .pick_next_ctx = session_sched_pick_next_ctx_rr, + .poll_policy = session_sched_poll_policy_rr, }, };
-int wd_sched_rr_instance(const struct wd_sched *sched, - struct sched_params *param) +int wd_sched_rr_instance(const struct wd_sched *sched, struct sched_params *param) { struct wd_sched_info *sched_info = NULL; struct wd_sched_ctx *sched_ctx = NULL; @@ -501,8 +496,7 @@ struct wd_sched *wd_sched_rr_alloc(__u8 sched_type, __u8 type_num, return NULL;
if (sched_type >= SCHED_POLICY_BUTT || !type_num) { - WD_ERR("invalid: sched_type is %u or type_num is %u!\n", - sched_type, type_num); + WD_ERR("invalid: sched_type is %u or type_num is %u!\n", sched_type, type_num); return NULL; }
Since CPU and device are not one-to-one correspondence, need to build a map to show which device is the best choice when requests sent from a certain cpu.
Signed-off-by: Yang Shen shenyang39@huawei.com --- wd_sched.c | 68 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 24 deletions(-)
diff --git a/wd_sched.c b/wd_sched.c index bef5f74..65569e0 100644 --- a/wd_sched.c +++ b/wd_sched.c @@ -70,13 +70,15 @@ struct wd_sched_info { * @numa_num: the max numa numbers of the scheduler. * @type_num: the max operation types of the scheduler. * @poll_func: the task's poll operation function. - * @sched_info: the context of the scheduler + * @numamap: a map of cpus to devices. + * @sched_info: the context of the scheduler. */ struct wd_sched_ctx { __u32 policy; __u32 type_num; __u16 numa_num; user_poll_func poll_func; + int numamap[NUMA_NUM_NODES]; struct wd_sched_info sched_info[0]; };
@@ -174,32 +176,12 @@ static __u32 session_sched_init_ctx(handle_t h_sched_ctx, void *sched_key, const return sched_get_next_pos_rr(region, NULL); }
-static int get_nearby_numa_id(handle_t h_sched_ctx) +static handle_t session_sched_init_rr(handle_t h_sched_ctx, void *sched_param) { -#define MAX_NUMA_DISTANCE 1024 struct wd_sched_ctx *sched_ctx = (struct wd_sched_ctx *)h_sched_ctx; - struct wd_sched_info *sched_info = sched_ctx->sched_info; + struct sched_params *param = (struct sched_params *)sched_param; int cpu = sched_getcpu(); int node = numa_node_of_cpu(cpu); - int dis = MAX_NUMA_DISTANCE; - int i, tmp, valid_id = -1; - - for (i = 0; i < sched_ctx->numa_num; i++) { - if (sched_info[i].valid) { - tmp = numa_distance(node, i); - if (dis > tmp) { - valid_id = i; - dis = tmp; - } - } - } - - return valid_id; -} - -static handle_t session_sched_init_rr(handle_t h_sched_ctx, void *sched_param) -{ - struct sched_params *param = (struct sched_params *)sched_param; struct sched_key *skey;
skey = malloc(sizeof(struct sched_key)); @@ -210,7 +192,7 @@ static handle_t session_sched_init_rr(handle_t h_sched_ctx, void *sched_param)
if (!param || param->numa_id < 0) { memset(skey, 0, sizeof(struct sched_key)); - skey->numa_id = get_nearby_numa_id(h_sched_ctx); + skey->numa_id = sched_ctx->numamap[node]; if (skey->numa_id < 0) { WD_ERR("failed to get valid sched numa region!\n"); free(skey); @@ -375,6 +357,42 @@ static struct wd_sched sched_table[SCHED_POLICY_BUTT] = { }, };
+static int wd_sched_get_nearby_numa_id(struct wd_sched_info *sched_info, int node, int numa_num) +{ + int dis = INT32_MAX; + int valid_id = -1; + int i, tmp; + + for (i = 0; i < numa_num; i++) { + if (sched_info[i].valid) { + tmp = numa_distance(node, i); + if (dis > tmp) { + valid_id = i; + dis = tmp; + } + } + } + + return valid_id; +} + +static void wd_sched_map_cpus_to_dev(struct wd_sched_ctx *sched_ctx) +{ + struct wd_sched_info *sched_info = sched_ctx->sched_info; + int *numamap = sched_ctx->numamap; + int i; + + memset(numamap, -1, sizeof(*numamap) * NUMA_NUM_NODES); + + for (i = 0; i < sched_ctx->numa_num; i++) { + if (sched_info[i].valid) + numamap[i] = i; + else + numamap[i] = wd_sched_get_nearby_numa_id(sched_info, i, + sched_ctx->numa_num); + } +} + int wd_sched_rr_instance(const struct wd_sched *sched, struct sched_params *param) { struct wd_sched_info *sched_info = NULL; @@ -429,6 +447,8 @@ int wd_sched_rr_instance(const struct wd_sched *sched, struct sched_params *para sched_info[numa_id].ctx_region[mode][type].valid = true; sched_info[numa_id].valid = true;
+ wd_sched_map_cpus_to_dev(sched_ctx); + pthread_mutex_init(&sched_info[numa_id].ctx_region[mode][type].lock, NULL);
-- 2.24.0