blob: 4899a3435d960205e0550cd6b2018bf358fe719a [file] [log] [blame]
Krzysztof Chruscinski1b3a12c2021-07-21 12:59:14 +02001/*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
Jordan Yatesaf515ef2024-05-04 14:58:43 +10007#include <errno.h>
8
Krzysztof Chruscinski1b3a12c2021-07-21 12:59:14 +02009#include "log_cache.h"
10
11#define LOG_CACHE_DBG 0
12
13#if LOG_CACHE_DBG
14#include <sys/printk.h>
15#define LOG_CACHE_PRINT(...) printk(__VA_ARGS__)
16#define LOG_CACHE_DBG_ENTRY(str, entry) \
17 printk(str " entry(%p) id %p\n", entry, (void *)entry->id)
18#else
19#define LOG_CACHE_PRINT(...)
20#define LOG_CACHE_DBG_ENTRY(...)
21#endif
22
23
24int log_cache_init(struct log_cache *cache, const struct log_cache_config *config)
25{
26 sys_slist_init(&cache->active);
27 sys_slist_init(&cache->idle);
28
29 size_t entry_size = ROUND_UP(sizeof(struct log_cache_entry) + config->item_size,
30 sizeof(uintptr_t));
31 uint32_t entry_cnt = config->buf_len / entry_size;
32 struct log_cache_entry *entry = config->buf;
33
Jordan Yatesaf515ef2024-05-04 14:58:43 +100034 /* Ensure the cache has at least one entry */
35 if (entry_cnt == 0) {
36 return -EINVAL;
37 }
38
Krzysztof Chruscinski1b3a12c2021-07-21 12:59:14 +020039 /* Add all entries to idle list */
40 for (uint32_t i = 0; i < entry_cnt; i++) {
41 sys_slist_append(&cache->idle, &entry->node);
42 entry = (struct log_cache_entry *)((uintptr_t)entry + entry_size);
43 }
44
45 cache->cmp = config->cmp;
46 cache->item_size = config->item_size;
47 cache->hit = 0;
48 cache->miss = 0;
49
50 return 0;
51}
52
53bool log_cache_get(struct log_cache *cache, uintptr_t id, uint8_t **data)
54{
55 sys_snode_t *prev_node = NULL;
56 struct log_cache_entry *entry;
57 bool hit = false;
58
59 LOG_CACHE_PRINT("cache_get for id %lx\n", id);
60 SYS_SLIST_FOR_EACH_CONTAINER(&cache->active, entry, node) {
61 LOG_CACHE_DBG_ENTRY("checking", entry);
62 if (cache->cmp(entry->id, id)) {
63 cache->hit++;
64 hit = true;
65 break;
66 }
67
68 if (&entry->node == sys_slist_peek_tail(&cache->active)) {
69 break;
70 }
71 prev_node = &entry->node;
72 }
73
74 if (hit) {
75 LOG_CACHE_DBG_ENTRY("moving up", entry);
76 sys_slist_remove(&cache->active, prev_node, &entry->node);
77 sys_slist_prepend(&cache->active, &entry->node);
78 } else {
79 cache->miss++;
80
81 sys_snode_t *from_idle = sys_slist_get(&cache->idle);
82
83 if (from_idle) {
84 entry = CONTAINER_OF(from_idle, struct log_cache_entry, node);
85 } else {
86 LOG_CACHE_DBG_ENTRY("removing", entry);
87 sys_slist_remove(&cache->active, prev_node, &entry->node);
88 }
89 }
90
91 *data = entry->data;
92 entry->id = id;
93
94 return hit;
95}
96
97void log_cache_put(struct log_cache *cache, uint8_t *data)
98{
Fabio Baltieri56b42252023-08-28 18:53:02 +000099 struct log_cache_entry *entry = CONTAINER_OF(data, struct log_cache_entry, data[0]);
Krzysztof Chruscinski1b3a12c2021-07-21 12:59:14 +0200100
101 LOG_CACHE_DBG_ENTRY("cache_put", entry);
102 sys_slist_prepend(&cache->active, &entry->node);
103}
104
105void log_cache_release(struct log_cache *cache, uint8_t *data)
106{
Fabio Baltieri56b42252023-08-28 18:53:02 +0000107 struct log_cache_entry *entry = CONTAINER_OF(data, struct log_cache_entry, data[0]);
Krzysztof Chruscinski1b3a12c2021-07-21 12:59:14 +0200108
109 LOG_CACHE_DBG_ENTRY("cache_release", entry);
110 sys_slist_prepend(&cache->idle, &entry->node);
111}