VirtualBox

Changeset 35955 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Feb 14, 2011 11:16:09 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
70015
Message:

DrvNAT: leave the critical section of the zone before working pfnXmitPending since the callback will try allocate packages which may result in a lock inversion if any driver/device up the chain is doing locking.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/slirp/misc.c

    r35922 r35955  
    126126    uma_zone_t master_zone;
    127127    void *area;
    128     bool fPending;  /* has some sense only in case master_zone == NULL */
     128    /** Needs call pfnXmitPending when memory becomes available if @c true.
     129     * @remarks Only applies to the master zone (master_zone == NULL) */
     130    bool fDoXmitPending;
    129131};
    130132
    131 static inline bool slirp_zone_has_pending(uma_zone_t zone)
    132 {
    133     return (   zone->master_zone == NULL
    134             && zone->fPending);
    135 }
    136 
    137 static inline void slirp_zone_check_and_send_pending(uma_zone_t zone)
    138 {
    139     if (slirp_zone_has_pending(zone))
    140     {
    141         zone->fPending = false;
     133
     134/**
     135 * Called when memory becomes available, works pfnXmitPending.
     136 *
     137 * @note    This will LEAVE the critical section of the zone and RE-ENTER it
     138 *          again.  Changes to the zone data should be expected across calls to
     139 *          this function!
     140 *
     141 * @param   zone        The zone.
     142 */
     143DECLINLINE(void) slirp_zone_check_and_send_pending(uma_zone_t zone)
     144{
     145    if (   zone->fDoXmitPending
     146        && zone->master_zone == NULL)
     147    {
     148        int rc2;
     149        zone->fDoXmitPending = false;
     150        rc2 = RTCritSectLeave(&zone->csZone); AssertRC(rc2);
     151
    142152        slirp_output_pending(zone->pData->pvUser);
     153
     154        rc2 = RTCritSectLeave(&zone->csZone); AssertRC(rc2);
    143155    }
    144156}
     
    167179                LIST_REMOVE(it, list);
    168180                LIST_INSERT_HEAD(&zone->used_items, it, list);
    169                 slirp_zone_check_and_send_pending(zone);
     181                slirp_zone_check_and_send_pending(zone); /* may exit+enter the cs! */
    170182                ret = (void *)&it[1];
    171183            }
     
    180192        if (!zone->master_zone)
    181193        {
    182             /* We're on master zone and we cant allocate more */
     194            /* We're on the master zone and we can't allocate more. */
    183195            Log2(("NAT: no room on %s zone\n", zone->name));
    184196            /* AssertMsgFailed(("NAT: OOM!")); */
    185             zone->fPending = true;
     197            zone->fDoXmitPending = true;
    186198            break;
    187199        }
    188200
    189         /* we're on sub-zone we need get chunk of master zone and split
    190          * it for sub-zone conforming chunks.
     201        /* we're on a sub-zone, we need get a chunk from the master zone and split
     202         * it into sub-zone conforming chunks.
    191203         */
    192204        sub_area = slirp_uma_alloc(zone->master_zone, zone->master_zone->size, NULL, 0);
     
    199211        zone->max_items++;
    200212        it = &((struct item *)sub_area)[-1];
    201         /* it's chunk descriptor of master zone we should remove it
    202          *  from the master list first
     213        /* It's the chunk descriptor of the master zone, we should remove it
     214         * from the master list first.
    203215         */
    204216        Assert((it->zone && it->zone->magic == ZONE_MAGIC));
    205217        RTCritSectEnter(&it->zone->csZone);
    206         /* @todo should we alter count of master counters? */
     218        /** @todo should we alter count of master counters? */
    207219        LIST_REMOVE(it, list);
    208220        RTCritSectLeave(&it->zone->csZone);
    209         /* @todo '+ zone->size' should be depend on flag */
     221
     222        /** @todo '+ zone->size' should be depend on flag */
    210223        memset(it, 0, sizeof(struct item));
    211224        it->zone = zone;
     
    224237    uma_zone_t zone;
    225238    uma_zone_t master_zone;
     239
    226240    Assert(item);
    227241    it = &((struct item *)item)[-1];
    228242    Assert(it->magic == ITEM_MAGIC);
    229243    zone = it->zone;
    230     /* check bourder magic */
     244    /* check border magic */
    231245    Assert((*(uint32_t *)(((uint8_t *)&it[1]) + zone->size) == 0xabadbabe));
     246
    232247    RTCritSectEnter(&zone->csZone);
    233248    Assert(zone->magic == ZONE_MAGIC);
     
    243258    LIST_INSERT_HEAD(&zone->free_items, it, list);
    244259    zone->cur_items--;
    245     slirp_zone_check_and_send_pending(zone);
     260    slirp_zone_check_and_send_pending(zone); /* may exit+enter the cs! */
    246261    RTCritSectLeave(&zone->csZone);
    247262}
     
    320335uint32_t *uma_find_refcnt(uma_zone_t zone, void *mem)
    321336{
    322     /*@todo (vvl) this function supposed to work with special zone storing
     337    /** @todo (vvl) this function supposed to work with special zone storing
    323338    reference counters */
    324339    struct item *it = (struct item *)mem; /* 1st element */
     
    381396    struct item *it;
    382397    uma_zone_t master_zone;
     398
    383399    /* vvl: Huh? What to do with zone which hasn't got backstore ? */
    384400    Assert((zone->master_zone));
    385401    master_zone = zone->master_zone;
    386     while(!LIST_EMPTY(&zone->free_items))
     402    while (!LIST_EMPTY(&zone->free_items))
    387403    {
    388404        it = LIST_FIRST(&zone->free_items);
    389405        Assert((it->magic == ITEM_MAGIC));
     406
    390407        RTCritSectEnter(&zone->csZone);
    391408        LIST_REMOVE(it, list);
    392409        zone->max_items--;
    393410        RTCritSectLeave(&zone->csZone);
     411
    394412        it->zone = master_zone;
     413
    395414        RTCritSectEnter(&master_zone->csZone);
    396415        LIST_INSERT_HEAD(&master_zone->free_items, it, list);
    397416        master_zone->cur_items--;
     417        slirp_zone_check_and_send_pending(master_zone); /* may exit+enter the cs! */
    398418        RTCritSectLeave(&master_zone->csZone);
    399         slirp_zone_check_and_send_pending(master_zone);
    400419    }
    401420}
     
    403422void slirp_null_arg_free(void *mem, void *arg)
    404423{
    405     /*@todo (r=vvl) make it wiser*/
     424    /** @todo (vvl) make it wiser  */
    406425    Assert(mem);
    407426    RTMemFree(mem);
     
    469488    zone_destroy(pData->zone_jumbo9);
    470489    zone_destroy(pData->zone_jumbo16);
    471     /*@todo do finalize here.*/
     490    /** @todo do finalize here.*/
    472491}
    473492
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette