diff --git a/sched/clock/CMakeLists.txt b/sched/clock/CMakeLists.txt index c2a12c8b167..9599bb972fd 100644 --- a/sched/clock/CMakeLists.txt +++ b/sched/clock/CMakeLists.txt @@ -28,6 +28,7 @@ set(SRCS clock_realtime2absticks.c clock_systime_ticks.c clock_systime_timespec.c + clock_sched_ticks.c clock_perf.c) # Unless a driver with a more accurate version of up_*delay is enabled, always diff --git a/sched/clock/Make.defs b/sched/clock/Make.defs index f0d281de23b..00b723b8af0 100644 --- a/sched/clock/Make.defs +++ b/sched/clock/Make.defs @@ -21,7 +21,7 @@ ############################################################################ CSRCS += clock.c clock_initialize.c clock_settime.c clock_gettime.c -CSRCS += clock_systime_ticks.c clock_systime_timespec.c +CSRCS += clock_systime_ticks.c clock_systime_timespec.c clock_sched_ticks.c CSRCS += clock_perf.c clock_realtime2absticks.c # Unless a driver with a more accurate version of up_*delay is enabled, always diff --git a/sched/clock/clock.h b/sched/clock/clock.h index acd076a6de1..cd9a3c9d42e 100644 --- a/sched/clock/clock.h +++ b/sched/clock/clock.h @@ -39,6 +39,10 @@ * Pre-processor Definitions ****************************************************************************/ +/* 32-bit mask for 64-bit timer values */ + +#define TIMER_MASK32 0x00000000ffffffff + /* Configuration ************************************************************/ /* If CONFIG_SYSTEM_TIME64 is selected and the CPU supports long long types, @@ -77,12 +81,10 @@ extern spinlock_t g_basetime_lock; int clock_basetime(FAR struct timespec *tp); void clock_initialize(void); -#if !defined(CONFIG_SCHED_TICKLESS) && \ - !defined(CONFIG_ALARM_ARCH) && !defined(CONFIG_TIMER_ARCH) -void clock_timer(void); -#else -# define clock_timer() -#endif + +void clock_increase_sched_ticks(clock_t ticks); + +clock_t clock_get_sched_ticks(void); /**************************************************************************** * perf_init diff --git a/sched/clock/clock_initialize.c b/sched/clock/clock_initialize.c index 8fa925730ee..124efbf1707 100644 --- a/sched/clock/clock_initialize.c +++ b/sched/clock/clock_initialize.c @@ -51,10 +51,7 @@ * Public Data ****************************************************************************/ -#if !defined(CONFIG_SCHED_TICKLESS) && \ - !defined(CONFIG_ALARM_ARCH) && !defined(CONFIG_TIMER_ARCH) volatile clock_t g_system_ticks = INITIAL_SYSTEM_TIMER_TICKS; -#endif #ifndef CONFIG_CLOCK_TIMEKEEPING struct timespec g_basetime; @@ -387,27 +384,3 @@ void clock_resynchronize(FAR struct timespec *rtc_diff) } } #endif - -/**************************************************************************** - * Name: clock_timer - * - * Description: - * This function must be called once every time the real time clock - * interrupt occurs. The interval of this clock interrupt must be - * USEC_PER_TICK - * - ****************************************************************************/ - -#if !defined(CONFIG_SCHED_TICKLESS) && \ - !defined(CONFIG_ALARM_ARCH) && !defined(CONFIG_TIMER_ARCH) -void clock_timer(void) -{ - /* Increment the per-tick system counter */ - -#ifdef CONFIG_SYSTEM_TIME64 - atomic64_fetch_add((FAR atomic64_t *)&g_system_ticks, 1); -#else - atomic_fetch_add((FAR atomic_t *)&g_system_ticks, 1); -#endif -} -#endif diff --git a/sched/clock/clock_sched_ticks.c b/sched/clock/clock_sched_ticks.c new file mode 100644 index 00000000000..0635a5d4b84 --- /dev/null +++ b/sched/clock/clock_sched_ticks.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * sched/clock/clock_sched_ticks.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include "clock/clock.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: clock_increase_sched_ticks + * + * Description: + * Increment the scheduler tick counter. This function should be called + * each time the real-time clock interrupt occurs, indicating the passage + * of one or more scheduling ticks. + * + * Input Parameters: + * ticks - The number of ticks to increment (typically 1) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void clock_increase_sched_ticks(clock_t ticks) +{ + /* Increment the per-tick scheduler counter */ + +#ifdef CONFIG_SYSTEM_TIME64 + atomic64_fetch_add((FAR atomic64_t *)&g_system_ticks, ticks); +#else + atomic_fetch_add((FAR atomic_t *)&g_system_ticks, ticks); +#endif +} + +/**************************************************************************** + * Name: clock_get_sched_ticks + * + * Description: + * Return the current value of the scheduler tick counter. This counter + * only increases while the scheduler is running, and is independent of + * the real-time clock. + * + * Returned Value: + * The current number of scheduler ticks. + * + ****************************************************************************/ + +clock_t clock_get_sched_ticks(void) +{ +#ifdef CONFIG_SYSTEM_TIME64 + clock_t sample; + clock_t verify; + + /* 64-bit accesses are not atomic on most architectures. The following + * loop samples the 64-bit counter twice and retries in the rare case + * that a 32-bit rollover occurs between samples. + * + * If no 32-bit rollover occurs: + * - The MS 32 bits of both samples will be identical, and + * - The LS 32 bits of the second sample will be greater than or equal + * to those of the first. + */ + + do + { + verify = g_system_ticks; + sample = g_system_ticks; + } + while ((sample & TIMER_MASK32) < (verify & TIMER_MASK32) || + (sample & ~TIMER_MASK32) != (verify & ~TIMER_MASK32)); + + return sample; +#else + /* On 32-bit systems, atomic access is guaranteed */ + + return g_system_ticks; +#endif +} diff --git a/sched/clock/clock_systime_ticks.c b/sched/clock/clock_systime_ticks.c index 5a377353e60..04939bb19e6 100644 --- a/sched/clock/clock_systime_ticks.c +++ b/sched/clock/clock_systime_ticks.c @@ -42,10 +42,6 @@ #undef clock_systime_ticks -/* 32-bit mask for 64-bit timer values */ - -#define TIMER_MASK32 0x00000000ffffffff - /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/sched/sched/sched_processtimer.c b/sched/sched/sched_processtimer.c index abea66b666b..6dbf2d15509 100644 --- a/sched/sched/sched_processtimer.c +++ b/sched/sched/sched_processtimer.c @@ -184,7 +184,7 @@ void nxsched_process_timer(void) /* Increment the system time (if in the link) */ - clock_timer(); + clock_increase_sched_ticks(1); /* Check if the currently executing task has exceeded its * timeslice. diff --git a/sched/sched/sched_timerexpiration.c b/sched/sched/sched_timerexpiration.c index c6ff34fecba..b1e99ab2537 100644 --- a/sched/sched/sched_timerexpiration.c +++ b/sched/sched/sched_timerexpiration.c @@ -480,6 +480,8 @@ void nxsched_alarm_tick_expiration(clock_t ticks) elapsed = ticks - update_time_tick(ticks); + clock_increase_sched_ticks(elapsed); + /* Process the timer ticks and set up the next interval (or not) */ nexttime = nxsched_timer_process(ticks, elapsed, false); @@ -528,6 +530,8 @@ void nxsched_timer_expiration(void) update_time_tick(ticks); elapsed = atomic_read(&g_timer_interval); + clock_increase_sched_ticks(elapsed); + /* Process the timer ticks and set up the next interval (or not) */ nexttime = nxsched_timer_process(ticks, elapsed, false);