Skip to content

Commit

Permalink
lib: fast-get: Implement fast_get() and fast_put() functions
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jyri Sarha committed Jan 6, 2025
1 parent a95cabc commit fe6b09a
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 0 deletions.
11 changes: 11 additions & 0 deletions Kconfig.sof
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,17 @@ config COMPILER_INLINE_FUNCTION_OPTION
help
When enabled, -fno-inline-function option is not passed to compiler

config FAST_GET
bool "Enable simple refcounting dram data copier"
default n
help
Enable simple refcounting DRAM data copier for copying processing
module data from DRAM to SRAM when the data is needed and freeing
the SRAM when the data is not needed anymore. If multiple module
instances need the same chunk the same copy is used with reference
counting. Source is src/lib/gast-get.c. The option should be selected
by the modules using it.

rsource "src/Kconfig"

# See zephyr/modules/Kconfig
Expand Down
16 changes: 16 additions & 0 deletions src/include/sof/lib/fast-get.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2024 Intel Corporation. All rights reserved.
*
* Author: Jyri Sarha <jyri.sarha@linux.intel.com>
*/

#ifndef __SOF_LIB_FAST_GET_H__
#define __SOF_LIB_FAST_GET_H__

#include <stddef.h>

void *fast_get(const void * const dram_ptr, size_t size);
void fast_put(void *sram_ptr);

#endif /* __SOF_LIB_FAST_GET_H__ */
171 changes: 171 additions & 0 deletions src/lib/fast-get.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2024 Intel Corporation. All rights reserved.
//
// Author: Jyri Sarha <jyri.sarha@linux.intel.com>

#include <stdbool.h>
#include <stdint.h>
#include <errno.h>

#include <sof/lib/fast-get.h>
#include <rtos/spinlock.h>
#include <rtos/alloc.h>
#include <ipc/topology.h>

/* for cmocka environment */
#ifndef EXPORT_SYMBOL
#define EXPORT_SYMBOL(a)
#endif

struct sof_fast_get_entry {
const void *dram_ptr;
void *sram_ptr;
size_t size;
uint32_t refcount;
};

struct sof_fast_get_data {
struct k_spinlock lock;
size_t num_entries;
struct sof_fast_get_entry *entries;
};

static struct sof_fast_get_data fast_get_data = {
.num_entries = 0,
.entries = NULL,
};

LOG_MODULE_REGISTER(fast_get, CONFIG_SOF_LOG_LEVEL);

static inline
int fast_get_realloc(struct sof_fast_get_data *data)
{
struct sof_fast_get_entry *entries;

if (!data->num_entries) {
data->entries = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
32 * sizeof(*entries));
if (!data->entries)
return -ENOMEM;
data->num_entries = 32;
return 0;
}

entries = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
2 * data->num_entries * sizeof(*entries));
if (!entries)
return -ENOMEM;

memcpy_s(entries, 2 * data->num_entries * sizeof(*entries), data->entries,
data->num_entries * sizeof(*entries));
rfree(data->entries);
data->entries = entries;
data->num_entries = 2 * data->num_entries;
return 0;
}

static inline
struct sof_fast_get_entry *fast_get_find_entry(struct sof_fast_get_data *data,
const void *dram_ptr)
{
int i;

for (i = 0; i < data->num_entries; i++) {
if (data->entries[i].dram_ptr == dram_ptr)
return &data->entries[i];
}

for (i = 0; i < data->num_entries; i++) {
if (data->entries[i].dram_ptr == NULL)
return &data->entries[i];
}

return NULL;
}

void *fast_get(const void *dram_ptr, size_t size)
{
struct sof_fast_get_data *data = &fast_get_data;
struct sof_fast_get_entry *entry;
k_spinlock_key_t key;
void *ret;

key = k_spin_lock(&data->lock);
do {
entry = fast_get_find_entry(data, dram_ptr);
if (!entry) {
if (fast_get_realloc(data)) {
ret = NULL;
goto out;
}
}
} while (!entry);

if (entry->sram_ptr) {
if (entry->size != size || entry->dram_ptr != dram_ptr) {
tr_err(fast_get, "size %u != %u or ptr %p != %p mismatch",
entry->size, size, entry->dram_ptr, dram_ptr);
ret = NULL;
goto out;
}

ret = entry->sram_ptr;
entry->refcount++;
goto out;
}

ret = rmalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, size);
if (!ret)
goto out;
entry->size = size;
entry->sram_ptr = ret;
memcpy_s(entry->sram_ptr, entry->size, dram_ptr, size);
entry->dram_ptr = dram_ptr;
entry->refcount = 1;
out:
k_spin_unlock(&data->lock, key);
tr_dbg(fast_get, "get %p, %p, size %u, refcnt %u", dram_ptr, ret, size,
entry ? entry->refcount : 0);

return ret;
}
EXPORT_SYMBOL(fast_get);

static inline
struct sof_fast_get_entry *fast_put_find_entry(struct sof_fast_get_data *data,
void *sram_ptr)
{
int i;

for (i = 0; i < data->num_entries; i++) {
if (data->entries[i].sram_ptr == sram_ptr)
return &data->entries[i];
}

return NULL;
}

void fast_put(void *sram_ptr)
{
struct sof_fast_get_data *data = &fast_get_data;
struct sof_fast_get_entry *entry;
k_spinlock_key_t key;

key = k_spin_lock(&fast_get_data.lock);
entry = fast_put_find_entry(data, sram_ptr);
if (!entry) {
tr_err(fast_get, "Put called to unknown address %p", sram_ptr);
goto out;
}
entry->refcount--;
if (entry->refcount > 0)
goto out;
rfree(entry->sram_ptr);
memset(entry, 0, sizeof(*entry));
out:
tr_dbg(fast_get, "put %p, dram %p size %u refcnt %u", sram_ptr, entry ? entry->dram_ptr : 0,
entry ? entry->size : 0, entry ? entry->refcount : 0);
k_spin_unlock(&data->lock, key);
}
EXPORT_SYMBOL(fast_put);
2 changes: 2 additions & 0 deletions zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,8 @@ zephyr_library_sources_ifdef(CONFIG_TRACE
zephyr_library_sources_ifdef(CONFIG_LOG_BACKEND_SOF_PROBE
${SOF_SRC_PATH}/logging/log_backend_probe.c)

zephyr_library_sources_ifdef(CONFIG_FAST_GET ${SOF_SRC_PATH}/lib/fast-get.c)

# Optional SOF sources - depends on Kconfig - WIP

if(CONFIG_IPC_MAJOR_3)
Expand Down

0 comments on commit fe6b09a

Please sign in to comment.