Skip to content

Commit

Permalink
mm/iob: remove csection
Browse files Browse the repository at this point in the history
  • Loading branch information
hujun260 authored and xiaoxiang781216 committed Dec 24, 2024
1 parent f771bfe commit 2c54896
Show file tree
Hide file tree
Showing 11 changed files with 230 additions and 236 deletions.
22 changes: 19 additions & 3 deletions mm/iob/iob.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include <nuttx/mm/iob.h>
#include <nuttx/semaphore.h>
#include <nuttx/spinlock.h>

#ifdef CONFIG_MM_IOB

Expand Down Expand Up @@ -76,14 +77,29 @@ extern FAR struct iob_qentry_s *g_iob_qcommitted;

/* Counting semaphores that tracks the number of free IOBs/qentries */

extern sem_t g_iob_sem; /* Counts free I/O buffers */
extern sem_t g_iob_sem;

/* Counts free I/O buffers */

extern volatile int16_t g_iob_count;

#if CONFIG_IOB_THROTTLE > 0
extern sem_t g_throttle_sem; /* Counts available I/O buffers when throttled */
extern sem_t g_throttle_sem;

/* Counts available I/O buffers when throttled */

extern volatile int16_t g_throttle_count;
#endif
#if CONFIG_IOB_NCHAINS > 0
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 */

extern volatile int16_t g_qentry_count;
#endif

extern volatile spinlock_t g_iob_lock;

/****************************************************************************
* Public Function Prototypes
****************************************************************************/
Expand Down
3 changes: 0 additions & 3 deletions mm/iob/iob_add_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ static int iob_add_queue_internal(FAR struct iob_s *iob,

qentry->qe_flink = NULL;

irqstate_t flags = enter_critical_section();
if (!iobq->qh_head)
{
iobq->qh_head = qentry;
Expand All @@ -76,8 +75,6 @@ static int iob_add_queue_internal(FAR struct iob_s *iob,
iobq->qh_tail = qentry;
}

leave_critical_section(flags);

return 0;
}

Expand Down
167 changes: 93 additions & 74 deletions mm/iob/iob_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ static FAR struct iob_s *iob_alloc_committed(void)
* 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 */

Expand All @@ -97,10 +97,82 @@ static FAR struct iob_s *iob_alloc_committed(void)
iob->io_pktlen = 0; /* Total length of the packet */
}

leave_critical_section(flags);
spin_unlock_irqrestore(&g_iob_lock, flags);
return iob;
}

static FAR struct iob_s *iob_tryalloc_internal(bool throttled)
{
FAR struct iob_s *iob;
#if CONFIG_IOB_THROTTLE > 0
int16_t count;
#endif

#if CONFIG_IOB_THROTTLE > 0
/* Select the count to check. */

count = (throttled ? g_throttle_count : g_iob_count);
#endif

/* We don't know what context we are called from so we use extreme measures
* to protect the free list: We disable interrupts very briefly.
*/

#if CONFIG_IOB_THROTTLE > 0
/* If there are free I/O buffers for this allocation */

if (count > 0)
#endif
{
/* Take the I/O buffer from the head of the free list */

iob = g_iob_freelist;
if (iob != NULL)
{
/* Remove the I/O buffer from the free list and decrement the
* counting semaphore(s) that tracks the number of available
* IOBs.
*/

g_iob_freelist = iob->io_flink;

/* Take a semaphore count. Note that we cannot do this in
* in the orthodox way by calling nxsem_wait() or nxsem_trywait()
* because this function may be called from an interrupt
* handler. Fortunately we know at at least one free buffer
* so a simple decrement is all that is needed.
*/

g_iob_count--;
DEBUGASSERT(g_iob_count >= 0);

#if CONFIG_IOB_THROTTLE > 0
/* The throttle semaphore is used to throttle the number of
* free buffers that are available. It is used to prevent
* the overrunning of the free buffer list. Please note that
* it can only be decremented to zero, which indicates no
* throttled buffers are available.
*/

if (g_throttle_count > 0)
{
g_throttle_count--;
}
#endif

/* Put the I/O buffer in a known state */

iob->io_flink = NULL; /* Not in a chain */
iob->io_len = 0; /* Length of the data in the entry */
iob->io_offset = 0; /* Offset to the beginning of data */
iob->io_pktlen = 0; /* Total length of the packet */
return iob;
}
}

return NULL;
}

