xiaoxiang781216 commented on code in PR #11165:
URL: https://github.com/apache/nuttx/pull/11165#discussion_r1390225032


##########
include/nuttx/tls.h:
##########
@@ -205,6 +205,12 @@ struct tls_info_s
   struct pthread_cleanup_s stack[CONFIG_PTHREAD_CLEANUP_STACKSIZE];
 #endif
 
+  uint8_t tl_cpstate;                  /* Cancellation state */

Review Comment:
   should we move into `#ifdef CONFIG_CANCELLATION_POINTS` too



##########
libs/libc/sched/task_cancelpt.c:
##########
@@ -0,0 +1,289 @@
+/****************************************************************************
+ * libs/libc/sched/task_cancelpt.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sched.h>
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include <nuttx/cancelpt.h>
+#include <nuttx/tls.h>
+
+#ifdef CONFIG_CANCELLATION_POINTS
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   true is returned if a cancellation is pending but cannot be performed
+ *   now due to the nesting level.
+ *
+ ****************************************************************************/
+
+bool enter_cancellation_point(void)
+{
+  FAR struct tls_info_s *tls = tls_get_info();
+  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 sufficient in SMP mode?
+   */
+
+  sched_lock();
+
+  /* If cancellation is disabled on this thread or if this thread is using
+   * asynchronous cancellation, then do nothing.
+   *
+   * Special case: if the cpcount count is greater than zero, then we are
+   * nested and the above condition was certainly true at the outermost
+   * nesting level.
+   */
+
+  if (((tls->tl_cpstate & CANCEL_FLAG_NONCANCELABLE) == 0 &&
+       (tls->tl_cpstate & CANCEL_FLAG_CANCEL_DEFERRED) != 0) ||
+      tls->tl_cpcount > 0)
+    {
+      /* Check if there is a pending cancellation */
+
+      if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_PENDING) != 0)
+        {
+          /* Yes... return true (if we don't exit here) */
+
+          ret = true;
+
+          /* If there is a pending cancellation and we are at the outermost
+           * nesting level of cancellation function calls, then exit
+           * according to the type of the thread.
+           */
+
+          if (tls->tl_cpcount == 0)
+            {
+#ifndef CONFIG_DISABLE_PTHREAD
+              pthread_exit(PTHREAD_CANCELED);
+#else
+              exit(EXIT_FAILURE);
+#endif
+            }
+        }
+
+      /* Otherwise, indicate that we are at a cancellation point by
+       * incrementing the nesting level of the cancellation point
+       * functions.
+       */
+
+      DEBUGASSERT(tls->tl_cpcount < INT16_MAX);
+      tls->tl_cpcount++;
+    }
+
+  sched_unlock();
+  return ret;
+}
+
+/****************************************************************************
+ * 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.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void leave_cancellation_point(void)
+{
+  FAR struct tls_info_s *tls = tls_get_info();
+
+  /* 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 sufficient in SMP mode?
+   */
+
+  sched_lock();
+
+  /* If cancellation is disabled on this thread or if this thread is using
+   * asynchronous cancellation, then do nothing.  Here we check only the
+   * nesting level: if the cpcount count is greater than zero, then the
+   * required condition was certainly true at the outermost nesting level.
+   */
+
+  if (tls->tl_cpcount > 0)
+    {
+      /* Decrement the nesting level.  If if would decrement to zero, then
+       * we are at the outermost nesting level and may need to do more.
+       */
+
+      if (tls->tl_cpcount == 1)
+        {
+          /* We are no longer at the cancellation point */
+
+          tls->tl_cpcount = 0;
+
+          /* If there is a pending cancellation then just exit according to
+           * the type of the thread.
+           */
+
+          if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_PENDING) != 0)
+            {
+#ifndef CONFIG_DISABLE_PTHREAD
+              pthread_exit(PTHREAD_CANCELED);
+#else
+              exit(EXIT_FAILURE);
+#endif
+            }
+        }
+      else
+        {
+          /* We are not at the outermost nesting level.  Just decrment the
+           * nesting level count.
+           */
+
+          tls->tl_cpcount--;
+        }
+    }
+
+  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 tls_info_s *tls = tls_get_info();
+  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 sufficient in SMP mode?
+   */
+
+  sched_lock();

