mirror of
https://github.com/apache/nuttx.git
synced 2026-02-06 12:42:21 +08:00
sched/sem_waitirq: Move kmm_map() call to sem_wait()
The kernel mapping should be performed in sem_wait (thread level) as virtual memory mappings cannot be added from interrupt, at least for now. The reason? kmm_map() depends on mm_map_add(), which in turn uses a mutex for mutual exclusion. Using mutexes from interrupt level is not permitted. Mapping tcb->waitobj into kernel virtual memory directly in sem_wait() makes sense, since accessing tcb->waitobj via a user virtual address can lead to unexpected results (the wrong mappings can be in place).
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/mm/kmap.h>
|
||||
|
||||
#include "semaphore/semaphore.h"
|
||||
|
||||
@@ -100,6 +101,10 @@ void nxsem_recover(FAR struct tcb_s *tcb)
|
||||
*/
|
||||
|
||||
atomic_fetch_add(NXSEM_COUNT(sem), 1);
|
||||
|
||||
#ifdef CONFIG_MM_KMAP
|
||||
kmm_unmap(sem);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Release all semphore holders for the task */
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <nuttx/init.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/mm/kmap.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "semaphore/semaphore.h"
|
||||
@@ -117,6 +118,10 @@ static int nxsem_wait_slow(FAR sem_t *sem)
|
||||
|
||||
DEBUGASSERT(rtcb->waitobj == NULL);
|
||||
|
||||
#ifdef CONFIG_MM_KMAP
|
||||
sem = kmm_map_user(rtcb, sem, sizeof(*sem));
|
||||
#endif
|
||||
|
||||
/* Save the waited on semaphore in the TCB */
|
||||
|
||||
rtcb->waitobj = sem;
|
||||
@@ -201,6 +206,10 @@ static int nxsem_wait_slow(FAR sem_t *sem)
|
||||
|
||||
ret = rtcb->errcode != OK ? -rtcb->errcode : OK;
|
||||
|
||||
#ifdef CONFIG_MM_KMAP
|
||||
kmm_unmap(sem);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PRIORITY_INHERITANCE
|
||||
if (prioinherit != 0)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/mm/kmap.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "semaphore/semaphore.h"
|
||||
@@ -74,10 +73,6 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode)
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
FAR sem_t *sem = wtcb->waitobj;
|
||||
|
||||
#ifdef CONFIG_MM_KMAP
|
||||
sem = kmm_map_user(wtcb, sem, sizeof(*sem));
|
||||
#endif
|
||||
|
||||
/* It is possible that an interrupt/context switch beat us to the punch
|
||||
* and already changed the task's state.
|
||||
*/
|
||||
@@ -102,10 +97,6 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode)
|
||||
|
||||
dq_rem((FAR dq_entry_t *)wtcb, SEM_WAITLIST(sem));
|
||||
|
||||
#ifdef CONFIG_MM_KMAP
|
||||
kmm_unmap(sem);
|
||||
#endif
|
||||
|
||||
/* Indicate that the wait is over. */
|
||||
|
||||
wtcb->waitobj = NULL;
|
||||
|
||||
Reference in New Issue
Block a user