Skip to content

Commit

Permalink
sched/semaphore: Move cancel point and errno handling to libc / user-…
Browse files Browse the repository at this point in the history
…space

This moves all the public POSIX semaphore functions into libc and with
this most of the user-space logic is also moved; namely cancel point and
errno handling.

This also removes the need for the _SEM_XX macros used to differentiate
which API is used per user-/kernel mode. Such macros are henceforth
unnecessary.
  • Loading branch information
pussuw committed Nov 23, 2023
1 parent ed877fd commit 538b731
Show file tree
Hide file tree
Showing 24 changed files with 566 additions and 470 deletions.
2 changes: 1 addition & 1 deletion arch/arm/src/stm32h7/stm32_ltdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1610,7 +1610,7 @@ static void stm32_ltdc_irqconfig(void)
*/

nxsem_init(g_interrupt.sem, 0, 0);
nxsem_set_protocol(g_interrupt.sem, SEM_PRIO_NONE);
nxsem_setprotocol(g_interrupt.sem, SEM_PRIO_NONE);

/* Attach LTDC interrupt vector */

Expand Down
51 changes: 3 additions & 48 deletions include/nuttx/semaphore.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,51 +57,6 @@
{(c), (f), SEM_WAITLIST_INITIALIZER}
#endif /* CONFIG_PRIORITY_INHERITANCE */

/* Most internal nxsem_* interfaces are not available in the user space in
* PROTECTED and KERNEL builds. In that context, the application semaphore
* interfaces must be used. The differences between the two sets of
* interfaces are: (1) the nxsem_* interfaces do not cause cancellation
* points and (2) they do not modify the errno variable.
*
* This is only important when compiling libraries (libc or libnx) that are
* used both by the OS (libkc.a and libknx.a) or by the applications
* (libc.a and libnx.a). In that case, the correct interface must be
* used for the build context.
*
* REVISIT: In the flat build, the same functions must be used both by
* the OS and by applications. We have to use the normal user functions
* in this case or we will fail to set the errno or fail to create the
* cancellation point.
*/

#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
# define _SEM_INIT(s,p,c) nxsem_init(s,p,c)
# define _SEM_DESTROY(s) nxsem_destroy(s)
# define _SEM_WAIT(s) nxsem_wait(s)
# define _SEM_TRYWAIT(s) nxsem_trywait(s)
# define _SEM_TIMEDWAIT(s,t) nxsem_timedwait(s,t)
# define _SEM_CLOCKWAIT(s,c,t) nxsem_clockwait(s,c,t)
# define _SEM_POST(s) nxsem_post(s)
# define _SEM_GETVALUE(s,v) nxsem_get_value(s,v)
# define _SEM_GETPROTOCOL(s,p) nxsem_get_protocol(s,p)
# define _SEM_SETPROTOCOL(s,p) nxsem_set_protocol(s,p)
# define _SEM_ERRNO(r) (-(r))
# define _SEM_ERRVAL(r) (r)
#else
# define _SEM_INIT(s,p,c) sem_init(s,p,c)
# define _SEM_DESTROY(s) sem_destroy(s)
# define _SEM_WAIT(s) sem_wait(s)
# define _SEM_TRYWAIT(s) sem_trywait(s)
# define _SEM_TIMEDWAIT(s,t) sem_timedwait(s,t)
# define _SEM_CLOCKWAIT(s,c,t) sem_clockwait(s,c,t)
# define _SEM_GETVALUE(s,v) sem_getvalue(s,v)
# define _SEM_POST(s) sem_post(s)
# define _SEM_GETPROTOCOL(s,p) sem_getprotocol(s,p)
# define _SEM_SETPROTOCOL(s,p) sem_setprotocol(s,p)
# define _SEM_ERRNO(r) errno
# define _SEM_ERRVAL(r) (-errno)
#endif

/****************************************************************************
* Public Type Definitions
****************************************************************************/
Expand Down Expand Up @@ -473,7 +428,7 @@ int nxsem_reset(FAR sem_t *sem, int16_t count);
#define nxsem_get_protocol(s,p) sem_getprotocol(s,p)

