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 |