From 5f36a436099c0cff65211c405ac6240666228ec3 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Fri, 17 Nov 2023 14:06:48 +0200 Subject: [PATCH] sched/semaphore: Move named semaphores to user space --- fs/semaphore/sem_close.c | 6 +- fs/semaphore/sem_open.c | 43 +++------- fs/semaphore/sem_unlink.c | 18 ++--- include/nuttx/semaphore.h | 92 +++++++++++++++++++++ include/sys/syscall_lookup.h | 6 +- libs/libc/semaphore/CMakeLists.txt | 4 + libs/libc/semaphore/Make.defs | 4 + libs/libc/semaphore/sem_close.c | 75 +++++++++++++++++ libs/libc/semaphore/sem_open.c | 124 +++++++++++++++++++++++++++++ libs/libc/semaphore/sem_unlink.c | 68 ++++++++++++++++ syscall/syscall.csv | 6 +- 11 files changed, 393 insertions(+), 53 deletions(-) create mode 100644 libs/libc/semaphore/sem_close.c create mode 100644 libs/libc/semaphore/sem_open.c create mode 100644 libs/libc/semaphore/sem_unlink.c diff --git a/fs/semaphore/sem_close.c b/fs/semaphore/sem_close.c index 122236b941..90bc1f34b5 100644 --- a/fs/semaphore/sem_close.c +++ b/fs/semaphore/sem_close.c @@ -41,7 +41,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: sem_close + * Name: nxsem_close * * Description: * This function is called to indicate that the calling task is finished @@ -57,7 +57,7 @@ * sem - semaphore descriptor * * Returned Value: - * 0 (OK), or -1 (ERROR) if unsuccessful. + * 0 (OK), or negated errno if unsuccessful. * * Assumptions: * - Care must be taken to avoid risking the deletion of a semaphore that @@ -66,7 +66,7 @@ * ****************************************************************************/ -int sem_close(FAR sem_t *sem) +int nxsem_close(FAR sem_t *sem) { FAR struct nsem_inode_s *nsem; struct inode *inode; diff --git a/fs/semaphore/sem_open.c b/fs/semaphore/sem_open.c index 58894a0fea..7468ca8972 100644 --- a/fs/semaphore/sem_open.c +++ b/fs/semaphore/sem_open.c @@ -49,7 +49,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: sem_open + * Name: nxsem_open * * Description: * This function establishes a connection between named semaphores and a @@ -81,43 +81,23 @@ * SEM_VALUE_MAX. * * Returned Value: - * A pointer to sem_t or SEM_FAILED if unsuccessful. + * A pointer to sem_t or negated errno if unsuccessful. * * Assumptions: * ****************************************************************************/ -FAR sem_t *sem_open(FAR const char *name, int oflags, ...) +FAR sem_t *nxsem_open(FAR const char *name, int oflags, ...) { FAR struct inode *inode; FAR struct nsem_inode_s *nsem; - FAR sem_t *sem = (FAR sem_t *)ERROR; + FAR sem_t *sem; struct inode_search_s desc; char fullpath[MAX_SEMPATH]; mode_t mode; unsigned value; - int errcode; int ret; - /* Make sure that a non-NULL name is supplied */ - - DEBUGASSERT(name != NULL); - - if (name[0] == '/') - { - if (strlen(name) >= PATH_MAX) - { - set_errno(ENAMETOOLONG); - return SEM_FAILED; - } - - if (strlen(strrchr(name, '/') + 1) >= NAME_MAX) - { - set_errno(ENAMETOOLONG); - return SEM_FAILED; - } - } - /* Get the full path to the semaphore */ snprintf(fullpath, MAX_SEMPATH, @@ -141,7 +121,7 @@ FAR sem_t *sem_open(FAR const char *name, int oflags, ...) if (!INODE_IS_NAMEDSEM(inode)) { - errcode = ENXIO; + ret = -ENXIO; goto errout_with_inode; } @@ -151,7 +131,7 @@ FAR sem_t *sem_open(FAR const char *name, int oflags, ...) if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { - errcode = EEXIST; + ret = -EEXIST; goto errout_with_inode; } @@ -171,7 +151,7 @@ FAR sem_t *sem_open(FAR const char *name, int oflags, ...) { /* The semaphore does not exist and O_CREAT is not set */ - errcode = ENOENT; + ret = -ENOENT; goto errout_with_lock; } @@ -189,7 +169,7 @@ FAR sem_t *sem_open(FAR const char *name, int oflags, ...) if (value > SEM_VALUE_MAX) { - errcode = EINVAL; + ret = -EINVAL; goto errout_with_lock; } @@ -200,7 +180,6 @@ FAR sem_t *sem_open(FAR const char *name, int oflags, ...) ret = inode_lock(); if (ret < 0) { - errcode = -ret; goto errout_with_lock; } @@ -209,7 +188,6 @@ FAR sem_t *sem_open(FAR const char *name, int oflags, ...) if (ret < 0) { - errcode = -ret; goto errout_with_lock; } @@ -220,7 +198,7 @@ FAR sem_t *sem_open(FAR const char *name, int oflags, ...) nsem = group_malloc(NULL, sizeof(struct nsem_inode_s)); if (!nsem) { - errcode = ENOMEM; + ret = -ENOMEM; goto errout_with_inode; } @@ -251,8 +229,7 @@ errout_with_inode: errout_with_lock: RELEASE_SEARCH(&desc); - set_errno(errcode); - return SEM_FAILED; + return (FAR sem_t *)(intptr_t)ret; } #endif /* CONFIG_FS_NAMED_SEMAPHORES */ diff --git a/fs/semaphore/sem_unlink.c b/fs/semaphore/sem_unlink.c index 0b72524912..b90fef5268 100644 --- a/fs/semaphore/sem_unlink.c +++ b/fs/semaphore/sem_unlink.c @@ -41,7 +41,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: sem_unlink + * Name: nxsem_unlink * * Description: * This function removes the semaphore named by the input parameter 'name.' @@ -55,18 +55,17 @@ * name - Semaphore name * * Returned Value: - * 0 (OK), or -1 (ERROR) if unsuccessful. + * 0 (OK), or negated errno if unsuccessful. * * Assumptions: * ****************************************************************************/ -int sem_unlink(FAR const char *name) +int nxsem_unlink(FAR const char *name) { FAR struct inode *inode; struct inode_search_s desc; char fullpath[MAX_SEMPATH]; - int errcode; int ret; /* Get the full path to the semaphore */ @@ -83,7 +82,6 @@ int sem_unlink(FAR const char *name) { /* There is no inode that includes in this path */ - errcode = -ret; goto errout_with_search; } @@ -95,7 +93,7 @@ int sem_unlink(FAR const char *name) if (!INODE_IS_NAMEDSEM(inode)) { - errcode = ENOENT; + ret = -ENOENT; goto errout_with_inode; } @@ -106,13 +104,12 @@ int sem_unlink(FAR const char *name) ret = inode_lock(); if (ret < 0) { - errcode = -ret; goto errout_with_inode; } if (inode->i_child != NULL) { - errcode = ENOTEMPTY; + ret = -ENOTEMPTY; goto errout_with_lock; } @@ -139,7 +136,7 @@ int sem_unlink(FAR const char *name) */ inode_unlock(); - ret = sem_close(&inode->u.i_nsem->ns_sem); + ret = nxsem_close(&inode->u.i_nsem->ns_sem); RELEASE_SEARCH(&desc); return ret; @@ -151,6 +148,5 @@ errout_with_inode: errout_with_search: RELEASE_SEARCH(&desc); - set_errno(errcode); - return ERROR; + return ret; } diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h index 0b1becf4ea..274c0a4284 100644 --- a/include/nuttx/semaphore.h +++ b/include/nuttx/semaphore.h @@ -429,6 +429,98 @@ int nxsem_post(FAR sem_t *sem); int nxsem_get_value(FAR sem_t *sem, FAR int *sval); +/**************************************************************************** + * Name: nxsem_open + * + * Description: + * This function establishes a connection between named semaphores and a + * task. Following a call to sem_open() with the semaphore name, the task + * may reference the semaphore associated with name using the address + * returned by this call. The semaphore may be used in subsequent calls + * to sem_wait(), sem_trywait(), and sem_post(). The semaphore remains + * usable until the semaphore is closed by a successful call to + * sem_close(). + * + * If a task makes multiple calls to sem_open() with the same name, then + * the same semaphore address is returned (provided there have been no + * calls to sem_unlink()). + * + * Input Parameters: + * name - Semaphore name + * oflags - Semaphore creation options. This may either or both of the + * following bit settings. + * oflags = 0: Connect to the semaphore only if it already exists. + * oflags = O_CREAT: Connect to the semaphore if it exists, otherwise + * create the semaphore. + * oflags = O_CREAT|O_EXCL: Create a new semaphore + * unless one of this name already exists. + * Optional parameters. When the O_CREAT flag is specified, two optional + * parameters are expected: + * 1. mode_t mode, and + * 2. unsigned int value. This initial value of the semaphore. Valid + * initial values of the semaphore must be less than or equal to + * SEM_VALUE_MAX. + * + * Returned Value: + * A pointer to sem_t or negated errno if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +FAR sem_t *nxsem_open(FAR const char *name, int oflags, ...); + +/**************************************************************************** + * Name: nxsem_close + * + * Description: + * This function is called to indicate that the calling task is finished + * with the specified named semaphore, 'sem'. The sem_close() deallocates + * any system resources allocated by the system for this named semaphore. + * + * If the semaphore has not been removed with a call to sem_unlink(), then + * sem_close() has no effect on the named semaphore. However, when the + * named semaphore has been fully unlinked, the semaphore will vanish when + * the last task closes it. + * + * Input Parameters: + * sem - semaphore descriptor + * + * Returned Value: + * 0 (OK), or negated errno if unsuccessful. + * + * Assumptions: + * - Care must be taken to avoid risking the deletion of a semaphore that + * another calling task has already locked. + * - sem_close must not be called for an un-named semaphore + * + ****************************************************************************/ + +int nxsem_close(FAR sem_t *sem); + +/**************************************************************************** + * Name: nxsem_unlink + * + * Description: + * This function removes the semaphore named by the input parameter 'name.' + * If the semaphore named by 'name' is currently referenced by other task, + * the sem_unlink() will have no effect on the state of the semaphore. If + * one or more processes have the semaphore open when sem_unlink() is + * called, destruction of the semaphore will be postponed until all + * references to the semaphore have been destroyed by calls of sem_close(). + * + * Input Parameters: + * name - Semaphore name + * + * Returned Value: + * 0 (OK), or negated errno if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +int nxsem_unlink(FAR const char *name); + /**************************************************************************** * Name: nxsem_reset * diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index f8345dd053..b45b51cd56 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -89,9 +89,9 @@ SYSCALL_LOOKUP(nxsem_wait, 1) /* Named semaphores */ #ifdef CONFIG_FS_NAMED_SEMAPHORES - SYSCALL_LOOKUP(sem_open, 4) - SYSCALL_LOOKUP(sem_close, 1) - SYSCALL_LOOKUP(sem_unlink, 1) + SYSCALL_LOOKUP(nxsem_open, 4) + SYSCALL_LOOKUP(nxsem_close, 1) + SYSCALL_LOOKUP(nxsem_unlink, 1) #endif #ifndef CONFIG_BUILD_KERNEL diff --git a/libs/libc/semaphore/CMakeLists.txt b/libs/libc/semaphore/CMakeLists.txt index 07828da11f..76220ac926 100644 --- a/libs/libc/semaphore/CMakeLists.txt +++ b/libs/libc/semaphore/CMakeLists.txt @@ -30,4 +30,8 @@ set(SRCS sem_clockwait.c sem_post.c) +if(CONFIG_FS_NAMED_SEMAPHORES) + list(APPEND SRCS sem_open.c sem_close.c sem_unlink.c) +endif() + target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/semaphore/Make.defs b/libs/libc/semaphore/Make.defs index e2474489c6..b95d9f3c29 100644 --- a/libs/libc/semaphore/Make.defs +++ b/libs/libc/semaphore/Make.defs @@ -24,6 +24,10 @@ 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 +ifeq ($(CONFIG_FS_NAMED_SEMAPHORES),y) +CSRCS += sem_open.c sem_close.c sem_unlink.c +endif + # Add the semaphore directory to the build DEPPATH += --dep-path semaphore diff --git a/libs/libc/semaphore/sem_close.c b/libs/libc/semaphore/sem_close.c new file mode 100644 index 0000000000..ecd2888814 --- /dev/null +++ b/libs/libc/semaphore/sem_close.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * libs/libc/semaphore/sem_close.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 + +#include + +#ifdef CONFIG_FS_NAMED_SEMAPHORES + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_close + * + * Description: + * This function is called to indicate that the calling task is finished + * with the specified named semaphore, 'sem'. The sem_close() deallocates + * any system resources allocated by the system for this named semaphore. + * + * If the semaphore has not been removed with a call to sem_unlink(), then + * sem_close() has no effect on the named semaphore. However, when the + * named semaphore has been fully unlinked, the semaphore will vanish when + * the last task closes it. + * + * Input Parameters: + * sem - semaphore descriptor + * + * Returned Value: + * 0 (OK), or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * - Care must be taken to avoid risking the deletion of a semaphore that + * another calling task has already locked. + * - sem_close must not be called for an un-named semaphore + * + ****************************************************************************/ + +int sem_close(FAR sem_t *sem) +{ + int ret; + + ret = nxsem_close(sem); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return ret; +} + +#endif /* CONFIG_FS_NAMED_SEMAPHORES */ diff --git a/libs/libc/semaphore/sem_open.c b/libs/libc/semaphore/sem_open.c new file mode 100644 index 0000000000..bb21b28e18 --- /dev/null +++ b/libs/libc/semaphore/sem_open.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * libs/libc/semaphore/sem_open.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 + +#include +#include +#include +#include + +#include + +#ifdef CONFIG_FS_NAMED_SEMAPHORES + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_open + * + * Description: + * This function establishes a connection between named semaphores and a + * task. Following a call to sem_open() with the semaphore name, the task + * may reference the semaphore associated with name using the address + * returned by this call. The semaphore may be used in subsequent calls + * to sem_wait(), sem_trywait(), and sem_post(). The semaphore remains + * usable until the semaphore is closed by a successful call to + * sem_close(). + * + * If a task makes multiple calls to sem_open() with the same name, then + * the same semaphore address is returned (provided there have been no + * calls to sem_unlink()). + * + * Input Parameters: + * name - Semaphore name + * oflags - Semaphore creation options. This may either or both of the + * following bit settings. + * oflags = 0: Connect to the semaphore only if it already exists. + * oflags = O_CREAT: Connect to the semaphore if it exists, otherwise + * create the semaphore. + * oflags = O_CREAT|O_EXCL: Create a new semaphore + * unless one of this name already exists. + * Optional parameters. When the O_CREAT flag is specified, two optional + * parameters are expected: + * 1. mode_t mode, and + * 2. unsigned int value. This initial value of the semaphore. Valid + * initial values of the semaphore must be less than or equal to + * SEM_VALUE_MAX. + * + * Returned Value: + * A pointer to sem_t or SEM_FAILED if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +FAR sem_t *sem_open(FAR const char *name, int oflags, ...) +{ + FAR sem_t *sem; + va_list ap; + mode_t mode; + unsigned int value; + + /* Make sure that a non-NULL name is supplied */ + + DEBUGASSERT(name != NULL); + + if (name[0] == '/') + { + if (strlen(name) >= PATH_MAX) + { + set_errno(ENAMETOOLONG); + return SEM_FAILED; + } + + if (strlen(strrchr(name, '/') + 1) >= NAME_MAX) + { + set_errno(ENAMETOOLONG); + return SEM_FAILED; + } + } + + /* Off-load the variadic list */ + + va_start(ap, oflags); + mode = va_arg(ap, mode_t); + value = va_arg(ap, unsigned int); + va_end(ap); + + /* Let nxsem_open() do the work */ + + sem = nxsem_open(name, oflags, mode, value); + if (sem < 0) + { + set_errno(-((intptr_t)sem)); + return SEM_FAILED; + } + + return sem; +} + +#endif /* CONFIG_FS_NAMED_SEMAPHORES */ diff --git a/libs/libc/semaphore/sem_unlink.c b/libs/libc/semaphore/sem_unlink.c new file mode 100644 index 0000000000..77f2f856e2 --- /dev/null +++ b/libs/libc/semaphore/sem_unlink.c @@ -0,0 +1,68 @@ +/**************************************************************************** + * libs/libc/semaphore/sem_unlink.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 + +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_unlink + * + * Description: + * This function removes the semaphore named by the input parameter 'name.' + * If the semaphore named by 'name' is currently referenced by other task, + * the sem_unlink() will have no effect on the state of the semaphore. If + * one or more processes have the semaphore open when sem_unlink() is + * called, destruction of the semaphore will be postponed until all + * references to the semaphore have been destroyed by calls of sem_close(). + * + * Input Parameters: + * name - Semaphore name + * + * Returned Value: + * 0 (OK), or -1 (ERROR) if unsuccessful. + * + * Assumptions: + * + ****************************************************************************/ + +int sem_unlink(FAR const char *name) +{ + int ret; + + ret = nxsem_unlink(name); + if (ret < 0) + { + set_errno(-ret); + return ERROR; + } + + return ret; +} diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 7f07f27605..adb54f8c72 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -82,11 +82,14 @@ "nx_vsyslog","nuttx/syslog/syslog.h","","int","int","FAR const IPTR char *","FAR va_list *" "nxsched_get_stackinfo","nuttx/sched.h","","int","pid_t","FAR struct stackinfo_s *" "nxsem_clockwait","nuttx/semaphore.h","","int","FAR sem_t *","clockid_t","FAR const struct timespec *" +"nxsem_close","nuttx/semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","int","FAR sem_t *" "nxsem_destroy","nuttx/semaphore.h","","int","FAR sem_t *" +"nxsem_open","nuttx/semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","FAR sem_t *","FAR const char *","int","...","mode_t","unsigned int" "nxsem_post","nuttx/semaphore.h","","int","FAR sem_t *" "nxsem_set_protocol","nuttx/semaphore.h","defined(CONFIG_PRIORITY_INHERITANCE)","int","FAR sem_t *","int" "nxsem_timedwait","nuttx/semaphore.h","","int","FAR sem_t *","FAR const struct timespec *" "nxsem_trywait","nuttx/semaphore.h","","int","FAR sem_t *" +"nxsem_unlink","nuttx/semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","int","FAR const char *" "nxsem_wait","nuttx/semaphore.h","","int","FAR sem_t *" "open","fcntl.h","","int","FAR const char *","int","...","mode_t" "pgalloc", "nuttx/arch.h", "defined(CONFIG_BUILD_KERNEL)", "uintptr_t", "uintptr_t", "unsigned int" @@ -141,9 +144,6 @@ "sched_unlock","sched.h","","int" "sched_yield","sched.h","","int" "select","sys/select.h","","int","int","FAR fd_set *","FAR fd_set *","FAR fd_set *","FAR struct timeval *" -"sem_close","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","int","FAR sem_t *" -"sem_open","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","FAR sem_t *","FAR const char *","int","...","mode_t","unsigned int" -"sem_unlink","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","int","FAR const char *" "send","sys/socket.h","defined(CONFIG_NET)","ssize_t","int","FAR const void *","size_t","int" "sendfile","sys/sendfile.h","","ssize_t","int","int","FAR off_t *","size_t" "sendmsg","sys/socket.h","defined(CONFIG_NET)","ssize_t","int","FAR struct msghdr *","int"