Spinlock

Spinlocks are one of the synchronization primitives that are implemented in CosmOS. A spinlock is designed to grant exclusive access to shared resources to a specific schedulable (task/thread). The spinlock locking mechanism can be used in task/threads within the operating system. In CosmOS, we implemented two ways of obtaining a spinlock. One way is the non-spinning method and does not cause spinning in the loop waiting for spinlock release in case of not successful locking of the spinlock. In case of unsuccessful locking of the spinlock, the other way will wait in a loop until the spinlock is unlocked again. The spinlock implementation also provides additional protection against a deadlock. For more information please read the spinlock section in the Whitepaper.

Configuration

1. Open the CustomBox

Then we have to open from the left panel Spinlock tab to see all configured spinlock elements in the system as it is shown in the picture below.

../../../_images/spinlock.png

2. Configure or add new spinlock

  • Name of the spinlock is set to spinlock_test_0, this is the name of the spinlock which will be used to generate spinlock identifier used in the spinlock get, try and release operations.

3. Generate

After we click on the Generate button in the CustomBox left panel on the bottom, the spinlock configuration code is generated and we can use it in the application layer. The code examples of spinlock usage are shown in the next section.

Code examples

Spinlock get and release

Click to see function spinlock_getSpinlock details
CosmOS_SpinlockStateType spinlock_getSpinlock(BitWidthType spinlockId)

Get spinlock. DEMO.

The implementation contains obtaining of the operating system and core configuration by calling functions os_getOsCfg and CILcore_getCoreCfg. Then the operating system configuration in function os_getOsNumberOfSpinlocks to get number of spinlocks. The input element id argument is then checked againts the number of spinlock, if it is greater than number of spinlocks SPINLOCK_STATE_ENUM__ERROR_INVALID_ID is returned. Spinlock variable is then obtained based on the id argument by the function os_getOsSpinlockVar. The function spinlock_willCauseDeadlock is called to check if the spinlock would cause eventually deadlock, if yes the spinlock state SPINLOCK_STATE_ENUM__ERROR_DEADLOCK is returned. Otherwise the function cosmosApiInternal_spinlock_getSpinlockInternal is called if the core is in the privileged mode or spinlock_getSpinlockInternal is called to get spinlock and result is then returned as spinlock state. The schedulable owner member in spinlock variable is set to the schedulable in execution.

Parameters

spinlockId[in] spinlock identifier

Returns

CosmOS_SpinlockStateType

Click to see function spinlock_releaseSpinlock details
CosmOS_SpinlockStateType spinlock_releaseSpinlock(BitWidthType spinlockId)

Release spinlock. DEMO.

The implementation contains obtaining of the operating system and core configuration by calling functions os_getOsCfg and CILcore_getCoreCfg. Then the operating system configuration in function os_getOsNumberOfSpinlocks to get number of spinlocks. The input element id argument is then checked againts the number of spinlock, if it is greater than number of spinlocks SPINLOCK_STATE_ENUM__ERROR_INVALID_ID is returned. Spinlock variable is then obtained based on the id argument by the function os_getOsSpinlockVar. The the boolean is obtained by calling function spinlock_ownsSchedulableSpinlock to know if the requesting schedulable owns the spinlock which means if the schedulable locked the spinlock before. The spinlock member of the spinlock variable structure is compared in the implemented if condition that checks if the spinlock is equal to the state SPINLOCK_STATE_ENUM__OCCUPIED otherwise the spinlock state is returned with the value SPINLOCK_STATE_ENUM__ERROR_NOT_IN_OCCUPIED_STATE. Another nested if condition is implemented to check the obtained boolean variable that stores value if the requesting schedulable owns the spinlock. If yes the cosmosApiInternal_spinlock_releaseSpinlockInternal function is called if the core is in the privileged mode or spinlock_releaseSpinlockInternal is called and the result is returned as spinlock state. Otherwise the spinlock state is SPINLOCK_STATE_ENUM__ERROR_SCHEDULABLE_IS_NOT_OWNER.

Parameters

spinlockId[in] spinlock identifier

Returns

CosmOS_SpinlockStateType

#include <spinlock.h>
#include <errorHandler.h>

CosmOS_SpinlockStateType spinlockState;

spinlockState = spinlock_getSpinlock( spinlock_test_0_id );
if( errorHandler_isError( spinlockState ) )
{
    //error was returned, check its value
}

//Critical code section (safe in inter-program synchronization)

spinlockState = spinlock_releaseSpinlock( spinlock_test_0_id );
if( errorHandler_isError( spinlockState ) )
{
    //error was returned, check its value
}
Click to see return values
enum CosmOS_SpinlockStateType

CosmOS_SpinlockStateType enum.

Values:

enumerator SPINLOCK_STATE_ENUM__RELEASED
enumerator SPINLOCK_STATE_ENUM__OCCUPIED
enumerator SPINLOCK_STATE_ENUM__SUCCESSFULLY_LOCKED
enumerator SPINLOCK_STATE_ENUM__ERROR_SCHEDULABLE_IS_NOT_OWNER
enumerator SPINLOCK_STATE_ENUM__ERROR_NOT_IN_OCCUPIED_STATE
enumerator SPINLOCK_STATE_ENUM__ERROR_INVALID_ID
enumerator SPINLOCK_STATE_ENUM__ERROR_DEADLOCK
enumerator SPINLOCK_STATE_ENUM__MAKE_ENUM_BITWIDTH_SIZE

Spinlock try and release

To try spinlock, the function spinlock_trySpinlock() was implemented.

CosmOS_SpinlockStateType spinlock_trySpinlock(BitWidthType spinlockId)

To get spinlock, the function spinlock_getSpinlock() was implemented.

CosmOS_SpinlockStateType spinlock_getSpinlock(BitWidthType spinlockId)

To release spinlock, the function spinlock_releaseSpinlock() was implemented.

CosmOS_SpinlockStateType spinlock_releaseSpinlock(BitWidthType spinlockId)
#include <spinlock.h>
#include <errorHandler.h>

CosmOS_SpinlockStateType spinlockState;

spinlockState = spinlock_trySpinlock( spinlock_test_0_id );
if ( spinlockState IS_EQUAL_TO SPINLOCK_STATE_ENUM__SUCCESSFULLY_LOCKED )
{

    //Critical code section (safe in inter-program synchronization)

    spinlockState = spinlock_releaseSpinlock( spinlock_test_0_id );
}
else
{
    if( errorHandler_isError( spinlockState ) )
    {
        //error was returned, check its value
    }
}