diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
commit | e6918187568dbd01842d8d1d2c808ce16a894239 (patch) | |
tree | 64f88b554b444a49f656b6c656111a145cbbaa28 /src/seastar/dpdk/lib/librte_jobstats | |
parent | Initial commit. (diff) | |
download | ceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip |
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/seastar/dpdk/lib/librte_jobstats')
-rw-r--r-- | src/seastar/dpdk/lib/librte_jobstats/Makefile | 23 | ||||
-rw-r--r-- | src/seastar/dpdk/lib/librte_jobstats/meson.build | 5 | ||||
-rw-r--r-- | src/seastar/dpdk/lib/librte_jobstats/rte_jobstats.c | 265 | ||||
-rw-r--r-- | src/seastar/dpdk/lib/librte_jobstats/rte_jobstats.h | 307 | ||||
-rw-r--r-- | src/seastar/dpdk/lib/librte_jobstats/rte_jobstats_version.map | 26 |
5 files changed, 626 insertions, 0 deletions
diff --git a/src/seastar/dpdk/lib/librte_jobstats/Makefile b/src/seastar/dpdk/lib/librte_jobstats/Makefile new file mode 100644 index 000000000..35e788f7f --- /dev/null +++ b/src/seastar/dpdk/lib/librte_jobstats/Makefile @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2015 Intel Corporation + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_jobstats.a + +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) +LDLIBS += -lrte_eal + +EXPORT_MAP := rte_jobstats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_JOBSTATS) := rte_jobstats.c + +# install this header file +SYMLINK-$(CONFIG_RTE_LIBRTE_JOBSTATS)-include := rte_jobstats.h + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/src/seastar/dpdk/lib/librte_jobstats/meson.build b/src/seastar/dpdk/lib/librte_jobstats/meson.build new file mode 100644 index 000000000..391e4f802 --- /dev/null +++ b/src/seastar/dpdk/lib/librte_jobstats/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017 Intel Corporation + +sources = files('rte_jobstats.c') +headers = files('rte_jobstats.h') diff --git a/src/seastar/dpdk/lib/librte_jobstats/rte_jobstats.c b/src/seastar/dpdk/lib/librte_jobstats/rte_jobstats.c new file mode 100644 index 000000000..9b8fde5d5 --- /dev/null +++ b/src/seastar/dpdk/lib/librte_jobstats/rte_jobstats.c @@ -0,0 +1,265 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2015 Intel Corporation + */ + +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +#include <rte_string_fns.h> +#include <rte_errno.h> +#include <rte_common.h> +#include <rte_eal.h> +#include <rte_log.h> +#include <rte_cycles.h> +#include <rte_branch_prediction.h> + +#include "rte_jobstats.h" + +#define ADD_TIME_MIN_MAX(obj, type, value) do { \ + typeof(value) tmp = (value); \ + (obj)->type ## _time += tmp; \ + if (tmp < (obj)->min_ ## type ## _time) \ + (obj)->min_ ## type ## _time = tmp; \ + if (tmp > (obj)->max_ ## type ## _time) \ + (obj)->max_ ## type ## _time = tmp; \ +} while (0) + +#define RESET_TIME_MIN_MAX(obj, type) do { \ + (obj)->type ## _time = 0; \ + (obj)->min_ ## type ## _time = UINT64_MAX; \ + (obj)->max_ ## type ## _time = 0; \ +} while (0) + +static inline uint64_t +get_time(void) +{ + rte_rmb(); + return rte_get_timer_cycles(); +} + +/* Those are steps used to adjust job period. + * Experiments show that for forwarding apps the up step must be less than down + * step to achieve optimal performance. + */ +#define JOB_UPDATE_STEP_UP 1 +#define JOB_UPDATE_STEP_DOWN 4 + +/* + * Default update function that implements simple period adjustment. + */ +static void +default_update_function(struct rte_jobstats *job, int64_t result) +{ + int64_t err = job->target - result; + + /* Job is happy. Nothing to do */ + if (err == 0) + return; + + if (err > 0) { + if (job->period + JOB_UPDATE_STEP_UP < job->max_period) + job->period += JOB_UPDATE_STEP_UP; + } else { + if (job->min_period + JOB_UPDATE_STEP_DOWN < job->period) + job->period -= JOB_UPDATE_STEP_DOWN; + } +} + +int +rte_jobstats_context_init(struct rte_jobstats_context *ctx) +{ + if (ctx == NULL) + return -EINVAL; + + /* Init only needed parameters. Zero out everything else. */ + memset(ctx, 0, sizeof(struct rte_jobstats_context)); + + rte_jobstats_context_reset(ctx); + + return 0; +} + +void +rte_jobstats_context_start(struct rte_jobstats_context *ctx) +{ + uint64_t now; + + ctx->loop_executed_jobs = 0; + + now = get_time(); + ADD_TIME_MIN_MAX(ctx, management, now - ctx->state_time); + ctx->state_time = now; +} + +void +rte_jobstats_context_finish(struct rte_jobstats_context *ctx) +{ + uint64_t now; + + if (likely(ctx->loop_executed_jobs)) + ctx->loop_cnt++; + + now = get_time(); + ADD_TIME_MIN_MAX(ctx, management, now - ctx->state_time); + ctx->state_time = now; +} + +void +rte_jobstats_context_reset(struct rte_jobstats_context *ctx) +{ + RESET_TIME_MIN_MAX(ctx, exec); + RESET_TIME_MIN_MAX(ctx, management); + ctx->start_time = get_time(); + ctx->state_time = ctx->start_time; + ctx->job_exec_cnt = 0; + ctx->loop_cnt = 0; +} + +void +rte_jobstats_set_target(struct rte_jobstats *job, int64_t target) +{ + job->target = target; +} + +int +rte_jobstats_start(struct rte_jobstats_context *ctx, struct rte_jobstats *job) +{ + uint64_t now; + + /* Some sanity check. */ + if (unlikely(ctx == NULL || job == NULL || job->context != NULL)) + return -EINVAL; + + /* Link job with context object. */ + job->context = ctx; + + now = get_time(); + ADD_TIME_MIN_MAX(ctx, management, now - ctx->state_time); + ctx->state_time = now; + + return 0; +} + +int +rte_jobstats_abort(struct rte_jobstats *job) +{ + struct rte_jobstats_context *ctx; + uint64_t now, exec_time; + + /* Some sanity check. */ + if (unlikely(job == NULL || job->context == NULL)) + return -EINVAL; + + ctx = job->context; + now = get_time(); + exec_time = now - ctx->state_time; + ADD_TIME_MIN_MAX(ctx, management, exec_time); + ctx->state_time = now; + job->context = NULL; + + return 0; +} + +int +rte_jobstats_finish(struct rte_jobstats *job, int64_t job_value) +{ + struct rte_jobstats_context *ctx; + uint64_t now, exec_time; + int need_update; + + /* Some sanity check. */ + if (unlikely(job == NULL || job->context == NULL)) + return -EINVAL; + + need_update = job->target != job_value; + /* Adjust period only if job is unhappy of its current period. */ + if (need_update) + (*job->update_period_cb)(job, job_value); + + ctx = job->context; + + /* Update execution time is considered as runtime so get time after it is + * executed. */ + now = get_time(); + exec_time = now - ctx->state_time; + ADD_TIME_MIN_MAX(job, exec, exec_time); + ADD_TIME_MIN_MAX(ctx, exec, exec_time); + + ctx->state_time = now; + + ctx->loop_executed_jobs++; + ctx->job_exec_cnt++; + + job->exec_cnt++; + job->context = NULL; + + return need_update; +} + +void +rte_jobstats_set_period(struct rte_jobstats *job, uint64_t period, + uint8_t saturate) +{ + if (saturate != 0) { + if (period < job->min_period) + period = job->min_period; + else if (period > job->max_period) + period = job->max_period; + } + + job->period = period; +} + +void +rte_jobstats_set_min(struct rte_jobstats *job, uint64_t period) +{ + job->min_period = period; + if (job->period < period) + job->period = period; +} + +void +rte_jobstats_set_max(struct rte_jobstats *job, uint64_t period) +{ + job->max_period = period; + if (job->period > period) + job->period = period; +} + +int +rte_jobstats_init(struct rte_jobstats *job, const char *name, + uint64_t min_period, uint64_t max_period, uint64_t initial_period, + int64_t target) +{ + if (job == NULL) + return -EINVAL; + + job->period = initial_period; + job->min_period = min_period; + job->max_period = max_period; + job->target = target; + job->update_period_cb = &default_update_function; + rte_jobstats_reset(job); + strlcpy(job->name, name == NULL ? "" : name, RTE_DIM(job->name)); + job->context = NULL; + + return 0; +} + +void +rte_jobstats_set_update_period_function(struct rte_jobstats *job, + rte_job_update_period_cb_t update_period_cb) +{ + if (update_period_cb == NULL) + update_period_cb = default_update_function; + + job->update_period_cb = update_period_cb; +} + +void +rte_jobstats_reset(struct rte_jobstats *job) +{ + RESET_TIME_MIN_MAX(job, exec); + job->exec_cnt = 0; +} diff --git a/src/seastar/dpdk/lib/librte_jobstats/rte_jobstats.h b/src/seastar/dpdk/lib/librte_jobstats/rte_jobstats.h new file mode 100644 index 000000000..023d9dd15 --- /dev/null +++ b/src/seastar/dpdk/lib/librte_jobstats/rte_jobstats.h @@ -0,0 +1,307 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2015 Intel Corporation + */ + +#ifndef JOBSTATS_H_ +#define JOBSTATS_H_ + +#include <stdint.h> + +#include <rte_memory.h> +#include <rte_memcpy.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define RTE_JOBSTATS_NAMESIZE 32 + +/* Forward declarations. */ +struct rte_jobstats_context; +struct rte_jobstats; + +/** + * This function should calculate new period and set it using + * rte_jobstats_set_period() function. Time spent in this function will be + * added to job's runtime. + * + * @param job + * The job data structure handler. + * @param job_result + * Result of calling job callback. + */ +typedef void (*rte_job_update_period_cb_t)(struct rte_jobstats *job, + int64_t job_result); + +struct rte_jobstats { + uint64_t period; + /**< Estimated period of execution. */ + + uint64_t min_period; + /**< Minimum period. */ + + uint64_t max_period; + /**< Maximum period. */ + + int64_t target; + /**< Desired value for this job. */ + + rte_job_update_period_cb_t update_period_cb; + /**< Period update callback. */ + + uint64_t exec_time; + /**< Total time (sum) that this job was executing. */ + + uint64_t min_exec_time; + /**< Minimum execute time. */ + + uint64_t max_exec_time; + /**< Maximum execute time. */ + + uint64_t exec_cnt; + /**< Execute count. */ + + char name[RTE_JOBSTATS_NAMESIZE]; + /**< Name of this job */ + + struct rte_jobstats_context *context; + /**< Job stats context object that is executing this job. */ +} __rte_cache_aligned; + +struct rte_jobstats_context { + /** Variable holding time at different points: + * -# loop start time if loop was started but no job executed yet. + * -# job start time if job is currently executing. + * -# job finish time if job finished its execution. + * -# loop finish time if loop finished its execution. */ + uint64_t state_time; + + uint64_t loop_executed_jobs; + /**< Count of executed jobs in this loop. */ + + /* Statistics start. */ + + uint64_t exec_time; + /**< Total time taken to execute jobs, not including management time. */ + + uint64_t min_exec_time; + /**< Minimum loop execute time. */ + + uint64_t max_exec_time; + /**< Maximum loop execute time. */ + + /** + * Sum of time that is not the execute time (ex: from job finish to next + * job start). + * + * This time might be considered as overhead of library + job scheduling. + */ + uint64_t management_time; + + uint64_t min_management_time; + /**< Minimum management time */ + + uint64_t max_management_time; + /**< Maximum management time */ + + uint64_t start_time; + /**< Time since last reset stats. */ + + uint64_t job_exec_cnt; + /**< Total count of executed jobs. */ + + uint64_t loop_cnt; + /**< Total count of executed loops with at least one executed job. */ +} __rte_cache_aligned; + +/** + * Initialize given context object with default values. + * + * @param ctx + * Job stats context object to initialize. + * + * @return + * 0 on success + * -EINVAL if *ctx* is NULL + */ +int +rte_jobstats_context_init(struct rte_jobstats_context *ctx); + +/** + * Mark that new set of jobs start executing. + * + * @param ctx + * Job stats context object. + */ +void +rte_jobstats_context_start(struct rte_jobstats_context *ctx); + +/** + * Mark that there is no more jobs ready to execute in this turn. Calculate + * stats for this loop turn. + * + * @param ctx + * Job stats context. + */ +void +rte_jobstats_context_finish(struct rte_jobstats_context *ctx); + +/** + * Function resets job context statistics. + * + * @param ctx + * Job stats context which statistics will be reset. + */ +void +rte_jobstats_context_reset(struct rte_jobstats_context *ctx); + +/** + * Initialize given job stats object. + * + * @param job + * Job object. + * @param name + * Optional job name. + * @param min_period + * Minimum period that this job can accept. + * @param max_period + * Maximum period that this job can accept. + * @param initial_period + * Initial period. It will be checked against *min_period* and *max_period*. + * @param target + * Target value that this job try to achieve. + * + * @return + * 0 on success + * -EINVAL if *job* is NULL + */ +int +rte_jobstats_init(struct rte_jobstats *job, const char *name, + uint64_t min_period, uint64_t max_period, uint64_t initial_period, + int64_t target); + +/** + * Set job desired target value. Difference between target and job value + * value must be used to properly adjust job execute period value. + * + * @param job + * The job object. + * @param target + * New target. + */ +void +rte_jobstats_set_target(struct rte_jobstats *job, int64_t target); + +/** + * Mark that *job* is starting of its execution in context of *ctx* object. + * + * @param ctx + * Job stats context. + * @param job + * Job object. + * @return + * 0 on success + * -EINVAL if *ctx* or *job* is NULL or *job* is executing in another context + * context already, + */ +int +rte_jobstats_start(struct rte_jobstats_context *ctx, struct rte_jobstats *job); + +/** + * Mark that *job* finished its execution, but time of this work will be skipped + * and added to management time. + * + * @param job + * Job object. + * + * @return + * 0 on success + * -EINVAL if job is NULL or job was not started (it have no context). + */ +int +rte_jobstats_abort(struct rte_jobstats *job); + +/** + * Mark that *job* finished its execution. Context in which it was executing + * will receive stat update. After this function call *job* object is ready to + * be executed in other context. + * + * @param job + * Job object. + * @param job_value + * Job value. Job should pass in this parameter a value that it try to optimize + * for example the number of packets it processed. + * + * @return + * 0 if job's period was not updated (job target equals *job_value*) + * 1 if job's period was updated + * -EINVAL if job is NULL or job was not started (it have no context). + */ +int +rte_jobstats_finish(struct rte_jobstats *job, int64_t job_value); + +/** + * Set execute period of given job. + * + * @param job + * The job object. + * @param period + * New period value. + * @param saturate + * If zero, skip period saturation to min, max range. + */ +void +rte_jobstats_set_period(struct rte_jobstats *job, uint64_t period, + uint8_t saturate); +/** + * Set minimum execute period of given job. Current period will be checked + * against new minimum value. + * + * @param job + * The job object. + * @param period + * New minimum period value. + */ +void +rte_jobstats_set_min(struct rte_jobstats *job, uint64_t period); +/** + * Set maximum execute period of given job. Current period will be checked + * against new maximum value. + * + * @param job + * The job object. + * @param period + * New maximum period value. + */ +void +rte_jobstats_set_max(struct rte_jobstats *job, uint64_t period); + +/** + * Set update period callback that is invoked after job finish. + * + * If application wants to do more sophisticated calculations than default + * it can provide this handler. + * + * @param job + * Job object. + * @param update_period_cb + * Callback to set. If NULL restore default update function. + */ +void +rte_jobstats_set_update_period_function(struct rte_jobstats *job, + rte_job_update_period_cb_t update_period_cb); + +/** + * Function resets job statistics. + * + * @param job + * Job which statistics will be reset. + */ +void +rte_jobstats_reset(struct rte_jobstats *job); + +#ifdef __cplusplus +} +#endif + +#endif /* JOBSTATS_H_ */ diff --git a/src/seastar/dpdk/lib/librte_jobstats/rte_jobstats_version.map b/src/seastar/dpdk/lib/librte_jobstats/rte_jobstats_version.map new file mode 100644 index 000000000..f89441438 --- /dev/null +++ b/src/seastar/dpdk/lib/librte_jobstats/rte_jobstats_version.map @@ -0,0 +1,26 @@ +DPDK_2.0 { + global: + + rte_jobstats_context_finish; + rte_jobstats_context_init; + rte_jobstats_context_reset; + rte_jobstats_context_start; + rte_jobstats_finish; + rte_jobstats_init; + rte_jobstats_reset; + rte_jobstats_set_max; + rte_jobstats_set_min; + rte_jobstats_set_period; + rte_jobstats_set_target; + rte_jobstats_set_update_period_function; + rte_jobstats_start; + + local: *; +}; + +DPDK_16.04 { + global: + + rte_jobstats_abort; + +} DPDK_2.0; |