-
Notifications
You must be signed in to change notification settings - Fork 327
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Jyri Sarha
committed
Jan 6, 2025
1 parent
a95cabc
commit fe6b09a
Showing
4 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters