Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mm/iob: remove csection #54

Merged
merged 1 commit into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading