Changeset cefb126 in mainline for kernel/generic/src/synch/futex.c


Ignore:
Timestamp:
2010-07-02T14:19:30Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
89c57b6
Parents:
fe7abd0 (diff), e3ee9b9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    rfe7abd0 rcefb126  
    3737
    3838#include <synch/futex.h>
    39 #include <synch/rwlock.h>
     39#include <synch/mutex.h>
    4040#include <synch/spinlock.h>
    4141#include <synch/synch.h>
     
    6565
    6666/**
    67  * Read-write lock protecting global futex hash table.
     67 * Mutex protecting global futex hash table.
    6868 * It is also used to serialize access to all futex_t structures.
    6969 * Must be acquired before the task futex B+tree lock.
    7070 */
    71 static rwlock_t futex_ht_lock;
     71static mutex_t futex_ht_lock;
    7272
    7373/** Futex hash table. */
     
    8484void futex_init(void)
    8585{
    86         rwlock_initialize(&futex_ht_lock);
     86        mutex_initialize(&futex_ht_lock, MUTEX_PASSIVE);
    8787        hash_table_create(&futex_ht, FUTEX_HT_SIZE, 1, &futex_ht_ops);
    8888}
     
    113113        uintptr_t paddr;
    114114        pte_t *t;
    115         ipl_t ipl;
    116115        int rc;
    117116       
    118         ipl = interrupts_disable();
    119 
    120117        /*
    121118         * Find physical address of futex counter.
     
    125122        if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
    126123                page_table_unlock(AS, true);
    127                 interrupts_restore(ipl);
    128124                return (unative_t) ENOENT;
    129125        }
     
    131127        page_table_unlock(AS, true);
    132128       
    133         interrupts_restore(ipl);       
    134 
    135129        futex = futex_find(paddr);
    136130
     
    156150        uintptr_t paddr;
    157151        pte_t *t;
    158         ipl_t ipl;
    159        
    160         ipl = interrupts_disable();
    161152       
    162153        /*
     
    167158        if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
    168159                page_table_unlock(AS, true);
    169                 interrupts_restore(ipl);
    170160                return (unative_t) ENOENT;
    171161        }
     
    173163        page_table_unlock(AS, true);
    174164       
    175         interrupts_restore(ipl);
    176 
    177165        futex = futex_find(paddr);
    178166               
     
    200188         * or allocate new one if it does not exist already.
    201189         */
    202         rwlock_read_lock(&futex_ht_lock);
     190        mutex_lock(&futex_ht_lock);
    203191        item = hash_table_find(&futex_ht, &paddr);
    204192        if (item) {
     
    212200                        /*
    213201                         * The futex is new to the current task.
    214                          * However, we only have read access.
    215                          * Gain write access and try again.
     202                         * Upgrade its reference count and put it to the
     203                         * current task's B+tree of known futexes.
    216204                         */
    217                         mutex_unlock(&TASK->futexes_lock);
    218                         goto gain_write_access;
     205                        futex->refcount++;
     206                        btree_insert(&TASK->futexes, paddr, futex, leaf);
    219207                }
    220208                mutex_unlock(&TASK->futexes_lock);
    221 
    222                 rwlock_read_unlock(&futex_ht_lock);
    223209        } else {
    224 gain_write_access:
     210                futex = (futex_t *) malloc(sizeof(futex_t), 0);
     211                futex_initialize(futex);
     212                futex->paddr = paddr;
     213                hash_table_insert(&futex_ht, &paddr, &futex->ht_link);
     214                       
    225215                /*
    226                  * Upgrade to writer is not currently supported,
    227                  * therefore, it is necessary to release the read lock
    228                  * and reacquire it as a writer.
     216                 * This is the first task referencing the futex.
     217                 * It can be directly inserted into its
     218                 * B+tree of known futexes.
    229219                 */
    230                 rwlock_read_unlock(&futex_ht_lock);
    231 
    232                 rwlock_write_lock(&futex_ht_lock);
    233                 /*
    234                  * Avoid possible race condition by searching
    235                  * the hash table once again with write access.
    236                  */
    237                 item = hash_table_find(&futex_ht, &paddr);
    238                 if (item) {
    239                         futex = hash_table_get_instance(item, futex_t, ht_link);
    240                        
    241                         /*
    242                          * See if this futex is known to the current task.
    243                          */
    244                         mutex_lock(&TASK->futexes_lock);
    245                         if (!btree_search(&TASK->futexes, paddr, &leaf)) {
    246                                 /*
    247                                  * The futex is new to the current task.
    248                                  * Upgrade its reference count and put it to the
    249                                  * current task's B+tree of known futexes.
    250                                  */
    251                                 futex->refcount++;
    252                                 btree_insert(&TASK->futexes, paddr, futex,
    253                                     leaf);
    254                         }
    255                         mutex_unlock(&TASK->futexes_lock);
    256        
    257                         rwlock_write_unlock(&futex_ht_lock);
    258                 } else {
    259                         futex = (futex_t *) malloc(sizeof(futex_t), 0);
    260                         futex_initialize(futex);
    261                         futex->paddr = paddr;
    262                         hash_table_insert(&futex_ht, &paddr, &futex->ht_link);
    263                        
    264                         /*
    265                          * This is the first task referencing the futex.
    266                          * It can be directly inserted into its
    267                          * B+tree of known futexes.
    268                          */
    269                         mutex_lock(&TASK->futexes_lock);
    270                         btree_insert(&TASK->futexes, paddr, futex, NULL);
    271                         mutex_unlock(&TASK->futexes_lock);
    272                        
    273                         rwlock_write_unlock(&futex_ht_lock);
    274                 }
     220                mutex_lock(&TASK->futexes_lock);
     221                btree_insert(&TASK->futexes, paddr, futex, NULL);
     222                mutex_unlock(&TASK->futexes_lock);
     223               
    275224        }
     225        mutex_unlock(&futex_ht_lock);
    276226       
    277227        return futex;
     
    324274        link_t *cur;
    325275       
    326         rwlock_write_lock(&futex_ht_lock);
     276        mutex_lock(&futex_ht_lock);
    327277        mutex_lock(&TASK->futexes_lock);
    328278
     
    344294       
    345295        mutex_unlock(&TASK->futexes_lock);
    346         rwlock_write_unlock(&futex_ht_lock);
     296        mutex_unlock(&futex_ht_lock);
    347297}
    348298
Note: See TracChangeset for help on using the changeset viewer.