/****************************************************************************
* Name: nxsem_set_protocol
* Name: nxsem_setprotocol
*
* Description:
* Set semaphore protocol attribute.
Expand All @@ -493,7 +448,7 @@ int nxsem_reset(FAR sem_t *sem, int16_t count);
* becomes *permanently* a holder of the semaphore and may have its
* priority boosted when any other task tries to acquire the semaphore.
*
* The fix is to call nxsem_set_protocol(SEM_PRIO_NONE) immediately after
* The fix is to call nxsem_setprotocol(SEM_PRIO_NONE) immediately after
* the sem_init() call so that there will be no priority inheritance
* operations on this semaphore.
*
Expand All @@ -509,7 +464,7 @@ int nxsem_reset(FAR sem_t *sem, int16_t count);
*
****************************************************************************/

int nxsem_set_protocol(FAR sem_t *sem, int protocol);
int nxsem_setprotocol(FAR sem_t *sem, int protocol);

/****************************************************************************
* Name: nxsem_wait_uninterruptible
Expand Down
14 changes: 6 additions & 8 deletions include/sys/syscall_lookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,15 @@ SYSCALL_LOOKUP(sethostname, 2)

/* Semaphores */

SYSCALL_LOOKUP(nxsem_destroy, 1)
SYSCALL_LOOKUP(nxsem_post, 1)
SYSCALL_LOOKUP(nxsem_clockwait, 3)
SYSCALL_LOOKUP(nxsem_timedwait, 2)
SYSCALL_LOOKUP(nxsem_trywait, 1)
SYSCALL_LOOKUP(nxsem_wait, 1)

SYSCALL_LOOKUP(sem_destroy, 1)
SYSCALL_LOOKUP(sem_post, 1)
SYSCALL_LOOKUP(sem_clockwait, 3)
SYSCALL_LOOKUP(sem_timedwait, 2)
SYSCALL_LOOKUP(sem_trywait, 1)
SYSCALL_LOOKUP(sem_wait, 1)

#ifdef CONFIG_PRIORITY_INHERITANCE
SYSCALL_LOOKUP(sem_setprotocol, 2)
SYSCALL_LOOKUP(nxsem_setprotocol, 2)
#endif

/* Named semaphores */
Expand Down
27 changes: 11 additions & 16 deletions libs/libc/misc/lib_mutex.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,18 @@ static bool nxmutex_is_reset(FAR mutex_t *mutex)

int nxmutex_init(FAR mutex_t *mutex)
{
int ret = _SEM_INIT(&mutex->sem, 0, 1);
int ret = nxsem_init(&mutex->sem, 0, 1);

if (ret < 0)
{
return _SEM_ERRVAL(ret);
return ret;
}

mutex->holder = NXMUTEX_NO_HOLDER;
#ifdef CONFIG_PRIORITY_INHERITANCE
_SEM_SETPROTOCOL(&mutex->sem, SEM_TYPE_MUTEX | SEM_PRIO_INHERIT);
nxsem_setprotocol(&mutex->sem, SEM_TYPE_MUTEX | SEM_PRIO_INHERIT);
#else
_SEM_SETPROTOCOL(&mutex->sem, SEM_TYPE_MUTEX);
nxsem_setprotocol(&mutex->sem, SEM_TYPE_MUTEX);
#endif
return ret;
}
Expand All @@ -119,11 +119,11 @@ int nxmutex_init(FAR mutex_t *mutex)

int nxmutex_destroy(FAR mutex_t *mutex)
{
int ret = _SEM_DESTROY(&mutex->sem);
int ret = nxsem_destroy(&mutex->sem);

if (ret < 0)
{
return _SEM_ERRVAL(ret);
return ret;
}

mutex->holder = NXMUTEX_NO_HOLDER;
Expand Down Expand Up @@ -167,7 +167,7 @@ bool nxmutex_is_locked(FAR mutex_t *mutex)
int cnt;
int ret;

ret = _SEM_GETVALUE(&mutex->sem, &cnt);
ret = nxsem_get_value(&mutex->sem, &cnt);

return ret >= 0 && cnt < 1;
}
Expand Down Expand Up @@ -242,10 +242,10 @@ int nxmutex_trylock(FAR mutex_t *mutex)
int ret;

DEBUGASSERT(!nxmutex_is_hold(mutex));
ret = _SEM_TRYWAIT(&mutex->sem);
ret = nxsem_trywait(&mutex->sem);
if (ret < 0)
{
return _SEM_ERRVAL(ret);
return ret;
}

mutex->holder = _SCHED_GETTID();
Expand Down Expand Up @@ -291,11 +291,7 @@ int nxmutex_timedlock(FAR mutex_t *mutex, unsigned int timeout)

