devif:fix issue about devif_callback being released wrongly,resulting in no access to it
Signed-off-by: wangchen <wangchen41@xiaomi.com>
This commit is contained in:
parent
065046b2a2
commit
48ecb6f922
2 changed files with 64 additions and 29 deletions
|
@ -274,6 +274,7 @@ struct devif_callback_s
|
|||
FAR devif_callback_event_t event;
|
||||
FAR void *priv;
|
||||
uint16_t flags;
|
||||
uint8_t free_flags;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -41,6 +41,13 @@
|
|||
#include "netdev/netdev.h"
|
||||
#include "devif/devif.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define DEVIF_CB_DONT_FREE (1 << 0)
|
||||
#define DEVIF_CB_PEND_FREE (1 << 1)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
@ -90,35 +97,6 @@ static void devif_callback_free(FAR struct net_driver_s *dev,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Remove the callback structure from the device notification list if
|
||||
* it is supposed to be in the device notification list.
|
||||
*/
|
||||
|
||||
if (dev != NULL)
|
||||
{
|
||||
/* Find the callback structure in the device event list */
|
||||
|
||||
for (prev = NULL, curr = dev->d_devcb;
|
||||
curr != NULL && curr != cb;
|
||||
prev = curr, curr = curr->nxtdev)
|
||||
{
|
||||
}
|
||||
|
||||
/* Remove the structure from the device event list */
|
||||
|
||||
if (curr != NULL)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
prev->nxtdev = cb->nxtdev;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->d_devcb = cb->nxtdev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the callback structure from the data notification list if
|
||||
* it is supposed to be in the data notification list.
|
||||
*/
|
||||
|
@ -167,6 +145,48 @@ static void devif_callback_free(FAR struct net_driver_s *dev,
|
|||
}
|
||||
}
|
||||
|
||||
/* check if the callback structure has DEVIF_CB_DONT_FREE,it indicates
|
||||
* the callback can't be free immediately,setting DEVIF_CB_PEND_FREE
|
||||
* flag with the callback,it indicates the callback will be free
|
||||
* finally
|
||||
*/
|
||||
|
||||
if (cb->free_flags & DEVIF_CB_DONT_FREE)
|
||||
{
|
||||
cb->free_flags |= DEVIF_CB_PEND_FREE;
|
||||
net_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove the callback structure from the device notification list if
|
||||
* it is supposed to be in the device notification list.
|
||||
*/
|
||||
|
||||
if (dev != NULL)
|
||||
{
|
||||
/* Find the callback structure in the device event list */
|
||||
|
||||
for (prev = NULL, curr = dev->d_devcb;
|
||||
curr != NULL && curr != cb;
|
||||
prev = curr, curr = curr->nxtdev)
|
||||
{
|
||||
}
|
||||
|
||||
/* Remove the structure from the device event list */
|
||||
|
||||
if (curr != NULL)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
prev->nxtdev = cb->nxtdev;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->d_devcb = cb->nxtdev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a preallocated or a batch allocated callback store it in
|
||||
* the free callbacks list. Else free it.
|
||||
*/
|
||||
|
@ -574,12 +594,26 @@ uint16_t devif_dev_event(FAR struct net_driver_s *dev, uint16_t flags)
|
|||
|
||||
if (cb->event != NULL && devif_event_trigger(flags, cb->flags))
|
||||
{
|
||||
cb->free_flags |= DEVIF_CB_DONT_FREE;
|
||||
|
||||
/* Yes.. perform the callback. Actions perform by the callback
|
||||
* may delete the current list entry or add a new list entry to
|
||||
* beginning of the list (which will be ignored on this pass)
|
||||
*/
|
||||
|
||||
flags = cb->event(dev, cb->priv, flags);
|
||||
cb->free_flags &= ~DEVIF_CB_DONT_FREE;
|
||||
|
||||
/* update the next callback to prevent previously recorded the
|
||||
* next callback from being deleted
|
||||
*/
|
||||
|
||||
next = cb->nxtdev;
|
||||
if ((cb->free_flags & DEVIF_CB_PEND_FREE) != 0)
|
||||
{
|
||||
cb->free_flags &= ~DEVIF_CB_PEND_FREE;
|
||||
devif_callback_free(dev, cb, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue