diff --git a/net/bluetooth/bluetooth_conn.c b/net/bluetooth/bluetooth_conn.c index f649943bd468d..ad529326b64de 100644 --- a/net/bluetooth/bluetooth_conn.c +++ b/net/bluetooth/bluetooth_conn.c @@ -42,10 +42,19 @@ #include #include "devif/devif.h" +#include "utils/utils.h" #include "bluetooth/bluetooth.h" #ifdef CONFIG_NET_BLUETOOTH +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_NET_BLUETOOTH_MAX_CONNS +# define CONFIG_NET_BLUETOOTH_MAX_CONNS 0 +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -54,14 +63,10 @@ * network lock. */ -#if CONFIG_NET_BLUETOOTH_PREALLOC_CONNS > 0 -static struct bluetooth_conn_s - g_bluetooth_connections[CONFIG_NET_BLUETOOTH_PREALLOC_CONNS]; -#endif - -/* A list of all free packet socket connections */ - -static dq_queue_t g_free_bluetooth_connections; +NET_BUFPOOL_DECLARE(g_bluetooth_connections, sizeof(struct bluetooth_conn_s), + CONFIG_NET_BLUETOOTH_PREALLOC_CONNS, + CONFIG_NET_BLUETOOTH_ALLOC_CONNS, + CONFIG_NET_BLUETOOTH_MAX_CONNS); /* A list of all allocated packet socket connections */ @@ -90,17 +95,7 @@ static const bt_addr_t g_any_addr = void bluetooth_conn_initialize(void) { -#if CONFIG_NET_BLUETOOTH_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_BLUETOOTH_PREALLOC_CONNS; i++) - { - /* Link each pre-allocated connection structure into the free list. */ - - dq_addlast(&g_bluetooth_connections[i].bc_conn.node, - &g_free_bluetooth_connections); - } -#endif + NET_BUFPOOL_INIT(g_bluetooth_connections); } /**************************************************************************** @@ -115,39 +110,12 @@ void bluetooth_conn_initialize(void) FAR struct bluetooth_conn_s *bluetooth_conn_alloc(void) { FAR struct bluetooth_conn_s *conn; -#if CONFIG_NET_BLUETOOTH_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by the network lock */ net_lock(); -#if CONFIG_NET_BLUETOOTH_ALLOC_CONNS > 0 - if (dq_peek(&g_active_bluetooth_connections) == NULL) - { -#if CONFIG_NET_BLUETOOTH_MAX_CONNS > 0 - if (dq_count(&g_active_bluetooth_connections) + - CONFIG_NET_BLUETOOTH_ALLOC_CONNS > CONFIG_NET_BLUETOOTH_MAX_CONNS) - { - net_unlock(); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_BLUETOOTH_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_NET_BLUETOOTH_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].bc_conn.node, - &g_active_bluetooth_connections); - } - } - } -#endif - conn = (FAR struct bluetooth_conn_s *) - dq_remfirst(&g_free_bluetooth_connections); + conn = NET_BUFPOOL_TRYALLOC(g_bluetooth_connections); if (conn) { /* Mark as unbound */ @@ -207,22 +175,9 @@ void bluetooth_conn_free(FAR struct bluetooth_conn_s *conn) bluetooth_container_free(container); } - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection structure */ -#if CONFIG_NET_BLUETOOTH_ALLOC_CONNS == 1 - if (conn < g_bluetooth_connections || conn >= (g_bluetooth_connections + - CONFIG_NET_BLUETOOTH_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->bc_conn.node, &g_free_bluetooth_connections); - } + NET_BUFPOOL_FREE(g_bluetooth_connections, conn); net_unlock(); } diff --git a/net/can/can_conn.c b/net/can/can_conn.c index 89be629af56b7..6f26bab4c87e5 100644 --- a/net/can/can_conn.c +++ b/net/can/can_conn.c @@ -46,18 +46,22 @@ #ifdef CONFIG_NET_CAN /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all NetLink connections. */ - -#if CONFIG_CAN_PREALLOC_CONNS > 0 -static struct can_conn_s g_can_connections[CONFIG_CAN_PREALLOC_CONNS]; +#ifndef CONFIG_CAN_MAX_CONNS +# define CONFIG_CAN_MAX_CONNS 0 #endif -/* A list of all free NetLink connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all NetLink connections. */ -static dq_queue_t g_free_can_connections; +NET_BUFPOOL_DECLARE(g_can_connections, sizeof(struct can_conn_s), + CONFIG_CAN_PREALLOC_CONNS, CONFIG_CAN_ALLOC_CONNS, + CONFIG_CAN_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated NetLink connections */ @@ -79,16 +83,7 @@ static dq_queue_t g_active_can_connections; void can_initialize(void) { -#if CONFIG_CAN_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_CAN_PREALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - dq_addlast(&g_can_connections[i].sconn.node, &g_free_can_connections); - } -#endif + NET_BUFPOOL_INIT(g_can_connections); } /**************************************************************************** @@ -103,37 +98,12 @@ void can_initialize(void) FAR struct can_conn_s *can_alloc(void) { FAR struct can_conn_s *conn; -#if CONFIG_CAN_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by a a mutex. */ nxmutex_lock(&g_free_lock); -#if CONFIG_CAN_ALLOC_CONNS > 0 - if (dq_peek(&g_free_can_connections) == NULL) - { -#if CONFIG_CAN_MAX_CONNS > 0 - if (dq_count(&g_active_can_connections) + - CONFIG_CAN_ALLOC_CONNS > CONFIG_CAN_MAX_CONNS) - { - nxmutex_unlock(&g_free_lock); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_CAN_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_CAN_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, &g_free_can_connections); - } - } - } -#endif - conn = (FAR struct can_conn_s *)dq_remfirst(&g_free_can_connections); + conn = NET_BUFPOOL_TRYALLOC(g_can_connections); if (conn != NULL) { /* FIXME SocketCAN default behavior enables loopback */ @@ -184,22 +154,9 @@ void can_free(FAR struct can_conn_s *conn) dq_rem(&conn->sconn.node, &g_active_can_connections); - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_CAN_ALLOC_CONNS == 1 - if (conn < g_can_connections || conn >= (g_can_connections + - CONFIG_CAN_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_can_connections); - } + NET_BUFPOOL_FREE(g_can_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/devif/devif_callback.c b/net/devif/devif_callback.c index ecd8283667792..6f451a2b381fc 100644 --- a/net/devif/devif_callback.c +++ b/net/devif/devif_callback.c @@ -39,6 +39,7 @@ #include #include "netdev/netdev.h" +#include "utils/utils.h" #include "devif/devif.h" /**************************************************************************** @@ -52,11 +53,9 @@ * Private Data ****************************************************************************/ -#if CONFIG_NET_PREALLOC_DEVIF_CALLBACKS > 0 -static struct devif_callback_s - g_cbprealloc[CONFIG_NET_PREALLOC_DEVIF_CALLBACKS]; -#endif -static FAR struct devif_callback_s *g_cbfreelist = NULL; +NET_BUFPOOL_DECLARE(g_cbprealloc, sizeof(struct devif_callback_s), + CONFIG_NET_PREALLOC_DEVIF_CALLBACKS, + CONFIG_NET_ALLOC_DEVIF_CALLBACKS, 0); /**************************************************************************** * Private Functions @@ -88,7 +87,7 @@ static void devif_callback_free(FAR struct net_driver_s *dev, #ifdef CONFIG_DEBUG_FEATURES /* Check for double freed callbacks */ - curr = g_cbfreelist; + curr = (FAR struct devif_callback_s *)g_cbprealloc.freebuffers.head; while (curr != NULL) { @@ -187,23 +186,9 @@ static void devif_callback_free(FAR struct net_driver_s *dev, } } - /* If this is a preallocated or a batch allocated callback store it in - * the free callbacks list. Else free it. - */ + /* Free the callback structure */ -#if CONFIG_NET_ALLOC_DEVIF_CALLBACKS == 1 - if (cb < g_cbprealloc || cb >= (g_cbprealloc + - CONFIG_NET_PREALLOC_DEVIF_CALLBACKS)) - { - kmm_free(cb); - } - else -#endif - { - cb->nxtconn = g_cbfreelist; - cb->nxtdev = NULL; - g_cbfreelist = cb; - } + NET_BUFPOOL_FREE(g_cbprealloc, cb); net_unlock(); } @@ -266,15 +251,7 @@ static bool devif_event_trigger(uint16_t events, uint16_t triggers) void devif_callback_init(void) { -#if CONFIG_NET_PREALLOC_DEVIF_CALLBACKS > 0 - int i; - - for (i = 0; i < CONFIG_NET_PREALLOC_DEVIF_CALLBACKS; i++) - { - g_cbprealloc[i].nxtconn = g_cbfreelist; - g_cbfreelist = &g_cbprealloc[i]; - } -#endif + NET_BUFPOOL_INIT(g_cbprealloc); } /**************************************************************************** @@ -299,9 +276,6 @@ FAR struct devif_callback_s * FAR struct devif_callback_s **list_tail) { FAR struct devif_callback_s *ret; -#if CONFIG_NET_ALLOC_DEVIF_CALLBACKS > 0 - int i; -#endif net_lock(); @@ -324,34 +298,11 @@ FAR struct devif_callback_s * return NULL; } - /* Allocate the callback entry from heap */ + /* Get a callback structure */ -#if CONFIG_NET_ALLOC_DEVIF_CALLBACKS > 0 - if (g_cbfreelist == NULL) - { - ret = kmm_zalloc(sizeof(struct devif_callback_s) * - CONFIG_NET_ALLOC_DEVIF_CALLBACKS); - if (ret != NULL) - { - for (i = 0; i < CONFIG_NET_ALLOC_DEVIF_CALLBACKS; i++) - { - ret[i].nxtconn = g_cbfreelist; - g_cbfreelist = &ret[i]; - } - } - } -#endif - - /* Check the head of the free list */ - - ret = g_cbfreelist; + ret = NET_BUFPOOL_TRYALLOC(g_cbprealloc); if (ret) { - /* Remove the next instance from the head of the free list */ - - g_cbfreelist = ret->nxtconn; - memset(ret, 0, sizeof(struct devif_callback_s)); - /* Add the newly allocated instance to the head of the device event * list. */ diff --git a/net/icmp/icmp_conn.c b/net/icmp/icmp_conn.c index a4eac7cd3a8fc..3fb3d1938ce44 100644 --- a/net/icmp/icmp_conn.c +++ b/net/icmp/icmp_conn.c @@ -41,22 +41,27 @@ #include "devif/devif.h" #include "icmp/icmp.h" +#include "utils/utils.h" #ifdef CONFIG_NET_ICMP_SOCKET /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all IPPROTO_ICMP socket connections */ - -#if CONFIG_NET_ICMP_PREALLOC_CONNS > 0 -static struct icmp_conn_s g_icmp_connections[CONFIG_NET_ICMP_PREALLOC_CONNS]; +#ifndef CONFIG_NET_ICMP_MAX_CONNS +# define CONFIG_NET_ICMP_MAX_CONNS 0 #endif -/* A list of all free IPPROTO_ICMP socket connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all IPPROTO_ICMP socket connections */ -static dq_queue_t g_free_icmp_connections; +NET_BUFPOOL_DECLARE(g_icmp_connections, sizeof(struct icmp_conn_s), + CONFIG_NET_ICMP_PREALLOC_CONNS, + CONFIG_NET_ICMP_ALLOC_CONNS, CONFIG_NET_ICMP_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated IPPROTO_ICMP socket connections */ @@ -78,17 +83,7 @@ static dq_queue_t g_active_icmp_connections; void icmp_sock_initialize(void) { -#if CONFIG_NET_ICMP_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_ICMP_PREALLOC_CONNS; i++) - { - /* Move the connection structure to the free list */ - - dq_addlast(&g_icmp_connections[i].sconn.node, - &g_free_icmp_connections); - } -#endif + NET_BUFPOOL_INIT(g_icmp_connections); } /**************************************************************************** @@ -111,31 +106,7 @@ FAR struct icmp_conn_s *icmp_alloc(void) ret = nxmutex_lock(&g_free_lock); if (ret >= 0) { -#if CONFIG_NET_ICMP_ALLOC_CONNS > 0 - if (dq_peek(&g_free_icmp_connections) == NULL) - { -#if CONFIG_NET_ICMP_MAX_CONNS > 0 - if (dq_count(&g_active_icmp_connections) + - CONFIG_NET_ICMP_ALLOC_CONNS > CONFIG_NET_ICMP_MAX_CONNS) - { - nxmutex_unlock(&g_free_lock); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_ICMP_ALLOC_CONNS); - if (conn != NULL) - { - for (ret = 0; ret < CONFIG_NET_ICMP_ALLOC_CONNS; ret++) - { - dq_addlast(&conn[ret].sconn.node, - &g_free_icmp_connections); - } - } - } -#endif - - conn = (FAR struct icmp_conn_s *)dq_remfirst(&g_free_icmp_connections); + conn = NET_BUFPOOL_TRYALLOC(g_icmp_connections); if (conn != NULL) { /* Enqueue the connection into the active list */ @@ -184,22 +155,9 @@ void icmp_free(FAR struct icmp_conn_s *conn) dq_rem(&conn->sconn.node, &g_active_icmp_connections); - /* If this is a preallocated or a batch allocated connection store it - * in the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_NET_ICMP_ALLOC_CONNS == 1 - if (conn < g_icmp_connections || conn >= (g_icmp_connections + - CONFIG_NET_ICMP_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_icmp_connections); - } + NET_BUFPOOL_FREE(g_icmp_connections, conn); } nxmutex_unlock(&g_free_lock); diff --git a/net/icmpv6/icmpv6_conn.c b/net/icmpv6/icmpv6_conn.c index ac3d65a4dbcd3..228f83e8d5e57 100644 --- a/net/icmpv6/icmpv6_conn.c +++ b/net/icmpv6/icmpv6_conn.c @@ -41,23 +41,28 @@ #include "devif/devif.h" #include "icmpv6/icmpv6.h" +#include "utils/utils.h" #ifdef CONFIG_NET_ICMPv6_SOCKET /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all IPPROTO_ICMP socket connections */ - -#if CONFIG_NET_ICMPv6_PREALLOC_CONNS > 0 -static struct icmpv6_conn_s - g_icmpv6_connections[CONFIG_NET_ICMPv6_PREALLOC_CONNS]; +#ifndef CONFIG_NET_ICMPv6_MAX_CONNS +# define CONFIG_NET_ICMPv6_MAX_CONNS 0 #endif -/* A list of all free IPPROTO_ICMP socket connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all IPPROTO_ICMP socket connections */ -static dq_queue_t g_free_icmpv6_connections; +NET_BUFPOOL_DECLARE(g_icmpv6_connections, sizeof(struct icmpv6_conn_s), + CONFIG_NET_ICMPv6_PREALLOC_CONNS, + CONFIG_NET_ICMPv6_ALLOC_CONNS, + CONFIG_NET_ICMPv6_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated IPPROTO_ICMP socket connections */ @@ -79,17 +84,7 @@ static dq_queue_t g_active_icmpv6_connections; void icmpv6_sock_initialize(void) { -#if CONFIG_NET_ICMPv6_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_ICMPv6_PREALLOC_CONNS; i++) - { - /* Move the connection structure to the free list */ - - dq_addlast(&g_icmpv6_connections[i].sconn.node, - &g_free_icmpv6_connections); - } -#endif + NET_BUFPOOL_INIT(g_icmpv6_connections); } /**************************************************************************** @@ -112,32 +107,7 @@ FAR struct icmpv6_conn_s *icmpv6_alloc(void) ret = nxmutex_lock(&g_free_lock); if (ret >= 0) { -#if CONFIG_NET_ICMPv6_ALLOC_CONNS > 0 - if (dq_peek(&g_active_icmpv6_connections) == NULL) - { -#if CONFIG_NET_ICMPv6_MAX_CONNS > 0 - if (dq_count(&g_active_icmpv6_connections) + - CONFIG_NET_ICMPv6_ALLOC_CONNS > CONFIG_NET_ICMPv6_MAX_CONNS) - { - nxmutex_unlock(&g_free_lock); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_ICMPv6_ALLOC_CONNS); - if (conn != NULL) - { - for (ret = 0; ret < CONFIG_NET_ICMPv6_ALLOC_CONNS; ret++) - { - dq_addlast(&conn[ret].sconn.node, - &g_free_icmpv6_connections); - } - } - } -#endif - - conn = (FAR struct icmpv6_conn_s *) - dq_remfirst(&g_free_icmpv6_connections); + conn = NET_BUFPOOL_TRYALLOC(g_icmpv6_connections); if (conn != NULL) { /* Enqueue the connection into the active list */ @@ -174,22 +144,9 @@ void icmpv6_free(FAR struct icmpv6_conn_s *conn) dq_rem(&conn->sconn.node, &g_active_icmpv6_connections); - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_NET_ICMPv6_ALLOC_CONNS == 1 - if (conn < g_icmpv6_connections || conn >= (g_icmpv6_connections + - CONFIG_NET_ICMPv6_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_icmpv6_connections); - } + NET_BUFPOOL_FREE(g_icmpv6_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/ieee802154/ieee802154_conn.c b/net/ieee802154/ieee802154_conn.c index d30f05c14ba62..46e7ff7047a7e 100644 --- a/net/ieee802154/ieee802154_conn.c +++ b/net/ieee802154/ieee802154_conn.c @@ -42,9 +42,18 @@ #include "devif/devif.h" #include "ieee802154/ieee802154.h" +#include "utils/utils.h" #ifdef CONFIG_NET_IEEE802154 +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_NET_IEEE802154_MAX_CONNS +# define CONFIG_NET_IEEE802154_MAX_CONNS 0 +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -53,14 +62,11 @@ * network lock. */ -#if CONFIG_NET_IEEE802154_PREALLOC_CONNS > 0 -static struct ieee802154_conn_s - g_ieee802154_connections[CONFIG_NET_IEEE802154_PREALLOC_CONNS]; -#endif - -/* A list of all free packet socket connections */ - -static dq_queue_t g_free_ieee802154_connections; +NET_BUFPOOL_DECLARE(g_ieee802154_connections, + sizeof(struct ieee802154_conn_s), + CONFIG_NET_IEEE802154_PREALLOC_CONNS, + CONFIG_NET_IEEE802154_ALLOC_CONNS, + CONFIG_NET_IEEE802154_MAX_CONNS); /* A list of all allocated packet socket connections */ @@ -84,17 +90,7 @@ static dq_queue_t g_active_ieee802154_connections; void ieee802154_conn_initialize(void) { -#if CONFIG_NET_IEEE802154_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_IEEE802154_PREALLOC_CONNS; i++) - { - /* Link each pre-allocated connection structure into the free list. */ - - dq_addlast(&g_ieee802154_connections[i].sconn.node, - &g_free_ieee802154_connections); - } -#endif + NET_BUFPOOL_INIT(g_ieee802154_connections); } /**************************************************************************** @@ -109,39 +105,12 @@ void ieee802154_conn_initialize(void) FAR struct ieee802154_conn_s *ieee802154_conn_alloc(void) { FAR struct ieee802154_conn_s *conn; -#if CONFIG_NET_IEEE802154_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by the network lock. */ net_lock(); -#if CONFIG_NET_IEEE802154_ALLOC_CONNS > 0 - if (dq_peek(&g_free_ieee802154_connections) == NULL) - { -#if CONFIG_NET_IEEE802154_MAX_CONNS > 0 - if (dq_count(&g_active_ieee802154_connections) + - CONFIG_NET_IEEE802154_ALLOC_CONNS > CONFIG_NET_IEEE802154_MAX_CONNS) - { - net_unlock(); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_IEEE802154_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_NET_IEEE802154_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, - &g_free_ieee802154_connections); - } - } - } -#endif - conn = (FAR struct ieee802154_conn_s *) - dq_remfirst(&g_free_ieee802154_connections); + conn = NET_BUFPOOL_TRYALLOC(g_ieee802154_connections); if (conn) { dq_addlast(&conn->sconn.node, &g_active_ieee802154_connections); @@ -195,22 +164,9 @@ void ieee802154_conn_free(FAR struct ieee802154_conn_s *conn) ieee802154_container_free(container); } - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_NET_IEEE802154_ALLOC_CONNS == 1 - if (conn < g_ieee802154_connections || conn >= (g_ieee802154_connections + - CONFIG_NET_IEEE802154_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_ieee802154_connections); - } + NET_BUFPOOL_FREE(g_ieee802154_connections, conn); net_unlock(); } diff --git a/net/ipforward/Kconfig b/net/ipforward/Kconfig index 3be48eac75998..96cf02104b470 100644 --- a/net/ipforward/Kconfig +++ b/net/ipforward/Kconfig @@ -40,3 +40,21 @@ config NET_IPFORWARD_NSTRUCT WARNING: DO NOT set this setting to a value greater than or equal to CONFIG_IOB_NBUFFERS, otherwise it may consume all the IOB and let netdev fail to work. + +config NET_IPFORWARD_ALLOC_STRUCT + int "Dynamic forwarding structures allocation" + default 0 + ---help--- + When set to 0 all dynamic allocations are disabled + + When set to 1 a new forwarding structure will be allocated every + time, and it will be free'd when no longer needed. + + Setting this to 2 or more will allocate the forwarding structures + in batches (with batch size equal to this config). When a I/O buffer + chain head is no longer needed, it will be returned to the free + forwarding structures pool, and it will never be deallocated! + + Note: maximum number of allocated forwarding structures is limited + to CONFIG_IOB_NBUFFERS - CONFIG_IOB_THROTTLE to avoid consuming all + the IOBs. diff --git a/net/ipforward/ipfwd_alloc.c b/net/ipforward/ipfwd_alloc.c index b0b5536dea8a5..dc3fb31ec0d52 100644 --- a/net/ipforward/ipfwd_alloc.c +++ b/net/ipforward/ipfwd_alloc.c @@ -37,6 +37,7 @@ #include #include "ipforward/ipforward.h" +#include "utils/utils.h" #ifdef CONFIG_NET_IPFORWARD @@ -66,13 +67,12 @@ * Private Data ****************************************************************************/ -/* This is an array of pre-allocating forwarding structures */ +/* This is the state of the global forwarding structures */ -static struct forward_s g_fwdpool[CONFIG_NET_IPFORWARD_NSTRUCT]; - -/* This is a list of free forwarding structures */ - -static FAR struct forward_s *g_fwdfree; +NET_BUFPOOL_DECLARE(g_fwdpool, sizeof(struct forward_s), + CONFIG_NET_IPFORWARD_NSTRUCT, + CONFIG_NET_IPFORWARD_ALLOC_STRUCT, + CONFIG_IOB_NBUFFERS - CONFIG_IOB_THROTTLE); /**************************************************************************** * Public Functions @@ -91,25 +91,13 @@ static FAR struct forward_s *g_fwdfree; void ipfwd_initialize(void) { - FAR struct forward_s *fwd; - int i; - /* The IOB size must be such that the maximum L2 and L3 headers fit into * the contiguous memory of the first IOB in the IOB chain. */ DEBUGASSERT(MAX_HDRLEN <= CONFIG_IOB_BUFSIZE); - /* Add all pre-allocated forwarding structures to the free list */ - - g_fwdfree = NULL; - - for (i = 0; i < CONFIG_NET_IPFORWARD_NSTRUCT; i++) - { - fwd = &g_fwdpool[i]; - fwd->f_flink = g_fwdfree; - g_fwdfree = fwd; - } + NET_BUFPOOL_INIT(g_fwdpool); } /**************************************************************************** @@ -127,16 +115,7 @@ void ipfwd_initialize(void) FAR struct forward_s *ipfwd_alloc(void) { - FAR struct forward_s *fwd; - - fwd = g_fwdfree; - if (fwd != NULL) - { - g_fwdfree = fwd->f_flink; - memset (fwd, 0, sizeof(struct forward_s)); - } - - return fwd; + return NET_BUFPOOL_TRYALLOC(g_fwdpool); } /**************************************************************************** @@ -153,8 +132,7 @@ FAR struct forward_s *ipfwd_alloc(void) void ipfwd_free(FAR struct forward_s *fwd) { - fwd->f_flink = g_fwdfree; - g_fwdfree = fwd; + NET_BUFPOOL_FREE(g_fwdpool, fwd); } #endif /* CONFIG_NET_IPFORWARD */ diff --git a/net/netlink/netlink_conn.c b/net/netlink/netlink_conn.c index 0a1b5f71da353..dddb52bd5cda8 100644 --- a/net/netlink/netlink_conn.c +++ b/net/netlink/netlink_conn.c @@ -49,19 +49,22 @@ #ifdef CONFIG_NET_NETLINK /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all NetLink connections. */ - -#if CONFIG_NETLINK_PREALLOC_CONNS > 0 -static struct netlink_conn_s -g_netlink_connections[CONFIG_NETLINK_PREALLOC_CONNS]; +#ifndef CONFIG_NETLINK_MAX_CONNS +# define CONFIG_NETLINK_MAX_CONNS 0 #endif -/* A list of all free NetLink connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all NetLink connections. */ -static dq_queue_t g_free_netlink_connections; +NET_BUFPOOL_DECLARE(g_netlink_connections, sizeof(struct netlink_conn_s), + CONFIG_NETLINK_PREALLOC_CONNS, + CONFIG_NETLINK_ALLOC_CONNS, CONFIG_NETLINK_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated NetLink connections */ @@ -147,17 +150,7 @@ netlink_get_terminator(FAR const struct nlmsghdr *req) void netlink_initialize(void) { -#if CONFIG_NETLINK_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NETLINK_PREALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - dq_addlast(&g_netlink_connections[i].sconn.node, - &g_free_netlink_connections); - } -#endif + NET_BUFPOOL_INIT(g_netlink_connections); } /**************************************************************************** @@ -172,38 +165,12 @@ void netlink_initialize(void) FAR struct netlink_conn_s *netlink_alloc(void) { FAR struct netlink_conn_s *conn; -#if CONFIG_NETLINK_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by a mutex. */ nxmutex_lock(&g_free_lock); -#if CONFIG_NETLINK_ALLOC_CONNS > 0 - if (dq_peek(&g_free_netlink_connections) == NULL) - { -#if CONFIG_NETLINK_MAX_CONNS > 0 - if (dq_count(&g_active_netlink_connections) + - CONFIG_NETLINK_ALLOC_CONNS > CONFIG_NETLINK_MAX_CONNS) - { - nxmutex_unlock(&g_free_lock); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NETLINK_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_NETLINK_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, &g_free_netlink_connections); - } - } - } -#endif - conn = (FAR struct netlink_conn_s *) - dq_remfirst(&g_free_netlink_connections); + conn = NET_BUFPOOL_TRYALLOC(g_netlink_connections); if (conn != NULL) { /* Enqueue the connection into the active list */ @@ -245,22 +212,9 @@ void netlink_free(FAR struct netlink_conn_s *conn) kmm_free(resp); } - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection */ -#if CONFIG_NETLINK_ALLOC_CONNS == 1 - if (conn < g_netlink_connections || conn >= (g_netlink_connections + - CONFIG_NETLINK_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_netlink_connections); - } + NET_BUFPOOL_FREE(g_netlink_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/pkt/pkt_conn.c b/net/pkt/pkt_conn.c index 601dff89f3941..8856acb5bb10b 100644 --- a/net/pkt/pkt_conn.c +++ b/net/pkt/pkt_conn.c @@ -42,6 +42,7 @@ #include "devif/devif.h" #include "pkt/pkt.h" +#include "utils/utils.h" /**************************************************************************** * Pre-processor Definitions @@ -52,19 +53,19 @@ (addr1[2] == addr2[2]) && (addr1[3] == addr2[3]) && \ (addr1[4] == addr2[4]) && (addr1[5] == addr2[5])) +#ifndef CONFIG_NET_PKT_MAX_CONNS +# define CONFIG_NET_PKT_MAX_CONNS 0 +#endif + /**************************************************************************** * Private Data ****************************************************************************/ /* The array containing all packet socket connections */ -#if CONFIG_NET_PKT_PREALLOC_CONNS > 0 -static struct pkt_conn_s g_pkt_connections[CONFIG_NET_PKT_PREALLOC_CONNS]; -#endif - -/* A list of all free packet socket connections */ - -static dq_queue_t g_free_pkt_connections; +NET_BUFPOOL_DECLARE(g_pkt_connections, sizeof(struct pkt_conn_s), + CONFIG_NET_PKT_PREALLOC_CONNS, + CONFIG_NET_PKT_ALLOC_CONNS, CONFIG_NET_PKT_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated packet socket connections */ @@ -86,14 +87,7 @@ static dq_queue_t g_active_pkt_connections; void pkt_initialize(void) { -#if CONFIG_NET_PKT_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_PKT_PREALLOC_CONNS; i++) - { - dq_addlast(&g_pkt_connections[i].sconn.node, &g_free_pkt_connections); - } -#endif + NET_BUFPOOL_INIT(g_pkt_connections); } /**************************************************************************** @@ -108,37 +102,12 @@ void pkt_initialize(void) FAR struct pkt_conn_s *pkt_alloc(void) { FAR struct pkt_conn_s *conn; -#if CONFIG_NET_PKT_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by a mutex. */ nxmutex_lock(&g_free_lock); -#if CONFIG_NET_PKT_ALLOC_CONNS > 0 - if (dq_peek(&g_free_pkt_connections) == NULL) - { -#if CONFIG_NET_PKT_MAX_CONNS > 0 - if (dq_count(&g_active_pkt_connections) + - CONFIG_NET_PKT_ALLOC_CONNS > CONFIG_NET_PKT_MAX_CONNS) - { - nxmutex_unlock(&g_free_lock); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_PKT_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_NET_PKT_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, &g_free_pkt_connections); - } - } - } -#endif - conn = (FAR struct pkt_conn_s *)dq_remfirst(&g_free_pkt_connections); + conn = NET_BUFPOOL_TRYALLOC(g_pkt_connections); if (conn) { /* Enqueue the connection into the active list */ @@ -171,22 +140,9 @@ void pkt_free(FAR struct pkt_conn_s *conn) dq_rem(&conn->sconn.node, &g_active_pkt_connections); - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_NET_PKT_ALLOC_CONNS == 1 - if (conn < g_pkt_connections || conn >= (g_pkt_connections + - CONFIG_NET_PKT_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_pkt_connections); - } + NET_BUFPOOL_FREE(g_pkt_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/tcp/Kconfig b/net/tcp/Kconfig index fd2bcec121177..28ce864133a06 100644 --- a/net/tcp/Kconfig +++ b/net/tcp/Kconfig @@ -259,6 +259,20 @@ config NET_TCP_NWRBCHAINS choice for this value would be the same as the maximum number of TCP connections. +config NET_TCP_ALLOC_WRBCHAINS + int "Dynamic I/O buffer chain heads allocation" + default 0 + ---help--- + When set to 0 all dynamic allocations are disabled + + When set to 1 a new I/O buffer chain head will be allocated every + time, and it will be free'd when no longer needed. + + Setting this to 2 or more will allocate the I/O buffer chain heads + in batches (with batch size equal to this config). When a I/O buffer + chain head is no longer needed, it will be returned to the free + I/O buffer chain heads pool, and it will never be deallocated! + config NET_TCP_WRBUFFER_DEBUG bool "Force write buffer debug" default n diff --git a/net/tcp/tcp_conn.c b/net/tcp/tcp_conn.c index 2cc05157f5b42..d8bc2eda91f60 100644 --- a/net/tcp/tcp_conn.c +++ b/net/tcp/tcp_conn.c @@ -74,18 +74,22 @@ #include "utils/utils.h" /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all TCP connections. */ - -#if CONFIG_NET_TCP_PREALLOC_CONNS > 0 -static struct tcp_conn_s g_tcp_connections[CONFIG_NET_TCP_PREALLOC_CONNS]; +#ifndef CONFIG_NET_TCP_MAX_CONNS +# define CONFIG_NET_TCP_MAX_CONNS 0 #endif -/* A list of all free TCP connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all TCP connections. */ -static dq_queue_t g_free_tcp_connections; +NET_BUFPOOL_DECLARE(g_tcp_connections, sizeof(struct tcp_conn_s), + CONFIG_NET_TCP_PREALLOC_CONNS, + CONFIG_NET_TCP_ALLOC_CONNS, CONFIG_NET_TCP_MAX_CONNS); /* A list of all connected TCP connections */ @@ -497,54 +501,6 @@ static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn, } #endif /* CONFIG_NET_IPv6 */ -/**************************************************************************** - * Name: tcp_alloc_conn - * - * Description: - * Find or allocate a free TCP/IP connection structure for use. - * - ****************************************************************************/ - -#if CONFIG_NET_TCP_ALLOC_CONNS > 0 -static FAR struct tcp_conn_s *tcp_alloc_conn(void) -{ - FAR struct tcp_conn_s *conn; - int i; - - /* Return the entry from the head of the free list */ - - if (dq_peek(&g_free_tcp_connections) == NULL) - { -#if CONFIG_NET_TCP_MAX_CONNS > 0 - if (dq_count(&g_active_tcp_connections) + - CONFIG_NET_TCP_ALLOC_CONNS > CONFIG_NET_TCP_MAX_CONNS) - { - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(struct tcp_conn_s) * - CONFIG_NET_TCP_ALLOC_CONNS); - if (conn == NULL) - { - return conn; - } - - /* Now initialize each connection structure */ - - for (i = 0; i < CONFIG_NET_TCP_ALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - conn[i].tcpstateflags = TCP_CLOSED; - dq_addlast(&conn[i].sconn.node, &g_free_tcp_connections); - } - } - - return (FAR struct tcp_conn_s *)dq_remfirst(&g_free_tcp_connections); -} -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -650,17 +606,7 @@ int tcp_selectport(uint8_t domain, void tcp_initialize(void) { -#if CONFIG_NET_TCP_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_TCP_PREALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - g_tcp_connections[i].tcpstateflags = TCP_CLOSED; - dq_addlast(&g_tcp_connections[i].sconn.node, &g_free_tcp_connections); - } -#endif + NET_BUFPOOL_INIT(g_tcp_connections); } /**************************************************************************** @@ -687,7 +633,7 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain) /* Return the entry from the head of the free list */ - conn = (FAR struct tcp_conn_s *)dq_remfirst(&g_free_tcp_connections); + conn = NET_BUFPOOL_TRYALLOC(g_tcp_connections); #ifndef CONFIG_NET_SOLINGER /* Is the free list empty? */ @@ -760,21 +706,11 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain) * a new connection. */ - conn = (FAR struct tcp_conn_s *) - dq_remfirst(&g_free_tcp_connections); + conn = NET_BUFPOOL_TRYALLOC(g_tcp_connections); } } #endif - /* Allocate the connect entry from heap */ - -#if CONFIG_NET_TCP_ALLOC_CONNS > 0 - if (conn == NULL) - { - conn = tcp_alloc_conn(); - } -#endif - net_unlock(); /* Mark the connection allocated */ @@ -972,21 +908,9 @@ void tcp_free(FAR struct tcp_conn_s *conn) conn->tcpstateflags = TCP_CLOSED; - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection structure */ -#if CONFIG_NET_TCP_ALLOC_CONNS == 1 - if (conn < g_tcp_connections || conn >= (g_tcp_connections + - CONFIG_NET_TCP_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - dq_addlast(&conn->sconn.node, &g_free_tcp_connections); - } + NET_BUFPOOL_FREE(g_tcp_connections, conn); net_unlock(); } diff --git a/net/tcp/tcp_wrbuffer.c b/net/tcp/tcp_wrbuffer.c index 4e426736092f3..e3fbf333bbfae 100644 --- a/net/tcp/tcp_wrbuffer.c +++ b/net/tcp/tcp_wrbuffer.c @@ -48,34 +48,15 @@ #if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_TCP_WRITE_BUFFERS) -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/* Package all globals used by this logic into a structure */ - -struct wrbuffer_s -{ - /* The semaphore to protect the buffers */ - - sem_t sem; - - /* This is the list of available write buffers */ - - sq_queue_t freebuffers; - - /* These are the pre-allocated write buffers */ - - struct tcp_wrbuffer_s buffers[CONFIG_NET_TCP_NWRBCHAINS]; -}; - /**************************************************************************** * Private Data ****************************************************************************/ /* This is the state of the global write buffer resource */ -static struct wrbuffer_s g_wrbuffer; +NET_BUFPOOL_DECLARE(g_wrbuffer, sizeof(struct tcp_wrbuffer_s), + CONFIG_NET_TCP_NWRBCHAINS, + CONFIG_NET_TCP_ALLOC_WRBCHAINS, 0); /**************************************************************************** * Public Functions @@ -94,16 +75,7 @@ static struct wrbuffer_s g_wrbuffer; void tcp_wrbuffer_initialize(void) { - int i; - - sq_init(&g_wrbuffer.freebuffers); - - nxsem_init(&g_wrbuffer.sem, 0, CONFIG_NET_TCP_NWRBCHAINS); - - for (i = 0; i < CONFIG_NET_TCP_NWRBCHAINS; i++) - { - sq_addfirst(&g_wrbuffer.buffers[i].wb_node, &g_wrbuffer.freebuffers); - } + NET_BUFPOOL_INIT(g_wrbuffer); } /**************************************************************************** @@ -127,7 +99,6 @@ void tcp_wrbuffer_initialize(void) FAR struct tcp_wrbuffer_s *tcp_wrbuffer_timedalloc(unsigned int timeout) { FAR struct tcp_wrbuffer_s *wrb; - int ret; /* We need to allocate two things: (1) A write buffer structure and (2) * at least one I/O buffer to start the chain. @@ -137,20 +108,12 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_timedalloc(unsigned int timeout) * buffer */ - ret = net_sem_timedwait_uninterruptible(&g_wrbuffer.sem, timeout); - if (ret != OK) + wrb = NET_BUFPOOL_TIMEDALLOC(g_wrbuffer, timeout); + if (wrb == NULL) { return NULL; } - /* Now, we are guaranteed to have a write buffer structure reserved - * for us in the free list. - */ - - wrb = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); - DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct tcp_wrbuffer_s)); - /* Now get the first I/O buffer for the write buffer structure */ wrb->wb_iob = net_iobtimedalloc(true, timeout); @@ -247,8 +210,7 @@ void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrb) /* Then free the write buffer structure */ - sq_addlast(&wrb->wb_node, &g_wrbuffer.freebuffers); - nxsem_post(&g_wrbuffer.sem); + NET_BUFPOOL_FREE(g_wrbuffer, wrb); } /**************************************************************************** @@ -304,16 +266,7 @@ uint32_t tcp_wrbuffer_inqueue_size(FAR struct tcp_conn_s *conn) int tcp_wrbuffer_test(void) { - int val = 0; - int ret; - - ret = nxsem_get_value(&g_wrbuffer.sem, &val); - if (ret >= 0) - { - ret = val > 0 ? OK : -ENOSPC; - } - - return ret; + return NET_BUFPOOL_TEST(g_wrbuffer); } #endif /* CONFIG_NET_TCP && CONFIG_NET_TCP_WRITE_BUFFERS */ diff --git a/net/udp/Kconfig b/net/udp/Kconfig index e147b7a608a90..a094e2850b9af 100644 --- a/net/udp/Kconfig +++ b/net/udp/Kconfig @@ -103,6 +103,20 @@ config NET_UDP_NWRBCHAINS choice for this value would be the same as the maximum number of UDP connections. +config NET_UDP_ALLOC_WRBCHAINS + int "Dynamic I/O buffer chain heads allocation" + default 0 + ---help--- + When set to 0 all dynamic allocations are disabled. + + When set to 1 a new I/O buffer chain head will be allocated every + time, and it will be free'd when no longer needed. + + Setting this to 2 or more will allocate the I/O buffer chain heads + in batches (with batch size equal to this config). When a I/O buffer + chain head is no longer needed, it will be returned to the free + I/O buffer chain heads pool, and it will never be deallocated! + config NET_UDP_WRBUFFER_DEBUG bool "Force write buffer debug" default n diff --git a/net/udp/udp_conn.c b/net/udp/udp_conn.c index 83a13e725ecfc..d2062b46aec56 100644 --- a/net/udp/udp_conn.c +++ b/net/udp/udp_conn.c @@ -75,18 +75,22 @@ #include "utils/utils.h" /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all UDP connections. */ - -#if CONFIG_NET_UDP_PREALLOC_CONNS > 0 -static struct udp_conn_s g_udp_connections[CONFIG_NET_UDP_PREALLOC_CONNS]; +#ifndef CONFIG_NET_UDP_MAX_CONNS +# define CONFIG_NET_UDP_MAX_CONNS 0 #endif -/* A list of all free UDP connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ -static dq_queue_t g_free_udp_connections; +/* The array containing all UDP connections. */ + +NET_BUFPOOL_DECLARE(g_udp_connections, sizeof(struct udp_conn_s), + CONFIG_NET_UDP_PREALLOC_CONNS, + CONFIG_NET_UDP_ALLOC_CONNS, CONFIG_NET_UDP_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated UDP connections */ @@ -460,54 +464,6 @@ udp_ipv6_active(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn, } #endif /* CONFIG_NET_IPv6 */ -/**************************************************************************** - * Name: udp_alloc_conn - * - * Description: - * Allocate a uninitialized UDP connection structure. - * - ****************************************************************************/ - -#if CONFIG_NET_UDP_ALLOC_CONNS > 0 -static FAR struct udp_conn_s *udp_alloc_conn(void) -{ - FAR struct udp_conn_s *conn; - int i; - - /* Return the entry from the head of the free list */ - - if (dq_peek(&g_free_udp_connections) == NULL) - { -#if CONFIG_NET_UDP_MAX_CONNS > 0 - if (dq_count(&g_active_udp_connections) + - CONFIG_NET_UDP_ALLOC_CONNS > CONFIG_NET_UDP_MAX_CONNS) - { - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(struct udp_conn_s) * - CONFIG_NET_UDP_ALLOC_CONNS); - if (conn == NULL) - { - return conn; - } - - /* Now initialize each connection structure */ - - for (i = 0; i < CONFIG_NET_UDP_ALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - conn[i].lport = 0; - dq_addlast(&conn[i].sconn.node, &g_free_udp_connections); - } - } - - return (FAR struct udp_conn_s *)dq_remfirst(&g_free_udp_connections); -} -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -593,17 +549,7 @@ uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u) void udp_initialize(void) { -#if CONFIG_NET_UDP_PREALLOC_CONNS > 0 - int i; - - for (i = 0; i < CONFIG_NET_UDP_PREALLOC_CONNS; i++) - { - /* Mark the connection closed and move it to the free list */ - - g_udp_connections[i].lport = 0; - dq_addlast(&g_udp_connections[i].sconn.node, &g_free_udp_connections); - } -#endif + NET_BUFPOOL_INIT(g_udp_connections); } /**************************************************************************** @@ -623,14 +569,7 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain) nxmutex_lock(&g_free_lock); - conn = (FAR struct udp_conn_s *)dq_remfirst(&g_free_udp_connections); - -#if CONFIG_NET_UDP_ALLOC_CONNS > 0 - if (conn == NULL) - { - conn = udp_alloc_conn(); - } -#endif + conn = NET_BUFPOOL_TRYALLOC(g_udp_connections); if (conn) { @@ -712,23 +651,9 @@ void udp_free(FAR struct udp_conn_s *conn) #endif - /* Free the connection. - * If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_NET_UDP_ALLOC_CONNS == 1 - if (conn < g_udp_connections || conn >= (g_udp_connections + - CONFIG_NET_UDP_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_udp_connections); - } + NET_BUFPOOL_FREE(g_udp_connections, conn); nxmutex_unlock(&g_free_lock); } diff --git a/net/udp/udp_wrbuffer.c b/net/udp/udp_wrbuffer.c index 0b9846c77f66e..37ca4b580c3fa 100644 --- a/net/udp/udp_wrbuffer.c +++ b/net/udp/udp_wrbuffer.c @@ -47,34 +47,15 @@ #include "utils/utils.h" #include "udp/udp.h" -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/* Package all globals used by this logic into a structure */ - -struct wrbuffer_s -{ - /* The semaphore to protect the buffers */ - - sem_t sem; - - /* This is the list of available write buffers */ - - sq_queue_t freebuffers; - - /* These are the pre-allocated write buffers */ - - struct udp_wrbuffer_s buffers[CONFIG_NET_UDP_NWRBCHAINS]; -}; - /**************************************************************************** * Private Data ****************************************************************************/ /* This is the state of the global write buffer resource */ -static struct wrbuffer_s g_wrbuffer; +NET_BUFPOOL_DECLARE(g_wrbuffer, sizeof(struct udp_wrbuffer_s), + CONFIG_NET_UDP_NWRBCHAINS, + CONFIG_NET_UDP_ALLOC_WRBCHAINS, 0); /**************************************************************************** * Public Functions @@ -93,16 +74,7 @@ static struct wrbuffer_s g_wrbuffer; void udp_wrbuffer_initialize(void) { - int i; - - sq_init(&g_wrbuffer.freebuffers); - - nxsem_init(&g_wrbuffer.sem, 0, CONFIG_NET_UDP_NWRBCHAINS); - - for (i = 0; i < CONFIG_NET_UDP_NWRBCHAINS; i++) - { - sq_addfirst(&g_wrbuffer.buffers[i].wb_node, &g_wrbuffer.freebuffers); - } + NET_BUFPOOL_INIT(g_wrbuffer); } /**************************************************************************** @@ -133,15 +105,8 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void) * buffer */ - net_sem_wait_uninterruptible(&g_wrbuffer.sem); - - /* Now, we are guaranteed to have a write buffer structure reserved - * for us in the free list. - */ - - wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); + wrb = NET_BUFPOOL_ALLOC(g_wrbuffer); DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct udp_wrbuffer_s)); /* Now get the first I/O buffer for the write buffer structure */ @@ -177,7 +142,6 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void) FAR struct udp_wrbuffer_s *udp_wrbuffer_timedalloc(unsigned int timeout) { FAR struct udp_wrbuffer_s *wrb; - int ret; /* We need to allocate two things: (1) A write buffer structure and (2) * at least one I/O buffer to start the chain. @@ -187,20 +151,12 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_timedalloc(unsigned int timeout) * buffer */ - ret = net_sem_timedwait_uninterruptible(&g_wrbuffer.sem, timeout); - if (ret != OK) + wrb = NET_BUFPOOL_TIMEDALLOC(g_wrbuffer, timeout); + if (wrb == NULL) { return NULL; } - /* Now, we are guaranteed to have a write buffer structure reserved - * for us in the free list. - */ - - wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); - DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct udp_wrbuffer_s)); - /* Now get the first I/O buffer for the write buffer structure */ wrb->wb_iob = net_iobtimedalloc(true, timeout); @@ -253,19 +209,12 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_tryalloc(void) * buffer */ - if (nxsem_trywait(&g_wrbuffer.sem) != OK) + wrb = NET_BUFPOOL_TRYALLOC(g_wrbuffer); + if (wrb == NULL) { return NULL; } - /* Now, we are guaranteed to have a write buffer structure reserved - * for us in the free list. - */ - - wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); - DEBUGASSERT(wrb); - memset(wrb, 0, sizeof(struct udp_wrbuffer_s)); - /* Now get the first I/O buffer for the write buffer structure */ wrb->wb_iob = @@ -312,8 +261,7 @@ void udp_wrbuffer_release(FAR struct udp_wrbuffer_s *wrb) /* Then free the write buffer structure */ - sq_addlast(&wrb->wb_node, &g_wrbuffer.freebuffers); - nxsem_post(&g_wrbuffer.sem); + NET_BUFPOOL_FREE(g_wrbuffer, wrb); } /**************************************************************************** @@ -363,9 +311,7 @@ uint32_t udp_wrbuffer_inqueue_size(FAR struct udp_conn_s *conn) int udp_wrbuffer_test(void) { - int val = 0; - nxsem_get_value(&g_wrbuffer.sem, &val); - return val > 0 ? OK : -ENOSPC; + return NET_BUFPOOL_TEST(g_wrbuffer); } #endif /* CONFIG_NET && CONFIG_NET_UDP && CONFIG_NET_UDP_WRITE_BUFFERS */ diff --git a/net/usrsock/usrsock_conn.c b/net/usrsock/usrsock_conn.c index c87703d915a67..496f248d35a1c 100644 --- a/net/usrsock/usrsock_conn.c +++ b/net/usrsock/usrsock_conn.c @@ -43,21 +43,26 @@ #include #include "usrsock/usrsock.h" +#include "utils/utils.h" /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -/* The array containing all usrsock connections. */ - -#if CONFIG_NET_USRSOCK_PREALLOC_CONNS > 0 -static struct usrsock_conn_s - g_usrsock_connections[CONFIG_NET_USRSOCK_PREALLOC_CONNS]; +#ifndef CONFIG_NET_USRSOCK_MAX_CONNS +# define CONFIG_NET_USRSOCK_MAX_CONNS 0 #endif -/* A list of all free usrsock connections */ +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The array containing all usrsock connections. */ -static dq_queue_t g_free_usrsock_connections; +NET_BUFPOOL_DECLARE(g_usrsock_connections, sizeof(struct usrsock_conn_s), + CONFIG_NET_USRSOCK_PREALLOC_CONNS, + CONFIG_NET_USRSOCK_ALLOC_CONNS, + CONFIG_NET_USRSOCK_MAX_CONNS); static mutex_t g_free_lock = NXMUTEX_INITIALIZER; /* A list of all allocated usrsock connections */ @@ -80,38 +85,12 @@ static dq_queue_t g_active_usrsock_connections; FAR struct usrsock_conn_s *usrsock_alloc(void) { FAR struct usrsock_conn_s *conn; -#if CONFIG_NET_USRSOCK_ALLOC_CONNS > 0 - int i; -#endif /* The free list is protected by a a mutex. */ nxmutex_lock(&g_free_lock); -#if CONFIG_NET_USRSOCK_ALLOC_CONNS > 0 - if (dq_peek(&g_free_usrsock_connections) == NULL) - { -#if CONFIG_NET_USRSOCK_MAX_CONNS > 0 - if (dq_count(&g_active_usrsock_connections) + - CONFIG_NET_USRSOCK_ALLOC_CONNS > CONFIG_NET_USRSOCK_MAX_CONNS) - { - nxmutex_unlock(&g_free_lock); - return NULL; - } -#endif - - conn = kmm_zalloc(sizeof(*conn) * CONFIG_NET_USRSOCK_ALLOC_CONNS); - if (conn != NULL) - { - for (i = 0; i < CONFIG_NET_USRSOCK_ALLOC_CONNS; i++) - { - dq_addlast(&conn[i].sconn.node, &g_free_usrsock_connections); - } - } - } -#endif - conn = (FAR struct usrsock_conn_s *) - dq_remfirst(&g_free_usrsock_connections); + conn = NET_BUFPOOL_TRYALLOC(g_usrsock_connections); if (conn) { /* Make sure that the connection is marked as uninitialized */ @@ -154,22 +133,9 @@ void usrsock_free(FAR struct usrsock_conn_s *conn) nxsem_destroy(&conn->resp.sem); - /* If this is a preallocated or a batch allocated connection store it in - * the free connections list. Else free it. - */ + /* Free the connection. */ -#if CONFIG_NET_USRSOCK_ALLOC_CONNS == 1 - if (conn < g_usrsock_connections || conn >= (g_usrsock_connections + - CONFIG_NET_USRSOCK_PREALLOC_CONNS)) - { - kmm_free(conn); - } - else -#endif - { - memset(conn, 0, sizeof(*conn)); - dq_addlast(&conn->sconn.node, &g_free_usrsock_connections); - } + NET_BUFPOOL_FREE(g_usrsock_connections, conn); nxmutex_unlock(&g_free_lock); } @@ -334,21 +300,7 @@ void usrsock_setup_datain(FAR struct usrsock_conn_s *conn, void usrsock_initialize(void) { -#if CONFIG_NET_USRSOCK_PREALLOC_CONNS > 0 - FAR struct usrsock_conn_s *conn; - int i; - - for (i = 0; i < CONFIG_NET_USRSOCK_PREALLOC_CONNS; i++) - { - conn = &g_usrsock_connections[i]; - - /* Mark the connection closed and move it to the free list */ - - conn->usockid = USRSOCK_USOCKID_INVALID; - conn->state = USRSOCK_CONN_STATE_UNINITIALIZED; - dq_addlast(&conn->sconn.node, &g_free_usrsock_connections); - } -#endif + NET_BUFPOOL_INIT(g_usrsock_connections); /* Register /dev/usrsock character device. */ diff --git a/net/utils/CMakeLists.txt b/net/utils/CMakeLists.txt index 8803381a3dccb..a960501fdbda0 100644 --- a/net/utils/CMakeLists.txt +++ b/net/utils/CMakeLists.txt @@ -33,7 +33,8 @@ set(SRCS net_snoop.c net_cmsg.c net_iob_concat.c - net_mask2pref.c) + net_mask2pref.c + net_bufpool.c) # IPv6 utilities diff --git a/net/utils/Make.defs b/net/utils/Make.defs index de2d96a28a8c5..a279cd2215144 100644 --- a/net/utils/Make.defs +++ b/net/utils/Make.defs @@ -25,6 +25,7 @@ NET_CSRCS += net_dsec2tick.c net_dsec2timeval.c net_timeval2dsec.c NET_CSRCS += net_chksum.c net_ipchksum.c net_incr32.c net_lock.c NET_CSRCS += net_snoop.c net_cmsg.c net_iob_concat.c net_mask2pref.c +NET_CSRCS += net_bufpool.c # IPv6 utilities diff --git a/net/utils/net_bufpool.c b/net/utils/net_bufpool.c new file mode 100644 index 0000000000000..8e65ced82ddae --- /dev/null +++ b/net/utils/net_bufpool.c @@ -0,0 +1,197 @@ +/**************************************************************************** + * net/utils/net_bufpool.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "utils/utils.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The node to store in the pool */ + +struct net_bufnode_s +{ + sq_entry_t node; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_bufpool_init + * + * Description: + * Initialize a network buffer pool. + * + * Input Parameters: + * pool - The pool to be initialized + * + ****************************************************************************/ + +void net_bufpool_init(FAR struct net_bufpool_s *pool) +{ + int i; + unsigned int maxalloc; + + if (pool->dynalloc > 0) + { + maxalloc = pool->u.maxalloc > 0 ? pool->u.maxalloc : INT16_MAX; + } + else + { + maxalloc = pool->prealloc; + } + + nxsem_init(&pool->u.sem, 0, maxalloc); + + sq_init(&pool->freebuffers); + for (i = 0; i < pool->prealloc; i++) + { + FAR struct net_bufnode_s *node = (FAR struct net_bufnode_s *) + (pool->pool + i * pool->nodesize); + sq_addlast(&node->node, &pool->freebuffers); + } +} + +/**************************************************************************** + * Name: net_bufpool_timedalloc + * + * Description: + * Allocate a buffer from the pool. If no buffer is available, then wait + * for the specified timeout. + * + * Input Parameters: + * pool - The pool from which to allocate the buffer + * timeout - The maximum time to wait for a buffer to become available. + * + * Returned Value: + * A reference to the allocated buffer, which is guaranteed to be zeroed. + * NULL is returned on a timeout. + * + ****************************************************************************/ + +FAR void *net_bufpool_timedalloc(FAR struct net_bufpool_s *pool, + unsigned int timeout) +{ + FAR struct net_bufnode_s *node; + int ret; + int i; + + ret = net_sem_timedwait_uninterruptible(&pool->u.sem, timeout); + if (ret != OK) + { + return NULL; + } + + /* If we get here, then we didn't exceed maxalloc. */ + + if (pool->dynalloc > 0 && sq_peek(&pool->freebuffers) == NULL) + { + node = kmm_zalloc(pool->nodesize * pool->dynalloc); + if (node == NULL) + { + return NULL; + } + + /* Now initialize each connection structure */ + + for (i = 0; i < pool->dynalloc; i++) + { + sq_addlast(&node->node, &pool->freebuffers); + node = (FAR struct net_bufnode_s *) + ((FAR char *)node + pool->nodesize); + } + } + + return sq_remfirst(&pool->freebuffers); +} + +/**************************************************************************** + * Name: net_bufpool_free + * + * Description: + * Free a buffer from the pool. + * + * Input Parameters: + * pool - The pool from which to allocate the buffer + * node - The buffer to be freed + * + ****************************************************************************/ + +void net_bufpool_free(FAR struct net_bufpool_s *pool, FAR void *node) +{ + if (pool->dynalloc == 1 && + ((FAR char *)node < pool->pool || + (FAR char *)node >= pool->pool + pool->prealloc * pool->nodesize)) + { + kmm_free(node); + } + else + { + FAR struct net_bufnode_s *net_bufnode = node; + + /* Set the buffer to zero, to make sure all nodes in the free buffer + * pool are zeroed. + */ + + memset(net_bufnode, 0, pool->nodesize); + sq_addlast(&net_bufnode->node, &pool->freebuffers); + } + + nxsem_post(&pool->u.sem); +} + +/**************************************************************************** + * Name: net_bufpool_test + * + * Description: + * Check if there is room in the buffer pool. Does not reserve any space. + * + * Assumptions: + * None. + * + ****************************************************************************/ + +int net_bufpool_test(FAR struct net_bufpool_s *pool) +{ + int val = 0; + int ret; + + ret = nxsem_get_value(&pool->u.sem, &val); + if (ret >= 0) + { + ret = val > 0 ? OK : -ENOSPC; + } + + return ret; +} diff --git a/net/utils/utils.h b/net/utils/utils.h index d5355d03d8d67..fa05c2690cb61 100644 --- a/net/utils/utils.h +++ b/net/utils/utils.h @@ -76,6 +76,34 @@ (nport) = HTONS(hport); \ } while (0) +/* Network buffer pool related macros, in which: + * pool: The name of the buffer pool + * nodesize: The size of each node in the pool + * prealloc: The number of pre-allocated buffers + * dynalloc: The number per dynamic allocations + * maxalloc: The number of max allocations, 0 means no limit + */ + +#define NET_BUFPOOL_DECLARE(pool,nodesize,prealloc,dynalloc,maxalloc) \ + static char pool##_buffer[prealloc][nodesize]; \ + static struct net_bufpool_s pool = \ + { \ + pool##_buffer[0], \ + prealloc, \ + dynalloc, \ + nodesize, \ + { \ + maxalloc \ + } \ + }; + +#define NET_BUFPOOL_INIT(p) net_bufpool_init(&p) +#define NET_BUFPOOL_TIMEDALLOC(p,t) net_bufpool_timedalloc(&p, t) +#define NET_BUFPOOL_TRYALLOC(p) net_bufpool_timedalloc(&p, 0) +#define NET_BUFPOOL_ALLOC(p) net_bufpool_timedalloc(&p, UINT_MAX) +#define NET_BUFPOOL_FREE(p,n) net_bufpool_free(&p, n) +#define NET_BUFPOOL_TEST(p) net_bufpool_test(&p) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -89,6 +117,26 @@ enum tv2ds_remainder_e TV2DS_CEIL /* Force to next larger full decisecond */ }; +/* This structure is used to manage a pool of network buffers */ + +struct net_bufpool_s +{ + /* Allocation configuration */ + + FAR char *pool; /* The beginning of the pre-allocated buffer pool */ + const int prealloc; /* The number of pre-allocated buffers */ + const int dynalloc; /* The number per dynamic allocations */ + const int nodesize; /* The size of each node in the pool */ + + union + { + int16_t maxalloc; /* The number of max allocations, used before init */ + sem_t sem; /* The semaphore for waiting for free buffers */ + } u; + + sq_queue_t freebuffers; +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -322,6 +370,66 @@ FAR void *net_ipv6_payload(FAR struct ipv6_hdr_s *ipv6, FAR uint8_t *proto); uint16_t net_iob_concat(FAR struct iob_s **iob1, FAR struct iob_s **iob2); #endif +/**************************************************************************** + * Name: net_bufpool_init + * + * Description: + * Initialize a network buffer pool. + * + * Input Parameters: + * pool - The pool to be initialized + * + ****************************************************************************/ + +void net_bufpool_init(FAR struct net_bufpool_s *pool); + +/**************************************************************************** + * Name: net_bufpool_timedalloc + * + * Description: + * Allocate a buffer from the pool. If no buffer is available, then wait + * for the specified timeout. + * + * Input Parameters: + * pool - The pool from which to allocate the buffer + * timeout - The maximum time to wait for a buffer to become available. + * + * Returned Value: + * A reference to the allocated buffer, which is guaranteed to be zeroed. + * NULL is returned on a timeout. + * + ****************************************************************************/ + +FAR void *net_bufpool_timedalloc(FAR struct net_bufpool_s *pool, + unsigned int timeout); + +/**************************************************************************** + * Name: net_bufpool_free + * + * Description: + * Free a buffer from the pool. + * + * Input Parameters: + * pool - The pool from which to allocate the buffer + * node - The buffer to be freed + * + ****************************************************************************/ + +void net_bufpool_free(FAR struct net_bufpool_s *pool, FAR void *node); + +/**************************************************************************** + * Name: net_bufpool_test + * + * Description: + * Check if there is room in the buffer pool. Does not reserve any space. + * + * Assumptions: + * None. + * + ****************************************************************************/ + +int net_bufpool_test(FAR struct net_bufpool_s *pool); + /**************************************************************************** * Name: net_chksum_adjust *