Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:27

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreThreadQueue
0007  *
0008  * @brief This source file contains the implementation of
0009  *   _Thread_queue_Add_timeout_ticks(), _Thread_queue_Add_timeout_timespec(),
0010  *   _Thread_queue_Add_timeout_monotonic_timespec(), and
0011  *   _Thread_queue_Add_timeout_realtime_timespec().
0012  */
0013 
0014 /*
0015  * Copyright (C) 2016, 2021 embedded brains GmbH & Co. KG
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042 
0043 #include <rtems/score/threadqimpl.h>
0044 #include <rtems/score/threadimpl.h>
0045 #include <rtems/score/watchdogimpl.h>
0046 
0047 void _Thread_queue_Add_timeout_ticks(
0048   Thread_queue_Queue   *queue,
0049   Thread_Control       *the_thread,
0050   Per_CPU_Control      *cpu_self,
0051   Thread_queue_Context *queue_context
0052 )
0053 {
0054   Watchdog_Interval ticks;
0055 
0056   (void) queue;
0057   ticks = queue_context->Timeout.ticks;
0058 
0059   if ( ticks != WATCHDOG_NO_TIMEOUT ) {
0060     _Thread_Add_timeout_ticks(
0061       the_thread,
0062       cpu_self,
0063       queue_context->Timeout.ticks
0064     );
0065   }
0066 }
0067 
0068 static void _Thread_queue_Add_timeout_timespec(
0069   Thread_queue_Queue    *queue,
0070   Thread_Control        *the_thread,
0071   Per_CPU_Control       *cpu_self,
0072   Thread_queue_Context  *queue_context,
0073   Watchdog_Header       *header,
0074   const struct timespec *now
0075 )
0076 {
0077   const struct timespec *abstime;
0078   struct timespec        base;
0079 
0080   if ( queue_context->timeout_absolute ) {
0081     abstime = queue_context->Timeout.arg;
0082   } else {
0083     base = *now;
0084     abstime = _Watchdog_Future_timespec( &base, queue_context->Timeout.arg );
0085   }
0086 
0087   if ( _Watchdog_Is_valid_timespec( abstime ) ) {
0088     uint64_t expire;
0089 
0090     if ( abstime->tv_sec < 0 ) {
0091       expire = 0;
0092     } else if ( _Watchdog_Is_far_future_timespec( abstime ) ) {
0093       expire = WATCHDOG_MAXIMUM_TICKS;
0094     } else {
0095       expire = _Watchdog_Ticks_from_timespec( abstime );
0096     }
0097 
0098     if ( expire > _Watchdog_Ticks_from_timespec( now ) ) {
0099       ISR_lock_Context lock_context;
0100 
0101       _ISR_lock_ISR_disable_and_acquire(
0102         &the_thread->Timer.Lock,
0103         &lock_context
0104       );
0105 
0106       the_thread->Timer.header = header;
0107       the_thread->Timer.Watchdog.routine = _Thread_Timeout;
0108       _Watchdog_Per_CPU_insert(
0109         &the_thread->Timer.Watchdog,
0110         cpu_self,
0111         header,
0112         expire
0113       );
0114 
0115       _ISR_lock_Release_and_ISR_enable(
0116         &the_thread->Timer.Lock,
0117         &lock_context
0118       );
0119     } else {
0120       _Thread_Continue( the_thread, STATUS_TIMEOUT );
0121     }
0122   } else {
0123     _Thread_Continue( the_thread, STATUS_INVALID_NUMBER );
0124   }
0125 }
0126 
0127 void _Thread_queue_Add_timeout_monotonic_timespec(
0128   Thread_queue_Queue   *queue,
0129   Thread_Control       *the_thread,
0130   Per_CPU_Control      *cpu_self,
0131   Thread_queue_Context *queue_context
0132 )
0133 {
0134   struct timespec now;
0135 
0136   _Timecounter_Nanouptime( &now );
0137   _Thread_queue_Add_timeout_timespec(
0138     queue,
0139     the_thread,
0140     cpu_self,
0141     queue_context,
0142     &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ],
0143     &now
0144   );
0145 }
0146 
0147 void _Thread_queue_Add_timeout_realtime_timespec(
0148   Thread_queue_Queue   *queue,
0149   Thread_Control       *the_thread,
0150   Per_CPU_Control      *cpu_self,
0151   Thread_queue_Context *queue_context
0152 )
0153 {
0154   struct timespec now;
0155 
0156   _Timecounter_Nanotime( &now );
0157   _Thread_queue_Add_timeout_timespec(
0158     queue,
0159     the_thread,
0160     cpu_self,
0161     queue_context,
0162     &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ],
0163     &now
0164   );
0165 }