Skip to content

Commit 8a595c2

Browse files
Jyri Sarhalyakh
authored andcommitted
lib: fast-get: Implement fast_get() and fast_put() functions
Implement fast_get() and fast_put() functions. The purpose of these functions is to maintain shared SRAM copies of data stored in DRAM. fast_get() First checks if there is already an SRAM copy of the same DRAM chunk. If there isn't reserve an SRAM chunk of the same size and copy the contents there, store the both pointers, size and reference count to in an internal data structure, and return the SRAM pointer. If there is, return the pointer to the existing SRAM copy and increase the reference count. fast_put() Look up the internal data record based on the SRAM address and decrement reference count. Free the SRAM chunk and the data record if reference count reaches zero, Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
1 parent 5c5069e commit 8a595c2

File tree

7 files changed

+196
-0
lines changed

7 files changed

+196
-0
lines changed

Kconfig.sof

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ config COLD_STORE_EXECUTE_DRAM
130130
option to enable this feature to save SRAM and to speed up SRAM
131131
copying of performance-critical data and code.
132132

133+
config FAST_GET
134+
bool "Enable simple refcounting DRAM data copier"
135+
default n
136+
help
137+
Enable simple refcounting DRAM data copier for copying processing
138+
module data from DRAM to SRAM when the data is needed and freeing
139+
the SRAM when the data is not needed anymore. If multiple module
140+
instances need the same chunk the same copy is used with reference
141+
counting. Source is src/lib/fast-get.c. The option should be selected
142+
on platforms, where __cold_rodata is supported.
143+
133144
rsource "src/Kconfig"
134145

135146
# See zephyr/modules/Kconfig

app/boards/intel_adsp_ace15_mtpm.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ CONFIG_PCM_CONVERTER_FORMAT_S24_C32_AND_S24_C24=y
2626
CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S16_C32=y
2727
CONFIG_PIPELINE_2_0=y
2828
CONFIG_SAMPLE_KEYPHRASE=y
29+
CONFIG_FAST_GET=y
2930

3031
# SOF / audio modules / mocks
3132
# This mock is part of official sof-bin releases because the CI that

app/boards/intel_adsp_ace20_lnl.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ CONFIG_PCM_CONVERTER_FORMAT_S24_C32_AND_S24_C24=y
2222
CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S16_C32=y
2323
CONFIG_PIPELINE_2_0=y
2424
CONFIG_SAMPLE_KEYPHRASE=y
25+
CONFIG_FAST_GET=y
2526

2627
# SOF / infrastructure
2728
CONFIG_AMS=y

app/boards/intel_adsp_ace30_ptl.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ CONFIG_PCM_CONVERTER_FORMAT_S24_C32_AND_S24_C24=y
2525
CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S16_C32=y
2626
CONFIG_PCM_CONVERTER_FORMAT_U8=y
2727
CONFIG_PIPELINE_2_0=y
28+
CONFIG_FAST_GET=y
2829

2930
# SOF / infrastructure
3031
CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n

src/include/sof/lib/fast-get.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* SPDX-License-Identifier: BSD-3-Clause
2+
*
3+
* Copyright(c) 2024 Intel Corporation. All rights reserved.
4+
*
5+
* Author: Jyri Sarha <jyri.sarha@linux.intel.com>
6+
*/
7+
8+
#ifndef __SOF_LIB_FAST_GET_H__
9+
#define __SOF_LIB_FAST_GET_H__
10+
11+
#include <stddef.h>
12+
13+
const void *fast_get(const void * const dram_ptr, size_t size);
14+
void fast_put(const void *sram_ptr);
15+
16+
#endif /* __SOF_LIB_FAST_GET_H__ */

