mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-22 12:29:17 +08:00
@@ -376,7 +376,7 @@ rtems_bsdnet_semaphore_obtain (void)
|
||||
rtems_panic ("rtems-net: network sema obtain: network not initialised\n");
|
||||
_Thread_queue_Context_initialize(&queue_context);
|
||||
_ISR_lock_ISR_disable(&queue_context.Lock_context.Lock_context);
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
status = _CORE_recursive_mutex_Seize (
|
||||
&the_networkSemaphore->Core_control.Mutex.Recursive,
|
||||
CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS,
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <rtems/posix/mqueue.h>
|
||||
#include <rtems/posix/posixapi.h>
|
||||
#include <rtems/score/coremsgimpl.h>
|
||||
#include <rtems/score/threadqimpl.h>
|
||||
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
@@ -63,12 +64,12 @@ void _POSIX_Message_queue_Delete(
|
||||
* @note This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open time.
|
||||
*/
|
||||
ssize_t _POSIX_Message_queue_Receive_support(
|
||||
mqd_t mqdes,
|
||||
char *msg_ptr,
|
||||
size_t msg_len,
|
||||
unsigned int *msg_prio,
|
||||
bool wait,
|
||||
Watchdog_Interval timeout
|
||||
mqd_t mqdes,
|
||||
char *msg_ptr,
|
||||
size_t msg_len,
|
||||
unsigned int *msg_prio,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Enqueue_callout enqueue_callout
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -77,12 +78,12 @@ ssize_t _POSIX_Message_queue_Receive_support(
|
||||
* This routine posts a message to a specified message queue.
|
||||
*/
|
||||
int _POSIX_Message_queue_Send_support(
|
||||
mqd_t mqdes,
|
||||
const char *msg_ptr,
|
||||
size_t msg_len,
|
||||
unsigned int msg_prio,
|
||||
bool wait,
|
||||
Watchdog_Interval timeout
|
||||
mqd_t mqdes,
|
||||
const char *msg_ptr,
|
||||
size_t msg_len,
|
||||
unsigned int msg_prio,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Enqueue_callout enqueue_callout
|
||||
);
|
||||
|
||||
RTEMS_INLINE_ROUTINE POSIX_Message_queue_Control *
|
||||
|
||||
@@ -132,7 +132,7 @@ Status_Control _POSIX_Mutex_Seize_slow(
|
||||
POSIX_Mutex_Control *the_mutex,
|
||||
const Thread_queue_Operations *operations,
|
||||
Thread_Control *executing,
|
||||
bool wait,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Context *queue_context
|
||||
);
|
||||
|
||||
@@ -171,7 +171,7 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Seize(
|
||||
unsigned long flags,
|
||||
const Thread_queue_Operations *operations,
|
||||
Thread_Control *executing,
|
||||
bool wait,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
@@ -198,7 +198,7 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Seize(
|
||||
the_mutex,
|
||||
operations,
|
||||
executing,
|
||||
wait,
|
||||
abstime,
|
||||
queue_context
|
||||
);
|
||||
}
|
||||
@@ -329,11 +329,11 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_set_owner(
|
||||
}
|
||||
|
||||
RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_seize(
|
||||
POSIX_Mutex_Control *the_mutex,
|
||||
unsigned long flags,
|
||||
Thread_Control *executing,
|
||||
bool wait,
|
||||
Thread_queue_Context *queue_context
|
||||
POSIX_Mutex_Control *the_mutex,
|
||||
unsigned long flags,
|
||||
Thread_Control *executing,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
Thread_Control *owner;
|
||||
@@ -371,7 +371,7 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_seize(
|
||||
the_mutex,
|
||||
POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS,
|
||||
executing,
|
||||
wait,
|
||||
abstime,
|
||||
queue_context
|
||||
);
|
||||
}
|
||||
@@ -444,16 +444,12 @@ RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_surrender(
|
||||
return STATUS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief POSIX Mutex Lock Support Method
|
||||
*
|
||||
* A support routine which implements guts of the blocking, non-blocking, and
|
||||
* timed wait version of mutex lock.
|
||||
*/
|
||||
#define POSIX_MUTEX_ABSTIME_TRY_LOCK ((uintptr_t) 1)
|
||||
|
||||
int _POSIX_Mutex_Lock_support(
|
||||
pthread_mutex_t *mutex,
|
||||
bool blocking,
|
||||
Watchdog_Interval timeout
|
||||
pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Enqueue_callout enqueue_callout
|
||||
);
|
||||
|
||||
static inline POSIX_Mutex_Control *_POSIX_Mutex_Get(
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <rtems/score/status.h>
|
||||
#include <rtems/score/threaddispatch.h>
|
||||
|
||||
static void _POSIX_Condition_variables_Enqueue_callout(
|
||||
static void _POSIX_Condition_variables_Mutex_unlock(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Thread_queue_Context *queue_context
|
||||
@@ -44,11 +44,52 @@ static void _POSIX_Condition_variables_Enqueue_callout(
|
||||
* case, so we follow their lead.
|
||||
*/
|
||||
_Assert( mutex_error == EINVAL || mutex_error == EPERM );
|
||||
_Thread_queue_Extract( the_thread );
|
||||
the_thread->Wait.return_code= STATUS_NOT_OWNER;
|
||||
_Thread_Continue( the_thread, STATUS_NOT_OWNER );
|
||||
}
|
||||
}
|
||||
|
||||
static void _POSIX_Condition_variables_Enqueue_no_timeout(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
_POSIX_Condition_variables_Mutex_unlock( queue, the_thread, queue_context );
|
||||
}
|
||||
|
||||
static void _POSIX_Condition_variables_Enqueue_with_timeout_monotonic(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
_Thread_queue_Add_timeout_monotonic_timespec(
|
||||
queue,
|
||||
the_thread,
|
||||
cpu_self,
|
||||
queue_context
|
||||
);
|
||||
_POSIX_Condition_variables_Mutex_unlock( queue, the_thread, queue_context );
|
||||
}
|
||||
|
||||
static void _POSIX_Condition_variables_Enqueue_with_timeout_realtime(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
_Thread_queue_Add_timeout_realtime_timespec(
|
||||
queue,
|
||||
the_thread,
|
||||
cpu_self,
|
||||
queue_context
|
||||
);
|
||||
_POSIX_Condition_variables_Mutex_unlock( queue, the_thread, queue_context );
|
||||
}
|
||||
|
||||
int _POSIX_Condition_variables_Wait_support(
|
||||
pthread_cond_t *cond,
|
||||
pthread_mutex_t *mutex,
|
||||
@@ -59,44 +100,32 @@ int _POSIX_Condition_variables_Wait_support(
|
||||
unsigned long flags;
|
||||
Thread_queue_Context queue_context;
|
||||
int error;
|
||||
int mutex_error;
|
||||
Thread_Control *executing;
|
||||
Watchdog_Interval timeout;
|
||||
bool already_timedout;
|
||||
TOD_Absolute_timeout_conversion_results status;
|
||||
|
||||
the_cond = _POSIX_Condition_variables_Get( cond );
|
||||
POSIX_CONDITION_VARIABLES_VALIDATE_OBJECT( the_cond, flags );
|
||||
|
||||
_Thread_queue_Context_initialize( &queue_context );
|
||||
already_timedout = false;
|
||||
|
||||
if ( abstime != NULL ) {
|
||||
/*
|
||||
* POSIX requires that blocking calls with timeouts that take
|
||||
* an absolute timeout must ignore issues with the absolute
|
||||
* time provided if the operation would otherwise succeed.
|
||||
* So we check the abstime provided, and hold on to whether it
|
||||
* is valid or not. If it isn't correct and in the future,
|
||||
* then we do a polling operation and convert the UNSATISFIED
|
||||
* status into the appropriate error.
|
||||
*/
|
||||
status = _TOD_Absolute_timeout_to_ticks(
|
||||
abstime,
|
||||
_POSIX_Condition_variables_Get_clock( flags ),
|
||||
&timeout
|
||||
);
|
||||
if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
|
||||
return EINVAL;
|
||||
_Thread_queue_Context_set_timeout_argument( &queue_context, abstime );
|
||||
|
||||
if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
|
||||
status == TOD_ABSOLUTE_TIMEOUT_IS_NOW ) {
|
||||
already_timedout = true;
|
||||
if ( _POSIX_Condition_variables_Get_clock( flags ) == CLOCK_MONOTONIC ) {
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&queue_context,
|
||||
_POSIX_Condition_variables_Enqueue_with_timeout_monotonic
|
||||
);
|
||||
} else {
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&queue_context,
|
||||
_POSIX_Condition_variables_Enqueue_with_timeout_realtime
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&queue_context,
|
||||
_POSIX_Condition_variables_Enqueue_no_timeout
|
||||
);
|
||||
}
|
||||
|
||||
executing = _POSIX_Condition_variables_Acquire( the_cond, &queue_context );
|
||||
@@ -111,32 +140,17 @@ int _POSIX_Condition_variables_Wait_support(
|
||||
|
||||
the_cond->mutex = mutex;
|
||||
|
||||
if ( !already_timedout ) {
|
||||
_Thread_queue_Context_set_thread_state(
|
||||
&queue_context,
|
||||
STATES_WAITING_FOR_CONDITION_VARIABLE
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&queue_context,
|
||||
_POSIX_Condition_variables_Enqueue_callout
|
||||
);
|
||||
_Thread_queue_Enqueue(
|
||||
&the_cond->Queue.Queue,
|
||||
POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
|
||||
executing,
|
||||
&queue_context
|
||||
);
|
||||
error = _POSIX_Get_error_after_wait( executing );
|
||||
} else {
|
||||
_POSIX_Condition_variables_Release( the_cond, &queue_context );
|
||||
|
||||
mutex_error = pthread_mutex_unlock( the_cond->mutex );
|
||||
if ( mutex_error != 0 ) {
|
||||
error = EPERM;
|
||||
} else {
|
||||
error = ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
_Thread_queue_Context_set_thread_state(
|
||||
&queue_context,
|
||||
STATES_WAITING_FOR_CONDITION_VARIABLE
|
||||
);
|
||||
_Thread_queue_Enqueue(
|
||||
&the_cond->Queue.Queue,
|
||||
POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
|
||||
executing,
|
||||
&queue_context
|
||||
);
|
||||
error = _POSIX_Get_error_after_wait( executing );
|
||||
|
||||
/*
|
||||
* If the thread is interrupted, while in the thread queue, by
|
||||
@@ -155,6 +169,8 @@ int _POSIX_Condition_variables_Wait_support(
|
||||
*/
|
||||
|
||||
if ( error != EPERM ) {
|
||||
int mutex_error;
|
||||
|
||||
mutex_error = pthread_mutex_lock( mutex );
|
||||
if ( mutex_error != 0 ) {
|
||||
_Assert( mutex_error == EINVAL );
|
||||
|
||||
@@ -18,17 +18,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <mqueue.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
#include <rtems/seterr.h>
|
||||
#include <rtems/posix/mqueueimpl.h>
|
||||
|
||||
ssize_t mq_receive(
|
||||
@@ -43,7 +32,7 @@ ssize_t mq_receive(
|
||||
msg_ptr,
|
||||
msg_len,
|
||||
msg_prio,
|
||||
true,
|
||||
WATCHDOG_NO_TIMEOUT
|
||||
NULL,
|
||||
_Thread_queue_Enqueue_do_nothing_extra
|
||||
);
|
||||
}
|
||||
|
||||
@@ -36,18 +36,17 @@ THREAD_QUEUE_OBJECT_ASSERT(
|
||||
*/
|
||||
|
||||
ssize_t _POSIX_Message_queue_Receive_support(
|
||||
mqd_t mqdes,
|
||||
char *msg_ptr,
|
||||
size_t msg_len,
|
||||
unsigned int *msg_prio,
|
||||
bool wait,
|
||||
Watchdog_Interval timeout
|
||||
mqd_t mqdes,
|
||||
char *msg_ptr,
|
||||
size_t msg_len,
|
||||
unsigned int *msg_prio,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Enqueue_callout enqueue_callout
|
||||
)
|
||||
{
|
||||
POSIX_Message_queue_Control *the_mq;
|
||||
Thread_queue_Context queue_context;
|
||||
size_t length_out;
|
||||
bool do_wait;
|
||||
Thread_Control *executing;
|
||||
Status_Control status;
|
||||
|
||||
@@ -67,22 +66,15 @@ ssize_t _POSIX_Message_queue_Receive_support(
|
||||
rtems_set_errno_and_return_minus_one( EMSGSIZE );
|
||||
}
|
||||
|
||||
_Thread_queue_Context_set_enqueue_callout( &queue_context, enqueue_callout );
|
||||
_Thread_queue_Context_set_timeout_argument( &queue_context, abstime );
|
||||
|
||||
/*
|
||||
* Now if something goes wrong, we return a "length" of -1
|
||||
* to indicate an error.
|
||||
*/
|
||||
|
||||
length_out = -1;
|
||||
|
||||
/*
|
||||
* A timed receive with a bad time will do a poll regardless.
|
||||
*/
|
||||
if ( wait ) {
|
||||
do_wait = ( the_mq->oflag & O_NONBLOCK ) == 0;
|
||||
} else {
|
||||
do_wait = wait;
|
||||
}
|
||||
|
||||
_CORE_message_queue_Acquire_critical(
|
||||
&the_mq->Message_queue,
|
||||
&queue_context
|
||||
@@ -97,13 +89,12 @@ ssize_t _POSIX_Message_queue_Receive_support(
|
||||
* Now perform the actual message receive
|
||||
*/
|
||||
executing = _Thread_Executing;
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
|
||||
status = _CORE_message_queue_Seize(
|
||||
&the_mq->Message_queue,
|
||||
executing,
|
||||
msg_ptr,
|
||||
&length_out,
|
||||
do_wait,
|
||||
( the_mq->oflag & O_NONBLOCK ) == 0,
|
||||
&queue_context
|
||||
);
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ int mq_send(
|
||||
msg_ptr,
|
||||
msg_len,
|
||||
msg_prio,
|
||||
true,
|
||||
WATCHDOG_NO_TIMEOUT
|
||||
NULL,
|
||||
_Thread_queue_Enqueue_do_nothing_extra
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,18 +35,17 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
int _POSIX_Message_queue_Send_support(
|
||||
mqd_t mqdes,
|
||||
const char *msg_ptr,
|
||||
size_t msg_len,
|
||||
unsigned int msg_prio,
|
||||
bool wait,
|
||||
Watchdog_Interval timeout
|
||||
mqd_t mqdes,
|
||||
const char *msg_ptr,
|
||||
size_t msg_len,
|
||||
unsigned int msg_prio,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Enqueue_callout enqueue_callout
|
||||
)
|
||||
{
|
||||
POSIX_Message_queue_Control *the_mq;
|
||||
Thread_queue_Context queue_context;
|
||||
Status_Control status;
|
||||
bool do_wait;
|
||||
Thread_Control *executing;
|
||||
|
||||
/*
|
||||
@@ -69,14 +68,8 @@ int _POSIX_Message_queue_Send_support(
|
||||
rtems_set_errno_and_return_minus_one( EBADF );
|
||||
}
|
||||
|
||||
/*
|
||||
* A timed receive with a bad time will do a poll regardless.
|
||||
*/
|
||||
if ( wait ) {
|
||||
do_wait = ( the_mq->oflag & O_NONBLOCK ) == 0;
|
||||
} else {
|
||||
do_wait = wait;
|
||||
}
|
||||
_Thread_queue_Context_set_enqueue_callout( &queue_context, enqueue_callout );
|
||||
_Thread_queue_Context_set_timeout_argument( &queue_context, abstime );
|
||||
|
||||
_CORE_message_queue_Acquire_critical(
|
||||
&the_mq->Message_queue,
|
||||
@@ -92,14 +85,13 @@ int _POSIX_Message_queue_Send_support(
|
||||
* Now perform the actual message receive
|
||||
*/
|
||||
executing = _Thread_Executing;
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
|
||||
status = _CORE_message_queue_Submit(
|
||||
&the_mq->Message_queue,
|
||||
executing,
|
||||
msg_ptr,
|
||||
msg_len,
|
||||
_POSIX_Message_queue_Priority_to_core( msg_prio ),
|
||||
do_wait,
|
||||
( the_mq->oflag & O_NONBLOCK ) == 0,
|
||||
&queue_context
|
||||
);
|
||||
return _POSIX_Zero_or_minus_one_plus_errno( status );
|
||||
|
||||
@@ -32,17 +32,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <mqueue.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
#include <rtems/seterr.h>
|
||||
#include <rtems/posix/mqueueimpl.h>
|
||||
|
||||
/*
|
||||
@@ -59,33 +48,12 @@ ssize_t mq_timedreceive(
|
||||
const struct timespec *__restrict abstime
|
||||
)
|
||||
{
|
||||
Watchdog_Interval ticks;
|
||||
bool do_wait = true;
|
||||
TOD_Absolute_timeout_conversion_results status;
|
||||
|
||||
/*
|
||||
* POSIX requires that blocking calls with timeouts that take
|
||||
* an absolute timeout must ignore issues with the absolute
|
||||
* time provided if the operation would otherwise succeed.
|
||||
* So we check the abstime provided, and hold on to whether it
|
||||
* is valid or not. If it isn't correct and in the future,
|
||||
* then we do a polling operation and convert the UNSATISFIED
|
||||
* status into the appropriate error.
|
||||
*
|
||||
* If the status is TOD_ABSOLUTE_TIMEOUT_INVALID,
|
||||
* TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
|
||||
* then we should not wait.
|
||||
*/
|
||||
status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
|
||||
if ( status != TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE )
|
||||
do_wait = false;
|
||||
|
||||
return _POSIX_Message_queue_Receive_support(
|
||||
mqdes,
|
||||
msg_ptr,
|
||||
msg_len,
|
||||
msg_prio,
|
||||
do_wait,
|
||||
ticks
|
||||
abstime,
|
||||
_Thread_queue_Add_timeout_realtime_timespec
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,17 +18,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <mqueue.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
#include <rtems/seterr.h>
|
||||
#include <rtems/posix/mqueueimpl.h>
|
||||
|
||||
int mq_timedsend(
|
||||
@@ -39,33 +28,12 @@ int mq_timedsend(
|
||||
const struct timespec *abstime
|
||||
)
|
||||
{
|
||||
Watchdog_Interval ticks;
|
||||
bool do_wait = true;
|
||||
TOD_Absolute_timeout_conversion_results status;
|
||||
|
||||
/*
|
||||
* POSIX requires that blocking calls with timeouts that take
|
||||
* an absolute timeout must ignore issues with the absolute
|
||||
* time provided if the operation would otherwise succeed.
|
||||
* So we check the abstime provided, and hold on to whether it
|
||||
* is valid or not. If it isn't correct and in the future,
|
||||
* then we do a polling operation and convert the UNSATISFIED
|
||||
* status into the appropriate error.
|
||||
*
|
||||
* If the status is TOD_ABSOLUTE_TIMEOUT_INVALID,
|
||||
* TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
|
||||
* then we should not wait.
|
||||
*/
|
||||
status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
|
||||
if ( status != TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE )
|
||||
do_wait = false;
|
||||
|
||||
return _POSIX_Message_queue_Send_support(
|
||||
mqdes,
|
||||
msg_ptr,
|
||||
msg_len,
|
||||
msg_prio,
|
||||
do_wait,
|
||||
ticks
|
||||
abstime,
|
||||
_Thread_queue_Add_timeout_realtime_timespec
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,14 +18,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/coremuteximpl.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
#include <rtems/posix/muteximpl.h>
|
||||
#include <rtems/posix/priorityimpl.h>
|
||||
|
||||
/*
|
||||
* 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
|
||||
@@ -37,5 +30,9 @@ int pthread_mutex_lock(
|
||||
pthread_mutex_t *mutex
|
||||
)
|
||||
{
|
||||
return _POSIX_Mutex_Lock_support( mutex, true, WATCHDOG_NO_TIMEOUT );
|
||||
return _POSIX_Mutex_Lock_support(
|
||||
mutex,
|
||||
NULL,
|
||||
_Thread_queue_Enqueue_do_nothing_extra
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,16 +25,15 @@ Status_Control _POSIX_Mutex_Seize_slow(
|
||||
POSIX_Mutex_Control *the_mutex,
|
||||
const Thread_queue_Operations *operations,
|
||||
Thread_Control *executing,
|
||||
bool wait,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
if ( wait ) {
|
||||
if ( (uintptr_t) abstime != POSIX_MUTEX_ABSTIME_TRY_LOCK ) {
|
||||
_Thread_queue_Context_set_thread_state(
|
||||
queue_context,
|
||||
STATES_WAITING_FOR_MUTEX
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
|
||||
_Thread_queue_Context_set_deadlock_callout(
|
||||
queue_context,
|
||||
_Thread_queue_Deadlock_status
|
||||
@@ -53,9 +52,9 @@ Status_Control _POSIX_Mutex_Seize_slow(
|
||||
}
|
||||
|
||||
int _POSIX_Mutex_Lock_support(
|
||||
pthread_mutex_t *mutex,
|
||||
bool wait,
|
||||
Watchdog_Interval timeout
|
||||
pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime,
|
||||
Thread_queue_Enqueue_callout enqueue_callout
|
||||
)
|
||||
{
|
||||
POSIX_Mutex_Control *the_mutex;
|
||||
@@ -68,7 +67,8 @@ int _POSIX_Mutex_Lock_support(
|
||||
POSIX_MUTEX_VALIDATE_OBJECT( the_mutex, flags );
|
||||
|
||||
executing = _POSIX_Mutex_Acquire( the_mutex, &queue_context );
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
|
||||
_Thread_queue_Context_set_enqueue_callout( &queue_context, enqueue_callout);
|
||||
_Thread_queue_Context_set_timeout_argument( &queue_context, abstime );
|
||||
|
||||
switch ( _POSIX_Mutex_Get_protocol( flags ) ) {
|
||||
case POSIX_MUTEX_PRIORITY_CEILING:
|
||||
@@ -76,7 +76,7 @@ int _POSIX_Mutex_Lock_support(
|
||||
the_mutex,
|
||||
flags,
|
||||
executing,
|
||||
wait,
|
||||
abstime,
|
||||
&queue_context
|
||||
);
|
||||
break;
|
||||
@@ -86,7 +86,7 @@ int _POSIX_Mutex_Lock_support(
|
||||
flags,
|
||||
POSIX_MUTEX_NO_PROTOCOL_TQ_OPERATIONS,
|
||||
executing,
|
||||
wait,
|
||||
abstime,
|
||||
&queue_context
|
||||
);
|
||||
break;
|
||||
@@ -99,7 +99,7 @@ int _POSIX_Mutex_Lock_support(
|
||||
flags,
|
||||
POSIX_MUTEX_PRIORITY_INHERIT_TQ_OPERATIONS,
|
||||
executing,
|
||||
wait,
|
||||
abstime,
|
||||
&queue_context
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -18,14 +18,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/coremuteximpl.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
#include <rtems/posix/muteximpl.h>
|
||||
#include <rtems/posix/priorityimpl.h>
|
||||
|
||||
/**
|
||||
* 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
|
||||
@@ -37,42 +30,9 @@ int pthread_mutex_timedlock(
|
||||
const struct timespec *abstime
|
||||
)
|
||||
{
|
||||
Watchdog_Interval ticks;
|
||||
bool do_wait = true;
|
||||
TOD_Absolute_timeout_conversion_results status;
|
||||
int lock_status;
|
||||
|
||||
/*
|
||||
* POSIX requires that blocking calls with timeouts that take
|
||||
* an absolute timeout must ignore issues with the absolute
|
||||
* time provided if the operation would otherwise succeed.
|
||||
* So we check the abstime provided, and hold on to whether it
|
||||
* is valid or not. If it isn't correct and in the future,
|
||||
* then we do a polling operation and convert the UNSATISFIED
|
||||
* status into the appropriate error.
|
||||
*
|
||||
* If the status is TOD_ABSOLUTE_TIMEOUT_INVALID,
|
||||
* TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
|
||||
* then we should not wait.
|
||||
*/
|
||||
status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
|
||||
if ( status != TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE )
|
||||
do_wait = false;
|
||||
|
||||
lock_status = _POSIX_Mutex_Lock_support( mutex, do_wait, ticks );
|
||||
/*
|
||||
* This service only gives us the option to block. We used a polling
|
||||
* attempt to lock if the abstime was not in the future. If we did
|
||||
* not obtain the mutex, then not look at the status immediately,
|
||||
* make sure the right reason is returned.
|
||||
*/
|
||||
if ( !do_wait && (lock_status == EBUSY) ) {
|
||||
if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
|
||||
return EINVAL;
|
||||
if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST ||
|
||||
status == TOD_ABSOLUTE_TIMEOUT_IS_NOW )
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
return lock_status;
|
||||
return _POSIX_Mutex_Lock_support(
|
||||
mutex,
|
||||
abstime,
|
||||
_Thread_queue_Add_timeout_realtime_timespec
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,14 +18,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/coremuteximpl.h>
|
||||
#include <rtems/score/watchdog.h>
|
||||
#include <rtems/posix/muteximpl.h>
|
||||
#include <rtems/posix/priorityimpl.h>
|
||||
|
||||
/**
|
||||
* 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
|
||||
@@ -36,8 +29,17 @@ int pthread_mutex_trylock(
|
||||
pthread_mutex_t *mutex
|
||||
)
|
||||
{
|
||||
int r = _POSIX_Mutex_Lock_support( mutex, false, WATCHDOG_NO_TIMEOUT );
|
||||
if ( r == EDEADLK )
|
||||
r = EBUSY;
|
||||
return r;
|
||||
int eno;
|
||||
|
||||
eno = _POSIX_Mutex_Lock_support(
|
||||
mutex,
|
||||
(const struct timespec *) POSIX_MUTEX_ABSTIME_TRY_LOCK,
|
||||
NULL
|
||||
);
|
||||
|
||||
if ( eno == EDEADLK ) {
|
||||
eno = EBUSY;
|
||||
}
|
||||
|
||||
return eno;
|
||||
}
|
||||
|
||||
+82
-169
@@ -21,100 +21,18 @@
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems/seterr.h>
|
||||
#include <rtems/score/threadimpl.h>
|
||||
#include <rtems/score/threadqimpl.h>
|
||||
#include <rtems/score/timespec.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
#include <rtems/score/watchdogimpl.h>
|
||||
#include <rtems/posix/posixapi.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
static Thread_queue_Control _Nanosleep_Pseudo_queue =
|
||||
THREAD_QUEUE_INITIALIZER( "Nanosleep" );
|
||||
|
||||
static inline int nanosleep_helper(
|
||||
clockid_t clock_id,
|
||||
uint64_t ticks,
|
||||
struct timespec *timeout,
|
||||
struct timespec *rmtp,
|
||||
Watchdog_Discipline discipline
|
||||
)
|
||||
{
|
||||
Thread_queue_Context queue_context;
|
||||
struct timespec stop;
|
||||
int err;
|
||||
|
||||
err = 0;
|
||||
|
||||
_Thread_queue_Context_initialize( &queue_context );
|
||||
_Thread_queue_Context_set_thread_state(
|
||||
&queue_context,
|
||||
STATES_WAITING_FOR_TIME | STATES_INTERRUPTIBLE_BY_SIGNAL
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
|
||||
if ( discipline == WATCHDOG_ABSOLUTE ) {
|
||||
_Thread_queue_Context_set_absolute_timeout( &queue_context, ticks );
|
||||
} else {
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
|
||||
}
|
||||
|
||||
/*
|
||||
* Block for the desired amount of time
|
||||
*/
|
||||
_Thread_queue_Acquire( &_Nanosleep_Pseudo_queue, &queue_context );
|
||||
_Thread_queue_Enqueue(
|
||||
&_Nanosleep_Pseudo_queue.Queue,
|
||||
&_Thread_queue_Operations_FIFO,
|
||||
_Thread_Executing,
|
||||
&queue_context
|
||||
);
|
||||
|
||||
clock_gettime( clock_id, &stop );
|
||||
/*
|
||||
* If the user wants the time remaining, do the conversion.
|
||||
*/
|
||||
if ( _Timespec_Less_than( &stop, timeout ) ) {
|
||||
/*
|
||||
* If there is time remaining, then we were interrupted by a signal.
|
||||
*/
|
||||
err = EINTR;
|
||||
if ( rmtp != NULL ) {
|
||||
_Timespec_Subtract( &stop, timeout, rmtp );
|
||||
}
|
||||
} else if ( rmtp != NULL ) {
|
||||
/* no time remaining */
|
||||
_Timespec_Set_to_zero( rmtp );
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* A nanosleep for zero time is implemented as a yield.
|
||||
* This behavior is also beyond the POSIX specification but is
|
||||
* consistent with the RTEMS API and yields desirable behavior.
|
||||
*/
|
||||
static inline int nanosleep_yield( struct timespec *rmtp )
|
||||
{
|
||||
/*
|
||||
* It is critical to obtain the executing thread after thread dispatching is
|
||||
* disabled on SMP configurations.
|
||||
*/
|
||||
Thread_Control *executing;
|
||||
Per_CPU_Control *cpu_self;
|
||||
|
||||
executing = _Thread_Get_executing();
|
||||
cpu_self = _Thread_Dispatch_disable();
|
||||
_Thread_Yield( executing );
|
||||
_Thread_Dispatch_direct( cpu_self );
|
||||
if ( rmtp ) {
|
||||
rmtp->tv_sec = 0;
|
||||
rmtp->tv_nsec = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
|
||||
*/
|
||||
@@ -123,43 +41,15 @@ int nanosleep(
|
||||
struct timespec *rmtp
|
||||
)
|
||||
{
|
||||
int err;
|
||||
struct timespec now;
|
||||
uint64_t ticks;
|
||||
Watchdog_Interval relative_interval;
|
||||
int eno;
|
||||
|
||||
/*
|
||||
* Return EINVAL if the delay interval is negative.
|
||||
*
|
||||
* NOTE: This behavior is beyond the POSIX specification.
|
||||
* FSU and GNU/Linux pthreads shares this behavior.
|
||||
*/
|
||||
if ( !_Timespec_Is_valid( rqtp ) ) {
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
eno = clock_nanosleep( CLOCK_REALTIME, 0, rqtp, rmtp );
|
||||
|
||||
if ( eno != 0 ) {
|
||||
rtems_set_errno_and_return_minus_one( eno );
|
||||
}
|
||||
|
||||
relative_interval = _Timespec_To_ticks( rqtp );
|
||||
if ( relative_interval == 0 )
|
||||
return nanosleep_yield( rmtp );
|
||||
|
||||
/* CLOCK_REALTIME can be adjusted during the timeout,
|
||||
* so convert to an absolute timeout value and put the
|
||||
* thread on the WATCHDOG_ABSOLUTE threadq. */
|
||||
err = clock_gettime( CLOCK_REALTIME, &now );
|
||||
if ( err != 0 )
|
||||
return -1;
|
||||
_Timespec_Add_to( &now, rqtp );
|
||||
ticks = _Watchdog_Realtime_from_timespec( &now );
|
||||
err = nanosleep_helper( CLOCK_REALTIME,
|
||||
ticks,
|
||||
&now,
|
||||
rmtp,
|
||||
WATCHDOG_ABSOLUTE
|
||||
);
|
||||
if ( err != 0 ) {
|
||||
rtems_set_errno_and_return_minus_one( err );
|
||||
}
|
||||
return 0;
|
||||
return eno;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -172,59 +62,82 @@ int clock_nanosleep(
|
||||
struct timespec *rmtp
|
||||
)
|
||||
{
|
||||
int err = 0;
|
||||
struct timespec timeout;
|
||||
uint64_t ticks;
|
||||
Watchdog_Interval relative_interval;
|
||||
TOD_Absolute_timeout_conversion_results status;
|
||||
Thread_queue_Context queue_context;
|
||||
struct timespec spare_end;
|
||||
const struct timespec *end;
|
||||
Thread_Control *executing;
|
||||
int eno;
|
||||
|
||||
if ( !_Timespec_Is_valid( rqtp ) )
|
||||
return EINVAL;
|
||||
|
||||
/* get relative ticks of the requested timeout */
|
||||
if ( flags & TIMER_ABSTIME ) {
|
||||
/* See if absolute time already passed */
|
||||
status = _TOD_Absolute_timeout_to_ticks(rqtp, clock_id, &relative_interval);
|
||||
if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
|
||||
return EINVAL;
|
||||
if ( status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST )
|
||||
return 0;
|
||||
if ( status == TOD_ABSOLUTE_TIMEOUT_IS_NOW )
|
||||
return nanosleep_yield( NULL );
|
||||
rmtp = NULL; /* Do not touch rmtp when using absolute time */
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_nsec = 0;
|
||||
} else {
|
||||
/* prepare to convert relative ticks to absolute timeout */
|
||||
err = clock_gettime( clock_id, &timeout );
|
||||
if ( err != 0 )
|
||||
return EINVAL;
|
||||
relative_interval = _Timespec_To_ticks( rqtp );
|
||||
if ( clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC ) {
|
||||
return ENOTSUP;
|
||||
}
|
||||
if ( relative_interval == 0 )
|
||||
return nanosleep_yield( rmtp );
|
||||
|
||||
_Timespec_Add_to( &timeout, rqtp );
|
||||
if ( clock_id == CLOCK_REALTIME ) {
|
||||
ticks = _Watchdog_Realtime_from_timespec( &timeout );
|
||||
err = nanosleep_helper(
|
||||
clock_id,
|
||||
ticks,
|
||||
&timeout,
|
||||
rmtp,
|
||||
WATCHDOG_ABSOLUTE
|
||||
);
|
||||
} else if ( clock_id == CLOCK_MONOTONIC ) {
|
||||
/* use the WATCHDOG_RELATIVE to ignore changes in wall time */
|
||||
err = nanosleep_helper(
|
||||
clock_id,
|
||||
relative_interval,
|
||||
&timeout,
|
||||
rmtp,
|
||||
WATCHDOG_RELATIVE
|
||||
);
|
||||
_Thread_queue_Context_initialize( &queue_context );
|
||||
_Thread_queue_Context_set_thread_state(
|
||||
&queue_context,
|
||||
STATES_WAITING_FOR_TIME | STATES_INTERRUPTIBLE_BY_SIGNAL
|
||||
);
|
||||
|
||||
if ( ( flags & TIMER_ABSTIME ) != 0 ) {
|
||||
end = rqtp;
|
||||
|
||||
if ( clock_id == CLOCK_REALTIME ) {
|
||||
_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
|
||||
&queue_context,
|
||||
end
|
||||
);
|
||||
} else {
|
||||
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
|
||||
&queue_context,
|
||||
end
|
||||
);
|
||||
}
|
||||
} else {
|
||||
err = ENOTSUP;
|
||||
if ( !_Watchdog_Is_valid_interval_timespec( rqtp ) ) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
_TOD_Get_zero_based_uptime_as_timespec( &spare_end );
|
||||
|
||||
/* In case this overflows, then the enqueue callout will reject it */
|
||||
_Timespec_Add_to( &spare_end, rqtp );
|
||||
|
||||
end = &spare_end;
|
||||
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
|
||||
&queue_context,
|
||||
end
|
||||
);
|
||||
}
|
||||
return err;
|
||||
|
||||
_Thread_queue_Acquire( &_Nanosleep_Pseudo_queue, &queue_context );
|
||||
executing = _Thread_Executing;
|
||||
_Thread_queue_Enqueue(
|
||||
&_Nanosleep_Pseudo_queue.Queue,
|
||||
&_Thread_queue_Operations_FIFO,
|
||||
executing,
|
||||
&queue_context
|
||||
);
|
||||
eno = _POSIX_Get_error_after_wait( executing );
|
||||
|
||||
if ( eno == ETIMEDOUT ) {
|
||||
eno = 0;
|
||||
}
|
||||
|
||||
if ( rmtp != NULL && ( flags & TIMER_ABSTIME ) == 0 ) {
|
||||
if ( eno == EINTR ) {
|
||||
struct timespec actual_end;
|
||||
|
||||
_TOD_Get_zero_based_uptime_as_timespec( &actual_end );
|
||||
|
||||
if ( _Timespec_Less_than( &actual_end, end ) ) {
|
||||
_Timespec_Subtract( &actual_end, end, rmtp );
|
||||
} else {
|
||||
_Timespec_Set_to_zero( rmtp );
|
||||
}
|
||||
} else {
|
||||
_Timespec_Set_to_zero( rmtp );
|
||||
}
|
||||
}
|
||||
|
||||
return eno;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ int pthread_barrier_wait( pthread_barrier_t *_barrier )
|
||||
STATES_WAITING_FOR_BARRIER
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Enqueue(
|
||||
&barrier->Queue.Queue,
|
||||
POSIX_BARRIER_TQ_OPERATIONS,
|
||||
|
||||
@@ -33,7 +33,7 @@ int pthread_rwlock_rdlock(
|
||||
POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock );
|
||||
|
||||
_Thread_queue_Context_initialize( &queue_context );
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
status = _CORE_RWLock_Seize_for_reading(
|
||||
&the_rwlock->RWLock,
|
||||
true, /* we are willing to wait forever */
|
||||
|
||||
@@ -20,59 +20,28 @@
|
||||
|
||||
#include <rtems/posix/rwlockimpl.h>
|
||||
#include <rtems/posix/posixapi.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
|
||||
int pthread_rwlock_timedrdlock(
|
||||
pthread_rwlock_t *rwlock,
|
||||
const struct timespec *abstime
|
||||
)
|
||||
{
|
||||
POSIX_RWLock_Control *the_rwlock;
|
||||
Thread_queue_Context queue_context;
|
||||
Watchdog_Interval ticks;
|
||||
bool do_wait;
|
||||
TOD_Absolute_timeout_conversion_results timeout_status;
|
||||
Status_Control status;
|
||||
|
||||
/*
|
||||
* POSIX requires that blocking calls with timeouts that take
|
||||
* an absolute timeout must ignore issues with the absolute
|
||||
* time provided if the operation would otherwise succeed.
|
||||
* So we check the abstime provided, and hold on to whether it
|
||||
* is valid or not. If it isn't correct and in the future,
|
||||
* then we do a polling operation and convert the STATUS_UNAVAILABLE
|
||||
* status into the appropriate error.
|
||||
*
|
||||
* If the timeout status is TOD_ABSOLUTE_TIMEOUT_INVALID,
|
||||
* TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
|
||||
* then we should not wait.
|
||||
*/
|
||||
timeout_status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
|
||||
do_wait = ( timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE );
|
||||
POSIX_RWLock_Control *the_rwlock;
|
||||
Thread_queue_Context queue_context;
|
||||
Status_Control status;
|
||||
|
||||
the_rwlock = _POSIX_RWLock_Get( rwlock );
|
||||
POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock );
|
||||
|
||||
_Thread_queue_Context_initialize( &queue_context );
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
|
||||
_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
|
||||
&queue_context,
|
||||
abstime
|
||||
);
|
||||
status = _CORE_RWLock_Seize_for_reading(
|
||||
&the_rwlock->RWLock,
|
||||
do_wait,
|
||||
true,
|
||||
&queue_context
|
||||
);
|
||||
|
||||
if ( !do_wait && status == STATUS_UNAVAILABLE ) {
|
||||
if ( timeout_status == TOD_ABSOLUTE_TIMEOUT_INVALID ) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (
|
||||
timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST
|
||||
|| timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_NOW
|
||||
) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return _POSIX_Get_error( status );
|
||||
}
|
||||
|
||||
@@ -22,59 +22,28 @@
|
||||
|
||||
#include <rtems/posix/rwlockimpl.h>
|
||||
#include <rtems/posix/posixapi.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
|
||||
int pthread_rwlock_timedwrlock(
|
||||
pthread_rwlock_t *rwlock,
|
||||
const struct timespec *abstime
|
||||
)
|
||||
{
|
||||
POSIX_RWLock_Control *the_rwlock;
|
||||
Thread_queue_Context queue_context;
|
||||
Watchdog_Interval ticks;
|
||||
bool do_wait;
|
||||
TOD_Absolute_timeout_conversion_results timeout_status;
|
||||
Status_Control status;
|
||||
|
||||
/*
|
||||
* POSIX requires that blocking calls with timeouts that take
|
||||
* an absolute timeout must ignore issues with the absolute
|
||||
* time provided if the operation would otherwise succeed.
|
||||
* So we check the abstime provided, and hold on to whether it
|
||||
* is valid or not. If it isn't correct and in the future,
|
||||
* then we do a polling operation and convert the STATUS_UNAVAILABLE
|
||||
* status into the appropriate error.
|
||||
*
|
||||
* If the timeout status is TOD_ABSOLUTE_TIMEOUT_INVALID,
|
||||
* TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW,
|
||||
* then we should not wait.
|
||||
*/
|
||||
timeout_status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks );
|
||||
do_wait = ( timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE );
|
||||
POSIX_RWLock_Control *the_rwlock;
|
||||
Thread_queue_Context queue_context;
|
||||
Status_Control status;
|
||||
|
||||
the_rwlock = _POSIX_RWLock_Get( rwlock );
|
||||
POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock );
|
||||
|
||||
_Thread_queue_Context_initialize( &queue_context );
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
|
||||
_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
|
||||
&queue_context,
|
||||
abstime
|
||||
);
|
||||
status = _CORE_RWLock_Seize_for_writing(
|
||||
&the_rwlock->RWLock,
|
||||
do_wait,
|
||||
true,
|
||||
&queue_context
|
||||
);
|
||||
|
||||
if ( !do_wait && status == STATUS_UNAVAILABLE ) {
|
||||
if ( timeout_status == TOD_ABSOLUTE_TIMEOUT_INVALID ) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (
|
||||
timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST
|
||||
|| timeout_status == TOD_ABSOLUTE_TIMEOUT_IS_NOW
|
||||
) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return _POSIX_Get_error( status );
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ int pthread_rwlock_wrlock(
|
||||
POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock );
|
||||
|
||||
_Thread_queue_Context_initialize( &queue_context );
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
status = _CORE_RWLock_Seize_for_writing(
|
||||
&the_rwlock->RWLock,
|
||||
true, /* do not timeout -- wait forever */
|
||||
|
||||
@@ -40,7 +40,6 @@ static int _POSIX_Threads_Join( pthread_t thread, void **value_ptr )
|
||||
|
||||
_Thread_queue_Context_initialize( &queue_context );
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
the_thread = _Thread_Get( thread, &queue_context.Lock_context.Lock_context );
|
||||
|
||||
if ( the_thread == NULL ) {
|
||||
|
||||
@@ -51,29 +51,16 @@ int sem_timedwait(
|
||||
_Sem_Queue_release( sem, level, &queue_context );
|
||||
return 0;
|
||||
} else {
|
||||
Watchdog_Interval ticks;
|
||||
Status_Control status;
|
||||
|
||||
switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
|
||||
case TOD_ABSOLUTE_TIMEOUT_INVALID:
|
||||
_Sem_Queue_release( sem, level, &queue_context );
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
break;
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
|
||||
_Sem_Queue_release( sem, level, &queue_context );
|
||||
rtems_set_errno_and_return_minus_one( ETIMEDOUT );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Status_Control status;
|
||||
|
||||
_Thread_queue_Context_set_thread_state(
|
||||
&queue_context,
|
||||
STATES_WAITING_FOR_SEMAPHORE
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
|
||||
_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
|
||||
&queue_context,
|
||||
abstime
|
||||
);
|
||||
_Thread_queue_Context_set_ISR_level( &queue_context, level );
|
||||
_Thread_queue_Enqueue(
|
||||
&sem->Queue.Queue,
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <rtems/posix/psignalimpl.h>
|
||||
#include <rtems/posix/posixapi.h>
|
||||
#include <rtems/score/threadqimpl.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
#include <rtems/score/watchdogimpl.h>
|
||||
#include <rtems/score/isr.h>
|
||||
|
||||
static int _POSIX_signals_Get_lowest(
|
||||
@@ -89,20 +91,24 @@ int sigtimedwait(
|
||||
* in the Open Group specification.
|
||||
*/
|
||||
|
||||
if ( timeout ) {
|
||||
Watchdog_Interval interval;
|
||||
if ( timeout != NULL ) {
|
||||
struct timespec end;
|
||||
|
||||
if ( !_Timespec_Is_valid( timeout ) )
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
if ( !_Watchdog_Is_valid_interval_timespec( timeout ) ) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
interval = _Timespec_To_ticks( timeout );
|
||||
_TOD_Get_zero_based_uptime_as_timespec( &end );
|
||||
|
||||
if ( !interval )
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
/* In case this overflows, then the enqueue callout will reject it */
|
||||
_Timespec_Add_to( &end, timeout );
|
||||
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, interval );
|
||||
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
|
||||
&queue_context,
|
||||
&end
|
||||
);
|
||||
} else {
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -160,7 +166,6 @@ int sigtimedwait(
|
||||
&queue_context,
|
||||
STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
_Thread_queue_Enqueue(
|
||||
&_POSIX_signals_Wait_queue.Queue,
|
||||
POSIX_SIGNALS_TQ_OPERATIONS,
|
||||
|
||||
@@ -38,7 +38,7 @@ rtems_status_code rtems_barrier_wait(
|
||||
return RTEMS_INVALID_ID;
|
||||
}
|
||||
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
|
||||
_Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, timeout );
|
||||
status = _CORE_barrier_Seize(
|
||||
&the_barrier->Barrier,
|
||||
_Thread_Executing,
|
||||
|
||||
@@ -61,7 +61,7 @@ rtems_status_code rtems_message_queue_receive(
|
||||
);
|
||||
|
||||
executing = _Thread_Executing;
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
|
||||
_Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, timeout );
|
||||
status = _CORE_message_queue_Seize(
|
||||
&the_message_queue->message_queue,
|
||||
executing,
|
||||
|
||||
@@ -27,11 +27,19 @@
|
||||
static void _Region_Enqueue_callout(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
Region_Control *the_region;
|
||||
|
||||
_Thread_queue_Add_timeout_ticks(
|
||||
queue,
|
||||
the_thread,
|
||||
cpu_self,
|
||||
queue_context
|
||||
);
|
||||
|
||||
the_region = REGION_OF_THREAD_QUEUE_QUEUE( queue );
|
||||
_Region_Unlock( the_region );
|
||||
}
|
||||
@@ -91,11 +99,11 @@ rtems_status_code rtems_region_get_segment(
|
||||
&queue_context,
|
||||
STATES_WAITING_FOR_SEGMENT
|
||||
);
|
||||
_Thread_queue_Context_set_timeout_ticks( &queue_context, timeout );
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&queue_context,
|
||||
_Region_Enqueue_callout
|
||||
);
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
|
||||
_Thread_queue_Enqueue(
|
||||
&the_region->Wait_queue.Queue,
|
||||
the_region->wait_operations,
|
||||
|
||||
@@ -69,7 +69,11 @@ rtems_status_code rtems_semaphore_obtain(
|
||||
executing = _Thread_Executing;
|
||||
wait = !_Options_Is_no_wait( option_set );
|
||||
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, timeout );
|
||||
if ( wait ) {
|
||||
_Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, timeout );
|
||||
} else {
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
}
|
||||
|
||||
switch ( the_semaphore->variant ) {
|
||||
case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
|
||||
|
||||
@@ -305,6 +305,7 @@ libscore_a_SOURCES += src/threadq.c \
|
||||
src/threadqextractwithproxy.c src/threadqfirst.c \
|
||||
src/threadqflush.c
|
||||
libscore_a_SOURCES += src/threadqops.c
|
||||
libscore_a_SOURCES += src/threadqtimeout.c
|
||||
|
||||
## TIMESPEC_C_FILES
|
||||
libscore_a_SOURCES += src/timespecaddto.c src/timespecfromticks.c \
|
||||
@@ -316,7 +317,6 @@ libscore_a_SOURCES += src/timespecaddto.c src/timespecfromticks.c \
|
||||
libscore_a_SOURCES += src/coretod.c src/coretodset.c \
|
||||
src/coretodtickspersec.c \
|
||||
src/coretodadjust.c
|
||||
libscore_a_SOURCES += src/coretodabsolutetimeout.c
|
||||
|
||||
## WATCHDOG_C_FILES
|
||||
libscore_a_SOURCES += src/watchdoginsert.c
|
||||
|
||||
@@ -188,7 +188,6 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_semaphore_Seize(
|
||||
queue_context,
|
||||
STATES_WAITING_FOR_SEMAPHORE
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
|
||||
_Thread_queue_Enqueue(
|
||||
&the_semaphore->Wait_queue.Queue,
|
||||
operations,
|
||||
|
||||
@@ -57,14 +57,16 @@ typedef struct Thread_queue_Operations Thread_queue_Operations;
|
||||
*
|
||||
* @param[in] queue The actual thread queue.
|
||||
* @param[in] the_thread The thread to enqueue.
|
||||
* @param[in] cpu_self The current processor.
|
||||
* @param[in] queue_context The thread queue context of the lock acquire.
|
||||
*
|
||||
* @see _Thread_queue_Context_set_enqueue_callout().
|
||||
*/
|
||||
typedef void ( *Thread_queue_Enqueue_callout )(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Thread_queue_Context *queue_context
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
struct Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -202,22 +204,31 @@ struct Thread_queue_Context {
|
||||
* @brief The enqueue callout for _Thread_queue_Enqueue().
|
||||
*
|
||||
* The callout is invoked after the release of the thread queue lock with
|
||||
* thread dispatching disabled. Afterwards the thread is blocked.
|
||||
* thread dispatching disabled. Afterwards the thread is blocked. This
|
||||
* callout must be used to install the thread watchdog for timeout handling.
|
||||
*
|
||||
* @see _Thread_queue_Enqueue_do_nothing_extra().
|
||||
* _Thread_queue_Add_timeout_ticks(), and
|
||||
* _Thread_queue_Add_timeout_realtime_timespec().
|
||||
*/
|
||||
Thread_queue_Enqueue_callout enqueue_callout;
|
||||
|
||||
/**
|
||||
* @brief The clock discipline for the interval timeout.
|
||||
* Use WATCHDOG_NO_TIMEOUT to block indefinitely.
|
||||
*/
|
||||
Watchdog_Discipline timeout_discipline;
|
||||
|
||||
/**
|
||||
* @brief Interval to wait.
|
||||
*
|
||||
* May be used by the enqueue callout to register a timeout handler.
|
||||
*/
|
||||
uint64_t timeout;
|
||||
union {
|
||||
/**
|
||||
* @brief The timeout in ticks.
|
||||
*/
|
||||
Watchdog_Interval ticks;
|
||||
|
||||
/**
|
||||
* @brief The timeout argument, e.g. pointer to struct timespec.
|
||||
*/
|
||||
const void *arg;
|
||||
} Timeout;
|
||||
|
||||
#if defined(RTEMS_SMP)
|
||||
/**
|
||||
|
||||
@@ -65,6 +65,28 @@ typedef struct {
|
||||
void _Thread_queue_Enqueue_do_nothing_extra(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
);
|
||||
|
||||
void _Thread_queue_Add_timeout_ticks(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
);
|
||||
|
||||
void _Thread_queue_Add_timeout_monotonic_timespec(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
);
|
||||
|
||||
void _Thread_queue_Add_timeout_realtime_timespec(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
);
|
||||
|
||||
@@ -117,6 +139,40 @@ _Thread_queue_Context_set_thread_state(
|
||||
queue_context->thread_state = thread_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the timeout ticks in the thread queue context.
|
||||
*
|
||||
* @param queue_context The thread queue context.
|
||||
* @param ticks The timeout in ticks.
|
||||
*
|
||||
* @see _Thread_queue_Enqueue().
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void
|
||||
_Thread_queue_Context_set_timeout_ticks(
|
||||
Thread_queue_Context *queue_context,
|
||||
Watchdog_Interval ticks
|
||||
)
|
||||
{
|
||||
queue_context->Timeout.ticks = ticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the timeout argument in the thread queue context.
|
||||
*
|
||||
* @param queue_context The thread queue context.
|
||||
* @param arg The timeout argument.
|
||||
*
|
||||
* @see _Thread_queue_Enqueue().
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void
|
||||
_Thread_queue_Context_set_timeout_argument(
|
||||
Thread_queue_Context *queue_context,
|
||||
const void *arg
|
||||
)
|
||||
{
|
||||
queue_context->Timeout.arg = arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the enqueue callout in the thread queue context.
|
||||
*
|
||||
@@ -150,55 +206,61 @@ _Thread_queue_Context_set_enqueue_do_nothing_extra(
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets an indefinite timeout interval in the thread queue context.
|
||||
* @brief Sets the enqueue callout to add a relative monotonic timeout in
|
||||
* ticks.
|
||||
*
|
||||
* @param queue_context The thread queue context.
|
||||
* @param timeout The new timeout.
|
||||
* @param ticks The timeout in ticks.
|
||||
*
|
||||
* @see _Thread_queue_Enqueue().
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void
|
||||
_Thread_queue_Context_set_no_timeout(
|
||||
Thread_queue_Context *queue_context
|
||||
_Thread_queue_Context_set_enqueue_timeout_ticks(
|
||||
Thread_queue_Context *queue_context,
|
||||
Watchdog_Interval ticks
|
||||
)
|
||||
{
|
||||
queue_context->timeout_discipline = WATCHDOG_NO_TIMEOUT;
|
||||
queue_context->Timeout.ticks = ticks;
|
||||
queue_context->enqueue_callout = _Thread_queue_Add_timeout_ticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a relative timeout in the thread queue context.
|
||||
* @brief Sets the enqueue callout to add an absolute monotonic timeout in
|
||||
* timespec format.
|
||||
*
|
||||
* @param queue_context The thread queue context.
|
||||
* @param discipline The clock discipline to use for the timeout.
|
||||
* @param abstime The absolute monotonic timeout.
|
||||
*
|
||||
* @see _Thread_queue_Enqueue().
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void
|
||||
_Thread_queue_Context_set_relative_timeout(
|
||||
Thread_queue_Context *queue_context,
|
||||
Watchdog_Interval timeout
|
||||
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
|
||||
Thread_queue_Context *queue_context,
|
||||
const struct timespec *abstime
|
||||
)
|
||||
{
|
||||
queue_context->timeout_discipline = WATCHDOG_RELATIVE;
|
||||
queue_context->timeout = timeout;
|
||||
queue_context->Timeout.arg = abstime;
|
||||
queue_context->enqueue_callout =
|
||||
_Thread_queue_Add_timeout_monotonic_timespec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets an absolute timeout in the thread queue context.
|
||||
* @brief Sets the enqueue callout to add an absolute realtime timeout in
|
||||
* timespec format.
|
||||
*
|
||||
* @param queue_context The thread queue context.
|
||||
* @param discipline The clock discipline to use for the timeout.
|
||||
* @param abstime The absolute realtime timeout.
|
||||
*
|
||||
* @see _Thread_queue_Enqueue().
|
||||
*/
|
||||
RTEMS_INLINE_ROUTINE void
|
||||
_Thread_queue_Context_set_absolute_timeout(
|
||||
Thread_queue_Context *queue_context,
|
||||
uint64_t timeout
|
||||
_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
|
||||
Thread_queue_Context *queue_context,
|
||||
const struct timespec *abstime
|
||||
)
|
||||
{
|
||||
queue_context->timeout_discipline = WATCHDOG_ABSOLUTE;
|
||||
queue_context->timeout = timeout;
|
||||
queue_context->Timeout.arg = abstime;
|
||||
queue_context->enqueue_callout = _Thread_queue_Add_timeout_realtime_timespec;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,11 +677,10 @@ Thread_Control *_Thread_queue_Do_dequeue(
|
||||
* - _Thread_queue_Context_set_thread_state(),
|
||||
*
|
||||
* - _Thread_queue_Context_set_enqueue_callout() or
|
||||
* _Thread_queue_Context_set_enqueue_do_nothing_extra(),
|
||||
*
|
||||
* - _Thread_queue_Context_set_no_timeout() or
|
||||
* _Thread_queue_Context_set_relative_timeout() or
|
||||
* _Thread_queue_Context_set_absolute_timeout(), and
|
||||
* _Thread_queue_Context_set_enqueue_do_nothing_extra() or
|
||||
* _Thread_queue_Context_set_enqueue_timeout_ticks() or
|
||||
* _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec() or
|
||||
* _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(),
|
||||
*
|
||||
* - _Thread_queue_Context_set_deadlock_callout().
|
||||
*
|
||||
@@ -652,7 +713,6 @@ Thread_Control *_Thread_queue_Do_dequeue(
|
||||
* STATES_WAITING_FOR_MUTEX
|
||||
* );
|
||||
* _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
* _Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
* _Thread_queue_Context_set_deadlock_callout(
|
||||
* queue_context,
|
||||
* _Thread_queue_Deadlock_fatal
|
||||
|
||||
@@ -298,46 +298,6 @@ RTEMS_INLINE_ROUTINE bool _TOD_Is_set( void )
|
||||
return _TOD.is_set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Absolute timeout conversion results.
|
||||
*
|
||||
* This enumeration defines the possible results of converting
|
||||
* an absolute time used for timeouts to POSIX blocking calls to
|
||||
* a number of ticks for example.
|
||||
*/
|
||||
typedef enum {
|
||||
/** The timeout is invalid. */
|
||||
TOD_ABSOLUTE_TIMEOUT_INVALID,
|
||||
/** The timeout represents a time that is in the past. */
|
||||
TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST,
|
||||
/** The timeout represents a time that is equal to the current time. */
|
||||
TOD_ABSOLUTE_TIMEOUT_IS_NOW,
|
||||
/** The timeout represents a time that is in the future. */
|
||||
TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE,
|
||||
} TOD_Absolute_timeout_conversion_results;
|
||||
|
||||
/**
|
||||
* @brief Convert absolute timeout to ticks.
|
||||
*
|
||||
* This method takes an absolute time being used as a timeout
|
||||
* to a blocking directive, validates it and returns the number
|
||||
* of corresponding clock ticks for use by the SuperCore.
|
||||
*
|
||||
* @param[in] abstime is a pointer to the timeout
|
||||
* @param[in] clock is the time source to use for the timeout
|
||||
* @param[out] ticks_out will contain the number of ticks
|
||||
*
|
||||
* @return This method returns the number of ticks in @a ticks_out
|
||||
* and a status value indicating whether the absolute time
|
||||
* is valid, in the past, equal to the current time or in
|
||||
* the future as it should be.
|
||||
*/
|
||||
TOD_Absolute_timeout_conversion_results _TOD_Absolute_timeout_to_ticks(
|
||||
const struct timespec *abstime,
|
||||
clockid_t clock,
|
||||
Watchdog_Interval *ticks_out
|
||||
);
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -53,36 +53,9 @@ typedef struct Watchdog_Control Watchdog_Control;
|
||||
typedef uint32_t Watchdog_Interval;
|
||||
|
||||
/**
|
||||
* @brief The clock discipline to use for the Watchdog timeout interval.
|
||||
* @brief Special watchdog ticks value to indicate an infinite wait.
|
||||
*/
|
||||
typedef enum {
|
||||
|
||||
/**
|
||||
* @brief Indefinite wait.
|
||||
*
|
||||
* This is to indicate there is no timeout and not to use a watchdog. It
|
||||
* must be equal to 0, which is an illegal relative clock interval, so that
|
||||
* it may be used as a Watchdog_Interval value with WATCHDOG_RELATIVE to
|
||||
* express an indefinite wait.
|
||||
*/
|
||||
WATCHDOG_NO_TIMEOUT = 0,
|
||||
|
||||
/**
|
||||
* @brief Relative clock.
|
||||
*
|
||||
* The reference time point for the watchdog is current ticks value
|
||||
* during insert. Time is measured in clock ticks.
|
||||
*/
|
||||
WATCHDOG_RELATIVE,
|
||||
|
||||
/**
|
||||
* @brief Absolute clock.
|
||||
*
|
||||
* The reference time point for this header is the POSIX Epoch. Time is
|
||||
* measured in nanoseconds since POSIX Epoch.
|
||||
*/
|
||||
WATCHDOG_ABSOLUTE
|
||||
} Watchdog_Discipline;
|
||||
#define WATCHDOG_NO_TIMEOUT 0
|
||||
|
||||
/**
|
||||
* @brief Return type from a Watchdog Service Routine.
|
||||
|
||||
@@ -284,6 +284,11 @@ RTEMS_INLINE_ROUTINE void _Watchdog_Next_first(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The maximum watchdog ticks value for the far future.
|
||||
*/
|
||||
#define WATCHDOG_MAXIMUM_TICKS UINT64_MAX
|
||||
|
||||
#define WATCHDOG_NANOSECONDS_PER_SECOND 1000000000
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,7 +33,7 @@ void _API_Mutex_Lock( API_Mutex_Control *the_mutex )
|
||||
|
||||
_Thread_queue_Context_initialize( &queue_context );
|
||||
_ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
_CORE_recursive_mutex_Seize(
|
||||
&the_mutex->Mutex,
|
||||
CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS,
|
||||
|
||||
@@ -84,11 +84,7 @@ typedef struct {
|
||||
struct _Mutex_Control *mutex;
|
||||
} Condition_Enqueue_context;
|
||||
|
||||
static void _Condition_Enqueue_callout(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
static void _Condition_Mutex_release( Thread_queue_Context *queue_context )
|
||||
{
|
||||
Condition_Enqueue_context *context;
|
||||
|
||||
@@ -96,6 +92,32 @@ static void _Condition_Enqueue_callout(
|
||||
_Mutex_Release( context->mutex );
|
||||
}
|
||||
|
||||
static void _Condition_Enqueue_no_timeout(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
_Condition_Mutex_release( queue_context );
|
||||
}
|
||||
|
||||
static void _Condition_Enqueue_with_timeout(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
_Thread_queue_Add_timeout_realtime_timespec(
|
||||
queue,
|
||||
the_thread,
|
||||
cpu_self,
|
||||
queue_context
|
||||
);
|
||||
_Condition_Mutex_release( queue_context );
|
||||
}
|
||||
|
||||
static Thread_Control *_Condition_Do_wait(
|
||||
struct _Condition_Control *_condition,
|
||||
struct _Mutex_Control *_mutex,
|
||||
@@ -107,15 +129,12 @@ static Thread_Control *_Condition_Do_wait(
|
||||
|
||||
context->mutex = _mutex;
|
||||
condition = _Condition_Get( _condition );
|
||||
_ISR_lock_ISR_disable( &context->Base.Lock_context.Lock_context );
|
||||
executing = _Condition_Queue_acquire_critical( condition, &context->Base );
|
||||
_Thread_queue_Context_set_thread_state(
|
||||
&context->Base,
|
||||
STATES_WAITING_FOR_CONDITION_VARIABLE
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&context->Base,
|
||||
_Condition_Enqueue_callout
|
||||
);
|
||||
_Thread_queue_Enqueue(
|
||||
&condition->Queue.Queue,
|
||||
CONDITION_TQ_OPERATIONS,
|
||||
@@ -134,8 +153,10 @@ void _Condition_Wait(
|
||||
Condition_Enqueue_context context;
|
||||
|
||||
_Thread_queue_Context_initialize( &context.Base );
|
||||
_ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
|
||||
_Thread_queue_Context_set_no_timeout( &context.Base );
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&context.Base,
|
||||
_Condition_Enqueue_no_timeout
|
||||
);
|
||||
_Condition_Do_wait( _condition, _mutex, &context );
|
||||
_Mutex_Acquire( _mutex );
|
||||
}
|
||||
@@ -149,24 +170,13 @@ int _Condition_Wait_timed(
|
||||
Condition_Enqueue_context context;
|
||||
Thread_Control *executing;
|
||||
int eno;
|
||||
Watchdog_Interval ticks;
|
||||
|
||||
_Thread_queue_Context_initialize( &context.Base );
|
||||
_ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
|
||||
|
||||
switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
|
||||
case TOD_ABSOLUTE_TIMEOUT_INVALID:
|
||||
_ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
|
||||
return EINVAL;
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
|
||||
_ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
|
||||
return ETIMEDOUT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_Thread_queue_Context_set_relative_timeout( &context.Base, ticks );
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&context.Base,
|
||||
_Condition_Enqueue_with_timeout
|
||||
);
|
||||
_Thread_queue_Context_set_timeout_argument( &context.Base, abstime );
|
||||
executing = _Condition_Do_wait( _condition, _mutex, &context );
|
||||
eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
|
||||
_Mutex_Acquire( _mutex );
|
||||
@@ -195,8 +205,10 @@ void _Condition_Wait_recursive(
|
||||
unsigned int nest_level;
|
||||
|
||||
_Thread_queue_Context_initialize( &context.Base );
|
||||
_ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
|
||||
_Thread_queue_Context_set_no_timeout( &context.Base );
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&context.Base,
|
||||
_Condition_Enqueue_no_timeout
|
||||
);
|
||||
nest_level = _Condition_Unnest_mutex( _mutex );
|
||||
_Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
|
||||
_Mutex_recursive_Acquire( _mutex );
|
||||
@@ -213,23 +225,13 @@ int _Condition_Wait_recursive_timed(
|
||||
Thread_Control *executing;
|
||||
int eno;
|
||||
unsigned int nest_level;
|
||||
Watchdog_Interval ticks;
|
||||
|
||||
_Thread_queue_Context_initialize( &context.Base );
|
||||
_ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
|
||||
|
||||
switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
|
||||
case TOD_ABSOLUTE_TIMEOUT_INVALID:
|
||||
_ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
|
||||
return EINVAL;
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
|
||||
_ISR_lock_ISR_enable( &context.Base.Lock_context.Lock_context );
|
||||
return ETIMEDOUT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_Thread_queue_Context_set_relative_timeout( &context.Base, ticks );
|
||||
_Thread_queue_Context_set_enqueue_callout(
|
||||
&context.Base,
|
||||
_Condition_Enqueue_with_timeout
|
||||
);
|
||||
_Thread_queue_Context_set_timeout_argument( &context.Base, abstime );
|
||||
nest_level = _Condition_Unnest_mutex( _mutex );
|
||||
executing = _Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
|
||||
eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
|
||||
|
||||
@@ -48,7 +48,6 @@ Status_Control _CORE_barrier_Seize(
|
||||
queue_context,
|
||||
STATES_WAITING_FOR_BARRIER
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
|
||||
_Thread_queue_Enqueue(
|
||||
&the_barrier->Wait_queue.Queue,
|
||||
CORE_BARRIER_TQ_OPERATIONS,
|
||||
|
||||
@@ -117,7 +117,6 @@ Status_Control _CORE_message_queue_Seize(
|
||||
queue_context,
|
||||
STATES_WAITING_FOR_MESSAGE
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
|
||||
_Thread_queue_Enqueue(
|
||||
&the_message_queue->Wait_queue.Queue,
|
||||
the_message_queue->operations,
|
||||
|
||||
@@ -135,7 +135,6 @@ Status_Control _CORE_message_queue_Submit(
|
||||
queue_context,
|
||||
STATES_WAITING_FOR_MESSAGE
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
|
||||
_Thread_queue_Enqueue(
|
||||
&the_message_queue->Wait_queue.Queue,
|
||||
the_message_queue->operations,
|
||||
|
||||
@@ -36,7 +36,6 @@ Status_Control _CORE_mutex_Seize_slow(
|
||||
queue_context,
|
||||
STATES_WAITING_FOR_MUTEX
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
|
||||
_Thread_queue_Context_set_deadlock_callout(
|
||||
queue_context,
|
||||
_Thread_queue_Deadlock_status
|
||||
|
||||
@@ -77,7 +77,6 @@ Status_Control _CORE_RWLock_Seize_for_reading(
|
||||
queue_context,
|
||||
STATES_WAITING_FOR_RWLOCK
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
|
||||
_Thread_queue_Enqueue(
|
||||
&the_rwlock->Queue.Queue,
|
||||
CORE_RWLOCK_TQ_OPERATIONS,
|
||||
|
||||
@@ -71,7 +71,6 @@ Status_Control _CORE_RWLock_Seize_for_writing(
|
||||
queue_context,
|
||||
STATES_WAITING_FOR_RWLOCK
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
|
||||
_Thread_queue_Enqueue(
|
||||
&the_rwlock->Queue.Queue,
|
||||
CORE_RWLOCK_TQ_OPERATIONS,
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Convert Absolute Timeout to Ticks
|
||||
* @ingroup ScoreTOD
|
||||
*/
|
||||
|
||||
/*
|
||||
* COPYRIGHT (c) 1989-2008.
|
||||
* 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/score/todimpl.h>
|
||||
|
||||
/*
|
||||
* The abstime is a walltime. We turn it into an interval.
|
||||
*/
|
||||
TOD_Absolute_timeout_conversion_results _TOD_Absolute_timeout_to_ticks(
|
||||
const struct timespec *abstime,
|
||||
clockid_t clock,
|
||||
Watchdog_Interval *ticks_out
|
||||
)
|
||||
{
|
||||
struct timespec current_time;
|
||||
struct timespec difference;
|
||||
|
||||
/*
|
||||
* Make sure there is always a value returned.
|
||||
*/
|
||||
*ticks_out = 0;
|
||||
|
||||
/*
|
||||
* Is the absolute time even valid?
|
||||
*/
|
||||
if ( !_Timespec_Is_valid(abstime) )
|
||||
return TOD_ABSOLUTE_TIMEOUT_INVALID;
|
||||
|
||||
/*
|
||||
* Is the absolute time in the past?
|
||||
*/
|
||||
if ( clock == CLOCK_REALTIME ) {
|
||||
_TOD_Get( ¤t_time );
|
||||
} else {
|
||||
_Assert( clock == CLOCK_MONOTONIC );
|
||||
_TOD_Get_zero_based_uptime_as_timespec( ¤t_time );
|
||||
}
|
||||
|
||||
if ( _Timespec_Less_than( abstime, ¤t_time ) )
|
||||
return TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST;
|
||||
|
||||
/*
|
||||
* How long until the requested absolute time?
|
||||
*/
|
||||
_Timespec_Subtract( ¤t_time, abstime, &difference );
|
||||
|
||||
/*
|
||||
* Internally the SuperCore uses ticks, so convert to them.
|
||||
*/
|
||||
*ticks_out = _Timespec_To_ticks( &difference );
|
||||
|
||||
/*
|
||||
* If the difference was 0, then the future is now. It is so bright
|
||||
* we better wear shades.
|
||||
*/
|
||||
if ( !*ticks_out )
|
||||
return TOD_ABSOLUTE_TIMEOUT_IS_NOW;
|
||||
|
||||
/*
|
||||
* This is the case we were expecting and it took this long to
|
||||
* get here.
|
||||
*/
|
||||
return TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,6 @@ int _Futex_Wait( struct _Futex_Control *_futex, int *uaddr, int val )
|
||||
STATES_WAITING_FOR_FUTEX
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_ISR_level( &queue_context, level );
|
||||
_Thread_queue_Enqueue(
|
||||
&futex->Queue.Queue,
|
||||
|
||||
+10
-33
@@ -102,7 +102,6 @@ static void _Mutex_Acquire_slow(
|
||||
queue_context,
|
||||
STATES_WAITING_FOR_MUTEX
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( queue_context );
|
||||
_Thread_queue_Context_set_deadlock_callout(
|
||||
queue_context,
|
||||
_Thread_queue_Deadlock_fatal
|
||||
@@ -163,7 +162,7 @@ void _Mutex_Acquire( struct _Mutex_Control *_mutex )
|
||||
_Thread_Resource_count_increment( executing );
|
||||
_Mutex_Queue_release( mutex, level, &queue_context );
|
||||
} else {
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
_Mutex_Acquire_slow( mutex, owner, executing, level, &queue_context );
|
||||
}
|
||||
}
|
||||
@@ -193,21 +192,10 @@ int _Mutex_Acquire_timed(
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
Watchdog_Interval ticks;
|
||||
|
||||
switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
|
||||
case TOD_ABSOLUTE_TIMEOUT_INVALID:
|
||||
_Mutex_Queue_release( mutex, level, &queue_context );
|
||||
return EINVAL;
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
|
||||
_Mutex_Queue_release( mutex, level, &queue_context );
|
||||
return ETIMEDOUT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
|
||||
_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
|
||||
&queue_context,
|
||||
abstime
|
||||
);
|
||||
_Mutex_Acquire_slow( mutex, owner, executing, level, &queue_context );
|
||||
|
||||
return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
|
||||
@@ -290,7 +278,7 @@ void _Mutex_recursive_Acquire( struct _Mutex_recursive_Control *_mutex )
|
||||
++mutex->nest_level;
|
||||
_Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
|
||||
} else {
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
_Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );
|
||||
}
|
||||
}
|
||||
@@ -325,21 +313,10 @@ int _Mutex_recursive_Acquire_timed(
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
Watchdog_Interval ticks;
|
||||
|
||||
switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) {
|
||||
case TOD_ABSOLUTE_TIMEOUT_INVALID:
|
||||
_Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
|
||||
return EINVAL;
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST:
|
||||
case TOD_ABSOLUTE_TIMEOUT_IS_NOW:
|
||||
_Mutex_Queue_release( &mutex->Mutex, level, &queue_context );
|
||||
return ETIMEDOUT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_Thread_queue_Context_set_relative_timeout( &queue_context, ticks );
|
||||
_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
|
||||
&queue_context,
|
||||
abstime
|
||||
);
|
||||
_Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context );
|
||||
|
||||
return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
|
||||
|
||||
@@ -61,7 +61,6 @@ void _Semaphore_Wait( struct _Semaphore_Control *_sem )
|
||||
STATES_WAITING_FOR_SEMAPHORE
|
||||
);
|
||||
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
|
||||
_Thread_queue_Context_set_no_timeout( &queue_context );
|
||||
_Thread_queue_Context_set_ISR_level( &queue_context, level );
|
||||
_Thread_queue_Enqueue(
|
||||
&sem->Queue.Queue,
|
||||
|
||||
@@ -359,6 +359,7 @@ bool _Thread_queue_Path_acquire_critical(
|
||||
void _Thread_queue_Enqueue_do_nothing_extra(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
@@ -375,36 +376,6 @@ void _Thread_queue_Deadlock_fatal( Thread_Control *the_thread )
|
||||
_Internal_error( INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK );
|
||||
}
|
||||
|
||||
static void _Thread_queue_Timeout(
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
switch ( queue_context->timeout_discipline ) {
|
||||
case WATCHDOG_RELATIVE:
|
||||
/* A relative timeout of 0 is a special case indefinite (no) timeout */
|
||||
if ( queue_context->timeout != 0 ) {
|
||||
_Thread_Add_timeout_ticks(
|
||||
the_thread,
|
||||
cpu_self,
|
||||
(Watchdog_Interval) queue_context->timeout
|
||||
);
|
||||
}
|
||||
break;
|
||||
case WATCHDOG_ABSOLUTE:
|
||||
_Thread_Timer_insert_realtime(
|
||||
the_thread,
|
||||
cpu_self,
|
||||
_Thread_Timeout,
|
||||
queue_context->timeout
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _Thread_queue_Enqueue(
|
||||
Thread_queue_Queue *queue,
|
||||
const Thread_queue_Operations *operations,
|
||||
@@ -416,7 +387,6 @@ void _Thread_queue_Enqueue(
|
||||
bool success;
|
||||
|
||||
_Assert( queue_context->enqueue_callout != NULL );
|
||||
_Assert( (uint8_t) queue_context->timeout_discipline != 0x7f );
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet ) {
|
||||
@@ -447,18 +417,18 @@ void _Thread_queue_Enqueue(
|
||||
cpu_self = _Thread_queue_Dispatch_disable( queue_context );
|
||||
_Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
|
||||
|
||||
( *queue_context->enqueue_callout )( queue, the_thread, queue_context );
|
||||
( *queue_context->enqueue_callout )(
|
||||
queue,
|
||||
the_thread,
|
||||
cpu_self,
|
||||
queue_context
|
||||
);
|
||||
|
||||
/*
|
||||
* Set the blocking state for this thread queue in the thread.
|
||||
*/
|
||||
_Thread_Set_state( the_thread, queue_context->thread_state );
|
||||
|
||||
/*
|
||||
* If the thread wants to timeout, then schedule its timer.
|
||||
*/
|
||||
_Thread_queue_Timeout( the_thread, cpu_self, queue_context );
|
||||
|
||||
/*
|
||||
* At this point thread dispatching is disabled, however, we already released
|
||||
* the thread queue lock. Thus, interrupts or threads on other processors
|
||||
@@ -491,6 +461,8 @@ Status_Control _Thread_queue_Enqueue_sticky(
|
||||
{
|
||||
Per_CPU_Control *cpu_self;
|
||||
|
||||
_Assert( queue_context->enqueue_callout != NULL );
|
||||
|
||||
_Thread_Wait_claim( the_thread, queue );
|
||||
|
||||
if ( !_Thread_queue_Path_acquire_critical( queue, the_thread, queue_context ) ) {
|
||||
@@ -519,7 +491,13 @@ Status_Control _Thread_queue_Enqueue_sticky(
|
||||
);
|
||||
}
|
||||
|
||||
_Thread_queue_Timeout( the_thread, cpu_self, queue_context );
|
||||
( *queue_context->enqueue_callout )(
|
||||
queue,
|
||||
the_thread,
|
||||
cpu_self,
|
||||
queue_context
|
||||
);
|
||||
|
||||
_Thread_Priority_update( queue_context );
|
||||
_Thread_Priority_and_sticky_update( the_thread, 1 );
|
||||
_Thread_Dispatch_enable( cpu_self );
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017 embedded brains GmbH
|
||||
*
|
||||
* 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/score/threadqimpl.h>
|
||||
#include <rtems/score/threadimpl.h>
|
||||
#include <rtems/score/watchdogimpl.h>
|
||||
|
||||
void _Thread_queue_Add_timeout_ticks(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
Watchdog_Interval ticks;
|
||||
|
||||
ticks = queue_context->Timeout.ticks;
|
||||
|
||||
if ( ticks != WATCHDOG_NO_TIMEOUT ) {
|
||||
_Thread_Add_timeout_ticks(
|
||||
the_thread,
|
||||
cpu_self,
|
||||
queue_context->Timeout.ticks
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static bool _Thread_queue_Lazy_insert_monotonic_timespec(
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
const struct timespec *abstime
|
||||
)
|
||||
{
|
||||
uint64_t expire;
|
||||
ISR_lock_Context lock_context;
|
||||
bool insert;
|
||||
|
||||
if ( abstime->tv_sec < 0 ) {
|
||||
expire = 0;
|
||||
} else if ( _Watchdog_Is_far_future_monotonic_timespec( abstime ) ) {
|
||||
expire = WATCHDOG_MAXIMUM_TICKS;
|
||||
} else {
|
||||
expire = _Watchdog_Monotonic_from_timespec( abstime );
|
||||
}
|
||||
|
||||
_ISR_lock_ISR_disable_and_acquire(
|
||||
&the_thread->Timer.Lock,
|
||||
&lock_context
|
||||
);
|
||||
|
||||
the_thread->Timer.header =
|
||||
&cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ];
|
||||
the_thread->Timer.Watchdog.routine = _Thread_Timeout;
|
||||
insert = _Watchdog_Per_CPU_lazy_insert_monotonic(
|
||||
&the_thread->Timer.Watchdog,
|
||||
cpu_self,
|
||||
expire
|
||||
);
|
||||
|
||||
_ISR_lock_Release_and_ISR_enable(
|
||||
&the_thread->Timer.Lock,
|
||||
&lock_context
|
||||
);
|
||||
return insert;
|
||||
}
|
||||
|
||||
void _Thread_queue_Add_timeout_monotonic_timespec(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
const struct timespec *abstime;
|
||||
|
||||
abstime = queue_context->Timeout.arg;
|
||||
|
||||
if ( _Watchdog_Is_valid_timespec( abstime ) ) {
|
||||
if (
|
||||
!_Thread_queue_Lazy_insert_monotonic_timespec(
|
||||
the_thread,
|
||||
cpu_self,
|
||||
abstime
|
||||
)
|
||||
) {
|
||||
_Thread_Continue( the_thread, STATUS_TIMEOUT );
|
||||
}
|
||||
} else {
|
||||
_Thread_Continue( the_thread, STATUS_INVALID_NUMBER );
|
||||
}
|
||||
}
|
||||
|
||||
void _Thread_queue_Add_timeout_realtime_timespec(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
const struct timespec *abstime;
|
||||
|
||||
abstime = queue_context->Timeout.arg;
|
||||
|
||||
if ( _Watchdog_Is_valid_timespec( abstime ) ) {
|
||||
uint64_t expire;
|
||||
struct timespec now;
|
||||
|
||||
if ( abstime->tv_sec < 0 ) {
|
||||
expire = 0;
|
||||
} else if ( _Watchdog_Is_far_future_realtime_timespec( abstime ) ) {
|
||||
expire = WATCHDOG_MAXIMUM_TICKS;
|
||||
} else {
|
||||
expire = _Watchdog_Realtime_from_timespec( abstime );
|
||||
}
|
||||
|
||||
_Timecounter_Getnanotime( &now );
|
||||
|
||||
if ( expire > _Watchdog_Realtime_from_timespec( &now ) ) {
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
_ISR_lock_ISR_disable_and_acquire(
|
||||
&the_thread->Timer.Lock,
|
||||
&lock_context
|
||||
);
|
||||
|
||||
the_thread->Timer.header =
|
||||
&cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ];
|
||||
the_thread->Timer.Watchdog.routine = _Thread_Timeout;
|
||||
_Watchdog_Per_CPU_insert_realtime(
|
||||
&the_thread->Timer.Watchdog,
|
||||
cpu_self,
|
||||
expire
|
||||
);
|
||||
|
||||
_ISR_lock_Release_and_ISR_enable(
|
||||
&the_thread->Timer.Lock,
|
||||
&lock_context
|
||||
);
|
||||
} else {
|
||||
_Thread_Continue( the_thread, STATUS_TIMEOUT );
|
||||
}
|
||||
} else {
|
||||
_Thread_Continue( the_thread, STATUS_INVALID_NUMBER );
|
||||
}
|
||||
}
|
||||
@@ -514,6 +514,7 @@ void _Thread_Cancel(
|
||||
static void _Thread_Close_enqueue_callout(
|
||||
Thread_queue_Queue *queue,
|
||||
Thread_Control *the_thread,
|
||||
Per_CPU_Control *cpu_self,
|
||||
Thread_queue_Context *queue_context
|
||||
)
|
||||
{
|
||||
@@ -534,7 +535,6 @@ void _Thread_Close(
|
||||
&context->Base,
|
||||
_Thread_Close_enqueue_callout
|
||||
);
|
||||
_Thread_queue_Context_set_no_timeout( &context->Base );
|
||||
_Thread_State_acquire_critical(
|
||||
the_thread,
|
||||
&context->Base.Lock_context.Lock_context
|
||||
|
||||
@@ -210,7 +210,7 @@ static void *POSIX_Init( void *argument )
|
||||
puts( "Init: pthread_create - SUCCESSFUL" );
|
||||
|
||||
/* Align with clock tick */
|
||||
usleep( 1 );
|
||||
sleep( 1 );
|
||||
|
||||
ctx->start = now();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user