Subversion Repositories HelenOS-historic

Rev

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

Rev 1109 Rev 1117
Line 27... Line 27...
27
 */
27
 */
28
 
28
 
29
/**
29
/**
30
 * Kernel backend for futexes.
30
 * Kernel backend for futexes.
31
 * Deallocation of orphaned kernel-side futex structures is not currently implemented.
31
 * Deallocation of orphaned kernel-side futex structures is not currently implemented.
32
 * Timeouting futexes are currently not implemented.
-
 
33
 */
32
 */
34
 
33
 
35
#include <synch/futex.h>
34
#include <synch/futex.h>
36
#include <synch/rwlock.h>
35
#include <synch/rwlock.h>
-
 
36
#include <synch/spinlock.h>
37
#include <synch/synch.h>
37
#include <synch/synch.h>
38
#include <mm/frame.h>
38
#include <mm/frame.h>
39
#include <mm/page.h>
39
#include <mm/page.h>
40
#include <mm/slab.h>
40
#include <mm/slab.h>
-
 
41
#include <proc/thread.h>
41
#include <genarch/mm/page_pt.h>
42
#include <genarch/mm/page_pt.h>
42
#include <genarch/mm/page_ht.h>
43
#include <genarch/mm/page_ht.h>
43
#include <adt/hash_table.h>
44
#include <adt/hash_table.h>
44
#include <adt/list.h>
45
#include <adt/list.h>
45
#include <arch.h>
46
#include <arch.h>
Line 88... Line 89...
88
}
89
}
89
 
90
 
90
/** Sleep in futex wait queue.
91
/** Sleep in futex wait queue.
91
 *
92
 *
92
 * @param uaddr Userspace address of the futex counter.
93
 * @param uaddr Userspace address of the futex counter.
-
 
94
 * @param usec If non-zero, number of microseconds this thread is willing to sleep.
-
 
95
 * @param trydown If usec is zero and trydown is non-zero, conditional operation will be attempted.
93
 *
96
 *
94
 * @return One of ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED. See synch.h.
97
 * @return One of ESYNCH_TIMEOUT, ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED. See synch.h.
95
 *     If there is no physical mapping for uaddr ENOENT is returned.
98
 *     If there is no physical mapping for uaddr ENOENT is returned.
96
 */
99
 */
97
__native sys_futex_sleep(__address uaddr)
100
__native sys_futex_sleep_timeout(__address uaddr, __u32 usec, int trydown)
98
{
101
{
99
    futex_t *futex;
102
    futex_t *futex;
100
    __address paddr;
103
    __address paddr;
101
    link_t *item;
104
    link_t *item;
102
    pte_t *t;
105
    pte_t *t;
-
 
106
    ipl_t ipl;
103
   
107
   
-
 
108
    ipl = interrupts_disable();
-
 
109
 
104
    /*
110
    /*
105
     * Find physical address of futex counter.
111
     * Find physical address of futex counter.
106
     */
112
     */
107
    page_table_lock(AS, true);
113
    page_table_lock(AS, true);
108
    t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
114
    t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
109
    if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
115
    if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
110
        page_table_unlock(AS, true);
116
        page_table_unlock(AS, true);
-
 
117
        interrupts_restore(ipl);
111
        return (__native) ENOENT;
118
        return (__native) ENOENT;
112
    }
119
    }
113
    paddr = PFN2ADDR(PTE_GET_FRAME(t)) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
120
    paddr = PFN2ADDR(PTE_GET_FRAME(t)) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
114
    page_table_unlock(AS, true);
121
    page_table_unlock(AS, true);
115
   
122
   
-
 
123
    interrupts_restore(ipl);   
-
 
124
 
116
    /*
125
    /*
117
     * Find the respective futex structure
126
     * Find the respective futex structure
118
     * or allocate new one if it does not exist already.
127
     * or allocate new one if it does not exist already.
119
     */
128
     */
120
    rwlock_read_lock(&futex_ht_lock);
129
    rwlock_read_lock(&futex_ht_lock);
Line 146... Line 155...
146
            hash_table_insert(&futex_ht, &paddr, &futex->ht_link);
155
            hash_table_insert(&futex_ht, &paddr, &futex->ht_link);
147
            rwlock_write_unlock(&futex_ht_lock);
156
            rwlock_write_unlock(&futex_ht_lock);
148
        }
157
        }
149
    }
158
    }
150
   
159
   
151
    return (__native) waitq_sleep(&futex->wq);
160
    return (__native) waitq_sleep_timeout(&futex->wq, usec, trydown);
152
}
161
}
153
 
162
 
154
/** Wakeup one thread waiting in futex wait queue.
163
/** Wakeup one thread waiting in futex wait queue.
155
 *
164
 *
156
 * @param uaddr Userspace address of the futex counter.
165
 * @param uaddr Userspace address of the futex counter.
Line 162... Line 171...
162
{
171
{
163
    futex_t *futex = NULL;
172
    futex_t *futex = NULL;
164
    __address paddr;
173
    __address paddr;
165
    link_t *item;
174
    link_t *item;
166
    pte_t *t;
175
    pte_t *t;
-
 
176
    ipl_t ipl;
-
 
177
   
-
 
178
    ipl = interrupts_disable();
167
   
179
   
168
    /*
180
    /*
169
     * Find physical address of futex counter.
181
     * Find physical address of futex counter.
170
     */
182
     */
171
    page_table_lock(AS, true);
183
    page_table_lock(AS, true);
172
    t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
184
    t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
173
    if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
185
    if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
174
        page_table_unlock(AS, true);
186
        page_table_unlock(AS, true);
-
 
187
        interrupts_restore(ipl);
175
        return (__native) ENOENT;
188
        return (__native) ENOENT;
176
    }
189
    }
177
    paddr = PFN2ADDR(PTE_GET_FRAME(t)) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
190
    paddr = PFN2ADDR(PTE_GET_FRAME(t)) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
178
    page_table_unlock(AS, true);
191
    page_table_unlock(AS, true);
179
   
192
   
-
 
193
    interrupts_restore(ipl);
-
 
194
 
180
    /*
195
    /*
181
     * Find the respective futex structure.
196
     * Find the respective futex structure.
182
     */
197
     */
183
    rwlock_read_lock(&futex_ht_lock);
198
    rwlock_read_lock(&futex_ht_lock);
184
    item = hash_table_find(&futex_ht, &paddr);
199
    item = hash_table_find(&futex_ht, &paddr);
185
    if (item) {
200
    if (item) {
186
        futex = hash_table_get_instance(item, futex_t, ht_link);
201
        futex = hash_table_get_instance(item, futex_t, ht_link);
187
    }
202
    }
188
    rwlock_read_unlock(&futex_ht_lock);
203
    rwlock_read_unlock(&futex_ht_lock);
189
   
204
 
190
    if (!futex)
205
    if (!futex)
191
        return (__native) ENOENT;  
206
        return (__native) ENOENT;  
192
       
207
       
193
    waitq_wakeup(&futex->wq, WAKEUP_FIRST);
208
    waitq_wakeup(&futex->wq, WAKEUP_FIRST);
194
   
209