diff --git a/include/nuttx/cancelpt.h b/include/nuttx/cancelpt.h index 8adfc8c217..87b560fd92 100644 --- a/include/nuttx/cancelpt.h +++ b/include/nuttx/cancelpt.h @@ -2,7 +2,7 @@ * include/nuttx/cancelpt.h * Definitions related to cancellation points * - * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2016-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -144,6 +144,31 @@ void leave_cancellation_point(void); # define leave_cancellation_point() #endif +/**************************************************************************** + * Name: check_cancellation_point + * + * Description: + * Returns true if: + * + * 1. Deferred cancellation does applies to this thread, + * 2. We are within a cancellation point (i.e., the nesting level in the + * TCB is greater than zero). + * + * Input Parameters: + * None + * + * Returned Value + * true is returned if a cancellation is pending but cannot be performed + * now due to the nesting level. + * + ****************************************************************************/ + +#ifdef CONFIG_CANCELLATION_POINTS +bool check_cancellation_point(void); +#else +# define check_cancellation_point() false +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/sched/task/task_cancelpt.c b/sched/task/task_cancelpt.c index df404f9284..a08e5d8266 100644 --- a/sched/task/task_cancelpt.c +++ b/sched/task/task_cancelpt.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/task/task_cancelpt.c * - * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2016-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -260,6 +260,59 @@ void leave_cancellation_point(void) sched_unlock(); } +/**************************************************************************** + * Name: check_cancellation_point + * + * Description: + * Returns true if: + * + * 1. Deferred cancellation does applies to this thread, + * 2. We are within a cancellation point (i.e., the nesting level in the + * TCB is greater than zero). + * + * Input Parameters: + * None + * + * Returned Value + * true is returned if a cancellation is pending but cannot be performed + * now due to the nesting level. + * + ****************************************************************************/ + +bool check_cancellation_point(void) +{ + FAR struct tcb_s *tcb = this_task(); + bool ret = false; + + /* 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(); + + /* If cancellation is disabled on this thread or if this thread is using + * asynchronous cancellation, then return false. + * + * If the cpcount count is greater than zero, then we within a + * cancellation and will true if there is a pending cancellation. + */ + + if (((tcb->flags & TCB_FLAG_NONCANCELABLE) == 0 && + (tcb->flags & TCB_FLAG_CANCEL_DEFERRED) != 0) || + tcb->cpcount > 0) + { + /* Check if there is a pending cancellation. If so, return true. */ + + ret = ((tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0); + } + + sched_unlock(); + return ret; +} + /**************************************************************************** * Name: notify_cancellation *