drivers/net/netdev: improve granularity of 'quota' locking

There is no need to use global spinlock to protect netdev
specific data counters. Allocate per-netdev specific spinlock
to get better locking granularity.

Move C/C++ atomic support checking to compiler.h

Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
This commit is contained in:
Petro Karashchenko 2023-06-16 23:05:09 +03:00 committed by Alan Carvalho de Assis
parent e78eade641
commit 46facd44b3
4 changed files with 40 additions and 24 deletions

View File

@ -91,10 +91,10 @@ struct netdev_upperhalf_s
static int quota_fetch_inc(FAR struct netdev_lowerhalf_s *lower,
enum netpkt_type_e type)
{
#ifndef HAVE_ATOMIC
irqstate_t flags = spin_lock_irqsave(NULL);
#ifndef HAVE_ATOMICS
irqstate_t flags = spin_lock_irqsave(&lower->lock);
int ret = lower->quota[type]++;
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&lower->lock, flags);
return ret;
#else
return atomic_fetch_add(&lower->quota[type], 1);
@ -104,10 +104,10 @@ static int quota_fetch_inc(FAR struct netdev_lowerhalf_s *lower,
static int quota_fetch_dec(FAR struct netdev_lowerhalf_s *lower,
enum netpkt_type_e type)
{
#ifndef HAVE_ATOMIC
irqstate_t flags = spin_lock_irqsave(NULL);
#ifndef HAVE_ATOMICS
irqstate_t flags = spin_lock_irqsave(&lower->lock);
int ret = lower->quota[type]--;
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&lower->lock, flags);
return ret;
#else
return atomic_fetch_sub(&lower->quota[type], 1);
@ -680,6 +680,9 @@ int netdev_lower_register(FAR struct netdev_lowerhalf_s *dev,
return -ENOMEM;
}
#ifndef HAVE_ATOMICS
spin_initialize(&dev->lock, SP_UNLOCKED);
#endif
dev->netdev.d_ifup = netdev_upper_ifup;
dev->netdev.d_ifdown = netdev_upper_ifdown;
dev->netdev.d_txavail = netdev_upper_txavail;
@ -846,10 +849,10 @@ void netdev_lower_txdone(FAR struct netdev_lowerhalf_s *dev)
int netdev_lower_quota_load(FAR struct netdev_lowerhalf_s *dev,
enum netpkt_type_e type)
{
#ifndef HAVE_ATOMIC
irqstate_t flags = spin_lock_irqsave(NULL);
#ifndef HAVE_ATOMICS
irqstate_t flags = spin_lock_irqsave(&dev->lock);
int ret = dev->quota[type];
spin_unlock_irqrestore(NULL, flags);
spin_unlock_irqrestore(&dev->lock, flags);
return ret;
#else
return atomic_load(&dev->quota[type]);

View File

@ -61,6 +61,16 @@
# define CONFIG_C99_BOOL 1
#endif
/* ISO C/C++11 atomic types support */
#undef CONFIG_HAVE_ATOMICS
#if ((defined(__cplusplus) && __cplusplus >= 201103L) || \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)) && \
!defined(__STDC_NO_ATOMICS__)
# define CONFIG_HAVE_ATOMICS
#endif
/* C++ support */
#undef CONFIG_HAVE_CXX14

View File

@ -28,6 +28,8 @@
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <nuttx/spinlock.h>
#include <net/if.h>
#include <netinet/in.h>
@ -37,10 +39,9 @@
*/
#if defined(CONFIG_OPENAMP)
#include <metal/atomic.h>
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
!defined(__STDC_NO_ATOMICS__)
#include <stdatomic.h>
# include <metal/atomic.h>
#elif defined(CONFIG_HAVE_ATOMICS)
# include <stdatomic.h>
#endif
#include <nuttx/net/ip.h>
@ -61,10 +62,8 @@
#define NETPKT_BUFLEN CONFIG_IOB_BUFSIZE
#if defined(CONFIG_OPENAMP) || \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
!defined(__STDC_NO_ATOMICS__))
#define HAVE_ATOMIC
#if defined(CONFIG_OPENAMP) || defined(CONFIG_HAVE_ATOMICS)
# define HAVE_ATOMICS
#endif
/****************************************************************************
@ -104,10 +103,11 @@ struct netdev_lowerhalf_s
/* Max # of buffer held by driver */
#ifdef HAVE_ATOMIC
#ifdef HAVE_ATOMICS
atomic_int quota[NETPKT_TYPENUM];
#else
int quota[NETPKT_TYPENUM];
spinlock_t lock;
#endif
/* The structure used by net stack.

View File

@ -33,6 +33,9 @@
#include <nuttx/irq.h>
#ifndef CONFIG_SPINLOCK
# define SP_UNLOCKED 0 /* The Un-locked state */
# define SP_LOCKED 1 /* The Locked state */
typedef uint8_t spinlock_t;
#else
@ -106,9 +109,9 @@ typedef uint8_t spinlock_t;
****************************************************************************/
#if defined(CONFIG_ARCH_HAVE_TESTSET)
spinlock_t up_testset(volatile FAR spinlock_t *lock);
spinlock_t up_testset(FAR volatile spinlock_t *lock);
#elif !defined(CONFIG_SMP)
static inline spinlock_t up_testset(volatile FAR spinlock_t *lock)
static inline spinlock_t up_testset(FAR volatile spinlock_t *lock)
{
irqstate_t flags;
spinlock_t ret;
@ -386,7 +389,7 @@ void spin_clrbit(FAR volatile cpu_set_t *set, unsigned int cpu,
****************************************************************************/
#if defined(CONFIG_SMP)
irqstate_t spin_lock_irqsave(spinlock_t *lock);
irqstate_t spin_lock_irqsave(FAR spinlock_t *lock);
#else
# define spin_lock_irqsave(l) ((void)(l), up_irq_save())
#endif
@ -396,7 +399,7 @@ irqstate_t spin_lock_irqsave(spinlock_t *lock);
****************************************************************************/
#if defined(CONFIG_SMP)
irqstate_t spin_lock_irqsave_wo_note(spinlock_t *lock);
irqstate_t spin_lock_irqsave_wo_note(FAR spinlock_t *lock);
#else
# define spin_lock_irqsave_wo_note(l) ((void)(l), up_irq_save())
#endif
@ -431,7 +434,7 @@ irqstate_t spin_lock_irqsave_wo_note(spinlock_t *lock);
****************************************************************************/
#if defined(CONFIG_SMP)
void spin_unlock_irqrestore(spinlock_t *lock, irqstate_t flags);
void spin_unlock_irqrestore(FAR spinlock_t *lock, irqstate_t flags);
#else
# define spin_unlock_irqrestore(l, f) up_irq_restore(f)
#endif
@ -441,7 +444,7 @@ void spin_unlock_irqrestore(spinlock_t *lock, irqstate_t flags);
****************************************************************************/
#if defined(CONFIG_SMP)
void spin_unlock_irqrestore_wo_note(spinlock_t *lock, irqstate_t flags);
void spin_unlock_irqrestore_wo_note(FAR spinlock_t *lock, irqstate_t flags);
#else
# define spin_unlock_irqrestore_wo_note(l, f) up_irq_restore(f)
#endif