Files
linux-nvgpu/nvsched/src/logging.c
Konsta Hölttä bfd7fc8649 nvsched: Initial core data
Add software scheduler and domain data structures for a general
scheduler and bookkeeping code to create, remove and list them and to
keep logs for debugging and development; as a first step, this will only
serve as the heart of nvgpu-internal domain scheduler.

Long term, this code is intended to work in arbitrary configurations -
running on GSP, CPU, or elsewhere, and controlling the GPU or something
else.

Jira NVGPU-6427

Change-Id: I2a1577fa9120bb8ae6b9552dd2a187cb2cdfe504
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Signed-off-by: Konsta Hölttä <kholtta@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2632286
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2021-12-07 07:06:49 -08:00

132 lines
3.3 KiB
C

/*
* Copyright (c) 2021 NVIDIA Corporation. All rights reserved.
*
* NVIDIA Corporation and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA Corporation is strictly prohibited.
*/
#include <nvs/log.h>
#include <nvs/sched.h>
#include <nvs/impl-internal.h>
#define LOG_INC(value, max) \
do { \
(value) += 1U; \
if ((value) >= (max)) { \
(value) = 0U; \
} \
} while (false)
static bool nvs_log_full(struct nvs_log_buffer *logger)
{
u32 updated_put = logger->put;
LOG_INC(updated_put, logger->entries);
/*
* If the next put is the same as get, then put has caught up to get,
* and the log is therefore full.
*/
return updated_put == logger->get;
}
int nvs_log_init(struct nvs_sched *sched)
{
struct nvs_log_buffer *logger;
logger = nvs_malloc(sched, sizeof(*logger));
if (logger == NULL) {
return -ENOMEM;
}
nvs_memset(logger, 0, sizeof(*logger));
logger->ts_offset = nvs_timestamp();
logger->entries = NVS_LOG_ENTRIES;
logger->events = nvs_malloc(sched,
NVS_LOG_ENTRIES * sizeof(*logger->events));
if (logger->events == NULL) {
nvs_free(sched, logger);
return -ENOMEM;
}
nvs_memset(logger->events, 0,
NVS_LOG_ENTRIES * sizeof(*logger->events));
sched->log = logger;
return 0;
}
void nvs_log_destroy(struct nvs_sched *sched)
{
nvs_free(sched, sched->log->events);
nvs_free(sched, sched->log);
sched->log = NULL;
}
void nvs_log_event(struct nvs_sched *sched, enum nvs_event event, u32 data)
{
struct nvs_log_buffer *logger = sched->log;
struct nvs_log_event *ev;
nvs_log(sched, "ev: %d", event);
nvs_log(sched, " Starting: G=%05u P=%05u", logger->get, logger->put);
/*
* If the log fills, just consume the oldest entry like with nvs_log_get().
*
* TODO: insert a "log overrun" entry, too, so readers will know.
*/
if (nvs_log_full(logger)) {
nvs_log(sched, "Log full; killing entry.");
LOG_INC(logger->get, logger->entries);
}
ev = &logger->events[logger->put];
ev->data = data;
ev->event = event;
ev->timestamp = nvs_timestamp() - logger->ts_offset;
LOG_INC(logger->put, logger->entries);
nvs_log(sched, " New: G=%05u P=%05u", logger->get, logger->put);
}
void nvs_log_get(struct nvs_sched *sched, struct nvs_log_event *ev)
{
struct nvs_log_buffer *logger = sched->log;
nvs_log(sched, "Getting log event.");
nvs_log(sched, " Starting: G=%05u P=%05u", logger->get, logger->put);
/*
* Check if the log is empty; if so, clear *ev to signal that.
*/
if (logger->get == logger->put) {
ev->event = NVS_EV_NO_EVENT;
nvs_log(sched, " Log empty!");
return;
}
*ev = logger->events[logger->get];
LOG_INC(logger->get, logger->entries);
nvs_log(sched, " New: G=%05u P=%05u", logger->get, logger->put);
}
const char *nvs_log_event_string(enum nvs_event ev)
{
switch (ev) {
case NVS_EV_NO_EVENT: return "No event";
case NVS_EV_CREATE_SCHED: return "Create scheduler";
case NVS_EV_CREATE_DOMAIN: return "Create domain";
case NVS_EV_REMOVE_DOMAIN: return "Remove domain";
case NVS_EV_MAX: return "Invalid MAX event";
}
return "Undefined event";
}