Review Comment:
   ditto



##########
libs/libc/sched/task_cancelpt.c:
##########
@@ -0,0 +1,289 @@
+/****************************************************************************
+ * libs/libc/sched/task_cancelpt.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sched.h>
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include <nuttx/cancelpt.h>
+#include <nuttx/tls.h>
+
+#ifdef CONFIG_CANCELLATION_POINTS
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   true is returned if a cancellation is pending but cannot be performed
+ *   now due to the nesting level.
+ *
+ ****************************************************************************/
+
+bool enter_cancellation_point(void)
+{
+  FAR struct tls_info_s *tls = tls_get_info();
+  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 sufficient in SMP mode?
+   */
+
+  sched_lock();

Review Comment:
   don't need sched_lock



##########
libs/libc/sched/task_cancelpt.c:
##########
@@ -0,0 +1,289 @@
+/****************************************************************************
+ * libs/libc/sched/task_cancelpt.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sched.h>
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include <nuttx/cancelpt.h>
+#include <nuttx/tls.h>
+
+#ifdef CONFIG_CANCELLATION_POINTS
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   true is returned if a cancellation is pending but cannot be performed
+ *   now due to the nesting level.
+ *
+ ****************************************************************************/
+
+bool enter_cancellation_point(void)
+{
+  FAR struct tls_info_s *tls = tls_get_info();
+  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 sufficient in SMP mode?
+   */
+
+  sched_lock();
+
+  /* If cancellation is disabled on this thread or if this thread is using
+   * asynchronous cancellation, then do nothing.
+   *
+   * Special case: if the cpcount count is greater than zero, then we are
+   * nested and the above condition was certainly true at the outermost
+   * nesting level.
+   */
+
+  if (((tls->tl_cpstate & CANCEL_FLAG_NONCANCELABLE) == 0 &&
+       (tls->tl_cpstate & CANCEL_FLAG_CANCEL_DEFERRED) != 0) ||
+      tls->tl_cpcount > 0)
+    {
+      /* Check if there is a pending cancellation */
+
+      if ((tls->tl_cpstate & CANCEL_FLAG_CANCEL_PENDING) != 0)
+        {
+          /* Yes... return true (if we don't exit here) */
+
+          ret = true;
+
+          /* If there is a pending cancellation and we are at the outermost
+           * nesting level of cancellation function calls, then exit
+           * according to the type of the thread.
+           */
+
+          if (tls->tl_cpcount == 0)
+            {
+#ifndef CONFIG_DISABLE_PTHREAD
+              pthread_exit(PTHREAD_CANCELED);
+#else
+              exit(EXIT_FAILURE);
+#endif
+            }
+        }
+
+      /* Otherwise, indicate that we are at a cancellation point by
+       * incrementing the nesting level of the cancellation point
+       * functions.
+       */
+
+      DEBUGASSERT(tls->tl_cpcount < INT16_MAX);
+      tls->tl_cpcount++;
+    }
+
+  sched_unlock();
+  return ret;
+}
+
+/****************************************************************************
+ * 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.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void leave_cancellation_point(void)
+{
+  FAR struct tls_info_s *tls = tls_get_info();
+
+  /* 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 sufficient in SMP mode?
+   */
+
+  sched_lock();

Review Comment:
   ditto



##########
libs/libc/sched/task_setcanceltype.c:
##########
@@ -46,14 +54,70 @@
 
 int task_setcanceltype(int type, FAR int *oldtype)
 {
+  FAR struct tls_info_s *tls = tls_get_info();
+  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();

Review Comment:
   yes, I think so.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to