do
{
ret = _SEM_CLOCKWAIT(&mutex->sem, CLOCK_MONOTONIC, &rqtp);
if (ret < 0)
{
ret = _SEM_ERRVAL(ret);
}
ret = nxsem_clockwait(&mutex->sem, CLOCK_MONOTONIC, &rqtp);
}
while (ret == -EINTR || ret == -ECANCELED);

Expand Down Expand Up @@ -340,11 +336,10 @@ int nxmutex_unlock(FAR mutex_t *mutex)

mutex->holder = NXMUTEX_NO_HOLDER;

ret = _SEM_POST(&mutex->sem);
ret = nxsem_post(&mutex->sem);
if (ret < 0)
{
mutex->holder = _SCHED_GETTID();
ret = _SEM_ERRVAL(ret);
}

return ret;
Expand Down
16 changes: 11 additions & 5 deletions libs/libc/semaphore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@
#
# ##############################################################################

set(SRCS sem_init.c sem_getprotocol.c sem_getvalue.c)

if(NOT CONFIG_PRIORITY_INHERITANCE)
list(APPEND SRCS sem_setprotocol.c)
endif()
set(SRCS
sem_init.c
sem_setprotocol.c
sem_getprotocol.c
sem_getvalue.c
sem_destroy.c
sem_wait.c
sem_trywait.c
sem_timedwait.c
sem_clockwait.c
sem_post.c)

target_sources(c PRIVATE ${SRCS})
8 changes: 3 additions & 5 deletions libs/libc/semaphore/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@

# Add the semaphore C files to the build

CSRCS += sem_init.c sem_getprotocol.c sem_getvalue.c

ifneq ($(CONFIG_PRIORITY_INHERITANCE),y)
CSRCS += sem_setprotocol.c
endif
CSRCS += sem_init.c sem_setprotocol.c sem_getprotocol.c sem_getvalue.c
CSRCS += sem_destroy.c sem_wait.c sem_trywait.c sem_timedwait.c
CSRCS += sem_clockwait.c sem_post.c

# Add the semaphore directory to the build

Expand Down
104 changes: 104 additions & 0 deletions libs/libc/semaphore/sem_clockwait.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/****************************************************************************
* sched/semaphore/sem_clockwait.c
*
* 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 <nuttx/config.h>

#include <time.h>
#include <errno.h>

#include <nuttx/cancelpt.h>
#include <nuttx/semaphore.h>

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* Name: sem_clockwait
*
* Description:
* This function will lock the semaphore referenced by sem as in the
* sem_wait() function. However, if the semaphore cannot be locked without
* waiting for another process or thread to unlock the semaphore by
* performing a sem_post() function, this wait will be terminated when the
* specified timeout expires.
*
* The timeout will expire when the absolute time specified by abstime
* passes, as measured by the clock on which timeouts are based (that is,
* when the value of that clock equals or exceeds abstime), or if the
* absolute time specified by abstime has already been passed at the
* time of the call.
*
* Input Parameters:
* sem - Semaphore object
* clockid - The timing source to use in the conversion
* abstime - The absolute time to wait until a timeout is declared.
*
* Returned Value:
* Zero (OK) is returned on success. On failure, -1 (ERROR) is returned
* and the errno is set appropriately:
*
* EINVAL The sem argument does not refer to a valid semaphore. Or the
* thread would have blocked, and the abstime parameter specified
* a nanoseconds field value less than zero or greater than or
* equal to 1000 million.
* ETIMEDOUT The semaphore could not be locked before the specified timeout
* expired.
* EDEADLK A deadlock condition was detected.
* EINTR A signal interrupted this function.
* ECANCELED May be returned if the thread is canceled while waiting.
*
****************************************************************************/

int sem_clockwait(FAR sem_t *sem, clockid_t clockid,
FAR const struct timespec *abstime)
{
int ret;

/* Verify the input parameters and, in case of an error, set
* errno appropriately.
*/

if (sem == NULL || abstime == NULL)
{
set_errno(EINVAL);
return ERROR;
}

/* sem_timedwait() is a cancellation point */

enter_cancellation_point();

/* Let nxsem_timedout() do the work */

ret = nxsem_clockwait(sem, clockid, abstime);
if (ret < 0)
{
set_errno(-ret);
ret = ERROR;
}

leave_cancellation_point();
return ret;
}
Loading

0 comments on commit 538b731

Please sign in to comment.