It was added by this commit commit 9568600ab19ef7da61ae7de4b43f1fc075556102 Author: Gregory Nutt <gn...@nuttx.org> Date: Wed Oct 4 15:22:27 2017 -0600
Squashed commit of the following: This commit backs out most of commit b4747286b19d3b15193b2a5e8a0fe48fa0a8638c. That change was added because sem_wait() would sometimes cause cancellation points inappropriated. But with these recent changes, nxsem_wait() is used instead and it is not a cancellation point. In the OS, all calls to sem_wait() changed to nxsem_wait(). nxsem_wait() does not return errors via errno so each place where nxsem_wait() is now called must not examine the errno variable. In all OS functions (not libraries), change sem_wait() to nxsem_wait(). This will prevent the OS from creating bogus cancellation points and from modifying the per-task errno variable. sched/semaphore: Add the function nxsem_wait(). This is a new internal OS interface. It is functionally equivalent to sem_wait() except that (1) it is not a cancellation point, and (2) it does not set the per-thread errno value on return. пт, 27 трав. 2022 р. о 16:57 Petro Karashchenko < petro.karashche...@gmail.com> пише: > Yes and no. I've posted a code from sem_wait that checks if a cancellation > is pending but cannot be performed due to the nesting level, > so enter_cancellation_point will just increment the nested count > and leave_cancellation_point will just decrement it. In this case ECANCELED > will be returned by sem_wait and _SEM_WAIT() will be called again > endlessly because cancelation nesting counted will just increment and > decrement. > > Best regards, > Petro > > пт, 27 трав. 2022 р. о 16:23 Gregory Nutt <spudan...@gmail.com> пише: > >> On 5/27/2022 12:52 AM, Petro Karashchenko wrote: >> > Hi, >> > >> > Ok. That makes sense. But there is a strane code in sem_wait: >> > >> > if (enter_cancellation_point()) >> > { >> > #ifdef CONFIG_CANCELLATION_POINTS >> > /* If there is a pending cancellation, then do not perform >> > * the wait. Exit now with ECANCELED. >> > */ >> > >> > errcode = ECANCELED; >> > goto errout_with_cancelpt; >> > #endif >> > } >> > >> > This code in conjunction with "while ((ret = _SEM_WAIT(sem)) < 0)" >> seems to >> > be a pure "deadlock" (endless loop) in case if _SEM_WAIT is defined to >> > sem_wait. Or am I missing something? >> > This is of course when sem_wait is called while the task entered the >> > cancellation point already. >> > >> > Best regards, >> > Petro >> >> "while ((ret = _SEM_WAIT(sem)) < 0)" is not an endless loop. >> >> ECANCEL is handled just like EINTR: For EINTR, when the signal is >> received, _SEM_WAIT wakes up and returns -EINTR. If _SEM_WAIT is called >> again, it does not remember that the thread was signaled; it does not >> return -EINTR again but behaves normally and waits for the semaphore. >> >> ECANCEL works the same: When a thread is canceled, _SEM_WAIT wakes up >> and return -ECANCELED. If _SEM_WAIT is called it again, it does not >> remember that the thread was canceled; it does not return -ECANCELED >> again but behaves normally and waits for the semaphore. >> >> So there is no infinite loop. >> >> >>