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

View File

@ -61,6 +61,16 @@
# define CONFIG_C99_BOOL 1 # define CONFIG_C99_BOOL 1
#endif #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 */ /* C++ support */
#undef CONFIG_HAVE_CXX14 #undef CONFIG_HAVE_CXX14

View File

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

View File

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