/** check if OK, free struct */ void checklock_destroy(enum check_lock_type type, struct checked_lock** lock, const char* func, const char* file, int line) { const size_t contention_interest = 1; /* promille contented locks */ struct checked_lock* e; if(!lock) return; e = *lock; if(!e) return; checktype(type, e, func, file, line); /* check if delete is OK */ acquire_locklock(e, func, file, line); if(e->hold_count != 0) lock_error(e, func, file, line, "delete while locked."); if(e->wait_count != 0) lock_error(e, func, file, line, "delete while waited on."); prot_check(e, func, file, line); *lock = NULL; /* use after free will fail */ LOCKRET(pthread_mutex_unlock(&e->lock)); /* contention, look at fraction in trouble. */ if(e->history_count > 1 && 1000*e->contention_count/e->history_count > contention_interest) { log_info("lock created %s %s %d has contention %u of %u (%d%%)", e->create_func, e->create_file, e->create_line, (unsigned int)e->contention_count, (unsigned int)e->history_count, (int)(100*e->contention_count/e->history_count)); } /* delete it */ LOCKRET(pthread_mutex_destroy(&e->lock)); prot_clear(e); /* since nobody holds the lock - see check above, no need to unlink * from the thread-held locks list. */ switch(e->type) { case check_lock_mutex: LOCKRET(pthread_mutex_destroy(&e->u.mutex)); break; case check_lock_spinlock: LOCKRET(pthread_spin_destroy(&e->u.spinlock)); break; case check_lock_rwlock: LOCKRET(pthread_rwlock_destroy(&e->u.rwlock)); break; default: log_assert(0); } memset(e, 0, sizeof(struct checked_lock)); free(e); }
/** * Locks the mutex, blocks if already locked. * * If a different thread already locked this mutex, the calling * thread will block. If the same thread tries to lock a mutex * it already owns, the behavior is undefined. * * @throw lock_error when an error occurs, this includes all * system related errors with the underlying implementation of * the mutex. */ void lock() { PMEMobjpool *pop = pmemobj_pool_by_ptr(this); if (int ret = pmemobj_mutex_lock(pop, &this->plock)) throw lock_error(ret, std::system_category(), "Failed to lock a mutex."); }
std::cv_status wait_until_impl( mutex &lock, const std::chrono::time_point<Clock, Duration> &abs_timeout) { PMEMobjpool *pop = pmemobj_pool_by_ptr(this); /* convert to my clock */ const typename Clock::time_point their_now = Clock::now(); const clock_type::time_point my_now = clock_type::now(); const auto delta = abs_timeout - their_now; const auto my_rel = my_now + delta; struct timespec ts = detail::timepoint_to_timespec(my_rel); auto ret = pmemobj_cond_timedwait(pop, &this->pcond, lock.native_handle(), &ts); if (ret == 0) return std::cv_status::no_timeout; else if (ret == ETIMEDOUT) return std::cv_status::timeout; else throw lock_error(ret, std::system_category(), "Error waiting on a condition " "variable."); }
/** * Obtain lock on debug lock structure. This could be a deadlock by the caller. * The debug code itself does not deadlock. Anyway, check with timeouts. * @param lock: on what to acquire lock. * @param func: user level caller identification. * @param file: user level caller identification. * @param line: user level caller identification. */ static void acquire_locklock(struct checked_lock* lock, const char* func, const char* file, int line) { struct timespec to; int err; int contend = 0; /* first try; inc contention counter if not immediately */ if((err = pthread_mutex_trylock(&lock->lock))) { if(err==EBUSY) contend++; else fatal_exit("error in mutex_trylock: %s", strerror(err)); } if(!err) return; /* immediate success */ to.tv_sec = time(NULL) + CHECK_LOCK_TIMEOUT; to.tv_nsec = 0; err = pthread_mutex_timedlock(&lock->lock, &to); if(err) { log_err("in acquiring locklock: %s", strerror(err)); lock_error(lock, func, file, line, "acquire locklock"); } /* since we hold the lock, we can edit the contention_count */ lock->contention_count += contend; }
bool timed_wait(L& lock, const xtime& xt) { if (!lock) throw lock_error(); return do_timed_wait(lock.m_mutex, xt); }
void wait(L& lock) { if (!lock) throw lock_error(); do_wait(lock.m_mutex); }
void lock() { int const res=pthread_mutex_lock(&m); if(res) { boost::throw_exception(lock_error(res)); } }
void wait(L& lock, Pr pred) { if (!lock) throw lock_error(); while (!pred()) do_wait(lock.m_mutex); }
void wait( unique_lock< mutex > & lk, Pred pred) { if ( ! lk) throw lock_error(); while ( ! pred() ) wait( * lk.mutex() ); }
/** * Notify and unblock one thread waiting on `*this` condition. * * Does nothing when no threads are waiting. It is unspecified * which thread is selected for unblocking. * * @throw lock_error when the signal fails on the #pcond. */ void notify_one() { PMEMobjpool *pop = pmemobj_pool_by_ptr(this); if (int ret = pmemobj_cond_signal(pop, &this->pcond)) throw lock_error(ret, std::system_category(), "Error notifying one on " "a condition variable."); }
bool try_lock() { int const res=pthread_mutex_trylock(&m); if(res && (res!=EBUSY)) { boost::throw_exception(lock_error(res)); } return !res; }
/** * Internal implementation of the wait call. */ void wait_impl(mutex &lock) { PMEMobjpool *pop = pmemobj_pool_by_ptr(this); if (int ret = pmemobj_cond_wait(pop, &this->pcond, lock.native_handle())) throw lock_error(ret, std::system_category(), "Error waiting on a condition " "variable."); }
/** check if type is OK for the lock given */ static void checktype(enum check_lock_type type, struct checked_lock* lock, const char* func, const char* file, int line) { if(!lock) fatal_exit("use of null/deleted lock at %s %s:%d", func, file, line); if(type != lock->type) { lock_error(lock, func, file, line, "wrong lock type"); } }
/** * Default constructor. * * @throw lock_error when the condition_variable is not from persistent * memory. */ condition_variable() { PMEMobjpool *pop; if ((pop = pmemobj_pool_by_ptr(&pcond)) == nullptr) throw lock_error( 1, std::generic_category(), "Persistent condition variable not from" " persistent memory."); pmemobj_cond_zero(pop, &pcond); }
void lock() { int res; do { res = pthread_mutex_lock(&m); } while (res == EINTR); if (res) { boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock")); } }
bool timed_wait(L& lock, const xtime& xt, Pr pred) { if (!lock) throw lock_error(); while (!pred()) { if (!do_timed_wait(lock.m_mutex, xt)) return false; } return true; }
/** * Tries to lock the mutex, returns regardless if the lock * succeeds. * * Returns `true` if locking succeeded, false otherwise. If * the same thread tries to lock a mutex it already owns, * the behavior is undefined. * * @return `true` on successful lock acquisition, `false` * otherwise. * * @throw lock_error when an error occurs, this includes all * system related errors with the underlying implementation of * the mutex. */ bool try_lock() { PMEMobjpool *pop = pmemobj_pool_by_ptr(this); int ret = pmemobj_mutex_trylock(pop, &this->plock); if (ret == 0) return true; else if (ret == EBUSY) return false; else throw lock_error(ret, std::system_category(), "Failed to lock a mutex."); }
/** * Locking routine. * @param type: as passed by user. * @param lock: as passed by user. * @param func: caller location. * @param file: caller location. * @param line: caller location. * @param tryfunc: the pthread_mutex_trylock or similar function. * @param timedfunc: the pthread_mutex_timedlock or similar function. * Uses absolute timeout value. * @param arg: what to pass to tryfunc and timedlock. * @param exclusive: if lock must be exclusive (only one allowed). * @param getwr: if attempts to get writelock (or readlock) for rwlocks. */ static void checklock_lockit(enum check_lock_type type, struct checked_lock* lock, const char* func, const char* file, int line, int (*tryfunc)(void*), int (*timedfunc)(void*, struct timespec*), void* arg, int exclusive, int getwr) { int err; int contend = 0; struct thr_check *thr = (struct thr_check*)pthread_getspecific( thr_debug_key); checktype(type, lock, func, file, line); if(!thr) lock_error(lock, func, file, line, "no thread info"); acquire_locklock(lock, func, file, line); lock->wait_count ++; thr->waiting = lock; if(exclusive && lock->hold_count > 0 && lock->holder == thr) lock_error(lock, func, file, line, "thread already owns lock"); if(type==check_lock_rwlock && getwr && lock->writeholder == thr) lock_error(lock, func, file, line, "thread already has wrlock"); LOCKRET(pthread_mutex_unlock(&lock->lock)); /* first try; if busy increase contention counter */ if((err=tryfunc(arg))) { struct timespec to; if(err != EBUSY) log_err("trylock: %s", strerror(err)); to.tv_sec = time(NULL) + CHECK_LOCK_TIMEOUT; to.tv_nsec = 0; if((err=timedfunc(arg, &to))) { if(err == ETIMEDOUT) lock_error(lock, func, file, line, "timeout possible deadlock"); log_err("timedlock: %s", strerror(err)); } contend ++; } /* got the lock */ acquire_locklock(lock, func, file, line); lock->contention_count += contend; lock->history_count++; if(exclusive && lock->hold_count > 0) lock_error(lock, func, file, line, "got nonexclusive lock"); if(type==check_lock_rwlock && getwr && lock->writeholder) lock_error(lock, func, file, line, "got nonexclusive wrlock"); if(type==check_lock_rwlock && getwr) lock->writeholder = thr; /* check the memory areas for unauthorized changes, * between last unlock time and current lock time. * we check while holding the lock (threadsafe). */ if(getwr || exclusive) prot_check(lock, func, file, line); finish_acquire_lock(thr, lock, func, file, line); LOCKRET(pthread_mutex_unlock(&lock->lock)); }
/** * Check protected memory region. Memory compare. Exit on error. * @param lock: which lock to check. * @param func: location we are now (when failure is detected). * @param file: location we are now (when failure is detected). * @param line: location we are now (when failure is detected). */ static void prot_check(struct checked_lock* lock, const char* func, const char* file, int line) { struct protected_area* p = lock->prot; while(p) { if(memcmp(p->hold, p->region, p->size) != 0) { log_hex("memory prev", p->hold, p->size); log_hex("memory here", p->region, p->size); lock_error(lock, func, file, line, "protected area modified"); } p = p->next; } }
void reception::start_scan () { scan_thread = new reception_thread(frontendfd , adapter_edit->text ().toStdString () , frontend_edit->text ().toStdString ()); scan_thread->start (); QObject::connect(this, SIGNAL(lock_frequency (unsigned int)), scan_thread , SLOT(lock_frequency(unsigned int)), Qt::QueuedConnection); QObject::connect(scan_thread, SIGNAL(lock_error_signal()), this , SLOT(lock_error()), Qt::QueuedConnection); QObject::connect(scan_thread, SIGNAL(network_found(std::string, unsigned int)), this , SLOT(network_found(std::string, unsigned int)), Qt::QueuedConnection); QObject::connect(scan_thread, SIGNAL(lock_end_signal()), this , SLOT(lock_end()), Qt::QueuedConnection); Q_EMIT lock_frequency(frequencies[current_frequency_index]); }
void recursive_mutex::unlock() { context * active_ctx = context::active(); detail::spinlock_lock lk( wait_queue_splk_); if ( BOOST_UNLIKELY( active_ctx != owner_) ) { throw lock_error( std::make_error_code( std::errc::operation_not_permitted), "boost fiber: no privilege to perform the operation"); } if ( 0 == --count_) { owner_ = nullptr; if ( ! wait_queue_.empty() ) { context * ctx = & wait_queue_.front(); wait_queue_.pop_front(); active_ctx->schedule( ctx); } } }
void recursive_timed_mutex::unlock() { context * ctx = context::active(); detail::spinlock_lock lk( wait_queue_splk_); if ( ctx != owner_) { throw lock_error( std::make_error_code( std::errc::operation_not_permitted), "boost fiber: no privilege to perform the operation"); } if ( 0 == --count_) { if ( ! wait_queue_.empty() ) { context * ctx = & wait_queue_.front(); wait_queue_.pop_front(); owner_ = ctx; count_ = 1; context::active()->set_ready( ctx); } else { owner_ = nullptr; return; } } }
bool timedlock_impl(const std::chrono::time_point<Clock, Duration> &abs_time) { PMEMobjpool *pop = pmemobj_pool_by_ptr(this); /* convert to my clock */ const typename Clock::time_point their_now = Clock::now(); const clock_type::time_point my_now = clock_type::now(); const auto delta = abs_time - their_now; const auto my_abs = my_now + delta; struct timespec ts = detail::timepoint_to_timespec(my_abs); auto ret = pmemobj_mutex_timedlock(pop, &this->plock, &ts); if (ret == 0) return true; else if (ret == ETIMEDOUT) return false; else throw lock_error(ret, std::system_category(), "Failed to lock a mutex"); }
/*---------------------------------------------------------------------+ | lock_file () | | ==================================================================== | | | | Function: ... | | | +---------------------------------------------------------------------*/ int lock_file(int fd, short lock_type, char *file) { int lock_attempt = 1; int lock_mode; #ifdef DEBUG lock_mode = F_SETLK; /* return if lock fails */ #else lock_mode = F_SETLKW; /* set lock and use system wait */ #endif /* file segment locking set data type flock - information * passed to system by user -- * l_whence: starting point of relative offset of file * l_start: defines relative offset in bytes from l_whence * l_len: number of consecutive bytes to be locked */ flock_ptr->l_whence = 0; flock_ptr->l_start = 0; flock_ptr->l_len = 0; flock_ptr->l_type = lock_type; while (fcntl(fd, lock_mode, flock_ptr) == -1) { if (lock_error(fd, file)) { sleep(NAPTIME); if (++lock_attempt > MAX_TRIES) { printf ("ERROR: max lock attempts of %d reached\n", MAX_TRIES); return (0); } } else return (0); } return (1); }
/** * @Requires mtx_ */ Stream& get() const { BOOST_THREAD_ASSERT_PRECONDITION( mtx_, lock_error() ); return mtx_->get(*this); }
bool try_lock() { if (m_locked) throw lock_error(); return (m_locked = lock_ops<TimedMutex>::trylock(m_mutex)); }
bool timed_lock(const xtime& xt) { if (m_locked) throw lock_error(); return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt)); }
void lock() { if (m_locked) throw lock_error(); lock_ops<Mutex>::lock(m_mutex); m_locked = true; }
void unlock() { if (!m_locked) throw lock_error(); lock_ops<Mutex>::unlock(m_mutex); m_locked = false; }
void wait( unique_lock< mutex > & lk) { if ( ! lk) throw lock_error(); wait( * lk.mutex() ); }