Changeset 89c57b6 in mainline for uspace/lib/c/generic/fibril_synch.c
- Timestamp:
- 2011-04-13T14:45:41Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 88634420
- Parents:
- cefb126 (diff), 17279ead (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
rcefb126 r89c57b6 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> … … 42 41 #include <errno.h> 43 42 #include <assert.h> 43 #include <stacktrace.h> 44 #include <stdlib.h> 45 #include "private/async.h" 44 46 45 47 static void optimize_execution_power(void) … … 53 55 */ 54 56 if (atomic_get(&threads_in_ipc_wait) > 0) 55 ipc_poke(); 56 } 57 async_poke(); 58 } 59 60 static void print_deadlock(fibril_owner_info_t *oi) 61 { 62 fibril_t *f = (fibril_t *) fibril_get_id(); 63 64 printf("Deadlock detected.\n"); 65 stacktrace_print(); 66 67 printf("Fibril %p waits for primitive %p.\n", f, oi); 68 69 while (oi && oi->owned_by) { 70 printf("Primitive %p is owned by fibril %p.\n", 71 oi, oi->owned_by); 72 if (oi->owned_by == f) 73 break; 74 stacktrace_print_fp_pc(context_get_fp(&oi->owned_by->ctx), 75 oi->owned_by->ctx.pc); 76 printf("Fibril %p waits for primitive %p.\n", 77 oi->owned_by, oi->owned_by->waits_for); 78 oi = oi->owned_by->waits_for; 79 } 80 } 81 82 83 static void check_for_deadlock(fibril_owner_info_t *oi) 84 { 85 while (oi && oi->owned_by) { 86 if (oi->owned_by == (fibril_t *) fibril_get_id()) { 87 print_deadlock(oi); 88 abort(); 89 } 90 oi = oi->owned_by->waits_for; 91 } 92 } 93 57 94 58 95 void fibril_mutex_initialize(fibril_mutex_t *fm) 59 96 { 97 fm->oi.owned_by = NULL; 60 98 fm->counter = 1; 61 99 list_initialize(&fm->waiters); … … 64 102 void fibril_mutex_lock(fibril_mutex_t *fm) 65 103 { 104 fibril_t *f = (fibril_t *) fibril_get_id(); 105 106 if (fibril_get_sercount() != 0) 107 abort(); 108 66 109 futex_down(&async_futex); 67 110 if (fm->counter-- <= 0) { … … 73 116 link_initialize(&wdata.wu_event.link); 74 117 list_append(&wdata.wu_event.link, &fm->waiters); 118 check_for_deadlock(&fm->oi); 119 f->waits_for = &fm->oi; 75 120 fibril_switch(FIBRIL_TO_MANAGER); 76 121 } else { 122 fm->oi.owned_by = f; 77 123 futex_up(&async_futex); 78 124 } … … 86 132 if (fm->counter > 0) { 87 133 fm->counter--; 134 fm->oi.owned_by = (fibril_t *) fibril_get_id(); 88 135 locked = true; 89 136 } … … 95 142 static void _fibril_mutex_unlock_unsafe(fibril_mutex_t *fm) 96 143 { 97 assert(fm->counter <= 0);98 144 if (fm->counter++ < 0) { 99 145 link_t *tmp; 100 146 awaiter_t *wdp; 147 fibril_t *f; 101 148 102 149 assert(!list_empty(&fm->waiters)); … … 105 152 wdp->active = true; 106 153 wdp->wu_event.inlist = false; 154 155 f = (fibril_t *) wdp->fid; 156 fm->oi.owned_by = f; 157 f->waits_for = NULL; 158 107 159 list_remove(&wdp->wu_event.link); 108 160 fibril_add_ready(wdp->fid); 109 161 optimize_execution_power(); 162 } else { 163 fm->oi.owned_by = NULL; 110 164 } 111 165 } … … 113 167 void fibril_mutex_unlock(fibril_mutex_t *fm) 114 168 { 169 assert(fibril_mutex_is_locked(fm)); 115 170 futex_down(&async_futex); 116 171 _fibril_mutex_unlock_unsafe(fm); … … 118 173 } 119 174 175 bool fibril_mutex_is_locked(fibril_mutex_t *fm) 176 { 177 bool locked = false; 178 179 futex_down(&async_futex); 180 if (fm->counter <= 0) 181 locked = true; 182 futex_up(&async_futex); 183 184 return locked; 185 } 186 120 187 void fibril_rwlock_initialize(fibril_rwlock_t *frw) 121 188 { 189 frw->oi.owned_by = NULL; 122 190 frw->writers = 0; 123 191 frw->readers = 0; … … 127 195 void fibril_rwlock_read_lock(fibril_rwlock_t *frw) 128 196 { 197 fibril_t *f = (fibril_t *) fibril_get_id(); 198 199 if (fibril_get_sercount() != 0) 200 abort(); 201 129 202 futex_down(&async_futex); 130 203 if (frw->writers) { 131 fibril_t *f = (fibril_t *) fibril_get_id();132 204 awaiter_t wdata; 133 205 … … 138 210 f->flags &= ~FIBRIL_WRITER; 139 211 list_append(&wdata.wu_event.link, &frw->waiters); 212 check_for_deadlock(&frw->oi); 213 f->waits_for = &frw->oi; 140 214 fibril_switch(FIBRIL_TO_MANAGER); 141 215 } else { 142 frw->readers++; 216 /* Consider the first reader the owner. */ 217 if (frw->readers++ == 0) 218 frw->oi.owned_by = f; 143 219 futex_up(&async_futex); 144 220 } … … 147 223 void fibril_rwlock_write_lock(fibril_rwlock_t *frw) 148 224 { 225 fibril_t *f = (fibril_t *) fibril_get_id(); 226 227 if (fibril_get_sercount() != 0) 228 abort(); 229 149 230 futex_down(&async_futex); 150 231 if (frw->writers || frw->readers) { 151 fibril_t *f = (fibril_t *) fibril_get_id();152 232 awaiter_t wdata; 153 233 … … 158 238 f->flags |= FIBRIL_WRITER; 159 239 list_append(&wdata.wu_event.link, &frw->waiters); 240 check_for_deadlock(&frw->oi); 241 f->waits_for = &frw->oi; 160 242 fibril_switch(FIBRIL_TO_MANAGER); 161 243 } else { 244 frw->oi.owned_by = f; 162 245 frw->writers++; 163 246 futex_up(&async_futex); … … 168 251 { 169 252 futex_down(&async_futex); 170 assert(frw->readers || (frw->writers == 1));171 253 if (frw->readers) { 172 if (--frw->readers) 254 if (--frw->readers) { 255 if (frw->oi.owned_by == (fibril_t *) fibril_get_id()) { 256 /* 257 * If this reader firbril was considered the 258 * owner of this rwlock, clear the ownership 259 * information even if there are still more 260 * readers. 261 * 262 * This is the limitation of the detection 263 * mechanism rooted in the fact that tracking 264 * all readers would require dynamically 265 * allocated memory for keeping linkage info. 266 */ 267 frw->oi.owned_by = NULL; 268 } 173 269 goto out; 270 } 174 271 } else { 175 272 frw->writers--; … … 177 274 178 275 assert(!frw->readers && !frw->writers); 276 277 frw->oi.owned_by = NULL; 179 278 180 279 while (!list_empty(&frw->waiters)) { … … 185 284 wdp = list_get_instance(tmp, awaiter_t, wu_event.link); 186 285 f = (fibril_t *) wdp->fid; 286 287 f->waits_for = NULL; 187 288 188 289 if (f->flags & FIBRIL_WRITER) { … … 194 295 fibril_add_ready(wdp->fid); 195 296 frw->writers++; 297 frw->oi.owned_by = f; 196 298 optimize_execution_power(); 197 299 break; … … 201 303 list_remove(&wdp->wu_event.link); 202 304 fibril_add_ready(wdp->fid); 203 frw->readers++; 305 if (frw->readers++ == 0) { 306 /* Consider the first reader the owner. */ 307 frw->oi.owned_by = f; 308 } 204 309 optimize_execution_power(); 205 310 } … … 211 316 void fibril_rwlock_read_unlock(fibril_rwlock_t *frw) 212 317 { 318 assert(fibril_rwlock_is_read_locked(frw)); 213 319 _fibril_rwlock_common_unlock(frw); 214 320 } … … 216 322 void fibril_rwlock_write_unlock(fibril_rwlock_t *frw) 217 323 { 324 assert(fibril_rwlock_is_write_locked(frw)); 218 325 _fibril_rwlock_common_unlock(frw); 326 } 327 328 bool fibril_rwlock_is_read_locked(fibril_rwlock_t *frw) 329 { 330 bool locked = false; 331 332 futex_down(&async_futex); 333 if (frw->readers) 334 locked = true; 335 futex_up(&async_futex); 336 337 return locked; 338 } 339 340 bool fibril_rwlock_is_write_locked(fibril_rwlock_t *frw) 341 { 342 bool locked = false; 343 344 futex_down(&async_futex); 345 if (frw->writers) { 346 assert(frw->writers == 1); 347 locked = true; 348 } 349 futex_up(&async_futex); 350 351 return locked; 352 } 353 354 bool fibril_rwlock_is_locked(fibril_rwlock_t *frw) 355 { 356 return fibril_rwlock_is_read_locked(frw) || 357 fibril_rwlock_is_write_locked(frw); 219 358 } 220 359 … … 229 368 { 230 369 awaiter_t wdata; 370 371 assert(fibril_mutex_is_locked(fm)); 231 372 232 373 if (timeout < 0)
Note:
See TracChangeset
for help on using the changeset viewer.