mirror of
https://github.com/apache/nuttx.git
synced 2026-06-01 07:45:16 +08:00
Merge branch 'cancelpt'
This commit is contained in:
+229
-122
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -47,27 +47,6 @@
|
||||
|
||||
#ifdef CONFIG_FS_AIO
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user