Subversion Repositories HelenOS-historic

Rev

Rev 1414 | Rev 1502 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1414 Rev 1460
Line 27... Line 27...
27
 */
27
 */
28
 
28
 
29
/**
29
/**
30
 * @file    futex.c
30
 * @file    futex.c
31
 * @brief   Kernel backend for futexes.
31
 * @brief   Kernel backend for futexes.
32
 *
-
 
33
 * @todo Deallocation of orphaned kernel-side futex structures is not currently implemented.
-
 
34
 */
32
 */
35
 
33
 
36
#include <synch/futex.h>
34
#include <synch/futex.h>
37
#include <synch/rwlock.h>
35
#include <synch/rwlock.h>
38
#include <synch/spinlock.h>
36
#include <synch/spinlock.h>
39
#include <synch/synch.h>
37
#include <synch/synch.h>
40
#include <mm/frame.h>
38
#include <mm/frame.h>
41
#include <mm/page.h>
39
#include <mm/page.h>
42
#include <mm/slab.h>
40
#include <mm/slab.h>
43
#include <proc/thread.h>
41
#include <proc/thread.h>
-
 
42
#include <proc/task.h>
44
#include <genarch/mm/page_pt.h>
43
#include <genarch/mm/page_pt.h>
45
#include <genarch/mm/page_ht.h>
44
#include <genarch/mm/page_ht.h>
46
#include <adt/hash_table.h>
45
#include <adt/hash_table.h>
47
#include <adt/list.h>
46
#include <adt/list.h>
48
#include <arch.h>
47
#include <arch.h>
Line 58... Line 57...
58
static futex_t *futex_find(__address paddr);
57
static futex_t *futex_find(__address paddr);
59
static index_t futex_ht_hash(__native *key);
58
static index_t futex_ht_hash(__native *key);
60
static bool futex_ht_compare(__native *key, count_t keys, link_t *item);
59
static bool futex_ht_compare(__native *key, count_t keys, link_t *item);
61
static void futex_ht_remove_callback(link_t *item);
60
static void futex_ht_remove_callback(link_t *item);
62
 
61
 
-
 
62
/**
63
/** Read-write lock protecting global futex hash table. */
63
 * Read-write lock protecting global futex hash table.
-
 
64
 * It is also used to serialize access to all futex_t structures.
-
 
65
 * Must be acquired before the task futex B+tree lock.
-
 
66
 */
64
static rwlock_t futex_ht_lock;
67
static rwlock_t futex_ht_lock;
65
 
68
 
66
/** Futex hash table. */
69
/** Futex hash table. */
67
static hash_table_t futex_ht;
70
static hash_table_t futex_ht;
68
 
71
 
Line 87... Line 90...
87
void futex_initialize(futex_t *futex)
90
void futex_initialize(futex_t *futex)
88
{
91
{
89
    waitq_initialize(&futex->wq);
92
    waitq_initialize(&futex->wq);
90
    link_initialize(&futex->ht_link);
93
    link_initialize(&futex->ht_link);
91
    futex->paddr = 0;
94
    futex->paddr = 0;
-
 
95
    futex->refcount = 1;
92
}
96
}
93
 
97
 
94
/** Sleep in futex wait queue.
98
/** Sleep in futex wait queue.
95
 *
99
 *
96
 * @param uaddr Userspace address of the futex counter.
100
 * @param uaddr Userspace address of the futex counter.
Line 166... Line 170...
166
    return 0;
170
    return 0;
167
}
171
}
168
 
172
 
169
/** Find kernel address of the futex structure corresponding to paddr.
173
/** Find kernel address of the futex structure corresponding to paddr.
170
 *
174
 *
171
 * If the structure does not exist alreay, a new one is created.
175
 * If the structure does not exist already, a new one is created.
172
 *
176
 *
173
 * @param paddr Physical address of the userspace futex counter.
177
 * @param paddr Physical address of the userspace futex counter.
174
 *
178
 *
175
 * @return Address of the kernel futex structure.
179
 * @return Address of the kernel futex structure.
176
 */
180
 */
