Cancellation points: Close up some logic to eliminte some race conditions.
This commit is contained in:
parent
e9d3c3362a
commit
bc3ca25cc7
@ -88,7 +88,7 @@ int close(int fd)
|
|||||||
|
|
||||||
/* close() is a cancellation point */
|
/* close() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
/* Did we get a valid file descriptor? */
|
/* Did we get a valid file descriptor? */
|
||||||
|
@ -223,7 +223,7 @@ int fcntl(int fd, int cmd, ...)
|
|||||||
|
|
||||||
/* fcntl() is a cancellation point */
|
/* fcntl() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Setup to access the variable argument list */
|
/* Setup to access the variable argument list */
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ int fsync(int fd)
|
|||||||
|
|
||||||
/* fsync() is a cancellation point */
|
/* fsync() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Get the file structure corresponding to the file descriptor. */
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ int open(const char *path, int oflags, ...)
|
|||||||
|
|
||||||
/* open() is a cancellation point */
|
/* open() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* If the file is opened for creation, then get the mode bits */
|
/* If the file is opened for creation, then get the mode bits */
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
|
|||||||
|
|
||||||
/* poll() is a cancellation point */
|
/* poll() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* This semaphore is used for signaling and, hence, should not have
|
/* This semaphore is used for signaling and, hence, should not have
|
||||||
* priority inheritance enabled.
|
* priority inheritance enabled.
|
||||||
|
@ -145,7 +145,7 @@ ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset)
|
|||||||
|
|
||||||
/* pread() is a cancellation point */
|
/* pread() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Get the file structure corresponding to the file descriptor. */
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset)
|
|||||||
|
|
||||||
/* pread() is a cancellation point */
|
/* pread() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Get the file structure corresponding to the file descriptor. */
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
@ -161,6 +161,6 @@ ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset)
|
|||||||
ret = file_pwrite(filep, buf, nbytes, offset);
|
ret = file_pwrite(filep, buf, nbytes, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ ssize_t read(int fd, FAR void *buf, size_t nbytes)
|
|||||||
|
|
||||||
/* read() is a cancellation point */
|
/* read() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Did we get a valid file descriptor? */
|
/* Did we get a valid file descriptor? */
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
|
|||||||
|
|
||||||
/* select() is cancellation point */
|
/* select() is cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* How many pollfd structures do we need to allocate? */
|
/* How many pollfd structures do we need to allocate? */
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes)
|
|||||||
|
|
||||||
/* write() is a cancellation point */
|
/* write() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Did we get a valid file descriptor? */
|
/* Did we get a valid file descriptor? */
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
|
||||||
@ -170,12 +172,19 @@ EXTERN const pthread_attr_t g_default_pthread_attr;
|
|||||||
* pending cancellation and, if so, calls either exit() or
|
* pending cancellation and, if so, calls either exit() or
|
||||||
* pthread_exit(), depending upon the type of the thread.
|
* pthread_exit(), depending upon the type of the thread.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value
|
||||||
|
* true is returned if a cancellation is pending but cannot be performed
|
||||||
|
* now due to the nesting level.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_CANCELLATION_POINTS
|
#ifdef CONFIG_CANCELLATION_POINTS
|
||||||
void enter_cancellation_point(void);
|
bool enter_cancellation_point(void);
|
||||||
#else
|
#else
|
||||||
# define enter_cancellation_point()
|
# define enter_cancellation_point() false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -193,6 +202,12 @@ void enter_cancellation_point(void);
|
|||||||
* pending cancellation and, if so, calls either exit() or
|
* pending cancellation and, if so, calls either exit() or
|
||||||
* pthread_exit(), depending upon the type of the thread.
|
* pthread_exit(), depending upon the type of the thread.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value
|
||||||
|
* None
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_CANCELLATION_POINTS
|
#ifdef CONFIG_CANCELLATION_POINTS
|
||||||
|
@ -135,7 +135,7 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
|
|||||||
|
|
||||||
/* Treat as a cancellation point */
|
/* Treat as a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Is the socket a stream? */
|
/* Is the socket a stream? */
|
||||||
|
|
||||||
@ -365,7 +365,7 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
|||||||
|
|
||||||
/* accept() is a cancellation point */
|
/* accept() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Verify that the sockfd corresponds to valid, allocated socket */
|
/* Verify that the sockfd corresponds to valid, allocated socket */
|
||||||
|
|
||||||
|
@ -519,7 +519,7 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
|
|||||||
|
|
||||||
/* Treat as a cancellation point */
|
/* Treat as a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Verify that the psock corresponds to valid, allocated socket */
|
/* Verify that the psock corresponds to valid, allocated socket */
|
||||||
|
|
||||||
@ -752,7 +752,7 @@ int connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen)
|
|||||||
|
|
||||||
/* accept() is a cancellation point */
|
/* accept() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Get the underlying socket structure */
|
/* Get the underlying socket structure */
|
||||||
|
|
||||||
|
@ -1854,7 +1854,7 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||||||
|
|
||||||
/* Treat as a cancellation point */
|
/* Treat as a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Verify that non-NULL pointers were passed */
|
/* Verify that non-NULL pointers were passed */
|
||||||
|
|
||||||
@ -2087,7 +2087,7 @@ ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
|
|||||||
|
|
||||||
/* recvfrom() is a cancellation point */
|
/* recvfrom() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Get the underlying socket structure */
|
/* Get the underlying socket structure */
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
|
|||||||
|
|
||||||
/* Treat as a cancellation point */
|
/* Treat as a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
switch (psock->s_type)
|
switch (psock->s_type)
|
||||||
{
|
{
|
||||||
@ -273,7 +273,7 @@ ssize_t send(int sockfd, FAR const void *buf, size_t len, int flags)
|
|||||||
|
|
||||||
/* send() is a cancellation point */
|
/* send() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Get the underlying socket structure */
|
/* Get the underlying socket structure */
|
||||||
|
|
||||||
|
@ -314,7 +314,7 @@ ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags,
|
|||||||
|
|
||||||
/* sendto() is a cancellation point */
|
/* sendto() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Get the underlying socket structure */
|
/* Get the underlying socket structure */
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
|
#include <nuttx/pthread.h>
|
||||||
|
|
||||||
#include "sched/sched.h"
|
#include "sched/sched.h"
|
||||||
#include "mqueue/mqueue.h"
|
#include "mqueue/mqueue.h"
|
||||||
@ -141,6 +142,21 @@ FAR struct mqueue_msg_s *mq_waitreceive(mqd_t mqdes)
|
|||||||
FAR struct mqueue_inode_s *msgq;
|
FAR struct mqueue_inode_s *msgq;
|
||||||
FAR struct mqueue_msg_s *rcvmsg;
|
FAR struct mqueue_msg_s *rcvmsg;
|
||||||
|
|
||||||
|
/* mq_waitreceive() is not a cancellation point, but it is always called
|
||||||
|
* from a cancellation point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (enter_cancellation_point())
|
||||||
|
{
|
||||||
|
/* If there is a pending cancellation, then do not perform
|
||||||
|
* the wait. Exit now with ECANCELED.
|
||||||
|
*/
|
||||||
|
|
||||||
|
set_errno(ECANCELED);
|
||||||
|
leave_cancellation_point();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a pointer to the message queue */
|
/* Get a pointer to the message queue */
|
||||||
|
|
||||||
msgq = mqdes->msgq;
|
msgq = mqdes->msgq;
|
||||||
@ -195,6 +211,7 @@ FAR struct mqueue_msg_s *mq_waitreceive(mqd_t mqdes)
|
|||||||
msgq->nmsgs--;
|
msgq->nmsgs--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leave_cancellation_point();
|
||||||
return rcvmsg;
|
return rcvmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ ssize_t mq_receive(mqd_t mqdes, FAR char *msg, size_t msglen,
|
|||||||
|
|
||||||
/* mq_receive() is a cancellation point */
|
/* mq_receive() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Verify the input parameters and, in case of an error, set
|
/* Verify the input parameters and, in case of an error, set
|
||||||
* errno appropriately.
|
* errno appropriately.
|
||||||
|
@ -106,7 +106,7 @@ int mq_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio)
|
|||||||
|
|
||||||
/* mq_send() is a cancellation point */
|
/* mq_send() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Verify the input parameters -- setting errno appropriately
|
/* Verify the input parameters -- setting errno appropriately
|
||||||
* on any failures to verify.
|
* on any failures to verify.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* sched/mqueue/mq_send.c
|
* sched/mqueue/mq_sndinternal.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2009, 2013-2016 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007, 2009, 2013-2016 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
@ -53,6 +53,7 @@
|
|||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/sched.h>
|
#include <nuttx/sched.h>
|
||||||
#include <nuttx/signal.h>
|
#include <nuttx/signal.h>
|
||||||
|
#include <nuttx/pthread.h>
|
||||||
|
|
||||||
#include "sched/sched.h"
|
#include "sched/sched.h"
|
||||||
#ifndef CONFIG_DISABLE_SIGNALS
|
#ifndef CONFIG_DISABLE_SIGNALS
|
||||||
@ -232,6 +233,21 @@ int mq_waitsend(mqd_t mqdes)
|
|||||||
FAR struct tcb_s *rtcb;
|
FAR struct tcb_s *rtcb;
|
||||||
FAR struct mqueue_inode_s *msgq;
|
FAR struct mqueue_inode_s *msgq;
|
||||||
|
|
||||||
|
/* mq_waitsend() is not a cancellation point, but it is always called from
|
||||||
|
* a cancellation point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (enter_cancellation_point())
|
||||||
|
{
|
||||||
|
/* If there is a pending cancellation, then do not perform
|
||||||
|
* the wait. Exit now with ECANCELED.
|
||||||
|
*/
|
||||||
|
|
||||||
|
set_errno(ECANCELED);
|
||||||
|
leave_cancellation_point();
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a pointer to the message queue */
|
/* Get a pointer to the message queue */
|
||||||
|
|
||||||
msgq = mqdes->msgq;
|
msgq = mqdes->msgq;
|
||||||
@ -249,6 +265,7 @@ int mq_waitsend(mqd_t mqdes)
|
|||||||
/* No... We will return an error to the caller. */
|
/* No... We will return an error to the caller. */
|
||||||
|
|
||||||
set_errno(EAGAIN);
|
set_errno(EAGAIN);
|
||||||
|
leave_cancellation_point();
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,12 +300,14 @@ int mq_waitsend(mqd_t mqdes)
|
|||||||
|
|
||||||
if (get_errno() != OK)
|
if (get_errno() != OK)
|
||||||
{
|
{
|
||||||
|
leave_cancellation_point();
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leave_cancellation_point();
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ ssize_t mq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen,
|
|||||||
|
|
||||||
/* mq_timedreceive() is a cancellation point */
|
/* mq_timedreceive() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Verify the input parameters and, in case of an error, set
|
/* Verify the input parameters and, in case of an error, set
|
||||||
* errno appropriately.
|
* errno appropriately.
|
||||||
|
@ -181,7 +181,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
|
|||||||
|
|
||||||
/* mq_timedsend() is a cancellation point */
|
/* mq_timedsend() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Verify the input parameters -- setting errno appropriately
|
/* Verify the input parameters -- setting errno appropriately
|
||||||
* on any failures to verify.
|
* on any failures to verify.
|
||||||
|
@ -181,7 +181,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex,
|
|||||||
|
|
||||||
/* pthread_cond_timedwait() is a cancellation point */
|
/* pthread_cond_timedwait() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Make sure that non-NULL references were provided. */
|
/* Make sure that non-NULL references were provided. */
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex)
|
|||||||
|
|
||||||
/* pthread_cond_wait() is a cancellation point */
|
/* pthread_cond_wait() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Make sure that non-NULL references were provided. */
|
/* Make sure that non-NULL references were provided. */
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
|
|||||||
|
|
||||||
/* pthread_join() is a cancellation point */
|
/* pthread_join() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* First make sure that this is not an attempt to join to
|
/* First make sure that this is not an attempt to join to
|
||||||
* ourself.
|
* ourself.
|
||||||
|
@ -62,6 +62,6 @@
|
|||||||
|
|
||||||
void pthread_testcancel(void)
|
void pthread_testcancel(void)
|
||||||
{
|
{
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
leave_cancellation_point();
|
leave_cancellation_point();
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
|
|||||||
|
|
||||||
/* waitid() is a cancellation point */
|
/* waitid() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* MISSING LOGIC: If WNOHANG is provided in the options, then this function
|
/* MISSING LOGIC: If WNOHANG is provided in the options, then this function
|
||||||
* should returned immediately. However, there is no mechanism available now
|
* should returned immediately. However, there is no mechanism available now
|
||||||
|
@ -188,7 +188,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
|
|||||||
|
|
||||||
/* waitpid() is a cancellation point */
|
/* waitpid() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* None of the options are supported */
|
/* None of the options are supported */
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
|
|||||||
|
|
||||||
/* waitpid() is a cancellation point */
|
/* waitpid() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* None of the options are supported */
|
/* None of the options are supported */
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
|
|||||||
|
|
||||||
/* sem_timedwait() is a cancellation point */
|
/* sem_timedwait() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Verify the input parameters and, in case of an error, set
|
/* Verify the input parameters and, in case of an error, set
|
||||||
* errno appropriately.
|
* errno appropriately.
|
||||||
|
@ -87,21 +87,31 @@ int sem_wait(FAR sem_t *sem)
|
|||||||
|
|
||||||
DEBUGASSERT(sem != NULL && up_interrupt_context() == false);
|
DEBUGASSERT(sem != NULL && up_interrupt_context() == false);
|
||||||
|
|
||||||
/* sem_wait is a cancellation point */
|
/* The following operations must be performed with interrupts
|
||||||
|
* disabled because sem_post() may be called from an interrupt
|
||||||
|
* handler.
|
||||||
|
*/
|
||||||
|
|
||||||
enter_cancellation_point();
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* sem_wait() is a cancellation point */
|
||||||
|
|
||||||
|
if (enter_cancellation_point())
|
||||||
|
{
|
||||||
|
/* If there is a pending cancellation, then do not perform
|
||||||
|
* the wait. Exit now with ECANCELED.
|
||||||
|
*/
|
||||||
|
|
||||||
|
set_errno(ECANCELED);
|
||||||
|
leave_cancellation_point();
|
||||||
|
leave_critical_section(flags);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure we were supplied with a valid semaphore. */
|
/* Make sure we were supplied with a valid semaphore. */
|
||||||
|
|
||||||
if (sem != NULL)
|
if (sem != NULL)
|
||||||
{
|
{
|
||||||
/* The following operations must be performed with interrupts
|
|
||||||
* disabled because sem_post() may be called from an interrupt
|
|
||||||
* handler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
flags = enter_critical_section();
|
|
||||||
|
|
||||||
/* Check if the lock is available */
|
/* Check if the lock is available */
|
||||||
|
|
||||||
if (sem->semcount > 0)
|
if (sem->semcount > 0)
|
||||||
@ -191,10 +201,6 @@ int sem_wait(FAR sem_t *sem)
|
|||||||
sched_unlock();
|
sched_unlock();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interrupts may now be enabled. */
|
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -202,5 +208,6 @@ int sem_wait(FAR sem_t *sem)
|
|||||||
}
|
}
|
||||||
|
|
||||||
leave_cancellation_point();
|
leave_cancellation_point();
|
||||||
|
leave_critical_section(flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp)
|
|||||||
|
|
||||||
/* nanosleep() is a cancellation point */
|
/* nanosleep() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
if (!rqtp || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000)
|
if (!rqtp || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000)
|
||||||
{
|
{
|
||||||
|
@ -80,7 +80,7 @@ int pause(void)
|
|||||||
|
|
||||||
/* pause() is a cancellation point */
|
/* pause() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Set up for the sleep. Using the empty set means that we are not
|
/* Set up for the sleep. Using the empty set means that we are not
|
||||||
* waiting for any particular signal. However, any unmasked signal
|
* waiting for any particular signal. However, any unmasked signal
|
||||||
|
@ -101,7 +101,7 @@ int sigsuspend(FAR const sigset_t *set)
|
|||||||
|
|
||||||
/* sigsuspend() is a cancellation point */
|
/* sigsuspend() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Several operations must be performed below: We must determine if any
|
/* Several operations must be performed below: We must determine if any
|
||||||
* signal is pending and, if not, wait for the signal. Since signals can
|
* signal is pending and, if not, wait for the signal. Since signals can
|
||||||
|
@ -176,7 +176,7 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
|
|||||||
|
|
||||||
/* sigtimedwait() is a cancellation point */
|
/* sigtimedwait() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
sched_lock(); /* Not necessary */
|
sched_lock(); /* Not necessary */
|
||||||
|
|
||||||
/* Several operations must be performed below: We must determine if any
|
/* Several operations must be performed below: We must determine if any
|
||||||
|
@ -72,7 +72,7 @@ int sigwaitinfo(FAR const sigset_t *set, FAR struct siginfo *info)
|
|||||||
|
|
||||||
/* sigwaitinfo() is a cancellation point */
|
/* sigwaitinfo() is a cancellation point */
|
||||||
|
|
||||||
enter_cancellation_point();
|
(void)enter_cancellation_point();
|
||||||
|
|
||||||
/* Just a wrapper around sigtimedwait() */
|
/* Just a wrapper around sigtimedwait() */
|
||||||
|
|
||||||
|
@ -99,11 +99,19 @@
|
|||||||
* pending cancellation and, if so, calls either exit() or
|
* pending cancellation and, if so, calls either exit() or
|
||||||
* pthread_exit(), depending upon the type of the thread.
|
* pthread_exit(), depending upon the type of the thread.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value
|
||||||
|
* true is returned if a cancellation is pending but cannot be performed
|
||||||
|
* now due to the nesting level.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void enter_cancellation_point(void)
|
bool enter_cancellation_point(void)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *tcb = this_task();
|
FAR struct tcb_s *tcb = this_task();
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
/* Disabling pre-emption should provide sufficient protection. We only
|
/* Disabling pre-emption should provide sufficient protection. We only
|
||||||
* need the TCB to be stationary (no interrupt level modification is
|
* need the TCB to be stationary (no interrupt level modification is
|
||||||
@ -126,24 +134,32 @@ void enter_cancellation_point(void)
|
|||||||
(tcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0) ||
|
(tcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0) ||
|
||||||
tcb->cpcount > 0)
|
tcb->cpcount > 0)
|
||||||
{
|
{
|
||||||
/* If there is a pending cancellation and we are at the outermost
|
/* Check if there is a pending cancellation */
|
||||||
* nesting level of cancellation function calls, then just exit
|
|
||||||
* according to the type of the thread.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0 &&
|
if ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0)
|
||||||
tcb->cpcount == 0)
|
|
||||||
{
|
{
|
||||||
|
/* Yes... return true (if we don't exit here) */
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
/* If there is a pending cancellation and we are at the outermost
|
||||||
|
* nesting level of cancellation function calls, then exit
|
||||||
|
* according to the type of the thread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (tcb->cpcount == 0)
|
||||||
|
{
|
||||||
#ifndef CONFIG_DISABLE_PTHREAD
|
#ifndef CONFIG_DISABLE_PTHREAD
|
||||||
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
|
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
|
||||||
{
|
{
|
||||||
pthread_exit(PTHREAD_CANCELED);
|
pthread_exit(PTHREAD_CANCELED);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, indicate that we are at a cancellation point by
|
/* Otherwise, indicate that we are at a cancellation point by
|
||||||
@ -156,6 +172,7 @@ void enter_cancellation_point(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sched_unlock();
|
sched_unlock();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -173,6 +190,12 @@ void enter_cancellation_point(void)
|
|||||||
* pending cancellation and, if so, calls either exit() or
|
* pending cancellation and, if so, calls either exit() or
|
||||||
* pthread_exit(), depending upon the type of the thread.
|
* pthread_exit(), depending upon the type of the thread.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value
|
||||||
|
* None
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void leave_cancellation_point(void)
|
void leave_cancellation_point(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user