Changeset a9ef68b in mainline


Ignore:
Timestamp:
2006-04-05T12:12:39Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
fe04594
Parents:
448743f
Message:

Because of another race condition, futex_wakeup() needs to be able to allocate and initialize the kernel futex structure too.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • generic/src/synch/futex.c

    r448743f ra9ef68b  
    5454static void futex_initialize(futex_t *futex);
    5555
     56static futex_t *futex_find(__address paddr);
    5657static index_t futex_ht_hash(__native *key);
    5758static bool futex_ht_compare(__native *key, count_t keys, link_t *item);
     
    102103        futex_t *futex;
    103104        __address paddr;
    104         link_t *item;
    105105        pte_t *t;
    106106        ipl_t ipl;
     
    123123        interrupts_restore(ipl);       
    124124
     125        futex = futex_find(paddr);
     126       
     127        return (__native) waitq_sleep_timeout(&futex->wq, usec, trydown);
     128}
     129
     130/** Wakeup one thread waiting in futex wait queue.
     131 *
     132 * @param uaddr Userspace address of the futex counter.
     133 *
     134 * @return ENOENT if there is no futex associated with the address
     135 *         or if there is no physical mapping for uaddr.
     136 */
     137__native sys_futex_wakeup(__address uaddr)
     138{
     139        futex_t *futex;
     140        __address paddr;
     141        pte_t *t;
     142        ipl_t ipl;
     143       
     144        ipl = interrupts_disable();
     145       
     146        /*
     147         * Find physical address of futex counter.
     148         */
     149        page_table_lock(AS, true);
     150        t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
     151        if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
     152                page_table_unlock(AS, true);
     153                interrupts_restore(ipl);
     154                return (__native) ENOENT;
     155        }
     156        paddr = PFN2ADDR(PTE_GET_FRAME(t)) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
     157        page_table_unlock(AS, true);
     158       
     159        interrupts_restore(ipl);
     160
     161        futex = futex_find(paddr);
     162               
     163        waitq_wakeup(&futex->wq, WAKEUP_FIRST);
     164       
     165        return 0;
     166}
     167
     168/** Find kernel address of the futex structure corresponding to paddr.
     169 *
     170 * If the structure does not exist alreay, a new one is created.
     171 *
     172 * @param paddr Physical address of the userspace futex counter.
     173 *
     174 * @return Address of the kernel futex structure.
     175 */
     176futex_t *futex_find(__address paddr)
     177{
     178        link_t *item;
     179        futex_t *futex;
     180       
    125181        /*
    126182         * Find the respective futex structure
     
    142198                rwlock_write_lock(&futex_ht_lock);
    143199                /*
    144                  * Detect possible race condition by searching
     200                 * Avoid possible race condition by searching
    145201                 * the hash table once again with write access.
    146202                 */
     
    158214        }
    159215       
    160         return (__native) waitq_sleep_timeout(&futex->wq, usec, trydown);
    161 }
    162 
    163 /** Wakeup one thread waiting in futex wait queue.
    164  *
    165  * @param uaddr Userspace address of the futex counter.
    166  *
    167  * @return ENOENT if there is no futex associated with the address
    168  *         or if there is no physical mapping for uaddr.
    169  */
    170 __native sys_futex_wakeup(__address uaddr)
    171 {
    172         futex_t *futex = NULL;
    173         __address paddr;
    174         link_t *item;
    175         pte_t *t;
    176         ipl_t ipl;
    177        
    178         ipl = interrupts_disable();
    179        
    180         /*
    181          * Find physical address of futex counter.
    182          */
    183         page_table_lock(AS, true);
    184         t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
    185         if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
    186                 page_table_unlock(AS, true);
    187                 interrupts_restore(ipl);
    188                 return (__native) ENOENT;
    189         }
    190         paddr = PFN2ADDR(PTE_GET_FRAME(t)) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
    191         page_table_unlock(AS, true);
    192        
    193         interrupts_restore(ipl);
    194 
    195         /*
    196          * Find the respective futex structure.
    197          */
    198         rwlock_read_lock(&futex_ht_lock);
    199         item = hash_table_find(&futex_ht, &paddr);
    200         if (item) {
    201                 futex = hash_table_get_instance(item, futex_t, ht_link);
    202         }
    203         rwlock_read_unlock(&futex_ht_lock);
    204 
    205         if (!futex)
    206                 return (__native) ENOENT;       
    207                
    208         waitq_wakeup(&futex->wq, WAKEUP_FIRST);
    209        
    210         return 0;
     216        return futex;
    211217}
    212218
Note: See TracChangeset for help on using the changeset viewer.