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 | ||