net: conn: Fix issues with SMP in connection code
When testing on qemu_x86_64 with e1000 Ethernet driver, there are several crashes due to list management simultaneously executing on different cores. Add mutexes similar to other parts on networking stack, for example tcp_lock. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This commit is contained in:
parent
8c86595289
commit
a5400407fc
1 changed files with 21 additions and 0 deletions
|
@ -114,17 +114,24 @@ void conn_register_debug(struct net_conn *conn,
|
||||||
#define conn_register_debug(...)
|
#define conn_register_debug(...)
|
||||||
#endif /* (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG) */
|
#endif /* (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG) */
|
||||||
|
|
||||||
|
static K_MUTEX_DEFINE(conn_lock);
|
||||||
|
|
||||||
static struct net_conn *conn_get_unused(void)
|
static struct net_conn *conn_get_unused(void)
|
||||||
{
|
{
|
||||||
sys_snode_t *node;
|
sys_snode_t *node;
|
||||||
|
|
||||||
|
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||||
|
|
||||||
node = sys_slist_peek_head(&conn_unused);
|
node = sys_slist_peek_head(&conn_unused);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
|
k_mutex_unlock(&conn_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_slist_remove(&conn_unused, NULL, node);
|
sys_slist_remove(&conn_unused, NULL, node);
|
||||||
|
|
||||||
|
k_mutex_unlock(&conn_lock);
|
||||||
|
|
||||||
return CONTAINER_OF(node, struct net_conn, node);
|
return CONTAINER_OF(node, struct net_conn, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,14 +139,18 @@ static void conn_set_used(struct net_conn *conn)
|
||||||
{
|
{
|
||||||
conn->flags |= NET_CONN_IN_USE;
|
conn->flags |= NET_CONN_IN_USE;
|
||||||
|
|
||||||
|
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||||
sys_slist_prepend(&conn_used, &conn->node);
|
sys_slist_prepend(&conn_used, &conn->node);
|
||||||
|
k_mutex_unlock(&conn_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void conn_set_unused(struct net_conn *conn)
|
static void conn_set_unused(struct net_conn *conn)
|
||||||
{
|
{
|
||||||
(void)memset(conn, 0, sizeof(*conn));
|
(void)memset(conn, 0, sizeof(*conn));
|
||||||
|
|
||||||
|
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||||
sys_slist_prepend(&conn_unused, &conn->node);
|
sys_slist_prepend(&conn_unused, &conn->node);
|
||||||
|
k_mutex_unlock(&conn_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we already have identical connection handler installed. */
|
/* Check if we already have identical connection handler installed. */
|
||||||
|
@ -152,6 +163,8 @@ static struct net_conn *conn_find_handler(uint16_t proto, uint8_t family,
|
||||||
struct net_conn *conn;
|
struct net_conn *conn;
|
||||||
struct net_conn *tmp;
|
struct net_conn *tmp;
|
||||||
|
|
||||||
|
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||||
|
|
||||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn_used, conn, tmp, node) {
|
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn_used, conn, tmp, node) {
|
||||||
if (conn->proto != proto) {
|
if (conn->proto != proto) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -235,9 +248,11 @@ static struct net_conn *conn_find_handler(uint16_t proto, uint8_t family,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k_mutex_unlock(&conn_lock);
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k_mutex_unlock(&conn_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +395,9 @@ int net_conn_unregister(struct net_conn_handle *handle)
|
||||||
|
|
||||||
NET_DBG("Connection handler %p removed", conn);
|
NET_DBG("Connection handler %p removed", conn);
|
||||||
|
|
||||||
|
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||||
sys_slist_find_and_remove(&conn_used, &conn->node);
|
sys_slist_find_and_remove(&conn_used, &conn->node);
|
||||||
|
k_mutex_unlock(&conn_lock);
|
||||||
|
|
||||||
conn_set_unused(conn);
|
conn_set_unused(conn);
|
||||||
|
|
||||||
|
@ -824,9 +841,13 @@ void net_conn_foreach(net_conn_foreach_cb_t cb, void *user_data)
|
||||||
{
|
{
|
||||||
struct net_conn *conn;
|
struct net_conn *conn;
|
||||||
|
|
||||||
|
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||||
|
|
||||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
|
SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
|
||||||
cb(conn, user_data);
|
cb(conn, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k_mutex_unlock(&conn_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_conn_init(void)
|
void net_conn_init(void)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue