blob: 5bc51f3635b9fb7878b760f1083ae28efcd70fbf [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
7#include "log_cache.h"
8
9#define LOG_CACHE_DBG 0
10
11#if LOG_CACHE_DBG
12#include <sys/printk.h>
13#define LOG_CACHE_PRINT(...) printk(__VA_ARGS__)
14#define LOG_CACHE_DBG_ENTRY(str, entry) \
15 printk(str " entry(%p) id %p\n", entry, (void *)entry->id)
16#else
17#define LOG_CACHE_PRINT(...)
18#define LOG_CACHE_DBG_ENTRY(...)
19#endif
20
21
22int log_cache_init(struct log_cache *cache, const struct log_cache_config *config)
23{
24 sys_slist_init(&cache->active);
25 sys_slist_init(&cache->idle);
26
27 size_t entry_size = ROUND_UP(sizeof(struct log_cache_entry) + config->item_size,
28 sizeof(uintptr_t));
29 uint32_t entry_cnt = config->buf_len / entry_size;
30 struct log_cache_entry *entry = config->buf;
31
32 /* Add all entries to idle list */
33 for (uint32_t i = 0; i < entry_cnt; i++) {
34 sys_slist_append(&cache->idle, &entry->node);
35 entry = (struct log_cache_entry *)((uintptr_t)entry + entry_size);
36 }
37
38 cache->cmp = config->cmp;
39 cache->item_size = config->item_size;
40 cache->hit = 0;
41 cache->miss = 0;
42
43 return 0;
44}
45
46bool log_cache_get(struct log_cache *cache, uintptr_t id, uint8_t **data)
47{
48 sys_snode_t *prev_node = NULL;
49 struct log_cache_entry *entry;
50 bool hit = false;
51
52 LOG_CACHE_PRINT("cache_get for id %lx\n", id);
53 SYS_SLIST_FOR_EACH_CONTAINER(&cache->active, entry, node) {
54 LOG_CACHE_DBG_ENTRY("checking", entry);
55 if (cache->cmp(entry->id, id)) {
56 cache->hit++;
57 hit = true;
58 break;
59 }
60
61 if (&entry->node == sys_slist_peek_tail(&cache->active)) {
62 break;
63 }
64 prev_node = &entry->node;
65 }
66
67 if (hit) {
68 LOG_CACHE_DBG_ENTRY("moving up", entry);
69 sys_slist_remove(&cache->active, prev_node, &entry->node);
70 sys_slist_prepend(&cache->active, &entry->node);
71 } else {
72 cache->miss++;
73
74 sys_snode_t *from_idle = sys_slist_get(&cache->idle);
75
76 if (from_idle) {
77 entry = CONTAINER_OF(from_idle, struct log_cache_entry, node);
78 } else {
79 LOG_CACHE_DBG_ENTRY("removing", entry);
80 sys_slist_remove(&cache->active, prev_node, &entry->node);
81 }
82 }
83
84 *data = entry->data;
85 entry->id = id;
86
87 return hit;
88}
89
90void log_cache_put(struct log_cache *cache, uint8_t *data)
91{
Fabio Baltieri56b42252023-08-28 18:53:02 +000092 struct log_cache_entry *entry = CONTAINER_OF(data, struct log_cache_entry, data[0]);
Krzysztof Chruscinski1b3a12c2021-07-21 12:59:14 +020093
94 LOG_CACHE_DBG_ENTRY("cache_put", entry);
95 sys_slist_prepend(&cache->active, &entry->node);
96}
97
98void log_cache_release(struct log_cache *cache, uint8_t *data)
99{
Fabio Baltieri56b42252023-08-28 18:53:02 +0000100 struct log_cache_entry *entry = CONTAINER_OF(data, struct log_cache_entry, data[0]);
Krzysztof Chruscinski1b3a12c2021-07-21 12:59:14 +0200101
102 LOG_CACHE_DBG_ENTRY("cache_release", entry);
103 sys_slist_prepend(&cache->idle, &entry->node);
104}