Merge branch 'cancelpt'

This commit is contained in:
Gregory Nutt
2016-12-09 17:02:18 -06:00
58 changed files with 1425 additions and 316 deletions
File diff suppressed because it is too large Load Diff
+47 -43
View File
@@ -166,9 +166,9 @@ o Task/Scheduler (sched/)
Priority: Low
Title: REMOVE TASK_DELETE
Description: Need to remove or fix task delete(). This interface is non-
standard and not safe. Arbitrary deleting tasks can cause
serious problems such as memory leaks and resources like
Description: Need to remove asychronous fix task_delete(). This interface
is non-standard and not safe. Arbitrary deleting tasks can
cause serious problems such as memory leaks and resources like
semaphores left in bad states.
Task/process exit callbacks registered via atexit() or
@@ -187,10 +187,12 @@ o Task/Scheduler (sched/)
apps/netutils/thttpd to kill CGI tasks that timeout. So not
so simple to remove.
Option: Perhaps task_delete() should not do asynchronous
deletion but should rather do the same kind of
synchronization such as the pthread_cancellation points?
(see pthread_cancel() issues).
Option: With CONFIG_CANCELLATION_POINTS=y task_delete()
does not do asynchronous deletion but should rather do the
same kind of synchronization such as the pthread cancellation
points. In this configuration, none of the issues above
apply. It is only the asyncrhonous task deletion that cannot
be supported.
Status: Open
Priority: Low and not easily removable.
@@ -528,42 +530,6 @@ o Signals (sched/signal, arch/)
o pthreads (sched/pthreads)
^^^^^^^^^^^^^^^^^
Title: CANCELLATION POINTS
Description: pthread_cancel(): Should implement cancellation points and
pthread_testcancel().
Internal implementation perhaps as follows. See list of
functions that are cancellation points on OpenGroup.org. In
general:
- Two types of cancellation. DEFFERRED and ASYCNCHOOUS:
PTHREAD_CANCEL_DEFERRED: A cancellation request is deferred
until the thread next calls a function that is a cancellation
point. This is the default cancelability type for all
threads.
PTHREAD_CANCEL_ASYNCHRONOUS: The thread can be canceled at
any time
DEFERRED should be the default but currently only
asyncrhononous is supported by NuttX
- To implement DEFERRED mode:
All cancellations must pend.
Check if the thread is within cancellation region, then
treat like a signal to wake up with -ECANCELED vs -EINTER
For each function/cancellation point
- Call enter_cancellation region() on entry. Checks for
pending cancellation and marks "within cancellation region"
in TCB flags.
- Will wake-up with -ECANCELED if cancellation occurs.
- Call leave_cancellation region() on exit. Checks for
pending cancellation and marks NOT "within cancellation region"
Perhaps task_delete() should do the same kind of synchronization?
Status: Open. No changes are planned.
Priority: Low, probably not that useful
Title: PTHREAD_PRIO_PROTECT
Description: Extend pthread_mutexattr_setprotocol() support PTHREAD_PRIO_PROTECT:
@@ -624,6 +590,44 @@ o pthreads (sched/pthreads)
solution. So I discarded a few hours of programming. Not a
big loss from the experience I gained."
Title: ISSUES WITH CANCELLATION POINTS
Description: According to POIX cancellation points must occur when a thread is executing
the following functions. There are some execptions as noted:
accept() mq_timedsend() NA putpmsg() sigtimedwait()
-4 aio_suspend() NA msgrcv() pwrite() NA sigwait()
NA clock_nanosleep() NA msgsnd() read() sigwaitinfo()
close() NA msync() NA readv() -1 sleep()
connect() nanosleep() recv() -2 system()
OK creat() open() recvfrom() NA tcdrain()
fcntl() pause() NA recvmsg() -1 usleep()
NA fdatasync() poll() select() OK wait()
fsync() pread() sem_timedwait() waitid()
NA getmsg() NA pselect() sem_wait() waitpid()
NA getpmsg() pthread_cond_timedwait() send() write()
NA lockf() pthread_cond_wait() NA sendmsg() NA writev()
mq_receive() pthread_join() sendto()
mq_send() pthread_testcancel() -3 sigpause()
mq_timedreceive() NA putmsg() sigsuspend()
NA Not supported
OK Doesn't need instrumentation. Handled by lower level calls.
-n See note n
NOTE 1: sleep() and usleep() are user-space functions in the C library and cannot
serve as cancellation points. They are, however, simple wrappers around nanosleep
which is a true cancellation point.
NOTE 2: system() is actually implemented in apps/ as part of NSH. It cannot be
a cancellation point either.
NOTE 3: sigpause() is a user-space function in the C library and cannot serve as
cancellation points. It is, however, a simple wrapper around sigsuspend()
which is a true cancellation point.
NOTE 4: aio_suspend() is a user-space function in the C library and cannot serve as
cancellation points. It does call around sigtimedwait() which is a true cancellation
point.
Status: Not really open. This is just the way it is.
Priority: Nothing additional is planned.
o Message Queues (sched/mqueue)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3
View File
@@ -62,7 +62,10 @@ pthread_mutex_init NXpthread_mutex_init
pthread_mutex_lock NXpthread_mutex_lock
pthread_mutex_unlock NXpthread_mutex_unlock
pthread_setspecific NXpthread_setspecific
pthread_setcancelstate NXpthread_setcancelstate
pthread_setcanceltype NXpthread_setcanceltype
pthread_sigmask NXpthread_sigmask
pthread_testcancel NXpthread_testcancel
pthread_yield NXpthread_yield
ptsname NXptsname
ptsname_r NXptsname_r
+14 -2
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_close.c
*
* Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2012, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,8 @@
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <nuttx/pthread.h>
#include <nuttx/fs/fs.h>
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
@@ -82,7 +84,13 @@ int close(int fd)
int errcode;
#if CONFIG_NFILE_DESCRIPTORS > 0
int ret;
#endif
/* close() is a cancellation point */
enter_cancellation_point();
#if CONFIG_NFILE_DESCRIPTORS > 0
/* Did we get a valid file descriptor? */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
@@ -93,7 +101,9 @@ int close(int fd)
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
return net_close(fd);
ret = net_close(fd);
leave_cancellation_point();
return ret;
}
else
#endif
@@ -123,11 +133,13 @@ int close(int fd)
goto errout;
}
leave_cancellation_point();
return OK;
#endif
errout:
set_errno(errcode);
leave_cancellation_point();
return ERROR;
}
+10 -10
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_fcntl.c
*
* Copyright (C) 2009, 2012-2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2009, 2012-2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -44,20 +44,13 @@
#include <errno.h>
#include <assert.h>
#include <nuttx/sched.h>
#include <nuttx/pthread.h>
#include <nuttx/fs/fs.h>
#include <nuttx/net/net.h>
#include <nuttx/sched.h>
#include "inode/inode.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -228,6 +221,10 @@ int fcntl(int fd, int cmd, ...)
va_list ap;
int ret;
/* fcntl() is a cancellation point */
enter_cancellation_point();
/* Setup to access the variable argument list */
va_start(ap, cmd);
@@ -244,6 +241,8 @@ int fcntl(int fd, int cmd, ...)
{
/* The errno value has already been set */
va_end(ap);
leave_cancellation_point();
return ERROR;
}
@@ -273,5 +272,6 @@ int fcntl(int fd, int cmd, ...)
}
va_end(ap);
leave_cancellation_point();
return ret;
}
+12 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_fsync.c
*
* Copyright (C) 2007-2009, 2013-2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2013-2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -44,8 +44,9 @@
#include <errno.h>
#include <assert.h>
#include <nuttx/fs/fs.h>
#include <nuttx/sched.h>
#include <nuttx/pthread.h>
#include <nuttx/fs/fs.h>
#include "inode/inode.h"
@@ -117,6 +118,11 @@ errout:
int fsync(int fd)
{
FAR struct file *filep;
int ret;
/* fsync() is a cancellation point */
enter_cancellation_point();
/* Get the file structure corresponding to the file descriptor. */
@@ -125,12 +131,15 @@ int fsync(int fd)
{
/* The errno value has already been set */
leave_cancellation_point();
return ERROR;
}
/* Perform the fsync operation */
return file_fsync(filep);
ret = file_fsync(filep);
leave_cancellation_point();
return ret;
}
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
+10 -5
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_open.c
*
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2012, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -48,15 +48,12 @@
#include <stdarg.h>
#endif
#include <nuttx/pthread.h>
#include <nuttx/fs/fs.h>
#include "inode/inode.h"
#include "driver/driver.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -106,6 +103,10 @@ int open(const char *path, int oflags, ...)
# warning "File creation not implemented"
# endif
/* open() is a cancellation point */
enter_cancellation_point();
/* If the file is opened for creation, then get the mode bits */
if ((oflags & (O_WRONLY | O_CREAT)) != 0)
@@ -159,6 +160,7 @@ int open(const char *path, int oflags, ...)
/* Return the file descriptor */
leave_cancellation_point();
return fd;
}
else
@@ -204,6 +206,7 @@ int open(const char *path, int oflags, ...)
{
/* The errno value has already been set */
leave_cancellation_point();
return ERROR;
}
@@ -264,6 +267,7 @@ int open(const char *path, int oflags, ...)
}
#endif
leave_cancellation_point();
return fd;
errout_with_fd:
@@ -272,5 +276,6 @@ errout_with_inode:
inode_release(inode);
errout:
set_errno(ret);
leave_cancellation_point();
return ERROR;
}
+6
View File
@@ -48,6 +48,7 @@
#include <nuttx/clock.h>
#include <nuttx/semaphore.h>
#include <nuttx/pthread.h>
#include <nuttx/fs/fs.h>
#include <nuttx/net/net.h>
@@ -365,6 +366,10 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
int errcode;
int ret;
/* poll() is a cancellation point */
enter_cancellation_point();
/* This semaphore is used for signaling and, hence, should not have
* priority inheritance enabled.
*/
@@ -425,6 +430,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
}
sem_destroy(&sem);
leave_cancellation_point();
/* Check for errors */
+16 -9
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_pread.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -43,12 +43,9 @@
#include <unistd.h>
#include <errno.h>
#include <nuttx/pthread.h>
#include <nuttx/fs/fs.h>
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -144,6 +141,11 @@ ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes,
ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset)
{
FAR struct file *filep;
ssize_t ret;
/* pread() is a cancellation point */
enter_cancellation_point();
/* Get the file structure corresponding to the file descriptor. */
@@ -152,10 +154,15 @@ ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset)
{
/* The errno value has already been set */
return (ssize_t)ERROR;
ret = (ssize_t)ERROR;
}
else
{
/* Let file_pread do the real work */
ret = file_pread(filep, buf, nbytes, offset);
}
/* Let file_pread do the real work */
return file_pread(filep, buf, nbytes, offset);
leave_cancellation_point();
return ret;
}
+16 -9
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_pwrite.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -43,12 +43,9 @@
#include <unistd.h>
#include <errno.h>
#include <nuttx/pthread.h>
#include <nuttx/fs/fs.h>
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -142,6 +139,11 @@ ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf,
ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset)
{
FAR struct file *filep;
ssize_t ret;
/* pread() is a cancellation point */
enter_cancellation_point();
/* Get the file structure corresponding to the file descriptor. */
@@ -150,10 +152,15 @@ ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset)
{
/* The errno value has already been set */
return (ssize_t)ERROR;
ret = (ssize_t)ERROR;
}
else
{
/* Let file_pread do the real work */
ret = file_pwrite(filep, buf, nbytes, offset);
}
/* Let file_pread do the real work */
return file_pwrite(filep, buf, nbytes, offset);
enter_cancellation_point();
return ret;
}
+29 -16
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_read.c
*
* Copyright (C) 2007-2009, 2012-2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2012-2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -38,19 +38,17 @@
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>
#include <errno.h>
#include "inode/inode.h"
#include <nuttx/pthread.h>
/****************************************************************************
* Private Functions
****************************************************************************/
#include "inode/inode.h"
/****************************************************************************
* Public Functions
@@ -136,23 +134,30 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
ssize_t read(int fd, FAR void *buf, size_t nbytes)
{
ssize_t ret;
/* read() is a cancellation point */
enter_cancellation_point();
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
/* No.. If networking is enabled, read() is the same as recv() with
* the flags parameter set to zero.
* the flags parameter set to zero. Note that recv() sets
* the errno variable.
*/
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
return recv(fd, buf, nbytes, 0);
ret = recv(fd, buf, nbytes, 0);
#else
/* No networking... it is a bad descriptor in any event */
set_errno(EBADF);
return ERROR;
ret = ERROR;
#endif
}
@@ -162,20 +167,28 @@ ssize_t read(int fd, FAR void *buf, size_t nbytes)
FAR struct file *filep;
/* The descriptor is in a valid range to file descriptor... do the
* read. First, get the file structure.
* read. First, get the file structure. Note that on failure,
* fs_getfilep() will set the errno variable.
*/
filep = fs_getfilep(fd);
if (!filep)
if (filep == NULL)
{
/* The errno value has already been set */
return ERROR;
ret = ERROR;
}
else
{
/* Then let file_read do all of the work. Note that file_read()
* sets the errno variable.
*/
/* Then let file_read do all of the work */
return file_read(filep, buf, nbytes);
ret = file_read(filep, buf, nbytes);
}
}
#endif
leave_cancellation_point();
return ret;
}
+6
View File
@@ -110,6 +110,10 @@ int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
int ndx;
int ret;
/* select() is cancellation point */
enter_cancellation_point();
/* How many pollfd structures do we need to allocate? */
/* Initialize the descriptor list for poll() */
@@ -134,6 +138,7 @@ int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
if (!pollset)
{
set_errno(ENOMEM);
leave_cancellation_point();
return ERROR;
}
@@ -280,6 +285,7 @@ int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
set_errno(errcode);
}
leave_cancellation_point();
return ret;
}
+39 -22
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_write.c
*
* Copyright (C) 2007-2009, 2012-2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2012-2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
@@ -49,11 +50,9 @@
# include <sys/socket.h>
#endif
#include "inode/inode.h"
#include <nuttx/pthread.h>
/****************************************************************************
* Private Functions
****************************************************************************/
#include "inode/inode.h"
/****************************************************************************
* Public Functions
@@ -72,7 +71,7 @@
ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
{
FAR struct inode *inode;
int ret;
ssize_t ret;
int errcode;
/* Was this file opened for write access? */
@@ -163,6 +162,11 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes)
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep;
#endif
ssize_t ret;
/* write() is a cancellation point */
enter_cancellation_point();
/* Did we get a valid file descriptor? */
@@ -170,31 +174,44 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes)
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
/* Write to a socket descriptor is equivalent to send with flags == 0 */
#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0
return send(fd, buf, nbytes, 0);
/* Write to a socket descriptor is equivalent to send with flags == 0.
* Note that send() will set the errno on failure.
*/
ret = send(fd, buf, nbytes, 0);
#else
set_errno(EBADF);
return ERROR;
ret = ERROR ERROR;
#endif
}
#if CONFIG_NFILE_DESCRIPTORS > 0
/* The descriptor is in the right range to be a file descriptor... write
* to the file.
*/
filep = fs_getfilep(fd);
if (!filep)
else
{
/* The errno value has already been set */
/* The descriptor is in the right range to be a file descriptor..
* write to the file. Note that fs_getfilep() will set the errno on
* failure.
*/
return ERROR;
filep = fs_getfilep(fd);
if (filep == NULL)
{
/* The errno value has already been set */
ret = ERROR;
}
else
{
/* Perform the write operation using the file descriptor as an
* index. Note that file_write() will set the errno on failure.
*/
ret = file_write(filep, buf, nbytes);
}
#endif
}
/* Perform the write operation using the file descriptor as an index */
return file_write(filep, buf, nbytes);
#endif
leave_cancellation_point();
return ret;
}
+75 -1
View File
@@ -2,7 +2,7 @@
* include/nuttx/pthread.h
* Non-standard, NuttX-specific pthread-related declarations.
*
* Copyright (C) 2011, 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2011, 2015-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -127,6 +127,80 @@ EXTERN const pthread_attr_t g_default_pthread_attr;
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Cancellation Points.
*
* Cancellation points shall occur when a thread is executing the following
* functions:
*
* accept() mq_timedsend() putpmsg() sigtimedwait()
* aio_suspend() msgrcv() pwrite() sigwait()
* clock_nanosleep() msgsnd() read() sigwaitinfo()
* close() msync() readv() sleep()
* connect() nanosleep() recv() system()
* creat() open() recvfrom() tcdrain()
* fcntl() pause() recvmsg() usleep()
* fdatasync() poll() select() wait()
* fsync() pread() sem_timedwait() waitid()
* getmsg() pselect() sem_wait() waitpid()
* getpmsg() pthread_cond_timedwait() send() write()
* lockf() pthread_cond_wait() sendmsg() writev()
* mq_receive() pthread_join() sendto()
* mq_send() pthread_testcancel() sigpause()
* mq_timedreceive() putmsg() sigsuspend()
*
* Each of the above function must call enter_cancellation_point() on entry
* in order to establish the cancellation point and leave_cancellation_point()
* on exit. These functions are described below.
*
****************************************************************************/
/****************************************************************************
* Name: enter_cancellation_point
*
* Description:
* Called at the beginning of the cancellation point to establish the
* cancellation point. This function does the following:
*
* 1. If deferred cancellation does not apply to this thread, nothing is
* done, otherwise, it
* 2. Sets state information in the caller's TCB and increments a nesting
* count.
* 3. If this is the outermost nesting level, it checks if there is a
* pending cancellation and, if so, calls either exit() or
* pthread_exit(), depending upon the type of the thread.
*
****************************************************************************/
#ifdef CONFIG_CANCELLATION_POINTS
void enter_cancellation_point(void);
#else
# define enter_cancellation_point()
#endif
/****************************************************************************
* Name: leave_cancellation_point
*
* Description:
* Called at the end of the cancellation point. This function does the
* following:
*
* 1. If deferred cancellation does not apply to this thread, nothing is
* done, otherwise, it
* 2. Clears state information in the caller's TCB and decrements a
* nesting count.
* 3. If this is the outermost nesting level, it checks if there is a
* pending cancellation and, if so, calls either exit() or
* pthread_exit(), depending upon the type of the thread.
*
****************************************************************************/
#ifdef CONFIG_CANCELLATION_POINTS
void leave_cancellation_point(void);
#else
# define leave_cancellation_point()
#endif
#undef EXTERN
#ifdef __cplusplus
}
+9 -5
View File
@@ -141,16 +141,17 @@
# define TCB_FLAG_TTYPE_PTHREAD (1 << TCB_FLAG_TTYPE_SHIFT) /* User pthread */
# define TCB_FLAG_TTYPE_KERNEL (2 << TCB_FLAG_TTYPE_SHIFT) /* Kernel thread */
#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */
#define TCB_FLAG_CANCEL_PENDING (1 << 3) /* Bit 3: Pthread cancel is pending */
#define TCB_FLAG_POLICY_SHIFT (4) /* Bit 4-5: Scheduling policy */
#define TCB_FLAG_CANCEL_DEFERRED (1 << 3) /* Bit 3: Deferred (vs asynch) cancellation type */
#define TCB_FLAG_CANCEL_PENDING (1 << 4) /* Bit 4: Pthread cancel is pending */
#define TCB_FLAG_POLICY_SHIFT (5) /* Bit 5-6: Scheduling policy */
#define TCB_FLAG_POLICY_MASK (3 << TCB_FLAG_POLICY_SHIFT)
# define TCB_FLAG_SCHED_FIFO (0 << TCB_FLAG_POLICY_SHIFT) /* FIFO scheding policy */
# define TCB_FLAG_SCHED_RR (1 << TCB_FLAG_POLICY_SHIFT) /* Round robin scheding policy */
# define TCB_FLAG_SCHED_SPORADIC (2 << TCB_FLAG_POLICY_SHIFT) /* Sporadic scheding policy */
# define TCB_FLAG_SCHED_OTHER (3 << TCB_FLAG_POLICY_SHIFT) /* Other scheding policy */
#define TCB_FLAG_CPU_LOCKED (1 << 6) /* Bit 6: Locked to this CPU */
#define TCB_FLAG_EXIT_PROCESSING (1 << 7) /* Bit 7: Exitting */
/* Bits 8-15: Available */
#define TCB_FLAG_CPU_LOCKED (1 << 7) /* Bit 7: Locked to this CPU */
#define TCB_FLAG_EXIT_PROCESSING (1 << 8) /* Bit 8: Exitting */
/* Bits 9-15: Available */
/* Values for struct task_group tg_flags */
@@ -582,6 +583,9 @@ struct tcb_s
#ifdef CONFIG_SMP
int16_t irqcount; /* 0=interrupts enabled */
#endif
#ifdef CONFIG_CANCELLATION_POINTS
int16_t cpcount; /* Nested cancellation point count */
#endif
#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC)
int32_t timeslice; /* RR timeslice OR Sporadic budget */
+7 -1
View File
@@ -115,11 +115,16 @@
#define PTHREAD_DEFAULT_PRIORITY 100
/* Cancellation states returned by pthread_cancelstate() */
/* Cancellation states used by pthread_setcancelstate() */
#define PTHREAD_CANCEL_ENABLE (0)
#define PTHREAD_CANCEL_DISABLE (1)
/* Cancellation types used by pthread_setcanceltype() */
#define PTHREAD_CANCEL_DEFERRED (0)
#define PTHREAD_CANCEL_ASYNCHRONOUS (1)
/* Thread return value when a pthread is canceled */
#define PTHREAD_CANCELED ((FAR void*)ERROR)
@@ -340,6 +345,7 @@ int pthread_detach(pthread_t thread);
void pthread_exit(pthread_addr_t value) noreturn_function;
int pthread_cancel(pthread_t thread);
int pthread_setcancelstate(int state, FAR int *oldstate);
int pthread_setcanceltype(int type, FAR int *oldtype);
void pthread_testcancel(void);
/* A thread may set up cleanup functions to execut when the thread exits or
-21
View File
@@ -47,27 +47,6 @@
#ifdef CONFIG_FS_AIO
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
-20
View File
@@ -43,26 +43,6 @@
#include <assert.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
+16 -1
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* net/socket/accept.c
*
* Copyright (C) 2007-2012, 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2012, 2015-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,7 @@
#include <assert.h>
#include <debug.h>
#include <nuttx/pthread.h>
#include <arch/irq.h>
#include "tcp/tcp.h"
@@ -132,6 +133,10 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
DEBUGASSERT(psock != NULL);
/* Treat as a cancellation point */
enter_cancellation_point();
/* Is the socket a stream? */
if (psock->s_type != SOCK_STREAM)
@@ -269,6 +274,8 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
newsock->s_flags |= _SF_CONNECTED;
newsock->s_flags &= ~_SF_CLOSED;
leave_cancellation_point();
return OK;
errout_after_accept:
@@ -276,6 +283,7 @@ errout_after_accept:
errout:
set_errno(errcode);
leave_cancellation_point();
return ERROR;
}
@@ -355,6 +363,10 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
int errcode;
int ret;
/* accept() is a cancellation point */
enter_cancellation_point();
/* Verify that the sockfd corresponds to valid, allocated socket */
if (psock == NULL || psock->s_crefs <= 0)
@@ -402,9 +414,11 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
/* The errno value has already been set */
sockfd_release(newfd);
leave_cancellation_point();
return ERROR;
}
leave_cancellation_point();
return newfd;
errout_with_socket:
@@ -412,6 +426,7 @@ errout_with_socket:
errout:
set_errno(errcode);
leave_cancellation_point();
return ERROR;
}
+16 -1
View File
@@ -51,6 +51,7 @@
#include <arch/irq.h>
#include <nuttx/semaphore.h>
#include <nuttx/pthread.h>
#include <nuttx/net/net.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/udp.h>
@@ -516,6 +517,10 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
#endif
int errcode;
/* Treat as a cancellation point */
enter_cancellation_point();
/* Verify that the psock corresponds to valid, allocated socket */
if (!psock || psock->s_crefs <= 0)
@@ -663,10 +668,12 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
goto errout;
}
leave_cancellation_point();
return OK;
errout:
set_errno(errcode);
leave_cancellation_point();
return ERROR;
}
@@ -741,13 +748,21 @@ errout:
int connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen)
{
int ret;
/* accept() is a cancellation point */
enter_cancellation_point();
/* Get the underlying socket structure */
FAR struct socket *psock = sockfd_socket(sockfd);
/* Then let psock_connect() do all of the work */
return psock_connect(psock, addr, addrlen);
ret = psock_connect(psock, addr, addrlen);
leave_cancellation_point();
return ret;
}
#endif /* CONFIG_NET */
+2
View File
@@ -71,6 +71,8 @@
ssize_t recv(int sockfd, FAR void *buf, size_t len, int flags)
{
/* recv is a cancellation point, but that can all be handled by recvfrom */
return recvfrom(sockfd, buf, len, flags, NULL, 0);
}
+15 -1
View File
@@ -57,6 +57,7 @@
#include <nuttx/clock.h>
#include <nuttx/semaphore.h>
#include <nuttx/pthread.h>
#include <nuttx/net/net.h>
#include <nuttx/net/iob.h>
#include <nuttx/net/netdev.h>
@@ -1851,6 +1852,10 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
ssize_t ret;
int errcode;
/* Treat as a cancellation point */
enter_cancellation_point();
/* Verify that non-NULL pointers were passed */
#ifdef CONFIG_DEBUG_FEATURES
@@ -2013,10 +2018,12 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
/* Success return */
leave_cancellation_point();
return ret;
errout:
set_errno(errcode);
leave_cancellation_point();
return ERROR;
}
@@ -2076,6 +2083,11 @@ ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
FAR struct sockaddr *from, FAR socklen_t *fromlen)
{
FAR struct socket *psock;
ssize_t ret;
/* recvfrom() is a cancellation point */
enter_cancellation_point();
/* Get the underlying socket structure */
@@ -2083,7 +2095,9 @@ ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
/* Then let psock_recvfrom() do all of the work */
return psock_recvfrom(psock, buf, len, flags, from, fromlen);
ret = psock_recvfrom(psock, buf, len, flags, from, fromlen);
leave_cancellation_point();
return ret;
}
#endif /* CONFIG_NET */
+24 -2
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* net/socket/send.c
*
* Copyright (C) 2007-2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -43,6 +43,8 @@
#include <sys/socket.h>
#include <errno.h>
#include <nuttx/pthread.h>
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
@@ -122,6 +124,10 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
{
int ret;
/* Treat as a cancellation point */
enter_cancellation_point();
switch (psock->s_type)
{
#if defined(CONFIG_NET_PKT)
@@ -192,6 +198,7 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
break;
}
leave_cancellation_point();
return ret;
}
@@ -261,5 +268,20 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
ssize_t send(int sockfd, FAR const void *buf, size_t len, int flags)
{
return psock_send(sockfd_socket(sockfd), buf, len, flags);
FAR struct socket *psock;
ssize_t ret;
/* send() is a cancellation point */
enter_cancellation_point();
/* Get the underlying socket structure */
psock = sockfd_socket(sockfd);
/* And let psock_send do all of the work */
ret = psock_send(psock, buf, len, flags, to, tolen);
leave_cancellation_point();
return ret;
}
+8 -1
View File
@@ -309,6 +309,11 @@ ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags,
FAR const struct sockaddr *to, socklen_t tolen)
{
FAR struct socket *psock;
ssize_t ret;
/* sendto() is a cancellation point */
enter_cancellation_point();
/* Get the underlying socket structure */
@@ -316,5 +321,7 @@ ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags,
/* And let psock_sendto do all of the work */
return psock_sendto(psock, buf, len, flags, to, tolen);
ret = psock_sendto(psock, buf, len, flags, to, tolen);
leave_cancellation_point();
return ret;
}
+9
View File
@@ -560,6 +560,15 @@ config PTHREAD_CLEANUP_STACKSIZE
endmenu # Pthread Options
config CANCELLATION_POINTS
bool "Cancellation points"
default n
depends on EXPERIMENTAL
---help---
Enable POSIX cancellation points for pthread_cancel(). If selected,
cancellation points will also used with the () task_delete() API even if
pthreads are not enabled.
menu "Performance Monitoring"
config SCHED_CPULOAD
+7
View File
@@ -218,6 +218,13 @@ int os_smp_start(void)
*/
up_initial_state(tcb);
/* Set the task flags to indicate that this is a kernel thread and that
* this task is locked to this CPU.
*/
tcb->flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_NONCANCELABLE | TCB_FLAG_CPU_LOCKED);
tcb->cpu = cpu;
}
/* Then start all of the other CPUs after we have completed the memory
+3 -2
View File
@@ -470,10 +470,11 @@ void os_start(void)
*/
#ifdef CONFIG_SMP
g_idletcb[cpu].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CPU_LOCKED);
g_idletcb[cpu].cmn.flags = (TCB_FLAG_TTYPE_KERNEL TCB_FLAG_NONCANCELABLE |
TCB_FLAG_CPU_LOCKED);
g_idletcb[cpu].cmn.cpu = cpu;
#else
g_idletcb[cpu].cmn.flags = TCB_FLAG_TTYPE_KERNEL;
g_idletcb[cpu].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_NONCANCELABLE);
#endif
#ifdef CONFIG_SMP
+7
View File
@@ -47,6 +47,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/pthread.h>
#include "mqueue/mqueue.h"
@@ -103,12 +104,17 @@ ssize_t mq_receive(mqd_t mqdes, FAR char *msg, size_t msglen,
DEBUGASSERT(up_interrupt_context() == false);
/* mq_receive() is a cancellation point */
enter_cancellation_point();
/* Verify the input parameters and, in case of an error, set
* errno appropriately.
*/
if (mq_verifyreceive(mqdes, msg, msglen) != OK)
{
leave_cancellation_point();
return ERROR;
}
@@ -145,5 +151,6 @@ ssize_t mq_receive(mqd_t mqdes, FAR char *msg, size_t msglen,
}
sched_unlock();
leave_cancellation_point();
return ret;
}
+7
View File
@@ -46,6 +46,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/pthread.h>
#include "mqueue/mqueue.h"
@@ -103,12 +104,17 @@ int mq_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio)
irqstate_t flags;
int ret = ERROR;
/* mq_send() is a cancellation point */
enter_cancellation_point();
/* Verify the input parameters -- setting errno appropriately
* on any failures to verify.
*/
if (mq_verifysend(mqdes, msg, msglen, prio) != OK)
{
leave_cancellation_point();
return ERROR;
}
@@ -177,5 +183,6 @@ int mq_send(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio)
}
sched_unlock();
leave_cancellation_point();
return ret;
}
+10
View File
@@ -50,6 +50,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
#include "clock/clock.h"
@@ -174,18 +175,24 @@ ssize_t mq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen,
DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL);
/* mq_timedreceive() is a cancellation point */
enter_cancellation_point();
/* Verify the input parameters and, in case of an error, set
* errno appropriately.
*/
if (mq_verifyreceive(mqdes, msg, msglen) != OK)
{
leave_cancellation_point();
return ERROR;
}
if (!abstime || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
{
set_errno(EINVAL);
leave_cancellation_point();
return ERROR;
}
@@ -198,6 +205,7 @@ ssize_t mq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen,
if (!rtcb->waitdog)
{
set_errno(EINVAL);
leave_cancellation_point();
return ERROR;
}
@@ -250,6 +258,7 @@ ssize_t mq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen,
rtcb->waitdog = NULL;
set_errno(result);
leave_cancellation_point();
return ERROR;
}
@@ -288,5 +297,6 @@ ssize_t mq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen,
sched_unlock();
wd_delete(rtcb->waitdog);
rtcb->waitdog = NULL;
leave_cancellation_point();
return ret;
}
+10
View File
@@ -50,6 +50,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#include <nuttx/pthread.h>
#include "clock/clock.h"
#include "sched/sched.h"
@@ -178,6 +179,10 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL);
/* mq_timedsend() is a cancellation point */
enter_cancellation_point();
/* Verify the input parameters -- setting errno appropriately
* on any failures to verify.
*/
@@ -186,6 +191,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
{
/* mq_verifysend() will set the errno appropriately */
leave_cancellation_point();
return ERROR;
}
@@ -199,6 +205,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
*/
set_errno(ENOMEM);
leave_cancellation_point();
return ERROR;
}
@@ -229,6 +236,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio);
sched_unlock();
leave_cancellation_point();
return ret;
}
@@ -320,6 +328,7 @@ int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio,
sched_unlock();
wd_delete(rtcb->waitdog);
rtcb->waitdog = NULL;
leave_cancellation_point();
return ret;
/* Exit here with (1) the scheduler locked, (2) a message allocated, (3) a
@@ -341,5 +350,6 @@ errout_with_mqmsg:
sched_unlock();
set_errno(result);
leave_cancellation_point();
return ERROR;
}
+4 -2
View File
@@ -42,8 +42,10 @@ CSRCS += pthread_mutexlock.c pthread_mutextrylock.c pthread_mutexunlock.c
CSRCS += pthread_condinit.c pthread_conddestroy.c
CSRCS += pthread_condwait.c pthread_condsignal.c pthread_condbroadcast.c
CSRCS += pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c
CSRCS += pthread_cancel.c pthread_setcancelstate.c
CSRCS += pthread_keycreate.c pthread_setspecific.c pthread_getspecific.c pthread_keydelete.c
CSRCS += pthread_cancel.c pthread_setcancelstate.c pthread_setcanceltype.c
CSRCS += pthread_testcancel.c
CSRCS += pthread_keycreate.c pthread_setspecific.c pthread_getspecific.c
CSRCS += pthread_keydelete.c
CSRCS += pthread_initialize.c pthread_completejoin.c pthread_findjoininfo.c
CSRCS += pthread_once.c pthread_release.c pthread_setschedprio.c
+30
View File
@@ -45,6 +45,7 @@
#include <errno.h>
#include "sched/sched.h"
#include "task/task.h"
#include "pthread/pthread.h"
/****************************************************************************
@@ -104,6 +105,35 @@ int pthread_cancel(pthread_t thread)
return OK;
}
#ifdef CONFIG_CANCELLATION_POINTS
/* Check if this thread supports deferred cancellation */
if ((tcb->cmn.flags & TCB_FLAG_CANCEL_DEFERRED) != 0)
{
/* Then we cannot cancel the thread asynchronoulsy. Mark the cancellation
* as pending.
*/
tcb->cmn.flags |= TCB_FLAG_CANCEL_PENDING;
/* If the thread is waiting at a cancellation point, then notify of the
* cancellation thereby waking the task up with an ECANCELED error.
*
* REVISIT: is locking the scheduler sufficent in SMP mode?
*/
if (tcb->cmn.cpcount > 0)
{
notify_cancellation(&tcb->cmn);
}
sched_unlock();
return OK;
}
#endif
/* Otherwise, perform the asyncrhonous cancellation */
sched_unlock();
/* Check to see if the ID refers to ourselves.. this would be the
+3
View File
@@ -67,6 +67,9 @@
* Return Value:
* None
*
* Assumptions:
* The scheduler is locked.
*
****************************************************************************/
static void pthread_cleanup_pop_tcb(FAR struct pthread_tcb_s *tcb, int execute)
+6
View File
@@ -51,6 +51,7 @@
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
#include "pthread/pthread.h"
@@ -178,6 +179,10 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex,
DEBUGASSERT(rtcb->waitdog == NULL);
/* pthread_cond_timedwait() is a cancellation point */
enter_cancellation_point();
/* Make sure that non-NULL references were provided. */
if (!cond || !mutex)
@@ -338,6 +343,7 @@ int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex,
}
}
leave_cancellation_point();
sinfo("Returning %d\n", ret);
return ret;
}
+8 -1
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread/pthread_condwait.c
*
* Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2012, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,8 @@
#include <errno.h>
#include <debug.h>
#include <nuttx/pthread.h>
#include "pthread/pthread.h"
/****************************************************************************
@@ -73,6 +75,10 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex)
sinfo("cond=0x%p mutex=0x%p\n", cond, mutex);
/* pthread_cond_wait() is a cancellation point */
enter_cancellation_point();
/* Make sure that non-NULL references were provided. */
if (!cond || !mutex)
@@ -111,6 +117,7 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex)
}
}
leave_cancellation_point();
sinfo("Returning %d\n", ret);
return ret;
}
+6
View File
@@ -483,6 +483,12 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
#endif
}
#ifdef CONFIG_CANCELLATION_POINTS
/* Set the deferred cancellation type */
ptcb->cmn.flags |= TCB_FLAG_CANCEL_DEFERRED;
#endif
/* Get the assigned pid before we start the task (who knows what
* could happen to ptcb after this!). Copy this ID into the join structure
* as well.
+11
View File
@@ -94,6 +94,17 @@ void pthread_exit(FAR void *exit_value)
}
#endif
#ifdef CONFIG_CANCELLATION_POINTS
/* Mark the pthread as non-cancelable to avoid additional calls to
* pthread_exit() due to any cancellation point logic that might get
* kicked off by actions taken during pthread_exit processing.
*/
tcb->flags |= TCB_FLAG_NONCANCELABLE;
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
tcb->cpcount = 0;
#endif
#ifdef CONFIG_PTHREAD_CLEANUP
/* Perform any stack pthread clean-up callbacks */
+11 -1
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread/pthread_join.c
*
* Copyright (C) 2007, 2008, 2011, 2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2008, 2011, 2013, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -37,12 +37,16 @@
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
#include "group/group.h"
#include "pthread/pthread.h"
@@ -90,12 +94,17 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
sinfo("thread=%d group=%p\n", thread, group);
DEBUGASSERT(group);
/* pthread_join() is a cancellation point */
enter_cancellation_point();
/* First make sure that this is not an attempt to join to
* ourself.
*/
if ((pid_t)thread == getpid())
{
leave_cancellation_point();
return EDEADLK;
}
@@ -230,6 +239,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
ret = OK;
}
leave_cancellation_point();
sinfo("Returning %d\n", ret);
return ret;
}
+44 -7
View File
@@ -37,8 +37,12 @@
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <pthread.h>
#include <errno.h>
#include "task/task.h"
#include "sched/sched.h"
/****************************************************************************
@@ -47,6 +51,18 @@
/****************************************************************************
* Name: pthread_setcancelstate
*
* Description:
* The pthread_setcancelstate() function atomically both sets the calling
* thread's cancelability state to the indicated state and returns the
* previous cancelability state at the location referenced by oldstate.
* Legal values for state are PTHREAD_CANCEL_ENABLE and
* PTHREAD_CANCEL_DISABLE.
*
* The cancelability state and type of any newly created threads,
* including the thread in which main() was first invoked, are
* PTHREAD_CANCEL_ENABLE and PTHREAD_CANCEL_DEFERRED respectively.
*
****************************************************************************/
int pthread_setcancelstate(int state, FAR int *oldstate)
@@ -78,17 +94,38 @@ int pthread_setcancelstate(int state, FAR int *oldstate)
if (state == PTHREAD_CANCEL_ENABLE)
{
unsigned flags = tcb->flags;
/* Clear the non-cancelable flag */
/* Clear the non-cancelable and cancel pending flags */
tcb->flags &= ~TCB_FLAG_NONCANCELABLE;
tcb->flags &= ~(TCB_FLAG_NONCANCELABLE | TCB_FLAG_CANCEL_PENDING);
/* Check if a cancellation was pending */
/* If the cancel was pending, then just exit as requested */
if (flags & TCB_FLAG_CANCEL_PENDING)
if ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0)
{
pthread_exit(PTHREAD_CANCELED);
#ifdef CONFIG_CANCELLATION_POINTS
/* If we are using deferred cancellation? */
if ((tcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0)
{
/* Yes.. If we are within a cancellation point, then
* notify of the cancellation.
*/
if (tcb->cpcount > 0)
{
notify_cancellation(tcb);
}
}
else
#endif
{
/* No.. We are using asynchronous cancellation. If the
* cancellation was pending in this case, then just exit.
*/
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
pthread_exit(PTHREAD_CANCELED);
}
}
}
else if (state == PTHREAD_CANCEL_DISABLE)
+128
View File
@@ -0,0 +1,128 @@
/****************************************************************************
* sched/pthread/pthread_setcanceltype.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <pthread.h>
#include <errno.h>
#include "sched/sched.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pthread_setcancelstate
*
* Description:
* The pthread_setcanceltype() function atomically both sets the calling
* thread's cancelability type to the indicated type and returns the
* previous cancelability type at the location referenced by oldtype
* Legal values for type are PTHREAD_CANCEL_DEFERRED and
* PTHREAD_CANCEL_ASYNCHRONOUS.
*
* The cancelability state and type of any newly created threads,
* including the thread in which main() was first invoked, are
* PTHREAD_CANCEL_ENABLE and PTHREAD_CANCEL_DEFERRED respectively.
*
****************************************************************************/
int pthread_setcanceltype(int type, FAR int *oldtype)
{
FAR struct tcb_s *tcb = this_task();
int ret = OK;
/* Suppress context changes for a bit so that the flags are stable. (the
* flags should not change in interrupt handling).
*/
sched_lock();
/* Return the current type if so requrested */
if (oldtype)
{
if ((tcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0)
{
*oldtype = PTHREAD_CANCEL_DEFERRED;
}
else
{
*oldtype = PTHREAD_CANCEL_ASYNCHRONOUS;
}
}
/* Set the new cancellation type */
if (type == PTHREAD_CANCEL_ASYNCHRONOUS)
{
/* Clear the deferred cancellation bit */
tcb->flags &= ~TCB_FLAG_CANCEL_DEFERRED;
#ifdef CONFIG_CANCELLATION_POINTS
/* If we just switched from deferred to asynchronous type and if a
* cancellation is pending, then exit now.
*/
if ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0 &&
(tcb->flags & TCB_FLAG_NONCANCELABLE) == 0)
{
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
pthread_exit(PTHREAD_CANCELED);
}
#endif
}
#ifdef CONFIG_CANCELLATION_POINTS
else if (type == PTHREAD_CANCEL_DEFERRED)
{
/* Set the deferred cancellation type */
tcb->flags |= TCB_FLAG_CANCEL_DEFERRED;
}
#endif
else
{
ret = EINVAL;
}
sched_unlock();
return ret;
}
+67
View File
@@ -0,0 +1,67 @@
/****************************************************************************
* sched/pthread/pthread_testcancel.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <pthread.h>
#include <errno.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pthread_testcancel
*
* Description:
* The pthread_testcancel() function creates a cancellation point in the
* calling thread. The pthread_testcancel() function has no effect if
* cancelability is disabled
*
****************************************************************************/
void pthread_testcancel(void)
{
enter_cancellation_point();
leave_cancellation_point();
}
+5 -1
View File
@@ -44,6 +44,7 @@
#include <errno.h>
#include <nuttx/sched.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
@@ -80,8 +81,11 @@
pid_t wait(FAR int *stat_loc)
{
/* wait() is a cancellation point, but nothings needs to be done for this
* trivial case.
*/
return waitpid((pid_t)-1, stat_loc, 0);
}
#endif /* CONFIG_SCHED_WAITPID && CONFIG_SCHED_HAVE_PARENT */
+7
View File
@@ -44,6 +44,7 @@
#include <errno.h>
#include <nuttx/sched.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
#include "group/group.h"
@@ -164,6 +165,10 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
int errcode;
int ret;
/* waitid() is a cancellation point */
enter_cancellation_point();
/* MISSING LOGIC: If WNOHANG is provided in the options, then this function
* should returned immediately. However, there is no mechanism available now
* know if the thread has child: The children remember their parents (if
@@ -404,12 +409,14 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
}
}
leave_cancellation_point();
sched_unlock();
return OK;
errout_with_errno:
set_errno(errcode);
errout:
leave_cancellation_point();
sched_unlock();
return ERROR;
}
+15
View File
@@ -45,6 +45,7 @@
#include <errno.h>
#include <nuttx/sched.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
#include "group/group.h"
@@ -185,12 +186,17 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
DEBUGASSERT(stat_loc);
/* waitpid() is a cancellation point */
enter_cancellation_point();
/* None of the options are supported */
#ifdef CONFIG_DEBUG_FEATURES
if (options != 0)
{
set_errno(ENOSYS);
leave_cancellation_point();
return ERROR;
}
#endif
@@ -268,12 +274,14 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
/* On success, return the PID */
leave_cancellation_point();
sched_unlock();
return pid;
errout_with_errno:
set_errno(errcode);
errout:
leave_cancellation_point();
sched_unlock();
return ERROR;
}
@@ -307,12 +315,17 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
DEBUGASSERT(stat_loc);
/* waitpid() is a cancellation point */
enter_cancellation_point();
/* None of the options are supported */
#ifdef CONFIG_DEBUG_FEATURES
if (options != 0)
{
set_errno(ENOSYS);
leave_cancellation_point();
return ERROR;
}
#endif
@@ -528,6 +541,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
}
}
leave_cancellation_point();
sched_unlock();
return (int)pid;
@@ -535,6 +549,7 @@ errout_with_errno:
set_errno(errcode);
errout_with_lock:
leave_cancellation_point();
sched_unlock();
return ERROR;
}
+7
View File
@@ -49,6 +49,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
#include "clock/clock.h"
@@ -103,6 +104,10 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL);
/* sem_timedwait() is a cancellation point */
enter_cancellation_point();
/* Verify the input parameters and, in case of an error, set
* errno appropriately.
*/
@@ -209,6 +214,7 @@ success_with_irqdisabled:
leave_critical_section(flags);
wd_delete(rtcb->waitdog);
rtcb->waitdog = NULL;
leave_cancellation_point();
return OK;
/* Error exits */
@@ -220,5 +226,6 @@ errout_with_irqdisabled:
errout:
set_errno(errcode);
leave_cancellation_point();
return ERROR;
}
+6
View File
@@ -46,6 +46,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
#include "semaphore/semaphore.h"
@@ -86,6 +87,10 @@ int sem_wait(FAR sem_t *sem)
DEBUGASSERT(sem != NULL && up_interrupt_context() == false);
/* sem_wait is a cancellation point */
enter_cancellation_point();
/* Make sure we were supplied with a valid semaphore. */
if (sem != NULL)
@@ -196,5 +201,6 @@ int sem_wait(FAR sem_t *sem)
set_errno(EINVAL);
}
leave_cancellation_point();
return ret;
}
+7
View File
@@ -46,6 +46,7 @@
#include <nuttx/clock.h>
#include <nuttx/irq.h>
#include <nuttx/pthread.h>
#include "clock/clock.h"
@@ -112,6 +113,10 @@ int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp)
int ret;
#endif
/* nanosleep() is a cancellation point */
enter_cancellation_point();
if (!rqtp || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000)
{
errval = EINVAL;
@@ -154,6 +159,7 @@ int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp)
/* The timeout "error" is the normal, successful result */
leave_critical_section(flags);
leave_cancellation_point();
return OK;
}
@@ -203,5 +209,6 @@ int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp)
errout:
set_errno(errval);
leave_cancellation_point();
return ERROR;
}
+12 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/signal/sig_pause.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,8 @@
#include <unistd.h>
#include <signal.h>
#include <nuttx/pthread.h>
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -72,8 +74,13 @@
int pause(void)
{
sigset_t set;
struct siginfo value;
sigset_t set;
int ret;
/* pause() is a cancellation point */
enter_cancellation_point();
/* Set up for the sleep. Using the empty set means that we are not
* waiting for any particular signal. However, any unmasked signal
@@ -86,5 +93,7 @@ int pause(void)
* meaning that some unblocked signal was caught.
*/
return sigwaitinfo(&set, &value);
ret = sigwaitinfo(&set, &value);
leave_cancellation_point();
return ret;
}
+7 -1
View File
@@ -46,6 +46,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/pthread.h>
#include "sched/sched.h"
#include "signal/signal.h"
@@ -98,6 +99,10 @@ int sigsuspend(FAR const sigset_t *set)
irqstate_t flags;
int unblocksigno;
/* sigsuspend() is a cancellation point */
enter_cancellation_point();
/* Several operations must be performed below: We must determine if any
* signal is pending and, if not, wait for the signal. Since signals can
* be posted from the interrupt level, there is a race condition that
@@ -154,5 +159,6 @@ int sigsuspend(FAR const sigset_t *set)
}
sched_unlock();
return ERROR;
leave_cancellation_point();
return ERROR; /* ??REVISIT: Always returns ERROR?? */
}

Some files were not shown because too many files have changed in this diff Show More