177
futex_t *futex_find(__address paddr)
181
futex_t *futex_find(__address paddr)
178
{
182
{
179
    link_t *item;
183
    link_t *item;
180
    futex_t *futex;
184
    futex_t *futex;
-
 
185
    btree_node_t *leaf;
181
   
186
   
182
    /*
187
    /*
183
     * Find the respective futex structure
188
     * Find the respective futex structure
184
     * or allocate new one if it does not exist already.
189
     * or allocate new one if it does not exist already.
185
     */
190
     */
186
    rwlock_read_lock(&futex_ht_lock);
191
    rwlock_read_lock(&futex_ht_lock);
187
    item = hash_table_find(&futex_ht, &paddr);
192
    item = hash_table_find(&futex_ht, &paddr);
188
    if (item) {
193
    if (item) {
189
        futex = hash_table_get_instance(item, futex_t, ht_link);
194
        futex = hash_table_get_instance(item, futex_t, ht_link);
-
 
195
 
-
 
196
        /*
-
 
197
         * See if the current task knows this futex.
-
 
198
         */
-
 
199
        mutex_lock(&TASK->futexes_lock);
-
 
200
        if (!btree_search(&TASK->futexes, paddr, &leaf)) {
-
 
201
            /*
-
 
202
             * The futex is new to the current task.
-
 
203
             * However, we only have read access.
-
 
204
             * Gain write access and try again.
-
 
205
             */
-
 
206
            mutex_unlock(&TASK->futexes_lock);
-
 
207
            goto gain_write_access;
-
 
208
        }
-
 
209
        mutex_unlock(&TASK->futexes_lock);
-
 
210
 
190
        rwlock_read_unlock(&futex_ht_lock);
211
        rwlock_read_unlock(&futex_ht_lock);
191
    } else {
212
    } else {
-
 
213
gain_write_access:
192
        /*
214
        /*
193
         * Upgrade to writer is not currently supported,
215
         * Upgrade to writer is not currently supported,
194
         * therefore, it is necessary to release the read lock
216
         * therefore, it is necessary to release the read lock
195
         * and reacquire it as a writer.
217
         * and reacquire it as a writer.
196
         */
218
         */
Line 202... Line 224...
202
         * the hash table once again with write access.
224
         * the hash table once again with write access.
203
         */
225
         */
204
        item = hash_table_find(&futex_ht, &paddr);
226
        item = hash_table_find(&futex_ht, &paddr);
205
        if (item) {
227
        if (item) {
206
            futex = hash_table_get_instance(item, futex_t, ht_link);
228
            futex = hash_table_get_instance(item, futex_t, ht_link);
-
 
229
           
-
 
230
            /*
-
 
231
             * See if this futex is known to the current task.
-
 
232
             */
-
 
233
            mutex_lock(&TASK->futexes_lock);
-
 
234
            if (!btree_search(&TASK->futexes, paddr, &leaf)) {
-
 
235
                /*
-
 
236
                 * The futex is new to the current task.
-
 
237
                 * Upgrade its reference count and put it to the
-
 
238
                 * current task's B+tree of known futexes.
-
 
239
                 */
-
 
240
                futex->refcount++;
-
 
241
                btree_insert(&TASK->futexes, paddr, futex, leaf);
-
 
242
            }
-
 
243
            mutex_unlock(&TASK->futexes_lock);
-
 
244
   
207
            rwlock_write_unlock(&futex_ht_lock);
245
            rwlock_write_unlock(&futex_ht_lock);
208
        } else {
246
        } else {
209
            futex = (futex_t *) malloc(sizeof(futex_t), 0);
247
            futex = (futex_t *) malloc(sizeof(futex_t), 0);
210
            futex_initialize(futex);
248
            futex_initialize(futex);
211
            futex->paddr = paddr;
249
            futex->paddr = paddr;
212
            hash_table_insert(&futex_ht, &paddr, &futex->ht_link);
250
            hash_table_insert(&futex_ht, &paddr, &futex->ht_link);
-
 
251
           
-
 
252
            /*
-
 
253
             * This is the first task referencing the futex.
-
 
254
             * It can be directly inserted into its
-
 
255
             * B+tree of known futexes.
-
 
256
             */
-
 
257
            mutex_lock(&TASK->futexes_lock);
-
 
258
            btree_insert(&TASK->futexes, paddr, futex, NULL);
-
 
259
            mutex_unlock(&TASK->futexes_lock);
-
 
260
           
213
            rwlock_write_unlock(&futex_ht_lock);
261
            rwlock_write_unlock(&futex_ht_lock);
214
        }
262
        }
215
    }
263
    }
216
   
264
   
217
    return futex;
265
    return futex;