2008-01-31 18:59:22 +01:00
|
|
|
/****************************************************************************
|
2014-08-08 21:53:29 +02:00
|
|
|
* sched/semaphore/sem_wait.c
|
2007-02-18 00:21:28 +01:00
|
|
|
*
|
2020-04-05 18:39:35 +02:00
|
|
|
* 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
|
2007-02-18 00:21:28 +01:00
|
|
|
*
|
2020-04-05 18:39:35 +02:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2007-02-18 00:21:28 +01:00
|
|
|
*
|
2020-04-05 18:39:35 +02:00
|
|
|
* 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.
|
2007-02-18 00:21:28 +01:00
|
|
|
*
|
2008-01-31 18:59:22 +01:00
|
|
|
****************************************************************************/
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2008-01-31 18:59:22 +01:00
|
|
|
/****************************************************************************
|
2007-02-18 00:21:28 +01:00
|
|
|
* Included Files
|
2008-01-31 18:59:22 +01:00
|
|
|
****************************************************************************/
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2009-12-14 19:39:29 +01:00
|
|
|
#include <nuttx/config.h>
|
|
|
|
|
2009-12-14 22:15:18 +01:00
|
|
|
#include <stdbool.h>
|
2007-02-18 00:21:28 +01:00
|
|
|
#include <errno.h>
|
|
|
|
#include <assert.h>
|
2016-02-14 15:17:46 +01:00
|
|
|
|
2022-02-21 11:14:10 +01:00
|
|
|
#include <nuttx/init.h>
|
2016-02-14 15:17:46 +01:00
|
|
|
#include <nuttx/irq.h>
|
2007-02-18 00:21:28 +01:00
|
|
|
#include <nuttx/arch.h>
|
2016-12-10 16:08:26 +01:00
|
|
|
#include <nuttx/cancelpt.h>
|
2009-03-10 12:41:20 +01:00
|
|
|
|
2014-08-09 01:53:55 +02:00
|
|
|
#include "sched/sched.h"
|
2014-08-08 21:53:29 +02:00
|
|
|
#include "semaphore/semaphore.h"
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2008-01-31 18:59:22 +01:00
|
|
|
/****************************************************************************
|
2007-02-18 00:21:28 +01:00
|
|
|
* Public Functions
|
2008-01-31 18:59:22 +01:00
|
|
|
****************************************************************************/
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2008-01-31 18:59:22 +01:00
|
|
|
/****************************************************************************
|
2017-10-04 23:22:27 +02:00
|
|
|
* Name: nxsem_wait
|
2007-02-18 00:21:28 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2008-01-31 18:59:22 +01:00
|
|
|
* This function attempts to lock the semaphore referenced by 'sem'. If
|
|
|
|
* the semaphore value is (<=) zero, then the calling task will not return
|
|
|
|
* until it successfully acquires the lock.
|
2007-02-18 00:21:28 +01:00
|
|
|
*
|
2017-10-04 23:22:27 +02:00
|
|
|
* This is an internal OS interface. It is functionally equivalent to
|
|
|
|
* sem_wait except that:
|
|
|
|
*
|
2019-08-23 19:57:35 +02:00
|
|
|
* - It is not a cancellation point, and
|
2017-10-04 23:22:27 +02:00
|
|
|
* - It does not modify the errno value.
|
|
|
|
*
|
2018-03-13 16:52:27 +01:00
|
|
|
* Input Parameters:
|
2007-02-18 00:21:28 +01:00
|
|
|
* sem - Semaphore descriptor.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-10-04 23:22:27 +02:00
|
|
|
* This is an internal OS interface and should not be used by applications.
|
|
|
|
* It follows the NuttX internal error return policy: Zero (OK) is
|
|
|
|
* returned on success. A negated errno value is returned on failure.
|
|
|
|
* Possible returned errors:
|
|
|
|
*
|
2007-02-18 00:21:28 +01:00
|
|
|
* - EINVAL: Invalid attempt to get the semaphore
|
2008-01-31 18:59:22 +01:00
|
|
|
* - EINTR: The wait was interrupted by the receipt of a signal.
|
2007-02-18 00:21:28 +01:00
|
|
|
*
|
2008-01-31 18:59:22 +01:00
|
|
|
****************************************************************************/
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2017-10-04 23:22:27 +02:00
|
|
|
int nxsem_wait(FAR sem_t *sem)
|
2007-02-18 00:21:28 +01:00
|
|
|
{
|
2016-02-07 00:44:41 +01:00
|
|
|
FAR struct tcb_s *rtcb = this_task();
|
2016-02-14 15:17:46 +01:00
|
|
|
irqstate_t flags;
|
2022-11-13 13:39:14 +01:00
|
|
|
bool switch_needed;
|
2022-10-20 18:00:08 +02:00
|
|
|
int ret;
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-02-21 11:14:10 +01:00
|
|
|
/* This API should not be called from interrupt handlers & idleloop */
|
2007-03-10 01:17:29 +01:00
|
|
|
|
2016-11-09 14:01:49 +01:00
|
|
|
DEBUGASSERT(sem != NULL && up_interrupt_context() == false);
|
2022-02-21 11:14:10 +01:00
|
|
|
DEBUGASSERT(!OSINIT_IDLELOOP() || !sched_idletask());
|
2007-03-10 01:17:29 +01:00
|
|
|
|
2016-12-10 15:36:58 +01:00
|
|
|
/* The following operations must be performed with interrupts
|
2017-10-03 23:35:24 +02:00
|
|
|
* disabled because nxsem_post() may be called from an interrupt
|
2016-12-10 15:36:58 +01:00
|
|
|
* handler.
|
|
|
|
*/
|
2016-12-09 17:31:40 +01:00
|
|
|
|
2016-12-10 15:36:58 +01:00
|
|
|
flags = enter_critical_section();
|
2016-12-09 17:31:40 +01:00
|
|
|
|
2016-12-10 15:36:58 +01:00
|
|
|
/* Make sure we were supplied with a valid semaphore. */
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
/* Check if the lock is available */
|
|
|
|
|
|
|
|
if (sem->semcount > 0)
|
2016-12-10 15:36:58 +01:00
|
|
|
{
|
2022-10-20 18:00:08 +02:00
|
|
|
/* It is, let the task take the semaphore. */
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
sem->semcount--;
|
|
|
|
nxsem_add_holder(sem);
|
|
|
|
rtcb->waitobj = NULL;
|
|
|
|
ret = OK;
|
|
|
|
}
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
/* The semaphore is NOT available, We will have to block the
|
|
|
|
* current thread of execution.
|
|
|
|
*/
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
else
|
|
|
|
{
|
2022-12-19 07:55:12 +01:00
|
|
|
#ifdef CONFIG_PRIORITY_INHERITANCE
|
2023-01-10 17:10:48 +01:00
|
|
|
uint8_t prioinherit = sem->flags & SEM_PRIO_MASK;
|
2022-12-19 07:55:12 +01:00
|
|
|
#endif
|
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
/* First, verify that the task is not already waiting on a
|
|
|
|
* semaphore
|
2007-02-18 00:21:28 +01:00
|
|
|
*/
|
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
DEBUGASSERT(rtcb->waitobj == NULL);
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
/* Handle the POSIX semaphore (but don't set the owner yet) */
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
sem->semcount--;
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
/* Save the waited on semaphore in the TCB */
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
rtcb->waitobj = sem;
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
/* If priority inheritance is enabled, then check the priority of
|
|
|
|
* the holder of the semaphore.
|
|
|
|
*/
|
2009-03-09 00:33:41 +01:00
|
|
|
|
|
|
|
#ifdef CONFIG_PRIORITY_INHERITANCE
|
2023-01-10 17:10:48 +01:00
|
|
|
if (prioinherit == SEM_PRIO_INHERIT)
|
2022-12-19 07:55:12 +01:00
|
|
|
{
|
|
|
|
/* Disable context switching. The following operations must be
|
|
|
|
* atomic with regard to the scheduler.
|
|
|
|
*/
|
2009-03-09 00:33:41 +01:00
|
|
|
|
2022-12-19 07:55:12 +01:00
|
|
|
sched_lock();
|
2009-03-10 12:41:20 +01:00
|
|
|
|
2022-12-19 07:55:12 +01:00
|
|
|
/* Boost the priority of any threads holding a count on the
|
|
|
|
* semaphore.
|
|
|
|
*/
|
2009-03-10 12:41:20 +01:00
|
|
|
|
2022-12-19 07:55:12 +01:00
|
|
|
nxsem_boost_priority(sem);
|
|
|
|
}
|
2009-03-09 00:33:41 +01:00
|
|
|
#endif
|
2022-12-19 07:55:12 +01:00
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
/* Set the errno value to zero (preserving the original errno)
|
|
|
|
* value). We reuse the per-thread errno to pass information
|
|
|
|
* between sem_waitirq() and this functions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
rtcb->errcode = OK;
|
|
|
|
|
|
|
|
/* Add the TCB to the prioritized semaphore wait queue, after
|
|
|
|
* checking this is not the idle task - descheduling that
|
|
|
|
* isn't going to end well.
|
|
|
|
*/
|
|
|
|
|
|
|
|
DEBUGASSERT(!is_idle_task(rtcb));
|
2022-11-13 13:39:14 +01:00
|
|
|
|
|
|
|
/* Remove the tcb task from the ready-to-run list. */
|
|
|
|
|
|
|
|
switch_needed = nxsched_remove_readytorun(rtcb, true);
|
|
|
|
|
|
|
|
/* Add the task to the specified blocked task list */
|
|
|
|
|
|
|
|
rtcb->task_state = TSTATE_WAIT_SEM;
|
|
|
|
nxsched_add_prioritized(rtcb, SEM_WAITLIST(sem));
|
|
|
|
|
|
|
|
/* Now, perform the context switch if one is needed */
|
|
|
|
|
|
|
|
if (switch_needed)
|
|
|
|
{
|
2022-11-15 09:52:40 +01:00
|
|
|
up_switch_context(this_task(), rtcb);
|
2022-11-13 13:39:14 +01:00
|
|
|
}
|
2022-10-20 18:00:08 +02:00
|
|
|
|
|
|
|
/* When we resume at this point, either (1) the semaphore has been
|
|
|
|
* assigned to this thread of execution, or (2) the semaphore wait
|
|
|
|
* has been interrupted by a signal or a timeout. We can detect
|
|
|
|
* these latter cases be examining the per-thread errno value.
|
|
|
|
*
|
|
|
|
* In the event that the semaphore wait was interrupted by a
|
|
|
|
* signal or a timeout, certain semaphore clean-up operations have
|
|
|
|
* already been performed (see sem_waitirq.c). Specifically:
|
|
|
|
*
|
|
|
|
* - nxsem_canceled() was called to restore the priority of all
|
|
|
|
* threads that hold a reference to the semaphore,
|
|
|
|
* - The semaphore count was decremented, and
|
|
|
|
* - tcb->waitobj was nullifed.
|
|
|
|
*
|
|
|
|
* It is necessary to do these things in sem_waitirq.c because a
|
|
|
|
* long time may elapse between the time that the signal was issued
|
|
|
|
* and this thread is awakened and this leaves a door open to
|
|
|
|
* several race conditions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Check if an error occurred while we were sleeping. Expected
|
|
|
|
* errors include EINTR meaning that we were awakened by a signal
|
|
|
|
* or ETIMEDOUT meaning that the timer expired for the case of
|
|
|
|
* sem_timedwait().
|
|
|
|
*
|
|
|
|
* If we were not awakened by a signal or a timeout, then
|
|
|
|
* nxsem_add_holder() was called by logic in sem_wait() fore this
|
|
|
|
* thread was restarted.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ret = rtcb->errcode != OK ? -rtcb->errcode : OK;
|
2009-03-12 02:53:20 +01:00
|
|
|
|
|
|
|
#ifdef CONFIG_PRIORITY_INHERITANCE
|
2022-12-19 07:55:12 +01:00
|
|
|
if (prioinherit != 0)
|
|
|
|
{
|
|
|
|
sched_unlock();
|
|
|
|
}
|
2009-03-12 02:53:20 +01:00
|
|
|
#endif
|
2007-02-18 00:21:28 +01:00
|
|
|
}
|
2017-10-04 23:22:27 +02:00
|
|
|
|
|
|
|
leave_critical_section(flags);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
include/nuttx: Fix improper use of inline
I finally figured out why the ez80 code has gotten so big. It is because people have been put putting big inline functions in header files. That is a violation of the coding standard, since only c89 compatibility is required in all common code. But we have been tolerating inline function it because include/nuttx/compiler.h defines 'inline' to be nothing for C89 compilers.
As a result, static inline functions declared within a C file not so bad; the inline qualifier is ignored, if not supported, but otherwise all is well.
But it is catastrophic in header files. Those static inline functions are included as static functions and implemented in EVERY file that includes those header files, even if the functions are never called. That makes the code base huge!So there is another PR coming to fix some of the worst offenders.
This commit fixes two of the worst offenders I have encountered so far: include/nuttx/sempahore.h and cache.h. But there may be a few other changes needed. Under include/nuttx there are still inline functions thread.h, inclue/nuttx/list.h, mutex.h, tree.h, and include/nuttx/crypto/blake2s.h with no protection for compilers that do not handler the inline qualifier. Otherwise we are clean.
With the changes to these two header files, the size of the z20x build is reduced by about 40%. And incredible size savings.
2020-03-02 21:51:28 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: nxsem_wait_uninterruptible
|
|
|
|
*
|
|
|
|
* Description:
|
2020-04-05 18:39:35 +02:00
|
|
|
* This function is wrapped version of nxsem_wait(), which is
|
|
|
|
* uninterruptible and convenient for use.
|
include/nuttx: Fix improper use of inline
I finally figured out why the ez80 code has gotten so big. It is because people have been put putting big inline functions in header files. That is a violation of the coding standard, since only c89 compatibility is required in all common code. But we have been tolerating inline function it because include/nuttx/compiler.h defines 'inline' to be nothing for C89 compilers.
As a result, static inline functions declared within a C file not so bad; the inline qualifier is ignored, if not supported, but otherwise all is well.
But it is catastrophic in header files. Those static inline functions are included as static functions and implemented in EVERY file that includes those header files, even if the functions are never called. That makes the code base huge!So there is another PR coming to fix some of the worst offenders.
This commit fixes two of the worst offenders I have encountered so far: include/nuttx/sempahore.h and cache.h. But there may be a few other changes needed. Under include/nuttx there are still inline functions thread.h, inclue/nuttx/list.h, mutex.h, tree.h, and include/nuttx/crypto/blake2s.h with no protection for compilers that do not handler the inline qualifier. Otherwise we are clean.
With the changes to these two header files, the size of the z20x build is reduced by about 40%. And incredible size savings.
2020-03-02 21:51:28 +01:00
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* sem - Semaphore descriptor.
|
|
|
|
*
|
|
|
|
* Return Value:
|
2020-04-05 18:39:35 +02:00
|
|
|
* Zero(OK) - On success
|
|
|
|
* EINVAL - Invalid attempt to get the semaphore
|
|
|
|
* ECANCELED - May be returned if the thread is canceled while waiting.
|
include/nuttx: Fix improper use of inline
I finally figured out why the ez80 code has gotten so big. It is because people have been put putting big inline functions in header files. That is a violation of the coding standard, since only c89 compatibility is required in all common code. But we have been tolerating inline function it because include/nuttx/compiler.h defines 'inline' to be nothing for C89 compilers.
As a result, static inline functions declared within a C file not so bad; the inline qualifier is ignored, if not supported, but otherwise all is well.
But it is catastrophic in header files. Those static inline functions are included as static functions and implemented in EVERY file that includes those header files, even if the functions are never called. That makes the code base huge!So there is another PR coming to fix some of the worst offenders.
This commit fixes two of the worst offenders I have encountered so far: include/nuttx/sempahore.h and cache.h. But there may be a few other changes needed. Under include/nuttx there are still inline functions thread.h, inclue/nuttx/list.h, mutex.h, tree.h, and include/nuttx/crypto/blake2s.h with no protection for compilers that do not handler the inline qualifier. Otherwise we are clean.
With the changes to these two header files, the size of the z20x build is reduced by about 40%. And incredible size savings.
2020-03-02 21:51:28 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int nxsem_wait_uninterruptible(FAR sem_t *sem)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
/* Take the semaphore (perhaps waiting) */
|
|
|
|
|
|
|
|
ret = nxsem_wait(sem);
|
|
|
|
}
|
2020-04-05 18:39:35 +02:00
|
|
|
while (ret == -EINTR);
|
include/nuttx: Fix improper use of inline
I finally figured out why the ez80 code has gotten so big. It is because people have been put putting big inline functions in header files. That is a violation of the coding standard, since only c89 compatibility is required in all common code. But we have been tolerating inline function it because include/nuttx/compiler.h defines 'inline' to be nothing for C89 compilers.
As a result, static inline functions declared within a C file not so bad; the inline qualifier is ignored, if not supported, but otherwise all is well.
But it is catastrophic in header files. Those static inline functions are included as static functions and implemented in EVERY file that includes those header files, even if the functions are never called. That makes the code base huge!So there is another PR coming to fix some of the worst offenders.
This commit fixes two of the worst offenders I have encountered so far: include/nuttx/sempahore.h and cache.h. But there may be a few other changes needed. Under include/nuttx there are still inline functions thread.h, inclue/nuttx/list.h, mutex.h, tree.h, and include/nuttx/crypto/blake2s.h with no protection for compilers that do not handler the inline qualifier. Otherwise we are clean.
With the changes to these two header files, the size of the z20x build is reduced by about 40%. And incredible size savings.
2020-03-02 21:51:28 +01:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-10-04 23:22:27 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: sem_wait
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function attempts to lock the semaphore referenced by 'sem'. If
|
|
|
|
* the semaphore value is (<=) zero, then the calling task will not return
|
|
|
|
* until it successfully acquires the lock.
|
|
|
|
*
|
2018-03-13 16:52:27 +01:00
|
|
|
* Input Parameters:
|
2017-10-04 23:22:27 +02:00
|
|
|
* sem - Semaphore descriptor.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-10-04 23:22:27 +02:00
|
|
|
* This function is a standard, POSIX application interface. It returns
|
|
|
|
* zero (OK) if successful. Otherwise, -1 (ERROR) is returned and
|
|
|
|
* the errno value is set appropriately. Possible errno values include:
|
|
|
|
*
|
|
|
|
* - EINVAL: Invalid attempt to get the semaphore
|
|
|
|
* - EINTR: The wait was interrupted by the receipt of a signal.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int sem_wait(FAR sem_t *sem)
|
|
|
|
{
|
|
|
|
int errcode;
|
|
|
|
int ret;
|
|
|
|
|
2022-10-20 18:00:08 +02:00
|
|
|
if (sem == NULL)
|
|
|
|
{
|
|
|
|
set_errno(EINVAL);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
|
2017-10-04 23:22:27 +02:00
|
|
|
/* sem_wait() is a cancellation point */
|
|
|
|
|
|
|
|
if (enter_cancellation_point())
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_CANCELLATION_POINTS
|
|
|
|
/* If there is a pending cancellation, then do not perform
|
|
|
|
* the wait. Exit now with ECANCELED.
|
|
|
|
*/
|
|
|
|
|
|
|
|
errcode = ECANCELED;
|
|
|
|
goto errout_with_cancelpt;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Let nxsem_wait() do the real work */
|
|
|
|
|
|
|
|
ret = nxsem_wait(sem);
|
|
|
|
if (ret < 0)
|
2016-06-28 16:06:30 +02:00
|
|
|
{
|
2017-10-04 23:22:27 +02:00
|
|
|
errcode = -ret;
|
|
|
|
goto errout_with_cancelpt;
|
2016-06-28 16:06:30 +02:00
|
|
|
}
|
2007-02-18 00:21:28 +01:00
|
|
|
|
2016-12-09 17:31:40 +01:00
|
|
|
leave_cancellation_point();
|
2017-10-04 23:22:27 +02:00
|
|
|
return OK;
|
|
|
|
|
|
|
|
errout_with_cancelpt:
|
|
|
|
set_errno(errcode);
|
|
|
|
leave_cancellation_point();
|
|
|
|
return ERROR;
|
2007-02-18 00:21:28 +01:00
|
|
|
}
|