cancellation points are basically function. More tested is needed and additional cancellation points must be implemented before this can be merged back to master.
This commit is contained in:
parent
018db84567
commit
c9ca97b4b5
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/pthread.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "group/group.h"
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/pthread.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "semaphore/semaphore.h"
|
||||
|
|
|
@ -108,6 +108,8 @@ void enter_cancellation_point(void)
|
|||
/* Disabling pre-emption should provide sufficient protection. We only
|
||||
* need the TCB to be stationary (no interrupt level modification is
|
||||
* anticipated).
|
||||
*
|
||||
* REVISIT: is locking the scheduler sufficent in SMP mode?
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
|
@ -135,7 +137,7 @@ void enter_cancellation_point(void)
|
|||
#ifndef CONFIG_DISABLE_PTHREAD
|
||||
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
|
||||
{
|
||||
pthread_exit(NULL);
|
||||
pthread_exit(PTHREAD_CANCELED);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -180,6 +182,8 @@ void leave_cancellation_point(void)
|
|||
/* Disabling pre-emption should provide sufficient protection. We only
|
||||
* need the TCB to be stationary (no interrupt level modification is
|
||||
* anticipated).
|
||||
*
|
||||
* REVISIT: is locking the scheduler sufficent in SMP mode?
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
|
@ -211,7 +215,7 @@ void leave_cancellation_point(void)
|
|||
#ifndef CONFIG_DISABLE_PTHREAD
|
||||
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
|
||||
{
|
||||
pthread_exit(NULL);
|
||||
pthread_exit(PTHREAD_CANCELED);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
|
@ -103,7 +103,37 @@ int task_delete(pid_t pid)
|
|||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Then let task_terminate do the heavy lifting */
|
||||
#ifdef CONFIG_CANCELLATION_POINTS
|
||||
/* Check if this task supports deferred cancellation */
|
||||
|
||||
sched_lock();
|
||||
if ((rtcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0)
|
||||
{
|
||||
/* Then we cannot cancel the task asynchronoulsy. Mark the cancellation
|
||||
* as pending.
|
||||
*/
|
||||
|
||||
rtcb->flags |= TCB_FLAG_CANCEL_PENDING;
|
||||
|
||||
/* If the task 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 (rtcb->cpcount > 0)
|
||||
{
|
||||
notify_cancellation(rtcb);
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Otherwise, perform the asynchronous cancellation, letting
|
||||
* task_terminate() do all of the heavy lifting.
|
||||
*/
|
||||
|
||||
return task_terminate(pid, false);
|
||||
}
|
||||
|
|
|
@ -612,6 +612,17 @@ void task_exithook(FAR struct tcb_s *tcb, int status, bool nonblocking)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CANCELLATION_POINTS
|
||||
/* Mark the task as non-cancelable to avoid additional calls to exit()
|
||||
* due to any cancellation point logic that might get kicked off by
|
||||
* actions taken during exit processing.
|
||||
*/
|
||||
|
||||
tcb->flags |= TCB_FLAG_NONCANCELABLE;
|
||||
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
|
||||
tcb->cpcount = 0;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCHED_ATEXIT) || defined(CONFIG_SCHED_ONEXIT)
|
||||
/* If exit function(s) were registered, call them now before we do any un-
|
||||
* initialization.
|
||||
|
|
Loading…
Reference in New Issue