Changeset b5e68c8 in mainline for uspace/lib/c/generic/fibril_synch.c
- Timestamp:
- 2011-05-12T16:49:44Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f36787d7
- Parents:
- e80329d6 (diff), 750636a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/fibril_synch.c
re80329d6 rb5e68c8 36 36 #include <fibril.h> 37 37 #include <async.h> 38 #include <async_priv.h>39 38 #include <adt/list.h> 40 39 #include <futex.h> … … 44 43 #include <stacktrace.h> 45 44 #include <stdlib.h> 45 #include <stdio.h> 46 #include "private/async.h" 46 47 47 48 static void optimize_execution_power(void) … … 55 56 */ 56 57 if (atomic_get(&threads_in_ipc_wait) > 0) 57 ipc_poke(); 58 } 59 60 static bool check_for_deadlock(fibril_owner_info_t *oi) 61 { 62 while (oi && oi->owned_by) { 63 if (oi->owned_by == (fibril_t *) fibril_get_id()) 64 return true; 65 oi = oi->owned_by->waits_for; 66 } 67 68 return false; 58 async_poke(); 69 59 } 70 60 … … 89 79 oi = oi->owned_by->waits_for; 90 80 } 91 92 abort(); 93 } 81 } 82 83 84 static void check_for_deadlock(fibril_owner_info_t *oi) 85 { 86 while (oi && oi->owned_by) { 87 if (oi->owned_by == (fibril_t *) fibril_get_id()) { 88 print_deadlock(oi); 89 abort(); 90 } 91 oi = oi->owned_by->waits_for; 92 } 93 } 94 94 95 95 96 void fibril_mutex_initialize(fibril_mutex_t *fm) … … 103 104 { 104 105 fibril_t *f = (fibril_t *) fibril_get_id(); 106 107 if (fibril_get_sercount() != 0) 108 abort(); 105 109 106 110 futex_down(&async_futex); … … 113 117 link_initialize(&wdata.wu_event.link); 114 118 list_append(&wdata.wu_event.link, &fm->waiters); 115 116 if (check_for_deadlock(&fm->oi)) 117 print_deadlock(&fm->oi); 119 check_for_deadlock(&fm->oi); 118 120 f->waits_for = &fm->oi; 119 120 121 fibril_switch(FIBRIL_TO_MANAGER); 121 122 } else { … … 142 143 static void _fibril_mutex_unlock_unsafe(fibril_mutex_t *fm) 143 144 { 144 assert(fm->counter <= 0);145 145 if (fm->counter++ < 0) { 146 146 link_t *tmp; … … 168 168 void fibril_mutex_unlock(fibril_mutex_t *fm) 169 169 { 170 assert(fibril_mutex_is_locked(fm)); 170 171 futex_down(&async_futex); 171 172 _fibril_mutex_unlock_unsafe(fm); 172 173 futex_up(&async_futex); 174 } 175 176 bool fibril_mutex_is_locked(fibril_mutex_t *fm) 177 { 178 bool locked = false; 179 180 futex_down(&async_futex); 181 if (fm->counter <= 0) 182 locked = true; 183 futex_up(&async_futex); 184 185 return locked; 173 186 } 174 187 … … 183 196 void fibril_rwlock_read_lock(fibril_rwlock_t *frw) 184 197 { 198 fibril_t *f = (fibril_t *) fibril_get_id(); 199 200 if (fibril_get_sercount() != 0) 201 abort(); 202 185 203 futex_down(&async_futex); 186 204 if (frw->writers) { 187 fibril_t *f = (fibril_t *) fibril_get_id();188 205 awaiter_t wdata; 189 206 … … 194 211 f->flags &= ~FIBRIL_WRITER; 195 212 list_append(&wdata.wu_event.link, &frw->waiters); 213 check_for_deadlock(&frw->oi); 214 f->waits_for = &frw->oi; 196 215 fibril_switch(FIBRIL_TO_MANAGER); 197 216 } else { 198 frw->readers++; 217 /* Consider the first reader the owner. */ 218 if (frw->readers++ == 0) 219 frw->oi.owned_by = f; 199 220 futex_up(&async_futex); 200 221 } … … 203 224 void fibril_rwlock_write_lock(fibril_rwlock_t *frw) 204 225 { 226 fibril_t *f = (fibril_t *) fibril_get_id(); 227 228 if (fibril_get_sercount() != 0) 229 abort(); 230 205 231 futex_down(&async_futex); 206 232 if (frw->writers || frw->readers) { 207 fibril_t *f = (fibril_t *) fibril_get_id();208 233 awaiter_t wdata; 209 234 … … 214 239 f->flags |= FIBRIL_WRITER; 215 240 list_append(&wdata.wu_event.link, &frw->waiters); 241 check_for_deadlock(&frw->oi); 242 f->waits_for = &frw->oi; 216 243 fibril_switch(FIBRIL_TO_MANAGER); 217 244 } else { 245 frw->oi.owned_by = f; 218 246 frw->writers++; 219 247 futex_up(&async_futex); … … 224 252 { 225 253 futex_down(&async_futex); 226 assert(frw->readers || (frw->writers == 1));227 254 if (frw->readers) { 228 if (--frw->readers) 255 if (--frw->readers) { 256 if (frw->oi.owned_by == (fibril_t *) fibril_get_id()) { 257 /* 258 * If this reader firbril was considered the 259 * owner of this rwlock, clear the ownership 260 * information even if there are still more 261 * readers. 262 * 263 * This is the limitation of the detection 264 * mechanism rooted in the fact that tracking 265 * all readers would require dynamically 266 * allocated memory for keeping linkage info. 267 */ 268 frw->oi.owned_by = NULL; 269 } 229 270 goto out; 271 } 230 272 } else { 231 273 frw->writers--; … … 233 275 234 276 assert(!frw->readers && !frw->writers); 277 278 frw->oi.owned_by = NULL; 235 279 236 280 while (!list_empty(&frw->waiters)) { … … 241 285 wdp = list_get_instance(tmp, awaiter_t, wu_event.link); 242 286 f = (fibril_t *) wdp->fid; 287 288 f->waits_for = NULL; 243 289 244 290 if (f->flags & FIBRIL_WRITER) { … … 250 296 fibril_add_ready(wdp->fid); 251 297 frw->writers++; 298 frw->oi.owned_by = f; 252 299 optimize_execution_power(); 253 300 break; … … 257 304 list_remove(&wdp->wu_event.link); 258 305 fibril_add_ready(wdp->fid); 259 frw->readers++; 306 if (frw->readers++ == 0) { 307 /* Consider the first reader the owner. */ 308 frw->oi.owned_by = f; 309 } 260 310 optimize_execution_power(); 261 311 } … … 267 317 void fibril_rwlock_read_unlock(fibril_rwlock_t *frw) 268 318 { 319 assert(fibril_rwlock_is_read_locked(frw)); 269 320 _fibril_rwlock_common_unlock(frw); 270 321 } … … 272 323 void fibril_rwlock_write_unlock(fibril_rwlock_t *frw) 273 324 { 325 assert(fibril_rwlock_is_write_locked(frw)); 274 326 _fibril_rwlock_common_unlock(frw); 327 } 328 329 bool fibril_rwlock_is_read_locked(fibril_rwlock_t *frw) 330 { 331 bool locked = false; 332 333 futex_down(&async_futex); 334 if (frw->readers) 335 locked = true; 336 futex_up(&async_futex); 337 338 return locked; 339 } 340 341 bool fibril_rwlock_is_write_locked(fibril_rwlock_t *frw) 342 { 343 bool locked = false; 344 345 futex_down(&async_futex); 346 if (frw->writers) { 347 assert(frw->writers == 1); 348 locked = true; 349 } 350 futex_up(&async_futex); 351 352 return locked; 353 } 354 355 bool fibril_rwlock_is_locked(fibril_rwlock_t *frw) 356 { 357 return fibril_rwlock_is_read_locked(frw) || 358 fibril_rwlock_is_write_locked(frw); 275 359 } 276 360 … … 285 369 { 286 370 awaiter_t wdata; 371 372 assert(fibril_mutex_is_locked(fm)); 287 373 288 374 if (timeout < 0)
Note:
See TracChangeset
for help on using the changeset viewer.