Skip to content

Commit

Permalink
arch: arc: add support for lock/unlock VPX
Browse files Browse the repository at this point in the history
Adds support for cooperative locking/unlocking the VPX vector registers.
Provided that all VPX enabled threads use these routines to control
access to the VPX vector registers, it will allow multiple threads to
safely use them without the need for saving/restoring them upon each
context switch.

Signed-off-by: Peter Mitsis <[email protected]>
  • Loading branch information
peter-mitsis committed Sep 10, 2024
1 parent cf6e7b8 commit a5b52d7
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 1 deletion.
10 changes: 10 additions & 0 deletions arch/arc/core/dsp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,14 @@ config ARC_AGU_LARGE
Save and restore large AGU registers, including 12 address pointers regs,
8 address offset regs and 24 modifiers regs.

config ARC_VPX_COOPERATIVE_SHARING
bool "Cooperative sharing of ARC VPX vector registers"
depends on ARC_DSP
select SCHED_CPU_MASK if MP_MAX_NUM_CPUS > 1
help
This option enables the cooperative sharing of the ARC VPX vector
registers. Threads that want to use those registers must successfully
call arc_vpx_lock() before using them, and call arc_vpx_unlock()
when done using them.

endmenu
44 changes: 43 additions & 1 deletion arch/arc/core/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@
#include <zephyr/arch/arc/v2/mpu/arc_core_mpu.h>
#endif

#if defined(CONFIG_ARC_DSP) && defined(CONFIG_DSP_SHARING)
#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING) || defined(CONFIG_DSP_SHARING)
#include <zephyr/arch/arc/v2/dsp/arc_dsp.h>
static struct k_spinlock lock;

#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING)
static struct k_sem vpx_sem[CONFIG_MP_MAX_NUM_CPUS];
#endif
#endif

/* initial stack frame */
struct init_stack_frame {
uintptr_t pc;
Expand Down Expand Up @@ -320,3 +325,40 @@ void arc_dsp_enable(struct k_thread *thread, unsigned int options)
k_spin_unlock(&lock, key);
}
#endif /* CONFIG_ARC_DSP && CONFIG_DSP_SHARING */

#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING)
int arc_vpx_lock(unsigned int *id, k_timeout_t timeout)
{
k_spinlock_key_t key;

__ASSERT(id != NULL, "");

key = k_spin_lock(&lock);

*id = _current_cpu->id;
#if (CONFIG_MP_MAX_NUM_CPUS > 1) && defined(CONFIG_SCHED_CPU_MASK)
__ASSERT(arch_is_in_isr() || (_current->base.cpu_mask == BIT(*id)), "");
#endif
k_spin_unlock(&lock, key);

return k_sem_take(&vpx_sem[*id], timeout);
}

void arc_vpx_unlock(unsigned int id)
{
__ASSERT((id >= 0) && (id < CONFIG_MP_MAX_NUM_CPUS), "");

k_sem_give(&vpx_sem[id]);
}

static int arc_vpx_sem_init(void)
{
for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) {
k_sem_init(vpx_sem, 1, 1);
}

return 0;
}

SYS_INIT(arc_vpx_sem_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
#endif
20 changes: 20 additions & 0 deletions doc/hardware/arch/arc-support-status.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,23 @@ Notes
.. [#f6] currently only ARC VPX scalar port is supported. The support of VPX vector pipeline, VCCM,
STU is not included in this port, and require additional development and / or other runtime
integration.
VPX Vector Registers
--------------------
Zephyr supports a limited form sharing of the VPX vector registers known as
cooperative sharing. Threads (or ISRs) that use these registers must bookend
the relevant sections with calls to :c:func:`arc_vpx_lock` and
:c_func:`arc_vpx_unlock` to control access to this resource.

.. note::
If the system has multiple CPUs, then it is the responsibility of the
application developer to both pin the thread to a single CPU before it
attempts to get the cooperative lock, and not modify the CPU affinity
while it is waiting for or holding that cooperative lock.

Configuration Options
=====================

The cooperative sharing of the VPX vector registers is selected when
configuration option :kconfig:option:`CONFIG_ARC_VPX_COOPERATIVE_SHARING`
is enabled.
32 changes: 32 additions & 0 deletions include/zephyr/arch/arc/v2/dsp/arc_dsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,36 @@ void arc_dsp_disable(struct k_thread *thread, unsigned int options);
*/
void arc_dsp_enable(struct k_thread *thread, unsigned int options);

/**
* @brief Obtain a cooperative lock on the VPX vector registers
*
* This function is used to obtain a cooperative lock on the current CPU's
* VPX vector registers before the calling thread or ISR uses them. Callers
* attempting to obtain the cooperative lock must be already restricted to
* executing on a single CPU, and continue to execute on that same CPU while
* both waiting and holding the lock.
*
* @note @a timeout must be set to K_NO_WAIT if called from an ISR.
*
* @param id Pointer to memory at which to store the ID of the cooperative
* lock on success
* @param timeout Waiting period to obtain the lock, or one of the special
* values K_NO_WAIT and K_FOREVER.
*
* @return Zero on success, otherwise error code
*/
int arc_vpx_lock(unsigned int *id, k_timeout_t timeout);

/**
* @brief Release cooperative lock on the VPX vector registers
*
* This function is used to release the cooperative lock on the CPU's VPX
* vector registers. It is called after the current thread (or ISR) no
* longer needs to use the VPX vector registers, thereby allowing another
* thread (or ISR) to use them.
*
* @param id ID of the lock obtained from arc_vpx_lock()
*/
void arc_vpx_unlock(unsigned int id);

#endif /* ZEPHYR_INCLUDE_ARCH_ARC_V2_DSP_ARC_DSP_H_ */

0 comments on commit a5b52d7

Please sign in to comment.