mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-22 10:25:05 +08:00
score: Avoid Giant lock for CORE spinlock
Use an ISR lock to protect the spinlock state. Remove empty attributes. Update #2555.
This commit is contained in:
@@ -75,26 +75,19 @@ RTEMS_INLINE_ROUTINE void _POSIX_Spinlock_Free (
|
||||
_Objects_Free( &_POSIX_Spinlock_Information, &the_spinlock->Object );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a spinlock control block.
|
||||
*
|
||||
* This function maps spinlock IDs to spinlock control blocks.
|
||||
* If ID corresponds to a local spinlock, then it returns
|
||||
* the_spinlock control pointer which maps to ID and location
|
||||
* is set to OBJECTS_LOCAL. if the spinlock ID is global and
|
||||
* resides on a remote node, then location is set to OBJECTS_REMOTE,
|
||||
* and the_spinlock is undefined. Otherwise, location is set
|
||||
* to OBJECTS_ERROR and the_spinlock is undefined.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE POSIX_Spinlock_Control *_POSIX_Spinlock_Get (
|
||||
RTEMS_INLINE_ROUTINE POSIX_Spinlock_Control *_POSIX_Spinlock_Get(
|
||||
pthread_spinlock_t *spinlock,
|
||||
Objects_Locations *location
|
||||
ISR_lock_Context *lock_context
|
||||
)
|
||||
{
|
||||
return (POSIX_Spinlock_Control *) _Objects_Get(
|
||||
&_POSIX_Spinlock_Information,
|
||||
(Objects_Id) *spinlock,
|
||||
location
|
||||
if ( spinlock == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (POSIX_Spinlock_Control *) _Objects_Get_local(
|
||||
&_POSIX_Spinlock_Information,
|
||||
*spinlock,
|
||||
lock_context
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,58 +18,35 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/posix/spinlockimpl.h>
|
||||
|
||||
/**
|
||||
* This directive allows a thread to delete a spinlock specified by
|
||||
* the spinlock id. The spinlock is freed back to the inactive
|
||||
* spinlock chain.
|
||||
*
|
||||
* @param[in] spinlock is the spinlock id
|
||||
*
|
||||
* @return This method returns 0 if there was not an
|
||||
* error. Otherwise, a status code is returned indicating the
|
||||
* source of the error.
|
||||
*/
|
||||
int pthread_spin_destroy(
|
||||
pthread_spinlock_t *spinlock
|
||||
)
|
||||
{
|
||||
POSIX_Spinlock_Control *the_spinlock = NULL;
|
||||
Objects_Locations location;
|
||||
#include <errno.h>
|
||||
|
||||
if ( !spinlock )
|
||||
return EINVAL;
|
||||
int pthread_spin_destroy( pthread_spinlock_t *spinlock )
|
||||
{
|
||||
POSIX_Spinlock_Control *the_spinlock;
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
_Objects_Allocator_lock();
|
||||
the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
|
||||
switch ( location ) {
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
if ( _CORE_spinlock_Is_busy( &the_spinlock->Spinlock ) ) {
|
||||
_Objects_Put( &the_spinlock->Object );
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
_Objects_Close( &_POSIX_Spinlock_Information, &the_spinlock->Object );
|
||||
_Objects_Put( &the_spinlock->Object );
|
||||
_POSIX_Spinlock_Free( the_spinlock );
|
||||
_Objects_Allocator_unlock();
|
||||
|
||||
return 0;
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
case OBJECTS_REMOTE:
|
||||
#endif
|
||||
case OBJECTS_ERROR:
|
||||
break;
|
||||
the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
|
||||
if ( the_spinlock == NULL ) {
|
||||
_Objects_Allocator_unlock();
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
_Objects_Allocator_unlock();
|
||||
_CORE_spinlock_Acquire_critical( &the_spinlock->Spinlock, &lock_context );
|
||||
|
||||
return EINVAL;
|
||||
if ( _CORE_spinlock_Is_busy( &the_spinlock->Spinlock ) ) {
|
||||
_CORE_spinlock_Release( &the_spinlock->Spinlock, &lock_context );
|
||||
_Objects_Allocator_unlock();
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
_CORE_spinlock_Release( &the_spinlock->Spinlock, &lock_context );
|
||||
|
||||
_Objects_Close( &_POSIX_Spinlock_Information, &the_spinlock->Object );
|
||||
_POSIX_Spinlock_Free( the_spinlock );
|
||||
_Objects_Allocator_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@ int pthread_spin_init(
|
||||
)
|
||||
{
|
||||
POSIX_Spinlock_Control *the_spinlock;
|
||||
CORE_spinlock_Attributes attributes;
|
||||
|
||||
if ( !spinlock )
|
||||
return EINVAL;
|
||||
@@ -67,9 +66,7 @@ int pthread_spin_init(
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
_CORE_spinlock_Initialize_attributes( &attributes );
|
||||
|
||||
_CORE_spinlock_Initialize( &the_spinlock->Spinlock, &attributes );
|
||||
_CORE_spinlock_Initialize( &the_spinlock->Spinlock );
|
||||
|
||||
_Objects_Open_u32( &_POSIX_Spinlock_Information, &the_spinlock->Object, 0 );
|
||||
|
||||
|
||||
@@ -18,46 +18,26 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/posix/spinlockimpl.h>
|
||||
|
||||
/**
|
||||
* This directive allows a thread to wait at a spinlock.
|
||||
*
|
||||
* @param[in] spinlock is spinlock id
|
||||
*
|
||||
* @return This method returns 0 if there was not an
|
||||
* error. Otherwise, a status code is returned indicating the
|
||||
* source of the error.
|
||||
*/
|
||||
int pthread_spin_lock(
|
||||
pthread_spinlock_t *spinlock
|
||||
)
|
||||
#include <errno.h>
|
||||
|
||||
int pthread_spin_lock( pthread_spinlock_t *spinlock )
|
||||
{
|
||||
POSIX_Spinlock_Control *the_spinlock = NULL;
|
||||
Objects_Locations location;
|
||||
CORE_spinlock_Status status;
|
||||
POSIX_Spinlock_Control *the_spinlock;
|
||||
ISR_lock_Context lock_context;
|
||||
CORE_spinlock_Status status;
|
||||
|
||||
if ( !spinlock )
|
||||
the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
|
||||
if ( the_spinlock == NULL ) {
|
||||
return EINVAL;
|
||||
|
||||
the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
|
||||
switch ( location ) {
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
status = _CORE_spinlock_Wait( &the_spinlock->Spinlock, true, 0 );
|
||||
_Objects_Put( &the_spinlock->Object );
|
||||
return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
case OBJECTS_REMOTE:
|
||||
#endif
|
||||
case OBJECTS_ERROR:
|
||||
break;
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
status = _CORE_spinlock_Seize(
|
||||
&the_spinlock->Spinlock,
|
||||
true,
|
||||
0,
|
||||
&lock_context
|
||||
);
|
||||
return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
|
||||
}
|
||||
|
||||
@@ -18,50 +18,26 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/posix/spinlockimpl.h>
|
||||
|
||||
/*
|
||||
* pthread_spin_trylock
|
||||
*
|
||||
* This directive allows a thread to poll an attempt at locking a spinlock.
|
||||
*
|
||||
* Input parameters:
|
||||
* spinlock - spinlock id
|
||||
*
|
||||
* Output parameters:
|
||||
* 0 - if successful
|
||||
* error code - if unsuccessful
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
int pthread_spin_trylock(
|
||||
pthread_spinlock_t *spinlock
|
||||
)
|
||||
int pthread_spin_trylock( pthread_spinlock_t *spinlock )
|
||||
{
|
||||
POSIX_Spinlock_Control *the_spinlock = NULL;
|
||||
Objects_Locations location;
|
||||
CORE_spinlock_Status status;
|
||||
POSIX_Spinlock_Control *the_spinlock;
|
||||
ISR_lock_Context lock_context;
|
||||
CORE_spinlock_Status status;
|
||||
|
||||
if ( !spinlock )
|
||||
the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
|
||||
if ( the_spinlock == NULL ) {
|
||||
return EINVAL;
|
||||
|
||||
the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
|
||||
switch ( location ) {
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
status = _CORE_spinlock_Wait( &the_spinlock->Spinlock, false, 0 );
|
||||
_Objects_Put( &the_spinlock->Object );
|
||||
return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
case OBJECTS_REMOTE:
|
||||
#endif
|
||||
case OBJECTS_ERROR:
|
||||
break;
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
status = _CORE_spinlock_Seize(
|
||||
&the_spinlock->Spinlock,
|
||||
false,
|
||||
0,
|
||||
&lock_context
|
||||
);
|
||||
return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
|
||||
}
|
||||
|
||||
@@ -20,50 +20,21 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/posix/spinlockimpl.h>
|
||||
|
||||
/*
|
||||
* pthread_spin_unlock
|
||||
*
|
||||
* This directive allows a thread to wait at a spinlock.
|
||||
*
|
||||
* Input parameters:
|
||||
* spinlock - spinlock id
|
||||
*
|
||||
* Output parameters:
|
||||
* 0 - if successful
|
||||
* error code - if unsuccessful
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
int pthread_spin_unlock(
|
||||
pthread_spinlock_t *spinlock
|
||||
)
|
||||
int pthread_spin_unlock( pthread_spinlock_t *spinlock )
|
||||
{
|
||||
POSIX_Spinlock_Control *the_spinlock = NULL;
|
||||
Objects_Locations location;
|
||||
CORE_spinlock_Status status;
|
||||
POSIX_Spinlock_Control *the_spinlock;
|
||||
ISR_lock_Context lock_context;
|
||||
CORE_spinlock_Status status;
|
||||
|
||||
if ( !spinlock )
|
||||
the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
|
||||
if ( the_spinlock == NULL ) {
|
||||
return EINVAL;
|
||||
|
||||
the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
|
||||
switch ( location ) {
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
status = _CORE_spinlock_Release( &the_spinlock->Spinlock );
|
||||
_Objects_Put( &the_spinlock->Object );
|
||||
return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
case OBJECTS_REMOTE:
|
||||
#endif
|
||||
case OBJECTS_ERROR:
|
||||
break;
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
status = _CORE_spinlock_Surrender( &the_spinlock->Spinlock, &lock_context );
|
||||
return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ libscore_a_SOURCES += src/coresem.c
|
||||
|
||||
## CORE_SPINLOCK_C_FILES
|
||||
if HAS_PTHREADS
|
||||
libscore_a_SOURCES += src/corespinlock.c src/corespinlockrelease.c \
|
||||
libscore_a_SOURCES += src/corespinlockrelease.c \
|
||||
src/corespinlockwait.c
|
||||
endif
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
#ifndef _RTEMS_SCORE_CORESPINLOCK_H
|
||||
#define _RTEMS_SCORE_CORESPINLOCK_H
|
||||
|
||||
#include <rtems/score/object.h>
|
||||
#include <rtems/score/isrlock.h>
|
||||
#include <rtems/score/thread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -35,38 +36,35 @@ extern "C" {
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* The following defines the control block used to manage the
|
||||
* attributes of each spinlock.
|
||||
*/
|
||||
typedef struct {
|
||||
/** This element indicates XXX
|
||||
*/
|
||||
uint32_t XXX;
|
||||
} CORE_spinlock_Attributes;
|
||||
|
||||
/**
|
||||
* The following defines the control block used to manage each
|
||||
* spinlock.
|
||||
*/
|
||||
typedef struct {
|
||||
/** XXX may not be needed */
|
||||
CORE_spinlock_Attributes Attributes;
|
||||
/**
|
||||
* @brief Lock to protect the other fields.
|
||||
*
|
||||
* This implementation is a bit stupid. However, test cases in the Linux
|
||||
* Test Project do things like sleep() and printf() while owning a
|
||||
* pthread_spinlock_t, e.g.
|
||||
* testcases/open_posix_testsuite/conformance/interfaces/pthread_spin_lock/1-2.c
|
||||
*/
|
||||
ISR_LOCK_MEMBER( Lock )
|
||||
|
||||
/** This field is the lock.
|
||||
*/
|
||||
volatile uint32_t lock;
|
||||
uint32_t lock;
|
||||
|
||||
/** This field is a count of the current number of threads using
|
||||
* this spinlock. It includes the thread holding the lock as well
|
||||
* as those waiting.
|
||||
*/
|
||||
volatile uint32_t users;
|
||||
uint32_t users;
|
||||
|
||||
/** This field is the Id of the thread holding the lock. It may or may
|
||||
* not be the thread which acquired it.
|
||||
*/
|
||||
volatile Objects_Id holder;
|
||||
Thread_Control *holder;
|
||||
} CORE_spinlock_Control;
|
||||
|
||||
/**@}*/
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <rtems/score/corespinlock.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -78,12 +80,29 @@ typedef enum {
|
||||
* This routine initializes the spinlock based on the parameters passed.
|
||||
*
|
||||
* @param[in] the_spinlock is the spinlock control block to initialize
|
||||
* @param[in] the_spinlock_attributes define the behavior of this instance
|
||||
*/
|
||||
void _CORE_spinlock_Initialize(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
CORE_spinlock_Attributes *the_spinlock_attributes
|
||||
);
|
||||
RTEMS_INLINE_ROUTINE void _CORE_spinlock_Initialize(
|
||||
CORE_spinlock_Control *the_spinlock
|
||||
)
|
||||
{
|
||||
memset( the_spinlock, 0, sizeof( *the_spinlock ) );
|
||||
}
|
||||
|
||||
RTEMS_INLINE_ROUTINE void _CORE_spinlock_Acquire_critical(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
ISR_lock_Context *lock_context
|
||||
)
|
||||
{
|
||||
_ISR_lock_Acquire( &the_spinlock->Lock, lock_context );
|
||||
}
|
||||
|
||||
RTEMS_INLINE_ROUTINE void _CORE_spinlock_Release(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
ISR_lock_Context *lock_context
|
||||
)
|
||||
{
|
||||
_ISR_lock_Release_and_ISR_enable( &the_spinlock->Lock, lock_context );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for spinlock.
|
||||
@@ -100,10 +119,11 @@ void _CORE_spinlock_Initialize(
|
||||
* @retval A status is returned which indicates the success or failure of
|
||||
* this operation.
|
||||
*/
|
||||
CORE_spinlock_Status _CORE_spinlock_Wait(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
bool wait,
|
||||
Watchdog_Interval timeout
|
||||
CORE_spinlock_Status _CORE_spinlock_Seize(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
bool wait,
|
||||
Watchdog_Interval timeout,
|
||||
ISR_lock_Context *lock_context
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -114,22 +134,11 @@ CORE_spinlock_Status _CORE_spinlock_Wait(
|
||||
*
|
||||
* @param[in] the_spinlock is the spinlock to surrender
|
||||
*/
|
||||
CORE_spinlock_Status _CORE_spinlock_Release(
|
||||
CORE_spinlock_Control *the_spinlock
|
||||
CORE_spinlock_Status _CORE_spinlock_Surrender(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
ISR_lock_Context *lock_context
|
||||
);
|
||||
|
||||
/**
|
||||
* This method is used to initialize core spinlock attributes.
|
||||
*
|
||||
* @param[in] the_attributes pointer to the attributes to initialize.
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void _CORE_spinlock_Initialize_attributes(
|
||||
CORE_spinlock_Attributes *the_attributes
|
||||
)
|
||||
{
|
||||
the_attributes->XXX = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to determine if the spinlock is available or not.
|
||||
*
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Initialize a Spinlock
|
||||
*
|
||||
* @ingroup ScoreSpinlock
|
||||
*/
|
||||
|
||||
/*
|
||||
* COPYRIGHT (c) 1989-2006.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/corespinlockimpl.h>
|
||||
#include <rtems/score/thread.h>
|
||||
|
||||
void _CORE_spinlock_Initialize(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
CORE_spinlock_Attributes *the_spinlock_attributes
|
||||
)
|
||||
{
|
||||
|
||||
the_spinlock->Attributes = *the_spinlock_attributes;
|
||||
|
||||
the_spinlock->lock = 0;
|
||||
the_spinlock->users = 0;
|
||||
the_spinlock->holder = 0;
|
||||
}
|
||||
@@ -20,30 +20,27 @@
|
||||
|
||||
#include <rtems/score/corespinlockimpl.h>
|
||||
#include <rtems/score/percpu.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
|
||||
CORE_spinlock_Status _CORE_spinlock_Release(
|
||||
CORE_spinlock_Control *the_spinlock
|
||||
CORE_spinlock_Status _CORE_spinlock_Surrender(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
ISR_lock_Context *lock_context
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
|
||||
_ISR_Disable( level );
|
||||
_CORE_spinlock_Acquire_critical( the_spinlock, lock_context );
|
||||
|
||||
/*
|
||||
* It must locked before it can be unlocked.
|
||||
*/
|
||||
if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) {
|
||||
_ISR_Enable( level );
|
||||
_CORE_spinlock_Release( the_spinlock, lock_context );
|
||||
return CORE_SPINLOCK_NOT_LOCKED;
|
||||
}
|
||||
|
||||
/*
|
||||
* It must locked by the current thread before it can be unlocked.
|
||||
*/
|
||||
if ( the_spinlock->holder != _Thread_Executing->Object.id ) {
|
||||
_ISR_Enable( level );
|
||||
if ( the_spinlock->holder != _Thread_Executing ) {
|
||||
_CORE_spinlock_Release( the_spinlock, lock_context );
|
||||
return CORE_SPINLOCK_NOT_HOLDER;
|
||||
}
|
||||
|
||||
@@ -54,6 +51,6 @@ CORE_spinlock_Status _CORE_spinlock_Release(
|
||||
the_spinlock->lock = CORE_SPINLOCK_UNLOCKED;
|
||||
the_spinlock->holder = 0;
|
||||
|
||||
_ISR_Enable( level );
|
||||
_CORE_spinlock_Release( the_spinlock, lock_context );
|
||||
return CORE_SPINLOCK_SUCCESSFUL;
|
||||
}
|
||||
|
||||
@@ -18,48 +18,36 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/corespinlockimpl.h>
|
||||
#include <rtems/score/thread.h>
|
||||
#include <rtems/score/threaddispatch.h>
|
||||
#include <rtems/score/percpu.h>
|
||||
|
||||
/*
|
||||
* _CORE_spinlock_Wait
|
||||
*
|
||||
* This function waits for the spinlock to become available. Optionally,
|
||||
* a limit may be placed on the duration of the spin.
|
||||
*
|
||||
* Input parameters:
|
||||
* the_spinlock - the spinlock control block to initialize
|
||||
* wait - true if willing to wait
|
||||
* timeout - the maximum number of ticks to spin (0 is forever)
|
||||
*
|
||||
* Output parameters: NONE
|
||||
*/
|
||||
|
||||
CORE_spinlock_Status _CORE_spinlock_Wait(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
bool wait,
|
||||
Watchdog_Interval timeout
|
||||
CORE_spinlock_Status _CORE_spinlock_Seize(
|
||||
CORE_spinlock_Control *the_spinlock,
|
||||
bool wait,
|
||||
Watchdog_Interval timeout,
|
||||
ISR_lock_Context *lock_context
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
Thread_Control *executing;
|
||||
|
||||
#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
|
||||
Watchdog_Interval limit = _Watchdog_Ticks_since_boot + timeout;
|
||||
#endif
|
||||
|
||||
_ISR_Disable( level );
|
||||
if ( (the_spinlock->lock == CORE_SPINLOCK_LOCKED) &&
|
||||
(the_spinlock->holder == _Thread_Executing->Object.id) ) {
|
||||
_ISR_Enable( level );
|
||||
executing = _Thread_Executing;
|
||||
|
||||
_CORE_spinlock_Acquire_critical( the_spinlock, lock_context );
|
||||
if ( the_spinlock->lock == CORE_SPINLOCK_LOCKED &&
|
||||
the_spinlock->holder == executing ) {
|
||||
_CORE_spinlock_Release( the_spinlock, lock_context );
|
||||
return CORE_SPINLOCK_HOLDER_RELOCKING;
|
||||
}
|
||||
the_spinlock->users += 1;
|
||||
for ( ;; ) {
|
||||
if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) {
|
||||
the_spinlock->lock = CORE_SPINLOCK_LOCKED;
|
||||
the_spinlock->holder = _Thread_Executing->Object.id;
|
||||
_ISR_Enable( level );
|
||||
the_spinlock->holder = executing;
|
||||
_CORE_spinlock_Release( the_spinlock, lock_context );
|
||||
return CORE_SPINLOCK_SUCCESSFUL;
|
||||
}
|
||||
|
||||
@@ -68,7 +56,7 @@ CORE_spinlock_Status _CORE_spinlock_Wait(
|
||||
*/
|
||||
if ( !wait ) {
|
||||
the_spinlock->users -= 1;
|
||||
_ISR_Enable( level );
|
||||
_CORE_spinlock_Release( the_spinlock, lock_context );
|
||||
return CORE_SPINLOCK_UNAVAILABLE;
|
||||
}
|
||||
|
||||
@@ -78,7 +66,7 @@ CORE_spinlock_Status _CORE_spinlock_Wait(
|
||||
*/
|
||||
if ( timeout && (limit <= _Watchdog_Ticks_since_boot) ) {
|
||||
the_spinlock->users -= 1;
|
||||
_ISR_Enable( level );
|
||||
_CORE_spinlock_Release( the_spinlock, lock_context );
|
||||
return CORE_SPINLOCK_TIMEOUT;
|
||||
}
|
||||
#endif
|
||||
@@ -100,16 +88,15 @@ CORE_spinlock_Status _CORE_spinlock_Wait(
|
||||
* safe from deletion.
|
||||
*/
|
||||
|
||||
_ISR_Enable( level );
|
||||
/* An ISR could occur here */
|
||||
_CORE_spinlock_Release( the_spinlock, lock_context );
|
||||
|
||||
_Thread_Enable_dispatch();
|
||||
/* Another thread could get dispatched here */
|
||||
/*
|
||||
* An ISR could occur here. Another thread could get dispatched here.
|
||||
* Reenter the critical sections so we can attempt the lock again.
|
||||
*/
|
||||
|
||||
/* Reenter the critical sections so we can attempt the lock again. */
|
||||
_Thread_Disable_dispatch();
|
||||
|
||||
_ISR_Disable( level );
|
||||
_ISR_lock_ISR_disable( lock_context );
|
||||
_CORE_spinlock_Acquire_critical( the_spinlock, lock_context );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user