/****************************************************************************
* Name: iob_allocwait
*
Expand All @@ -113,6 +185,7 @@ static FAR struct iob_s *iob_alloc_committed(void)
static FAR struct iob_s *iob_allocwait(bool throttled, unsigned int timeout)
{
FAR struct iob_s *iob;
FAR volatile int16_t *count;
irqstate_t flags;
FAR sem_t *sem;
clock_t start;
Expand All @@ -121,8 +194,10 @@ static FAR struct iob_s *iob_allocwait(bool throttled, unsigned int timeout)
#if CONFIG_IOB_THROTTLE > 0
/* Select the semaphore count to check. */

count = (throttled ? &g_throttle_count : &g_iob_count);
sem = (throttled ? &g_throttle_sem : &g_iob_sem);
#else
count = &g_iob_count;
sem = &g_iob_sem;
#endif

Expand All @@ -132,28 +207,32 @@ static FAR struct iob_s *iob_allocwait(bool throttled, unsigned int timeout)
* we are waiting for I/O buffers to become free.
*/

flags = enter_critical_section();
flags = spin_lock_irqsave(&g_iob_lock);

/* Try to get an I/O buffer. If successful, the semaphore count will be
* decremented atomically.
*/

start = clock_systime_ticks();
iob = iob_tryalloc(throttled);
while (ret == OK && iob == NULL)
iob = iob_tryalloc_internal(throttled);
if (iob == NULL)
{
/* If not successful, then the semaphore count was less than or equal
* to zero (meaning that there are no free buffers). We need to wait
* for an I/O buffer to be released and placed in the committed
* list.
*/

(*count)--;

spin_unlock_irqrestore(&g_iob_lock, flags);

if (timeout == UINT_MAX)
{
ret = nxsem_wait_uninterruptible(sem);
}
else
{
start = clock_systime_ticks();
ret = nxsem_tickwait_uninterruptible(sem,
iob_allocwait_gettimeout(start, timeout));
}
Expand All @@ -165,10 +244,13 @@ static FAR struct iob_s *iob_allocwait(bool throttled, unsigned int timeout)
*/

iob = iob_alloc_committed();
DEBUGASSERT(iob != NULL);
}

return iob;
}

leave_critical_section(flags);
spin_unlock_irqrestore(&g_iob_lock, flags);
return iob;
}

Expand Down Expand Up @@ -250,78 +332,15 @@ FAR struct iob_s *iob_tryalloc(bool throttled)
{
FAR struct iob_s *iob;
irqstate_t flags;
#if CONFIG_IOB_THROTTLE > 0
FAR sem_t *sem;
#endif

#if CONFIG_IOB_THROTTLE > 0
/* Select the semaphore count to check. */

sem = (throttled ? &g_throttle_sem : &g_iob_sem);
#endif

/* We don't know what context we are called from so we use extreme measures
* to protect the free list: We disable interrupts very briefly.
*/

flags = enter_critical_section();

#if CONFIG_IOB_THROTTLE > 0
/* If there are free I/O buffers for this allocation */

if (sem->semcount > 0)
#endif
{
/* Take the I/O buffer from the head of the free list */

iob = g_iob_freelist;
if (iob != NULL)
{
/* Remove the I/O buffer from the free list and decrement the
* counting semaphore(s) that tracks the number of available
* IOBs.
*/

g_iob_freelist = iob->io_flink;

/* Take a semaphore count. Note that we cannot do this in
* in the orthodox way by calling nxsem_wait() or nxsem_trywait()
* because this function may be called from an interrupt
* handler. Fortunately we know at at least one free buffer
* so a simple decrement is all that is needed.
*/

g_iob_sem.semcount--;
DEBUGASSERT(g_iob_sem.semcount >= 0);

#if CONFIG_IOB_THROTTLE > 0
/* The throttle semaphore is used to throttle the number of
* free buffers that are available. It is used to prevent
* the overrunning of the free buffer list. Please note that
* it can only be decremented to zero, which indicates no
* throttled buffers are available.
*/

if (g_throttle_sem.semcount > 0)
{
g_throttle_sem.semcount--;
}
#endif

leave_critical_section(flags);

/* Put the I/O buffer in a known state */

iob->io_flink = NULL; /* Not in a chain */
iob->io_len = 0; /* Length of the data in the entry */
iob->io_offset = 0; /* Offset to the beginning of data */
iob->io_pktlen = 0; /* Total length of the packet */
return iob;
}
}

leave_critical_section(flags);
return NULL;
flags = spin_lock_irqsave(&g_iob_lock);
iob = iob_tryalloc_internal(throttled);
spin_unlock_irqrestore(&g_iob_lock, flags);
return iob;
}

#ifdef CONFIG_IOB_ALLOC
Expand Down
Loading

0 comments on commit 2c54896

Please sign in to comment.