int main(int argc, char** argv) { #if defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) { pthread_mutex_t m = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; fprintf(stderr, "Recursive mutex (statically initialized).\n"); lock_twice(&m); pthread_mutex_destroy(&m); } #endif #if defined(HAVE_PTHREAD_MUTEX_RECURSIVE_NP) { pthread_mutex_t m; pthread_mutexattr_t attr; fprintf(stderr, "\nRecursive mutex (initialized via mutex attributes).\n"); pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); pthread_mutex_init(&m, &attr); pthread_mutexattr_destroy(&attr); lock_twice(&m); pthread_mutex_destroy(&m); } #endif #if defined(HAVE_PTHREAD_MUTEX_ERRORCHECK_NP) { pthread_mutex_t m; pthread_mutexattr_t attr; fprintf(stderr, "\nError checking mutex.\n"); pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); pthread_mutex_init(&m, &attr); pthread_mutexattr_destroy(&attr); lock_twice(&m); pthread_mutex_destroy(&m); } #endif { pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; fprintf(stderr, "\nNon-recursive mutex.\n"); lock_twice(&m); } fprintf(stderr, "\nDone.\n"); return 0; }
void erts_lc_lock_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 = make_my_locked_locks(); l_lck = new_locked_lock(lck, op_flags); if (!l_lcks->locked.last) { ASSERT(!l_lcks->locked.first); l_lcks->locked.last = l_lcks->locked.first = l_lck; } else if (l_lcks->locked.last->id < lck->id || (l_lcks->locked.last->id == lck->id && l_lcks->locked.last->extra < lck->extra)) { if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, l_lcks->locked.last->flags)) type_order_violation("locking ", l_lcks, lck); l_lck->prev = l_lcks->locked.last; l_lcks->locked.last->next = l_lck; l_lcks->locked.last = l_lck; } else if (l_lcks->locked.last->id == lck->id && l_lcks->locked.last->extra == lck->extra) lock_twice("Locking", l_lcks, lck, op_flags); else lock_order_violation(l_lcks, lck); }
void test_lock_twice() { boost::fibers::round_robin ds; boost::fibers::scheduling_algorithm( & ds); lock_twice(); }
void erts_lc_trylock_flg_x(int locked, erts_lc_lock_t *lck, Uint16 op_flags, char *file, unsigned int line) { 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 = make_my_locked_locks(); l_lck = locked ? new_locked_lock(lck, op_flags, file, line) : NULL; if (!l_lcks->locked.last) { ASSERT(!l_lcks->locked.first); if (locked) l_lcks->locked.first = l_lcks->locked.last = l_lck; } else { erts_lc_locked_lock_t *tl_lck; #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 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); if (locked) { l_lck->next = tl_lck->next; l_lck->prev = tl_lck; if (tl_lck->next) tl_lck->next->prev = l_lck; else l_lcks->locked.last = l_lck; tl_lck->next = l_lck; } return; } } if (locked) { l_lck->next = l_lcks->locked.first; l_lcks->locked.first->prev = l_lck; l_lcks->locked.first = l_lck; } } }
void erts_lc_trylock_flg_x(int locked, erts_lc_lock_t *lck, erts_lock_options_t options, char *file, unsigned int line) { lc_thread_t *thr; lc_locked_lock_t *ll; if (lck->inited != ERTS_LC_INITITALIZED) uninitialized_lock(); if (lck->id < 0) return; thr = make_my_locked_locks(); ll = locked ? new_locked_lock(thr, lck, options, file, line) : NULL; if (!thr->locked.last) { ASSERT(!thr->locked.first); if (locked) thr->locked.first = thr->locked.last = ll; } else { lc_locked_lock_t *tl_lck; #if 0 /* Ok when trylocking I guess... */ if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, thr->locked.last->flags)) type_order_violation("trylocking ", thr, lck); #endif for (tl_lck = thr->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 && lck->check_order) lock_twice("Trylocking", thr, lck, options); if (locked) { ll->next = tl_lck->next; ll->prev = tl_lck; if (tl_lck->next) tl_lck->next->prev = ll; else thr->locked.last = ll; tl_lck->next = ll; } return; } } if (locked) { ll->next = thr->locked.first; thr->locked.first->prev = ll; thr->locked.first = ll; } } }
void erts_lc_lock_flg_x(erts_lc_lock_t *lck, erts_lock_options_t options, char *file, unsigned int line) { lc_thread_t *thr; lc_locked_lock_t *new_ll; if (lck->inited != ERTS_LC_INITITALIZED) uninitialized_lock(); if (lck->id < 0) return; thr = make_my_locked_locks(); new_ll = new_locked_lock(thr, lck, options, file, line); if (!thr->locked.last) { ASSERT(!thr->locked.first); thr->locked.last = thr->locked.first = new_ll; ASSERT(0 < lck->id && lck->id < ERTS_LOCK_ORDER_SIZE); thr->matrix.m[lck->id][0] = 1; } else if (( ! lck->check_order && thr->locked.last->id == lck->id) || (thr->locked.last->id < lck->id || (thr->locked.last->id == lck->id && thr->locked.last->extra < lck->extra))) { lc_locked_lock_t* ll; if (LOCK_IS_TYPE_ORDER_VIOLATION(lck->flags, thr->locked.last->flags)) { type_order_violation("locking ", thr, lck); } ASSERT(0 < lck->id && lck->id < ERTS_LOCK_ORDER_SIZE); ll = thr->locked.last; thr->matrix.m[lck->id][ll->id] |= 1; for (ll = ll->prev; ll; ll = ll->prev) { ASSERT(0 < ll->id && ll->id < ERTS_LOCK_ORDER_SIZE); thr->matrix.m[lck->id][ll->id] |= 2; } new_ll->prev = thr->locked.last; thr->locked.last->next = new_ll; thr->locked.last = new_ll; } else if (thr->locked.last->id == lck->id && thr->locked.last->extra == lck->extra) lock_twice("Locking", thr, lck, options); else lock_order_violation(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 }
void test_lock_twice() { lock_twice(); }