diff --git a/include/nuttx/mm/iob.h b/include/nuttx/mm/iob.h index afd63c01cb3..e64130d748b 100644 --- a/include/nuttx/mm/iob.h +++ b/include/nuttx/mm/iob.h @@ -233,6 +233,23 @@ struct iob_userstats_s void iob_initialize(void); +/**************************************************************************** + * Name: iob_timedalloc + * + * Description: + * Allocate an I/O buffer by taking the buffer at the head of the free list. + * This wait will be terminated when the specified timeout expires. + * + * Input Parameters: + * throttled - An indication of the IOB allocation is "throttled" + * timeout - Timeout value in milliseconds. + * consumerid - id representing who is consuming the IOB + * + ****************************************************************************/ + +FAR struct iob_s *iob_timedalloc(bool throttled, unsigned int timeout, + enum iob_user_e consumerid); + /**************************************************************************** * Name: iob_alloc * diff --git a/mm/iob/iob_alloc.c b/mm/iob/iob_alloc.c index c26269f3c0f..7df00e82278 100644 --- a/mm/iob/iob_alloc.c +++ b/mm/iob/iob_alloc.c @@ -93,7 +93,7 @@ static FAR struct iob_s *iob_alloc_committed(enum iob_user_e consumerid) * ****************************************************************************/ -static FAR struct iob_s *iob_allocwait(bool throttled, +static FAR struct iob_s *iob_allocwait(bool throttled, unsigned int timeout, enum iob_user_e consumerid) { FAR struct iob_s *iob; @@ -130,7 +130,27 @@ static FAR struct iob_s *iob_allocwait(bool throttled, * list. */ - ret = nxsem_wait_uninterruptible(sem); + if (timeout == UINT_MAX) + { + ret = nxsem_wait_uninterruptible(sem); + } + else + { + struct timespec abstime; + + DEBUGVERIFY(clock_gettime(CLOCK_REALTIME, &abstime)); + + abstime.tv_sec += timeout / MSEC_PER_SEC; + abstime.tv_nsec += timeout % MSEC_PER_SEC * NSEC_PER_MSEC; + if (abstime.tv_nsec >= NSEC_PER_SEC) + { + abstime.tv_sec++; + abstime.tv_nsec -= NSEC_PER_SEC; + } + + ret = nxsem_timedwait_uninterruptible(sem, &abstime); + } + if (ret >= 0) { /* When we wake up from wait successfully, an I/O buffer was @@ -180,18 +200,25 @@ static FAR struct iob_s *iob_allocwait(bool throttled, ****************************************************************************/ /**************************************************************************** - * Name: iob_alloc + * Name: iob_timedalloc * * Description: * Allocate an I/O buffer by taking the buffer at the head of the free list. + * This wait will be terminated when the specified timeout expires. + * + * Input Parameters: + * throttled - An indication of the IOB allocation is "throttled" + * timeout - Timeout value in milliseconds. + * consumerid - id representing who is consuming the IOB * ****************************************************************************/ -FAR struct iob_s *iob_alloc(bool throttled, enum iob_user_e consumerid) +FAR struct iob_s *iob_timedalloc(bool throttled, unsigned int timeout, + enum iob_user_e consumerid) { /* Were we called from the interrupt level? */ - if (up_interrupt_context() || sched_idletask()) + if (up_interrupt_context() || sched_idletask() || timeout == 0) { /* Yes, then try to allocate an I/O buffer without waiting */ @@ -201,10 +228,23 @@ FAR struct iob_s *iob_alloc(bool throttled, enum iob_user_e consumerid) { /* Then allocate an I/O buffer, waiting as necessary */ - return iob_allocwait(throttled, consumerid); + return iob_allocwait(throttled, timeout, consumerid); } } +/**************************************************************************** + * Name: iob_alloc + * + * Description: + * Allocate an I/O buffer by taking the buffer at the head of the free list. + * + ****************************************************************************/ + +FAR struct iob_s *iob_alloc(bool throttled, enum iob_user_e consumerid) +{ + return iob_timedalloc(throttled, UINT_MAX, consumerid); +} + /**************************************************************************** * Name: iob_tryalloc *