void erts_lc_unlock_flg(erts_lc_lock_t *lck, erts_lock_options_t options) { erts_lc_locked_locks_t *l_lcks; erts_lc_locked_lock_t *l_lck; if (lck->inited != ERTS_LC_INITITALIZED) uninitialized_lock(); if (lck->id < 0) return; l_lcks = get_my_locked_locks(); if (l_lcks) { l_lck = l_lcks->required.first; if (find_lock(&l_lck, lck)) unlock_of_required_lock(l_lcks, lck); } for (l_lck = l_lcks ? l_lcks->locked.last : NULL; l_lck; l_lck = l_lck->prev) { if (l_lck->id == lck->id && l_lck->extra == lck->extra) { if ((l_lck->taken_options & ERTS_LOCK_OPTIONS_RDWR) != options) unlock_op_mismatch(l_lcks, lck, options); if (l_lck->prev) l_lck->prev->next = l_lck->next; else l_lcks->locked.first = l_lck->next; if (l_lck->next) l_lck->next->prev = l_lck->prev; else l_lcks->locked.last = l_lck->prev; lc_free((void *) l_lck); return; } } unlock_of_not_locked(l_lcks, lck); }
void erts_lc_unlock_flg(erts_lc_lock_t *lck, erts_lock_options_t options) { lc_thread_t *thr; lc_locked_lock_t *ll; if (lck->inited != ERTS_LC_INITITALIZED) uninitialized_lock(); if (lck->id < 0) return; thr = get_my_locked_locks(); if (thr) { ll = thr->required.first; if (find_lock(&ll, lck)) unlock_of_required_lock(thr, lck); } for (ll = thr ? thr->locked.last : NULL; ll; ll = ll->prev) { if (ll->id == lck->id && ll->extra == lck->extra) { if ((ll->taken_options & ERTS_LOCK_OPTIONS_RDWR) != options) unlock_op_mismatch(thr, lck, options); if (ll->prev) ll->prev->next = ll->next; else thr->locked.first = ll->next; if (ll->next) ll->next->prev = ll->prev; else thr->locked.last = ll->prev; lc_free(thr, ll); return; } } unlock_of_not_locked(thr, lck); }
void erts_lc_might_unlock_flg(erts_lc_lock_t *lck, Uint16 op_flags) { erts_lc_locked_locks_t *l_lcks; erts_lc_locked_lock_t *l_lck; if (lck->inited != ERTS_LC_INITITALIZED) uninitialized_lock(); if (lck->id < 0) return; l_lcks = get_my_locked_locks(); if (l_lcks) { l_lck = l_lcks->required.first; if (find_lock(&l_lck, lck)) unlock_of_required_lock(l_lcks, lck); } l_lck = l_lcks->locked.first; if (!find_lock(&l_lck, lck)) unlock_of_not_locked(l_lcks, lck); }
void erts_lc_might_unlock_flg(erts_lc_lock_t *lck, erts_lock_options_t options) { lc_thread_t *thr; lc_locked_lock_t *ll; if (lck->inited != ERTS_LC_INITITALIZED) uninitialized_lock(); if (lck->id < 0) return; thr = get_my_locked_locks(); if (thr) { ll = thr->required.first; if (find_lock(&ll, lck)) unlock_of_required_lock(thr, lck); } ll = thr->locked.first; if (!find_lock(&ll, lck)) unlock_of_not_locked(thr, lck); }
int erts_lc_trylock_force_busy_flg(erts_lc_lock_t *lck, Uint16 op_flags) { #ifdef ERTS_LC_DO_NOT_FORCE_BUSY_TRYLOCK_ON_LOCK_ORDER_VIOLATION return 0; #else /* * Force busy trylock if locking doesn't follow lock order. * This in order to make sure that caller can handle * the situation without causing a lock order violation. */ erts_lc_locked_locks_t *l_lcks; if (lck->inited != ERTS_LC_INITITALIZED) uninitialized_lock(); if (lck->id < 0) return 0; l_lcks = get_my_locked_locks(); if (!l_lcks || !l_lcks->locked.first) { ASSERT(!l_lcks || !l_lcks->locked.last); return 0; } else { erts_lc_locked_lock_t *tl_lck; ASSERT(l_lcks->locked.last); #if 0 /* Ok when trylocking I guess... */ if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, l_lcks->locked.last->flags)) type_order_violation("trylocking ", l_lcks, lck); #endif if (l_lcks->locked.last->id < lck->id || (l_lcks->locked.last->id == lck->id && l_lcks->locked.last->extra < lck->extra)) return 0; /* * Lock order violation */ /* Check that we are not trying to lock this lock twice */ for (tl_lck = l_lcks->locked.last; tl_lck; tl_lck = tl_lck->prev) { if (tl_lck->id < lck->id || (tl_lck->id == lck->id && tl_lck->extra <= lck->extra)) { if (tl_lck->id == lck->id && tl_lck->extra == lck->extra) lock_twice("Trylocking", l_lcks, lck, op_flags); break; } } #ifndef ERTS_LC_ALLWAYS_FORCE_BUSY_TRYLOCK_ON_LOCK_ORDER_VIOLATION /* We only force busy if a lock order violation would occur and when on an even millisecond. */ { SysTimeval tv; sys_gettimeofday(&tv); if ((tv.tv_usec / 1000) & 1) return 0; } #endif return 1; } #endif }
int erts_lc_is_emu_thr(void) { erts_lc_locked_locks_t *l_lcks = get_my_locked_locks(); return l_lcks->emu_thread; }
/* * erts_lc_pll(): print locked locks... */ void erts_lc_pll(void) { print_curr_locks(get_my_locked_locks()); }
int erts_lc_is_emu_thr(void) { lc_thread_t *thr = get_my_locked_locks(); return thr->emu_thread; }