Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2021 Nordic Semiconductor ASA
3 : : *
4 : : * SPDX-License-Identifier: Apache-2.0
5 : : */
6 : :
7 : : #include <errno.h>
8 : :
9 : : #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 : :
24 : 0 : int log_cache_init(struct log_cache *cache, const struct log_cache_config *config)
25 : : {
26 : 0 : sys_slist_init(&cache->active);
27 : 0 : sys_slist_init(&cache->idle);
28 : :
29 : 0 : size_t entry_size = ROUND_UP(sizeof(struct log_cache_entry) + config->item_size,
30 : : sizeof(uintptr_t));
31 : 0 : uint32_t entry_cnt = config->buf_len / entry_size;
32 : 0 : struct log_cache_entry *entry = config->buf;
33 : :
34 : : /* Ensure the cache has at least one entry */
35 [ # # ]: 0 : if (entry_cnt == 0) {
36 : : return -EINVAL;
37 : : }
38 : :
39 : : /* Add all entries to idle list */
40 [ # # ]: 0 : for (uint32_t i = 0; i < entry_cnt; i++) {
41 : 0 : sys_slist_append(&cache->idle, &entry->node);
42 : 0 : entry = (struct log_cache_entry *)((uintptr_t)entry + entry_size);
43 : : }
44 : :
45 : 0 : cache->cmp = config->cmp;
46 : 0 : cache->item_size = config->item_size;
47 : 0 : cache->hit = 0;
48 : 0 : cache->miss = 0;
49 : :
50 : 0 : return 0;
51 : : }
52 : :
53 : 0 : bool log_cache_get(struct log_cache *cache, uintptr_t id, uint8_t **data)
54 : : {
55 : 0 : sys_snode_t *prev_node = NULL;
56 : 0 : struct log_cache_entry *entry;
57 : 0 : bool hit = false;
58 : :
59 : 0 : LOG_CACHE_PRINT("cache_get for id %lx\n", id);
60 [ # # # # ]: 0 : SYS_SLIST_FOR_EACH_CONTAINER(&cache->active, entry, node) {
61 : 0 : LOG_CACHE_DBG_ENTRY("checking", entry);
62 [ # # ]: 0 : if (cache->cmp(entry->id, id)) {
63 : 0 : cache->hit++;
64 : 0 : hit = true;
65 : 0 : break;
66 : : }
67 : :
68 [ # # ]: 0 : if (&entry->node == sys_slist_peek_tail(&cache->active)) {
69 : : break;
70 : : }
71 [ # # ]: 0 : prev_node = &entry->node;
72 : : }
73 : :
74 : 0 : if (hit) {
75 : 0 : LOG_CACHE_DBG_ENTRY("moving up", entry);
76 : 0 : sys_slist_remove(&cache->active, prev_node, &entry->node);
77 : 0 : sys_slist_prepend(&cache->active, &entry->node);
78 : : } else {
79 : 0 : cache->miss++;
80 : :
81 : 0 : sys_snode_t *from_idle = sys_slist_get(&cache->idle);
82 : :
83 [ # # ]: 0 : if (from_idle) {
84 : : entry = CONTAINER_OF(from_idle, struct log_cache_entry, node);
85 : : } else {
86 : 0 : LOG_CACHE_DBG_ENTRY("removing", entry);
87 : 0 : sys_slist_remove(&cache->active, prev_node, &entry->node);
88 : : }
89 : : }
90 : :
91 : 0 : *data = entry->data;
92 : 0 : entry->id = id;
93 : :
94 : 0 : return hit;
95 : : }
96 : :
97 : 0 : void log_cache_put(struct log_cache *cache, uint8_t *data)
98 : : {
99 : 0 : struct log_cache_entry *entry = CONTAINER_OF(data, struct log_cache_entry, data[0]);
100 : :
101 : 0 : LOG_CACHE_DBG_ENTRY("cache_put", entry);
102 : 0 : sys_slist_prepend(&cache->active, &entry->node);
103 : 0 : }
104 : :
105 : 0 : void log_cache_release(struct log_cache *cache, uint8_t *data)
106 : : {
107 : 0 : struct log_cache_entry *entry = CONTAINER_OF(data, struct log_cache_entry, data[0]);
108 : :
109 : 0 : LOG_CACHE_DBG_ENTRY("cache_release", entry);
110 : 0 : sys_slist_prepend(&cache->idle, &entry->node);
111 : 0 : }
|