Ignore:
File:
1 edited

Legend:

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

    r98000fb r96b02eb9  
    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>
     
    6060
    6161static futex_t *futex_find(uintptr_t paddr);
    62 static size_t futex_ht_hash(unative_t *key);
    63 static bool futex_ht_compare(unative_t *key, size_t keys, link_t *item);
     62static size_t futex_ht_hash(sysarg_t *key);
     63static bool futex_ht_compare(sysarg_t *key, size_t keys, link_t *item);
    6464static void futex_ht_remove_callback(link_t *item);
    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}
     
    9090/** Initialize kernel futex structure.
    9191 *
    92  * @param futex Kernel futex structure.
     92 * @param futex         Kernel futex structure.
    9393 */
    9494void futex_initialize(futex_t *futex)
     
    102102/** Sleep in futex wait queue.
    103103 *
    104  * @param uaddr Userspace address of the futex counter.
    105  * @param usec If non-zero, number of microseconds this thread is willing to
    106  *     sleep.
    107  * @param flags Select mode of operation.
    108  *
    109  * @return One of ESYNCH_TIMEOUT, ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED. See
    110  *     synch.h. If there is no physical mapping for uaddr ENOENT is returned.
    111  */
    112 unative_t sys_futex_sleep_timeout(uintptr_t uaddr, uint32_t usec, int flags)
     104 * @param uaddr         Userspace address of the futex counter.
     105 *
     106 * @return              If there is no physical mapping for uaddr ENOENT is
     107 *                      returned. Otherwise returns a wait result as defined in
     108 *                      synch.h.
     109 */
     110sysarg_t sys_futex_sleep(uintptr_t uaddr)
    113111{
    114112        futex_t *futex;
    115113        uintptr_t paddr;
    116114        pte_t *t;
    117         ipl_t ipl;
    118115        int rc;
    119116       
    120         ipl = interrupts_disable();
    121 
    122117        /*
    123118         * Find physical address of futex counter.
     
    127122        if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
    128123                page_table_unlock(AS, true);
    129                 interrupts_restore(ipl);
    130                 return (unative_t) ENOENT;
     124                return (sysarg_t) ENOENT;
    131125        }
    132126        paddr = PTE_GET_FRAME(t) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
    133127        page_table_unlock(AS, true);
    134128       
    135         interrupts_restore(ipl);       
    136 
    137129        futex = futex_find(paddr);
    138130
     
    140132        udebug_stoppable_begin();
    141133#endif
    142         rc = waitq_sleep_timeout(&futex->wq, usec, flags |
    143             SYNCH_FLAGS_INTERRUPTIBLE);
    144 
     134        rc = waitq_sleep_timeout(&futex->wq, 0, SYNCH_FLAGS_INTERRUPTIBLE);
    145135#ifdef CONFIG_UDEBUG
    146136        udebug_stoppable_end();
    147137#endif
    148         return (unative_t) rc;
     138        return (sysarg_t) rc;
    149139}
    150140
    151141/** Wakeup one thread waiting in futex wait queue.
    152142 *
    153  * @param uaddr Userspace address of the futex counter.
    154  *
    155  * @return ENOENT if there is no physical mapping for uaddr.
    156  */
    157 unative_t sys_futex_wakeup(uintptr_t uaddr)
     143 * @param uaddr         Userspace address of the futex counter.
     144 *
     145 * @return              ENOENT if there is no physical mapping for uaddr.
     146 */
     147sysarg_t sys_futex_wakeup(uintptr_t uaddr)
    158148{
    159149        futex_t *futex;
    160150        uintptr_t paddr;
    161151        pte_t *t;
    162         ipl_t ipl;
    163        
    164         ipl = interrupts_disable();
    165152       
    166153        /*
     
    171158        if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
    172159                page_table_unlock(AS, true);
    173                 interrupts_restore(ipl);
    174                 return (unative_t) ENOENT;
     160                return (sysarg_t) ENOENT;
    175161        }
    176162        paddr = PTE_GET_FRAME(t) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
    177163        page_table_unlock(AS, true);
    178164       
    179         interrupts_restore(ipl);
    180 
    181165        futex = futex_find(paddr);
    182166               
     
    190174 * If the structure does not exist already, a new one is created.
    191175 *
    192  * @param paddr Physical address of the userspace futex counter.
    193  *
    194  * @return Address of the kernel futex structure.
     176 * @param paddr         Physical address of the userspace futex counter.
     177 *
     178 * @return              Address of the kernel futex structure.
    195179 */
    196180futex_t *futex_find(uintptr_t paddr)
     
    204188         * or allocate new one if it does not exist already.
    205189         */
    206         rwlock_read_lock(&futex_ht_lock);
     190        mutex_lock(&futex_ht_lock);
    207191        item = hash_table_find(&futex_ht, &paddr);
    208192        if (item) {
     
    216200                        /*
    217201                         * The futex is new to the current task.
    218                          * However, we only have read access.
    219                          * 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.
    220204                         */
    221                         mutex_unlock(&TASK->futexes_lock);
    222                         goto gain_write_access;
     205                        futex->refcount++;
     206                        btree_insert(&TASK->futexes, paddr, futex, leaf);
    223207                }
    224208                mutex_unlock(&TASK->futexes_lock);
    225 
    226                 rwlock_read_unlock(&futex_ht_lock);
    227209        } else {
    228 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                       
    229215                /*
    230                  * Upgrade to writer is not currently supported,
    231                  * therefore, it is necessary to release the read lock
    232                  * 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.
    233219                 */
    234                 rwlock_read_unlock(&futex_ht_lock);
    235 
    236                 rwlock_write_lock(&futex_ht_lock);
    237                 /*
    238                  * Avoid possible race condition by searching
    239                  * the hash table once again with write access.
    240                  */
    241                 item = hash_table_find(&futex_ht, &paddr);
    242                 if (item) {
    243                         futex = hash_table_get_instance(item, futex_t, ht_link);
    244                        
    245                         /*
    246                          * See if this futex is known to the current task.
    247                          */
    248                         mutex_lock(&TASK->futexes_lock);
    249                         if (!btree_search(&TASK->futexes, paddr, &leaf)) {
    250                                 /*
    251                                  * The futex is new to the current task.
    252                                  * Upgrade its reference count and put it to the
    253                                  * current task's B+tree of known futexes.
    254                                  */
    255                                 futex->refcount++;
    256                                 btree_insert(&TASK->futexes, paddr, futex,
    257                                     leaf);
    258                         }
    259                         mutex_unlock(&TASK->futexes_lock);
    260        
    261                         rwlock_write_unlock(&futex_ht_lock);
    262                 } else {
    263                         futex = (futex_t *) malloc(sizeof(futex_t), 0);
    264                         futex_initialize(futex);
    265                         futex->paddr = paddr;
    266                         hash_table_insert(&futex_ht, &paddr, &futex->ht_link);
    267                        
    268                         /*
    269                          * This is the first task referencing the futex.
    270                          * It can be directly inserted into its
    271                          * B+tree of known futexes.
    272                          */
    273                         mutex_lock(&TASK->futexes_lock);
    274                         btree_insert(&TASK->futexes, paddr, futex, NULL);
    275                         mutex_unlock(&TASK->futexes_lock);
    276                        
    277                         rwlock_write_unlock(&futex_ht_lock);
    278                 }
     220                mutex_lock(&TASK->futexes_lock);
     221                btree_insert(&TASK->futexes, paddr, futex, NULL);
     222                mutex_unlock(&TASK->futexes_lock);
     223               
    279224        }
     225        mutex_unlock(&futex_ht_lock);
    280226       
    281227        return futex;
     
    284230/** Compute hash index into futex hash table.
    285231 *
    286  * @param key Address where the key (i.e. physical address of futex counter) is
    287  *    stored.
    288  *
    289  * @return Index into futex hash table.
    290  */
    291 size_t futex_ht_hash(unative_t *key)
     232 * @param key           Address where the key (i.e. physical address of futex
     233 *                      counter) is stored.
     234 *
     235 * @return              Index into futex hash table.
     236 */
     237size_t futex_ht_hash(sysarg_t *key)
    292238{
    293239        return (*key & (FUTEX_HT_SIZE - 1));
     
    296242/** Compare futex hash table item with a key.
    297243 *
    298  * @param key Address where the key (i.e. physical address of futex counter) is
    299  *    stored.
    300  *
    301  * @return True if the item matches the key. False otherwise.
    302  */
    303 bool futex_ht_compare(unative_t *key, size_t keys, link_t *item)
     244 * @param key           Address where the key (i.e. physical address of futex
     245 *                      counter) is stored.
     246 *
     247 * @return              True if the item matches the key. False otherwise.
     248 */
     249bool futex_ht_compare(sysarg_t *key, size_t keys, link_t *item)
    304250{
    305251        futex_t *futex;
     
    313259/** Callback for removal items from futex hash table.
    314260 *
    315  * @param item Item removed from the hash table.
     261 * @param item          Item removed from the hash table.
    316262 */
    317263void futex_ht_remove_callback(link_t *item)
     
    328274        link_t *cur;
    329275       
    330         rwlock_write_lock(&futex_ht_lock);
     276        mutex_lock(&futex_ht_lock);
    331277        mutex_lock(&TASK->futexes_lock);
    332278
     
    348294       
    349295        mutex_unlock(&TASK->futexes_lock);
    350         rwlock_write_unlock(&futex_ht_lock);
     296        mutex_unlock(&futex_ht_lock);
    351297}
    352298
Note: See TracChangeset for help on using the changeset viewer.