forked from nuttx/nuttx-update
Squashed commit of the following:
net/utils: return from net_breaklock() was being clobbered. net/: Replace all calls to iob_alloc() with calls to net_ioballoc() which will release the network lock, if necessary. net/utils, tcp, include/net: Separate out the special IOB allocation logic and place it in its own function. Prototype is available in a public header file where it can also be used by network drivers. net/utils: net_timedwait() now uses new net_breaklock() and net_restorelock().
This commit is contained in:
parent
75cc19ebb4
commit
427b3b8fcb
8 changed files with 110 additions and 59 deletions
|
@ -290,12 +290,15 @@ void net_initialize(void);
|
|||
/****************************************************************************
|
||||
* Critical section management.
|
||||
*
|
||||
* Semaphore based locking is used:
|
||||
* Re-entrant mutex based locking of the network is supported:
|
||||
*
|
||||
* net_lock() - Takes the semaphore(). Implements a re-entrant mutex.
|
||||
* net_unlock() - Gives the semaphore().
|
||||
* net_lockedwait() - Like pthread_cond_wait(); releases the semaphore
|
||||
* momentarily to wait on another semaphore()
|
||||
* net_lock() - Locks the network via a re-entrant mutex.
|
||||
* net_unlock() - Unlocks the network.
|
||||
* net_lockedwait() - Like pthread_cond_wait() except releases the
|
||||
* network momentarily to wait on another semaphore.
|
||||
* net_ioballoc() - Like iob_alloc() except releases the network
|
||||
* momentarily to wait for an IOB to become
|
||||
* available.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -368,6 +371,27 @@ int net_timedwait(sem_t *sem, FAR const struct timespec *abstime);
|
|||
|
||||
int net_lockedwait(sem_t *sem);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: net_ioballoc
|
||||
*
|
||||
* Description:
|
||||
* Allocate an IOB. If no IOBs are available, then atomically wait for
|
||||
* for the IOB while temporarily releasing the lock on the network.
|
||||
*
|
||||
* Input Parameters:
|
||||
* throttled - An indication of the IOB allocation is "throttled"
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the newly allocated IOB is returned on success. NULL is
|
||||
* returned on any allocation failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MM_IOB
|
||||
struct iob_s; /* Forward reference */
|
||||
FAR struct iob_s *net_ioballoc(bool throttled);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: net_setipid
|
||||
*
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include <nuttx/net/ip.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_hci.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "netdev/netdev.h"
|
||||
#include "devif/devif.h"
|
||||
#include "socket/socket.h"
|
||||
|
@ -158,7 +159,7 @@ static uint16_t bluetooth_sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||
|
||||
/* Allocate an IOB to hold the frame data */
|
||||
|
||||
iob = iob_alloc(0);
|
||||
iob = net_ioballoc(false);
|
||||
if (iob == NULL)
|
||||
{
|
||||
nwarn("WARNING: Failed to allocate IOB\n");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* net/ieee802154/ieee802154_sendto.c
|
||||
*
|
||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -57,6 +57,7 @@
|
|||
#include <nuttx/net/radiodev.h>
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "netdev/netdev.h"
|
||||
#include "devif/devif.h"
|
||||
#include "socket/socket.h"
|
||||
|
@ -345,7 +346,7 @@ static uint16_t ieee802154_sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||
|
||||
/* Allocate an IOB to hold the frame data */
|
||||
|
||||
iob = iob_alloc(0);
|
||||
iob = net_ioballoc(false);
|
||||
if (iob == NULL)
|
||||
{
|
||||
nwarn("WARNING: Failed to allocate IOB\n");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* net/sixlowpan/sixlowpan_framelist.c
|
||||
*
|
||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Parts of this file derive from Contiki:
|
||||
|
@ -59,6 +59,7 @@
|
|||
#include <nuttx/net/radiodev.h>
|
||||
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "sixlowpan/sixlowpan_internal.h"
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN
|
||||
|
@ -409,7 +410,7 @@ int sixlowpan_queue_frames(FAR struct radio_driver_s *radio,
|
|||
* necessary.
|
||||
*/
|
||||
|
||||
iob = iob_alloc(false);
|
||||
iob = net_ioballoc(false);
|
||||
DEBUGASSERT(iob != NULL);
|
||||
|
||||
/* Initialize the IOB */
|
||||
|
@ -633,7 +634,7 @@ int sixlowpan_queue_frames(FAR struct radio_driver_s *radio,
|
|||
* necessary.
|
||||
*/
|
||||
|
||||
iob = iob_alloc(false);
|
||||
iob = net_ioballoc(false);
|
||||
DEBUGASSERT(iob != NULL);
|
||||
|
||||
/* Initialize the IOB */
|
||||
|
|
|
@ -212,7 +212,7 @@ int socket(int domain, int type, int protocol)
|
|||
sockfd = sockfd_allocate(0);
|
||||
if (sockfd < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to allodate a socket descriptor\n");
|
||||
nerr("ERROR: Failed to allocate a socket descriptor\n");
|
||||
errcode = ENFILE;
|
||||
goto errout;
|
||||
}
|
||||
|
|
|
@ -161,23 +161,7 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void)
|
|||
|
||||
/* Now get the first I/O buffer for the write buffer structure */
|
||||
|
||||
wrb->wb_iob = iob_tryalloc(false);
|
||||
if (wrb->wb_iob == NULL)
|
||||
{
|
||||
unsigned int count;
|
||||
int ret;
|
||||
|
||||
/* There are no buffers available now. We will have to wait for one to
|
||||
* become available. But let's not do that with the network locked.
|
||||
*/
|
||||
|
||||
ret = net_breaklock(&count);
|
||||
wrb->wb_iob = iob_alloc(false);
|
||||
if (ret >= 0)
|
||||
{
|
||||
net_restorelock(count);
|
||||
}
|
||||
}
|
||||
wrb->wb_iob = net_ioballoc(false);
|
||||
|
||||
/* Did we get an IOB? We should always get one except under some really weird
|
||||
* error conditions.
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/mm/iob.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "udp/udp.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -156,7 +157,7 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void)
|
|||
|
||||
/* Now get the first I/O buffer for the write buffer structure */
|
||||
|
||||
wrb->wb_iob = iob_alloc(false);
|
||||
wrb->wb_iob = net_ioballoc(false);
|
||||
if (!wrb->wb_iob)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate I/O buffer\n");
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/mm/iob.h>
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
|
@ -283,48 +284,40 @@ int net_timedwait(sem_t *sem, FAR const struct timespec *abstime)
|
|||
{
|
||||
unsigned int count;
|
||||
irqstate_t flags;
|
||||
int blresult;
|
||||
int ret;
|
||||
|
||||
flags = enter_critical_section(); /* No interrupts */
|
||||
sched_lock(); /* No context switches */
|
||||
|
||||
pid_t me = getpid();
|
||||
/* Release the network lock, remembering my count. net_breaklock will
|
||||
* return a negated value if the caller does not hold the network lock.
|
||||
*/
|
||||
|
||||
sched_lock(); /* No context switches */
|
||||
if (g_holder == me)
|
||||
blresult = net_breaklock(&count);
|
||||
|
||||
/* Now take the semaphore, waiting if so requested. */
|
||||
|
||||
if (abstime != NULL)
|
||||
{
|
||||
/* Release the network lock, remembering my count */
|
||||
/* Wait until we get the lock or until the timeout expires */
|
||||
|
||||
count = g_count;
|
||||
g_holder = NO_HOLDER;
|
||||
g_count = 0;
|
||||
nxsem_post(&g_netlock);
|
||||
|
||||
/* Now take the semaphore, waiting if so requested. */
|
||||
|
||||
if (abstime != NULL)
|
||||
{
|
||||
/* Wait until we get the lock or until the timeout expires */
|
||||
|
||||
ret = nxsem_timedwait(sem, abstime);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait as long as necessary to get the lock */
|
||||
|
||||
ret = nxsem_wait(sem);
|
||||
}
|
||||
|
||||
/* Recover the network lock at the proper count */
|
||||
|
||||
_net_takesem();
|
||||
g_holder = me;
|
||||
g_count = count;
|
||||
ret = nxsem_timedwait(sem, abstime);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait as long as necessary to get the lock */
|
||||
|
||||
ret = nxsem_wait(sem);
|
||||
}
|
||||
|
||||
/* Recover the network lock at the proper count (if we held it before) */
|
||||
|
||||
if (blresult >= 0)
|
||||
{
|
||||
net_restorelock(count);
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
leave_critical_section(flags);
|
||||
return ret;
|
||||
|
@ -350,3 +343,49 @@ int net_lockedwait(sem_t *sem)
|
|||
return net_timedwait(sem, NULL);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: net_ioballoc
|
||||
*
|
||||
* Description:
|
||||
* Allocate an IOB. If no IOBs are available, then atomically wait for
|
||||
* for the IOB while temporarily releasing the lock on the network.
|
||||
*
|
||||
* Input Parameters:
|
||||
* throttled - An indication of the IOB allocation is "throttled"
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the newly allocated IOB is returned on success. NULL is
|
||||
* returned on any allocation failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MM_IOB
|
||||
FAR struct iob_s *net_ioballoc(bool throttled)
|
||||
{
|
||||
FAR struct iob_s *iob;
|
||||
|
||||
iob = iob_tryalloc(throttled);
|
||||
if (iob == NULL)
|
||||
{
|
||||
irqstate_t flags;
|
||||
unsigned int count;
|
||||
int blresult;
|
||||
|
||||
/* There are no buffers available now. We will have to wait for one to
|
||||
* become available. But let's not do that with the network locked.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
blresult = net_breaklock(&count);
|
||||
iob = iob_alloc(throttled);
|
||||
if (blresult >= 0)
|
||||
{
|
||||
net_restorelock(count);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
return iob;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue