mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 05:16:47 +08:00
mm/iob: Replace the critical section with spin lock
Base on discusion: https://github.com/apache/nuttx/issues/10981 Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
committed by
Petro Karashchenko
parent
d5d4006c6b
commit
9e4a1be8d4
@@ -30,6 +30,7 @@
|
|||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#include <nuttx/mm/iob.h>
|
#include <nuttx/mm/iob.h>
|
||||||
|
#include <nuttx/spinlock.h>
|
||||||
#include <nuttx/semaphore.h>
|
#include <nuttx/semaphore.h>
|
||||||
|
|
||||||
#ifdef CONFIG_MM_IOB
|
#ifdef CONFIG_MM_IOB
|
||||||
@@ -80,6 +81,8 @@ extern sem_t g_throttle_sem; /* Counts available I/O buffers when throttled */
|
|||||||
extern sem_t g_qentry_sem; /* Counts free I/O buffer queue containers */
|
extern sem_t g_qentry_sem; /* Counts free I/O buffer queue containers */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern spinlock_t g_iob_lock;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ static int iob_add_queue_internal(FAR struct iob_s *iob,
|
|||||||
|
|
||||||
qentry->qe_flink = NULL;
|
qentry->qe_flink = NULL;
|
||||||
|
|
||||||
irqstate_t flags = enter_critical_section();
|
irqstate_t flags = spin_lock_irqsave(&g_iob_lock);
|
||||||
if (!iobq->qh_head)
|
if (!iobq->qh_head)
|
||||||
{
|
{
|
||||||
iobq->qh_head = qentry;
|
iobq->qh_head = qentry;
|
||||||
@@ -74,7 +74,7 @@ static int iob_add_queue_internal(FAR struct iob_s *iob,
|
|||||||
iobq->qh_tail = qentry;
|
iobq->qh_tail = qentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -73,7 +73,7 @@ static FAR struct iob_s *iob_alloc_committed(void)
|
|||||||
* to protect the committed list: We disable interrupts very briefly.
|
* to protect the committed list: We disable interrupts very briefly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_iob_lock);
|
||||||
|
|
||||||
/* Take the I/O buffer from the head of the committed list */
|
/* Take the I/O buffer from the head of the committed list */
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ static FAR struct iob_s *iob_alloc_committed(void)
|
|||||||
iob->io_pktlen = 0; /* Total length of the packet */
|
iob->io_pktlen = 0; /* Total length of the packet */
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
return iob;
|
return iob;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +272,7 @@ FAR struct iob_s *iob_tryalloc(bool throttled)
|
|||||||
* to protect the free list: We disable interrupts very briefly.
|
* to protect the free list: We disable interrupts very briefly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_iob_lock);
|
||||||
|
|
||||||
#if CONFIG_IOB_THROTTLE > 0
|
#if CONFIG_IOB_THROTTLE > 0
|
||||||
/* If there are free I/O buffers for this allocation */
|
/* If there are free I/O buffers for this allocation */
|
||||||
@@ -314,7 +314,7 @@ FAR struct iob_s *iob_tryalloc(bool throttled)
|
|||||||
g_throttle_sem.semcount--;
|
g_throttle_sem.semcount--;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
|
|
||||||
/* Put the I/O buffer in a known state */
|
/* Put the I/O buffer in a known state */
|
||||||
|
|
||||||
@@ -326,6 +326,6 @@ FAR struct iob_s *iob_tryalloc(bool throttled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ static FAR struct iob_qentry_s *iob_alloc_qcommitted(void)
|
|||||||
* to protect the committed list: We disable interrupts very briefly.
|
* to protect the committed list: We disable interrupts very briefly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_iob_lock);
|
||||||
|
|
||||||
/* Take the I/O buffer from the head of the committed list */
|
/* Take the I/O buffer from the head of the committed list */
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ static FAR struct iob_qentry_s *iob_alloc_qcommitted(void)
|
|||||||
iobq->qe_head = NULL; /* Nothing is contained */
|
iobq->qe_head = NULL; /* Nothing is contained */
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
return iobq;
|
return iobq;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ FAR struct iob_qentry_s *iob_tryalloc_qentry(void)
|
|||||||
* to protect the free list: We disable interrupts very briefly.
|
* to protect the free list: We disable interrupts very briefly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_iob_lock);
|
||||||
iobq = g_iob_freeqlist;
|
iobq = g_iob_freeqlist;
|
||||||
if (iobq)
|
if (iobq)
|
||||||
{
|
{
|
||||||
@@ -225,7 +225,7 @@ FAR struct iob_qentry_s *iob_tryalloc_qentry(void)
|
|||||||
iobq->qe_head = NULL; /* Nothing is contained */
|
iobq->qe_head = NULL; /* Nothing is contained */
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
return iobq;
|
return iobq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -118,7 +118,7 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
|
|||||||
* interrupts very briefly.
|
* interrupts very briefly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_iob_lock);
|
||||||
|
|
||||||
/* Which list? If there is a task waiting for an IOB, then put
|
/* Which list? If there is a task waiting for an IOB, then put
|
||||||
* the IOB on either the free list or on the committed list where
|
* the IOB on either the free list or on the committed list where
|
||||||
@@ -137,6 +137,8 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
|
|||||||
g_iob_freelist = iob;
|
g_iob_freelist = iob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
|
|
||||||
/* Signal that an IOB is available. If there is a thread blocked,
|
/* Signal that an IOB is available. If there is a thread blocked,
|
||||||
* waiting for an IOB, this will wake up exactly one thread. The
|
* waiting for an IOB, this will wake up exactly one thread. The
|
||||||
* semaphore count will correctly indicated that the awakened task
|
* semaphore count will correctly indicated that the awakened task
|
||||||
@@ -168,8 +170,6 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
|
|
||||||
/* And return the I/O buffer after the one that was freed */
|
/* And return the I/O buffer after the one that was freed */
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ FAR struct iob_qentry_s *iob_free_qentry(FAR struct iob_qentry_s *iobq)
|
|||||||
* interrupts very briefly.
|
* interrupts very briefly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = spin_lock_irqsave(&g_iob_lock);
|
||||||
|
|
||||||
/* Which list? If there is a task waiting for an IOB chain, then put
|
/* Which list? If there is a task waiting for an IOB chain, then put
|
||||||
* the IOB chain on either the free list or on the committed list where
|
* the IOB chain on either the free list or on the committed list where
|
||||||
@@ -77,6 +77,8 @@ FAR struct iob_qentry_s *iob_free_qentry(FAR struct iob_qentry_s *iobq)
|
|||||||
g_iob_freeqlist = iobq;
|
g_iob_freeqlist = iobq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
|
|
||||||
/* Signal that an I/O buffer chain container is available. If there
|
/* Signal that an I/O buffer chain container is available. If there
|
||||||
* is a thread waiting for an I/O buffer chain container, this will
|
* is a thread waiting for an I/O buffer chain container, this will
|
||||||
* wake up exactly one thread. The semaphore count will correctly
|
* wake up exactly one thread. The semaphore count will correctly
|
||||||
@@ -85,7 +87,6 @@ FAR struct iob_qentry_s *iob_free_qentry(FAR struct iob_qentry_s *iobq)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
nxsem_post(&g_qentry_sem);
|
nxsem_post(&g_qentry_sem);
|
||||||
leave_critical_section(flags);
|
|
||||||
|
|
||||||
/* And return the I/O buffer chain container after the one that was freed */
|
/* And return the I/O buffer chain container after the one that was freed */
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ void iob_free_queue_qentry(FAR struct iob_s *iob,
|
|||||||
FAR struct iob_qentry_s *prev = NULL;
|
FAR struct iob_qentry_s *prev = NULL;
|
||||||
FAR struct iob_qentry_s *qentry;
|
FAR struct iob_qentry_s *qentry;
|
||||||
|
|
||||||
irqstate_t flags = enter_critical_section();
|
irqstate_t flags = spin_lock_irqsave(&g_iob_lock);
|
||||||
for (qentry = iobq->qh_head; qentry != NULL;
|
for (qentry = iobq->qh_head; qentry != NULL;
|
||||||
prev = qentry, qentry = qentry->qe_flink)
|
prev = qentry, qentry = qentry->qe_flink)
|
||||||
{
|
{
|
||||||
@@ -73,6 +73,8 @@ void iob_free_queue_qentry(FAR struct iob_s *iob,
|
|||||||
iobq->qh_tail = prev;
|
iobq->qh_tail = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
|
|
||||||
/* Remove the queue container */
|
/* Remove the queue container */
|
||||||
|
|
||||||
iob_free_qentry(qentry);
|
iob_free_qentry(qentry);
|
||||||
@@ -81,11 +83,11 @@ void iob_free_queue_qentry(FAR struct iob_s *iob,
|
|||||||
|
|
||||||
iob_free_chain(iob);
|
iob_free_chain(iob);
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_IOB_NCHAINS > 0 */
|
#endif /* CONFIG_IOB_NCHAINS > 0 */
|
||||||
|
|||||||
@@ -102,6 +102,8 @@ sem_t g_throttle_sem = SEM_INITIALIZER(CONFIG_IOB_NBUFFERS -
|
|||||||
sem_t g_qentry_sem = SEM_INITIALIZER(CONFIG_IOB_NCHAINS);
|
sem_t g_qentry_sem = SEM_INITIALIZER(CONFIG_IOB_NCHAINS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
spinlock_t g_iob_lock = SP_UNLOCKED;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ FAR struct iob_s *iob_remove_queue(FAR struct iob_queue_s *iobq)
|
|||||||
|
|
||||||
/* Remove the I/O buffer chain from the head of the queue */
|
/* Remove the I/O buffer chain from the head of the queue */
|
||||||
|
|
||||||
irqstate_t flags = enter_critical_section();
|
irqstate_t flags = spin_lock_irqsave(&g_iob_lock);
|
||||||
qentry = iobq->qh_head;
|
qentry = iobq->qh_head;
|
||||||
if (qentry)
|
if (qentry)
|
||||||
{
|
{
|
||||||
@@ -66,6 +66,8 @@ FAR struct iob_s *iob_remove_queue(FAR struct iob_queue_s *iobq)
|
|||||||
iobq->qh_tail = NULL;
|
iobq->qh_tail = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
|
|
||||||
/* Extract the I/O buffer chain from the container and free the
|
/* Extract the I/O buffer chain from the container and free the
|
||||||
* container.
|
* container.
|
||||||
*/
|
*/
|
||||||
@@ -73,8 +75,11 @@ FAR struct iob_s *iob_remove_queue(FAR struct iob_queue_s *iobq)
|
|||||||
iob = qentry->qe_head;
|
iob = qentry->qe_head;
|
||||||
iob_free_qentry(qentry);
|
iob_free_qentry(qentry);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
return iob;
|
return iob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user