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(...)
|
||||
#endif /* (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG) */
|
||||
|
||||
static K_MUTEX_DEFINE(conn_lock);
|
||||
|
||||
static struct net_conn *conn_get_unused(void)
|
||||
{
|
||||
sys_snode_t *node;
|
||||
|
||||
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||
|
||||
node = sys_slist_peek_head(&conn_unused);
|
||||
if (!node) {
|
||||
k_mutex_unlock(&conn_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_slist_remove(&conn_unused, NULL, node);
|
||||
|
||||
k_mutex_unlock(&conn_lock);
|
||||
|
||||
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;
|
||||
|
||||
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||
sys_slist_prepend(&conn_used, &conn->node);
|
||||
k_mutex_unlock(&conn_lock);
|
||||
}
|
||||
|
||||
static void conn_set_unused(struct net_conn *conn)
|
||||
{
|
||||
(void)memset(conn, 0, sizeof(*conn));
|
||||
|
||||
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||
sys_slist_prepend(&conn_unused, &conn->node);
|
||||
k_mutex_unlock(&conn_lock);
|
||||
}
|
||||
|
||||
/* 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 *tmp;
|
||||
|
||||
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn_used, conn, tmp, node) {
|
||||
if (conn->proto != proto) {
|
||||
continue;
|
||||
|
@ -235,9 +248,11 @@ static struct net_conn *conn_find_handler(uint16_t proto, uint8_t family,
|
|||
continue;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&conn_lock);
|
||||
return conn;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&conn_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -380,7 +395,9 @@ int net_conn_unregister(struct net_conn_handle *handle)
|
|||
|
||||
NET_DBG("Connection handler %p removed", conn);
|
||||
|
||||
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||
sys_slist_find_and_remove(&conn_used, &conn->node);
|
||||
k_mutex_unlock(&conn_lock);
|
||||
|
||||
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;
|
||||
|
||||
k_mutex_lock(&conn_lock, K_FOREVER);
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
|
||||
cb(conn, user_data);
|
||||
}
|
||||
|
||||
k_mutex_unlock(&conn_lock);
|
||||
}
|
||||
|
||||
void net_conn_init(void)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue