/**************************************************************************** * sched/hrtimer/hrtimer_cancel.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 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 "hrtimer/hrtimer.h" /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: hrtimer_cancel * * Description: * Cancel a high-resolution timer asynchronously. * * If the timer is currently pending, it will be removed from the * hrtimer queue and will not be executed. * * If the timer callback is currently executing. This function set the * timer to the cancelled state. The caller will acquire the limited * ownership of the hrtimer, which allow the caller restart the hrtimer, * but the callback function may still be executing on another CPU, * which prevent the caller from freeing the hrtimer. * The caller must call `hrtimer_cancel_sync` to wait for the callback * to be finished. Please use the function with care. * Concurrency errors are prone to occur in this use case. * * If the canceled timer was the earliest expired timer in the queue, * the expiration of the underlying hardware timer will be updated to the * expiration time of the next earliest timer * * This function is non-blocking and does not wait for a running callback * to finish. * * Input Parameters: * hrtimer - Pointer to the high-resolution timer instance to cancel. * * Returned Value: * OK (0) on success; a negated errno value on failure. * > 0 on if the timer callback is running. * * Assumptions: * - The hrtimer is not NULL. * ****************************************************************************/ int hrtimer_cancel(FAR hrtimer_t *hrtimer) { FAR hrtimer_t *first; irqstate_t flags; int ret; DEBUGASSERT(hrtimer != NULL); /* Acquire the lock and seize the ownership of the hrtimer queue. */ flags = write_seqlock_irqsave(&g_hrtimer_lock); /* Ensure no core can write the hrtimer. */ ret = hrtimer_cancel_running(hrtimer); if (hrtimer_is_pending(hrtimer)) { /* Update the hardware timer if the queue head changed. */ if (hrtimer_remove(hrtimer)) { first = hrtimer_get_first(); hrtimer_reprogram(first->expired); } } /* Release the lock and give up the ownership of the hrtimer queue. */ write_sequnlock_irqrestore(&g_hrtimer_lock, flags); return ret; } /**************************************************************************** * Name: hrtimer_cancel_sync * * Description: * Cancel a high-resolution timer and synchronously wait the callback to * be finished. * * If the timer callback is running, this function set the timer to the * cancelled state and wait for all all references to be released. * The caller will then acquire full ownership of the hrtimer. After the * function returns, the caller can safely deallocate the hrtimer. * - If sleeping is allowed (normal task context), yields CPU briefly * to avoid busy-waiting. * - Otherwise (interrupt or idle task context), spins until completion. * * Input Parameters: * hrtimer - Pointer to the high-resolution timer instance to cancel. * * Returned Value: * OK (0) on success; a negated errno value on failure. * ****************************************************************************/ int hrtimer_cancel_sync(FAR hrtimer_t *hrtimer) { int ret = OK; DEBUGASSERT(hrtimer != NULL); /* Request cancellation of the timer */ ret = hrtimer_cancel(hrtimer); if (ret > 0) { /* Wait until all the timer callbacks finish. */ hrtimer_wait(hrtimer); } return ret; }