Rev 1757 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1757 | Rev 1780 | ||
|---|---|---|---|
| Line 56... | Line 56... | ||
| 56 | 56 | ||
| 57 | #define FUTEX_HT_SIZE 1024 /* keep it a power of 2 */ |
57 | #define FUTEX_HT_SIZE 1024 /* keep it a power of 2 */ |
| 58 | 58 | ||
| 59 | static void futex_initialize(futex_t *futex); |
59 | static void futex_initialize(futex_t *futex); |
| 60 | 60 | ||
| 61 | static futex_t *futex_find(__address paddr); |
61 | static futex_t *futex_find(uintptr_t paddr); |
| 62 | static index_t futex_ht_hash(__native *key); |
62 | static index_t futex_ht_hash(unative_t *key); |
| 63 | static bool futex_ht_compare(__native *key, count_t keys, link_t *item); |
63 | static bool futex_ht_compare(unative_t *key, count_t keys, link_t *item); |
| 64 | static void futex_ht_remove_callback(link_t *item); |
64 | static void futex_ht_remove_callback(link_t *item); |
| 65 | 65 | ||
| 66 | /** |
66 | /** |
| 67 | * Read-write lock protecting global futex hash table. |
67 | * Read-write lock protecting global futex hash table. |
| 68 | * It is also used to serialize access to all futex_t structures. |
68 | * It is also used to serialize access to all futex_t structures. |
| Line 106... | Line 106... | ||
| 106 | * @param flags Select mode of operation. |
106 | * @param flags Select mode of operation. |
| 107 | * |
107 | * |
| 108 | * @return One of ESYNCH_TIMEOUT, ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED. See synch.h. |
108 | * @return One of ESYNCH_TIMEOUT, ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED. See synch.h. |
| 109 | * If there is no physical mapping for uaddr ENOENT is returned. |
109 | * If there is no physical mapping for uaddr ENOENT is returned. |
| 110 | */ |
110 | */ |
| 111 | __native sys_futex_sleep_timeout(__address uaddr, __u32 usec, int flags) |
111 | unative_t sys_futex_sleep_timeout(uintptr_t uaddr, uint32_t usec, int flags) |
| 112 | { |
112 | { |
| 113 | futex_t *futex; |
113 | futex_t *futex; |
| 114 | __address paddr; |
114 | uintptr_t paddr; |
| 115 | pte_t *t; |
115 | pte_t *t; |
| 116 | ipl_t ipl; |
116 | ipl_t ipl; |
| 117 | 117 | ||
| 118 | ipl = interrupts_disable(); |
118 | ipl = interrupts_disable(); |
| 119 | 119 | ||
| Line 123... | Line 123... | ||
| 123 | page_table_lock(AS, true); |
123 | page_table_lock(AS, true); |
| 124 | t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE)); |
124 | t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE)); |
| 125 | if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) { |
125 | if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) { |
| 126 | page_table_unlock(AS, true); |
126 | page_table_unlock(AS, true); |
| 127 | interrupts_restore(ipl); |
127 | interrupts_restore(ipl); |
| 128 | return (__native) ENOENT; |
128 | return (unative_t) ENOENT; |
| 129 | } |
129 | } |
| 130 | paddr = PTE_GET_FRAME(t) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE)); |
130 | paddr = PTE_GET_FRAME(t) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE)); |
| 131 | page_table_unlock(AS, true); |
131 | page_table_unlock(AS, true); |
| 132 | 132 | ||
| 133 | interrupts_restore(ipl); |
133 | interrupts_restore(ipl); |
| 134 | 134 | ||
| 135 | futex = futex_find(paddr); |
135 | futex = futex_find(paddr); |
| 136 | 136 | ||
| 137 | return (__native) waitq_sleep_timeout(&futex->wq, usec, flags | SYNCH_FLAGS_INTERRUPTIBLE); |
137 | return (unative_t) waitq_sleep_timeout(&futex->wq, usec, flags | SYNCH_FLAGS_INTERRUPTIBLE); |
| 138 | } |
138 | } |
| 139 | 139 | ||
| 140 | /** Wakeup one thread waiting in futex wait queue. |
140 | /** Wakeup one thread waiting in futex wait queue. |
| 141 | * |
141 | * |
| 142 | * @param uaddr Userspace address of the futex counter. |
142 | * @param uaddr Userspace address of the futex counter. |
| 143 | * |
143 | * |
| 144 | * @return ENOENT if there is no physical mapping for uaddr. |
144 | * @return ENOENT if there is no physical mapping for uaddr. |
| 145 | */ |
145 | */ |
| 146 | __native sys_futex_wakeup(__address uaddr) |
146 | unative_t sys_futex_wakeup(uintptr_t uaddr) |
| 147 | { |
147 | { |
| 148 | futex_t *futex; |
148 | futex_t *futex; |
| 149 | __address paddr; |
149 | uintptr_t paddr; |
| 150 | pte_t *t; |
150 | pte_t *t; |
| 151 | ipl_t ipl; |
151 | ipl_t ipl; |
| 152 | 152 | ||
| 153 | ipl = interrupts_disable(); |
153 | ipl = interrupts_disable(); |
| 154 | 154 | ||
| Line 158... | Line 158... | ||
| 158 | page_table_lock(AS, true); |
158 | page_table_lock(AS, true); |
| 159 | t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE)); |
159 | t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE)); |
| 160 | if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) { |
160 | if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) { |
| 161 | page_table_unlock(AS, true); |
161 | page_table_unlock(AS, true); |
| 162 | interrupts_restore(ipl); |
162 | interrupts_restore(ipl); |
| 163 | return (__native) ENOENT; |
163 | return (unative_t) ENOENT; |
| 164 | } |
164 | } |
| 165 | paddr = PTE_GET_FRAME(t) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE)); |
165 | paddr = PTE_GET_FRAME(t) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE)); |
| 166 | page_table_unlock(AS, true); |
166 | page_table_unlock(AS, true); |
| 167 | 167 | ||
| 168 | interrupts_restore(ipl); |
168 | interrupts_restore(ipl); |
| Line 180... | Line 180... | ||
| 180 | * |
180 | * |
| 181 | * @param paddr Physical address of the userspace futex counter. |
181 | * @param paddr Physical address of the userspace futex counter. |
| 182 | * |
182 | * |
| 183 | * @return Address of the kernel futex structure. |
183 | * @return Address of the kernel futex structure. |
| 184 | */ |
184 | */ |
| 185 | futex_t *futex_find(__address paddr) |
185 | futex_t *futex_find(uintptr_t paddr) |
| 186 | { |
186 | { |
| 187 | link_t *item; |
187 | link_t *item; |
| 188 | futex_t *futex; |
188 | futex_t *futex; |
| 189 | btree_node_t *leaf; |
189 | btree_node_t *leaf; |
| 190 | 190 | ||
| Line 273... | Line 273... | ||
| 273 | * |
273 | * |
| 274 | * @param key Address where the key (i.e. physical address of futex counter) is stored. |
274 | * @param key Address where the key (i.e. physical address of futex counter) is stored. |
| 275 | * |
275 | * |
| 276 | * @return Index into futex hash table. |
276 | * @return Index into futex hash table. |
| 277 | */ |
277 | */ |
| 278 | index_t futex_ht_hash(__native *key) |
278 | index_t futex_ht_hash(unative_t *key) |
| 279 | { |
279 | { |
| 280 | return *key & (FUTEX_HT_SIZE-1); |
280 | return *key & (FUTEX_HT_SIZE-1); |
| 281 | } |
281 | } |
| 282 | 282 | ||
| 283 | /** Compare futex hash table item with a key. |
283 | /** Compare futex hash table item with a key. |
| 284 | * |
284 | * |
| 285 | * @param key Address where the key (i.e. physical address of futex counter) is stored. |
285 | * @param key Address where the key (i.e. physical address of futex counter) is stored. |
| 286 | * |
286 | * |
| 287 | * @return True if the item matches the key. False otherwise. |
287 | * @return True if the item matches the key. False otherwise. |
| 288 | */ |
288 | */ |
| 289 | bool futex_ht_compare(__native *key, count_t keys, link_t *item) |
289 | bool futex_ht_compare(unative_t *key, count_t keys, link_t *item) |
| 290 | { |
290 | { |
| 291 | futex_t *futex; |
291 | futex_t *futex; |
| 292 | 292 | ||
| 293 | ASSERT(keys == 1); |
293 | ASSERT(keys == 1); |
| 294 | 294 | ||
| Line 321... | Line 321... | ||
| 321 | int i; |
321 | int i; |
| 322 | 322 | ||
| 323 | node = list_get_instance(cur, btree_node_t, leaf_link); |
323 | node = list_get_instance(cur, btree_node_t, leaf_link); |
| 324 | for (i = 0; i < node->keys; i++) { |
324 | for (i = 0; i < node->keys; i++) { |
| 325 | futex_t *ftx; |
325 | futex_t *ftx; |
| 326 | __address paddr = node->key[i]; |
326 | uintptr_t paddr = node->key[i]; |
| 327 | 327 | ||
| 328 | ftx = (futex_t *) node->value[i]; |
328 | ftx = (futex_t *) node->value[i]; |
| 329 | if (--ftx->refcount == 0) |
329 | if (--ftx->refcount == 0) |
| 330 | hash_table_remove(&futex_ht, &paddr, 1); |
330 | hash_table_remove(&futex_ht, &paddr, 1); |
| 331 | } |
331 | } |