libparanut
A Hardware Abstraction Layer for ParaNut Architectures.
Classes
Spinlock Module

Functions and structure used for synchronizing memory access. More...

Collaboration diagram for Spinlock Module:

Classes

struct  __pn_spinlock
 A synchronization primitive. Use _pn_spinlock instead of this. More...
 
int pn_spinlock_init (_pn_spinlock *spinlock)
 Creates a lock. More...
 
int pn_spinlock_lock (_pn_spinlock *spinlock)
 Waits for a lock. Forever, if it must. Use with caution. More...
 
int pn_spinlock_trylock (_pn_spinlock *spinlock)
 Tries to acquire a lock. Nonblocking. More...
 
int pn_spinlock_unlock (_pn_spinlock *spinlock)
 Unlocks a lock. More...
 
int pn_spinlock_destroy (_pn_spinlock *spinlock)
 Destroys a lock. More...
 

Detailed Description

Functions and structure used for synchronizing memory access.

Warning
The functions in here are really kinda performance critical, since it is always important to do as little as possible when you have reserved a memory area. This means that the functions will do extremly little security checks, which means you have to use them the way they are described. Read the detailed descriptions of the functions carefully. Or don't. I'm not the coding police.
Using the spinlock functions in linked Mode (see Link Module and Modes) results in undefined behaviour.
If you want to use the Spinlock Module on RISC-V ParaNut, your ParaNut has to support the A Extension and you have to compile your application with the flag mabi=rv32ia. The libparanut Makefile sets this flag automatically when you chose the Spinlock Module or one of the Modules that has Spinlock Module as a dependency.

Return value of functions is always error code, except when stated otherwise in the description of the function.

Function Documentation

◆ pn_spinlock_destroy()

int pn_spinlock_destroy ( _pn_spinlock spinlock)

Destroys a lock.

Behaviour of this function is undefined if the lock wasn't initialized by pn_spinlock_init().

A destroyed lock can be re-initialized by using pn_spinlock_init().

The lock can either be owned by current hart or unlocked, else the function will fail.

Parameters
spinlockis a pointer to a lock that we want to destroy. The function will return PN_ERR_PARAM if NULL is passed.
Returns
Either PN_SUCCESS, PN_ERR_LOCKOCC or PN_ERR_PARAM. If something internally went very wrong, the function is also theoretically able to return PN_ERR_NOIMP.

◆ pn_spinlock_init()

int pn_spinlock_init ( _pn_spinlock spinlock)

Creates a lock.

You allocate the space for the spinlock. Really don't care where you get it from (check __pn_spinlock for a recommendation). You pass a reference to this function, and the function initializes it for you. And you shall never touch what's in it.

Afterwards, you can use the other functions in this module on the same lock. Behaviour will always be undefined if you don't call this function first.

The function does not care if your lock was already initialized. It will fail if the CPU did not get the memory reservation (PN_ERR_LOCKOCC), which should never happen. This is a very good indicator that something is very wrong with your program.

After initialization, the lock is free. It will not be automatically owned by the hart that initialized it.

Parameters
spinlockis a pointer to the lock. The function will return PN_ERR_PARAM if NULL is passed.
Returns
Either PN_SUCCESS, PN_ERR_PARAM, or PN_ERR_LOCKOCC. If something internally went very wrong, the function is also theoretically able to return PN_ERR_NOIMP.

◆ pn_spinlock_lock()

int pn_spinlock_lock ( _pn_spinlock spinlock)

Waits for a lock. Forever, if it must. Use with caution.

Behaviour of this function is undefined if the lock wasn't initialized by pn_spinlock_init().

Warning
The function will be stuck in eternity if the lock is already in the current harts posession, or if someone else owns the lock and forgot to unlock it, or if the lock was destroyed.
Parameters
spinlockis a pointer to a lock that we want to aquire. The function will return PN_ERR_PARAM if NULL is passed.
Returns
Either PN_SUCCESS or PN_ERR_PARAM.

◆ pn_spinlock_trylock()

int pn_spinlock_trylock ( _pn_spinlock spinlock)

Tries to acquire a lock. Nonblocking.

Behaviour of this function is undefined if the lock wasn't initialized by pn_spinlock_init().

Will fail if lock is already owned (no matter by whom), another CPU got the memory reservation, or if lock was destroyed.

Parameters
spinlockis a pointer to a lock that we want to aquire. The function will return PN_ERR_PARAM if NULL is passed.
Returns
Either PN_SUCCESS, PN_ERR_LOCKOCC or PN_ERR_PARAM. If something internally went very wrong, the function is also theoretically able to return PN_ERR_NOIMP.

◆ pn_spinlock_unlock()

int pn_spinlock_unlock ( _pn_spinlock spinlock)

Unlocks a lock.

Behaviour of this function is undefined if the lock wasn't initialized by pn_spinlock_init().

Will fail is lock is not owned by current hart (PN_ERR_PARAM).

Parameters
spinlockis a pointer to a lock that we want to unlock. The function will return PN_ERR_PARAM if NULL is passed.
Returns
Either PN_SUCCESS or PN_ERR_PARAM. If something internally went very wrong, the function is also theoretically able to return PN_ERR_NOIMP.