1
0
Fork 0
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:
Gregory Nutt 2018-07-07 08:26:13 -06:00
parent 75cc19ebb4
commit 427b3b8fcb
8 changed files with 110 additions and 59 deletions

View file

@ -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
*

View file

@ -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");

View file

@ -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");

View file

@ -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 */

View file

@ -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;
}

View file

@ -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.

View file

@ -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");

View file

@ -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