zephyr/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,8 @@ zephyr_library_sources_ifdef(CONFIG_TRACE
637637
zephyr_library_sources_ifdef(CONFIG_LOG_BACKEND_SOF_PROBE
638638
${SOF_SRC_PATH}/logging/log_backend_probe.c)
639639

640+
zephyr_library_sources_ifdef(CONFIG_FAST_GET lib/fast-get.c)
641+
640642
# Optional SOF sources - depends on Kconfig - WIP
641643

642644
if(CONFIG_IPC_MAJOR_3)

zephyr/lib/fast-get.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//
3+
// Copyright(c) 2024 Intel Corporation. All rights reserved.
4+
//
5+
// Author: Jyri Sarha <jyri.sarha@linux.intel.com>
6+
7+
#include <stdbool.h>
8+
#include <stdint.h>
9+
#include <errno.h>
10+
11+
#include <sof/lib/fast-get.h>
12+
#include <rtos/alloc.h>
13+
#include <rtos/spinlock.h>
14+
#include <rtos/symbol.h>
15+
#include <ipc/topology.h>
16+
17+
struct sof_fast_get_entry {
18+
const void *dram_ptr;
19+
void *sram_ptr;
20+
size_t size;
21+
unsigned int refcount;
22+
};
23+
24+
struct sof_fast_get_data {
25+
struct k_spinlock lock;
26+
size_t num_entries;
27+
struct sof_fast_get_entry *entries;
28+
};
29+
30+
static struct sof_fast_get_data fast_get_data = {
31+
.num_entries = 0,
32+
.entries = NULL,
33+
};
34+
35+
LOG_MODULE_REGISTER(fast_get, CONFIG_SOF_LOG_LEVEL);
36+
37+
static int fast_get_realloc(struct sof_fast_get_data *data)
38+
{
39+
struct sof_fast_get_entry *entries;
40+
41+
if (!data->num_entries) {
42+
data->entries = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
43+
32 * sizeof(*entries));
44+
if (!data->entries)
45+
return -ENOMEM;
46+
data->num_entries = 32;
47+
return 0;
48+
}
49+
50+
entries = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
51+
2 * data->num_entries * sizeof(*entries));
52+
if (!entries)
53+
return -ENOMEM;
54+
55+
memcpy_s(entries, 2 * data->num_entries * sizeof(*entries), data->entries,
56+
data->num_entries * sizeof(*entries));
57+
rfree(data->entries);
58+
data->entries = entries;
59+
data->num_entries = 2 * data->num_entries;
60+
return 0;
61+
}
62+
63+
static struct sof_fast_get_entry *fast_get_find_entry(struct sof_fast_get_data *data,
64+
const void *dram_ptr)
65+
{
66+
int i;
67+
68+
for (i = 0; i < data->num_entries; i++) {
69+
if (data->entries[i].dram_ptr == dram_ptr)
70+
return &data->entries[i];
71+
}
72+
73+
for (i = 0; i < data->num_entries; i++) {
74+
if (data->entries[i].dram_ptr == NULL)
75+
return &data->entries[i];
76+
}
77+
78+
return NULL;
79+
}
80+
81+
const void *fast_get(const void *dram_ptr, size_t size)
82+
{
83+
struct sof_fast_get_data *data = &fast_get_data;
84+
struct sof_fast_get_entry *entry;
85+
k_spinlock_key_t key;
86+
void *ret;
87+
88+
key = k_spin_lock(&data->lock);
89+
do {
90+
entry = fast_get_find_entry(data, dram_ptr);
91+
if (!entry) {
92+
if (fast_get_realloc(data)) {
93+
ret = NULL;
94+
goto out;
95+
}
96+
}
97+
} while (!entry);
98+
99+
if (entry->sram_ptr) {
100+
if (entry->size != size || entry->dram_ptr != dram_ptr) {
101+
tr_err(fast_get, "size %u != %u or ptr %p != %p mismatch",
102+
entry->size, size, entry->dram_ptr, dram_ptr);
103+
ret = NULL;
104+
goto out;
105+
}
106+
107+
ret = entry->sram_ptr;
108+
entry->refcount++;
109+
goto out;
110+
}
111+
112+
ret = rmalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, size);
113+
if (!ret)
114+
goto out;
115+
entry->size = size;
116+
entry->sram_ptr = ret;
117+
memcpy_s(entry->sram_ptr, entry->size, dram_ptr, size);
118+
entry->dram_ptr = dram_ptr;
119+
entry->refcount = 1;
120+
out:
121+
k_spin_unlock(&data->lock, key);
122+
tr_dbg(fast_get, "get %p, %p, size %u, refcnt %u", dram_ptr, ret, size,
123+
entry ? entry->refcount : 0);
124+
125+
return ret;
126+
}
127+
EXPORT_SYMBOL(fast_get);
128+
129+
static struct sof_fast_get_entry *fast_put_find_entry(struct sof_fast_get_data *data,
130+
const void *sram_ptr)
131+
{
132+
int i;
133+
134+
for (i = 0; i < data->num_entries; i++) {
135+
if (data->entries[i].sram_ptr == sram_ptr)
136+
return &data->entries[i];
137+
}
138+
139+
return NULL;
140+
}
141+
142+
void fast_put(const void *sram_ptr)
143+
{
144+
struct sof_fast_get_data *data = &fast_get_data;
145+
struct sof_fast_get_entry *entry;
146+
k_spinlock_key_t key;
147+
148+
key = k_spin_lock(&fast_get_data.lock);
149+
entry = fast_put_find_entry(data, sram_ptr);
150+
if (!entry) {
151+
tr_err(fast_get, "Put called to unknown address %p", sram_ptr);
152+
goto out;
153+
}
154+
entry->refcount--;
155+
if (entry->refcount > 0)
156+
goto out;
157+
rfree(entry->sram_ptr);
158+
memset(entry, 0, sizeof(*entry));
159+
out:
160+
tr_dbg(fast_get, "put %p, DRAM %p size %u refcnt %u", sram_ptr, entry ? entry->dram_ptr : 0,
161+
entry ? entry->size : 0, entry ? entry->refcount : 0);
162+
k_spin_unlock(&data->lock, key);
163+
}
164+
EXPORT_SYMBOL(fast_put);

0 commit comments

Comments
 (0)