Changeset 87e373b in mainline for uspace/srv/net/il/arp/arp.c


Ignore:
Timestamp:
2011-01-13T21:18:25Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
08abd81, c4fb95d3
Parents:
80cd7cd
Message:

Do not prevent new ARP requests to be made when the first one times out.
Add explanatory comments where useful.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/il/arp/arp.c

    r80cd7cd r87e373b  
    4040#include <mem.h>
    4141#include <fibril_synch.h>
     42#include <assert.h>
    4243#include <stdio.h>
    4344#include <str.h>
     
    708709        bool retry = false;
    709710        int rc;
     711
     712        assert(fibril_mutex_is_locked(&arp_globals.lock));
    710713       
    711714restart:
     
    725728        if (trans) {
    726729                if (trans->hw_addr) {
     730                        /* The translation is in place. */
    727731                        *translation = trans->hw_addr;
    728732                        return EOK;
     
    730734               
    731735                if (retry) {
    732                         /* Remove the translation from the map */
     736                        /*
     737                         * We may get here as a result of being signalled for
     738                         * some reason while waiting for the translation (e.g.
     739                         * translation becoming available, record being removed
     740                         * from the table) and then losing the race for
     741                         * the arp_globals.lock with someone else who modified
     742                         * the table.
     743                         *
     744                         * Remove the incomplete record so that it is possible
     745                         * to make new ARP requests.
     746                         */
    733747                        arp_clear_trans(trans);
    734748                        arp_addr_exclude(&proto->addresses, target->value,
     
    737751                }
    738752               
     753                /*
     754                 * We are a random passer-by who merely joins an already waiting
     755                 * fibril in waiting for the translation.
     756                 */
    739757                rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    740758                    ARP_TRANS_WAIT);
     
    742760                        return ENOENT;
    743761               
     762                /*
     763                 * Need to recheck because we did not hold the lock while
     764                 * sleeping on the condition variable.
     765                 */
    744766                retry = true;
    745767                goto restart;
     
    748770        if (retry)
    749771                return EAGAIN;
     772
     773        /*
     774         * We are under the protection of arp_globals.lock, so we can afford to
     775         * first send the ARP request and then insert an incomplete ARP record.
     776         * The incomplete record is used to tell any other potential waiter
     777         * that this fibril has already sent the request and that it is waiting
     778         * for the answer. Lastly, any fibril which sees the incomplete request
     779         * can perform a timed wait on its condition variable to wait for the
     780         * ARP reply to arrive.
     781         */
     782
     783        rc = arp_send_request(device_id, protocol, target, device, proto);
     784        if (rc != EOK)
     785                return rc;
    750786       
    751787        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
     
    763799        }
    764800       
    765         rc = arp_send_request(device_id, protocol, target, device, proto);
    766         if (rc != EOK)
    767                 return rc;
    768        
    769801        rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    770802            ARP_TRANS_WAIT);
    771         if (rc == ETIMEOUT)
     803        if (rc == ETIMEOUT) {
     804                /*
     805                 * Remove the incomplete record so that it is possible to make
     806                 * new ARP requests.
     807                 */
     808                arp_clear_trans(trans);
     809                arp_addr_exclude(&proto->addresses, target->value,
     810                    target->length);
    772811                return ENOENT;
    773        
     812        }
     813       
     814        /*
     815         * We need to recheck that the translation has indeed become available,
     816         * because we dropped the arp_globals.lock while sleeping on the
     817         * condition variable and someone else might have e.g. removed the
     818         * translation before we managed to lock arp_globals.lock again.
     819         */
     820
    774821        retry = true;
    775822        goto restart;
Note: See TracChangeset for help on using the changeset viewer.