Skip to content
Snippets Groups Projects
lock.c 35.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • 						ast_reentrancy_lock(lt);
    
    						__dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
    
    						__ast_mutex_logger("%s line %d (%s): '%s' was locked  here.\n",
    								lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
    								lt->func[lt->reentrancy-1], name);
    
    						__dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
    
    						ast_reentrancy_unlock(lt);
    					}
    
    					reported_wait = wait_time;
    				}
    				usleep(200);
    			}
    		} while (res == EBUSY);
    	}
    #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
    	res = pthread_rwlock_wrlock(&t->lock);
    #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
    
    #ifdef DEBUG_THREADS
    
    		ast_reentrancy_lock(lt);
    		if (lt->reentrancy < AST_MAX_REENTRANCY) {
    			lt->file[lt->reentrancy] = filename;
    			lt->lineno[lt->reentrancy] = line;
    			lt->func[lt->reentrancy] = func;
    
    			lt->thread_id[lt->reentrancy] = pthread_self();
    
    			lt->reentrancy++;
    		}
    		ast_reentrancy_unlock(lt);
    
    		ast_mark_lock_acquired(t);
    	} else if (lt) {
    
    #ifdef HAVE_BKTR
    		if (lt->reentrancy) {
    			ast_reentrancy_lock(lt);
    			bt = &lt->backtrace[lt->reentrancy-1];
    			ast_reentrancy_unlock(lt);
    		} else {
    			bt = NULL;
    		}
    
    		__ast_mutex_logger("%s line %d (%s): Error obtaining write lock: %s\n",
    				filename, line, func, strerror(res));
    		DO_THREAD_CRASH;
    	}
    #endif /* DEBUG_THREADS */
    
    	return res;
    }
    
    
    int __ast_rwlock_timedrdlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name,
    	const struct timespec *abs_timeout)
    
    	struct ast_lock_track *lt = NULL;
    	int canlog = t->tracking && strcmp(filename, "logger.c");
    
    #ifdef HAVE_BKTR
    	struct ast_bt *bt = NULL;
    #endif
    
    
    	if (t->tracking) {
    		lt = ast_get_reentrancy(&t->track);
    
    		struct ast_bt tmp;
    
    		/* The implementation of backtrace() may have its own locks.
    		 * Capture the backtrace outside of the reentrancy lock to
    		 * avoid deadlocks. See ASTERISK-22455. */
    		ast_bt_get_addresses(&tmp);
    
    
    		if (lt->reentrancy < AST_MAX_REENTRANCY) {
    
    			lt->backtrace[lt->reentrancy] = tmp;
    
    			bt = &lt->backtrace[lt->reentrancy];
    		}
    		ast_reentrancy_unlock(lt);
    
    		ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
    #else
    		ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
    #endif
    	}
    #endif /* DEBUG_THREADS */
    
    #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
    	res = pthread_rwlock_timedrdlock(&t->lock, abs_timeout);
    #else
    	do {
    
    		for (;;) {
    			if (!(res = pthread_rwlock_tryrdlock(&t->lock))) {
    				break;
    			}
    
    			_now = ast_tvnow();
    			if (_now.tv_sec > abs_timeout->tv_sec || (_now.tv_sec == abs_timeout->tv_sec && _now.tv_usec * 1000 > abs_timeout->tv_nsec)) {
    
    		ast_reentrancy_lock(lt);
    		if (lt->reentrancy < AST_MAX_REENTRANCY) {
    			lt->file[lt->reentrancy] = filename;
    			lt->lineno[lt->reentrancy] = line;
    			lt->func[lt->reentrancy] = func;
    
    			lt->thread_id[lt->reentrancy] = pthread_self();
    
    			lt->reentrancy++;
    		}
    		ast_reentrancy_unlock(lt);
    
    		ast_mark_lock_acquired(t);
    	} else if (lt) {
    
    #ifdef HAVE_BKTR
    		if (lt->reentrancy) {
    			ast_reentrancy_lock(lt);
    			bt = &lt->backtrace[lt->reentrancy-1];
    			ast_reentrancy_unlock(lt);
    		} else {
    			bt = NULL;
    		}
    
    		ast_remove_lock_info(t, bt);
    
    		ast_remove_lock_info(t);
    
    		__ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
    				filename, line, func, strerror(res));
    		DO_THREAD_CRASH;
    	}
    #endif /* DEBUG_THREADS */
    
    	return res;
    }
    
    
    int __ast_rwlock_timedwrlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name,
    	const struct timespec *abs_timeout)
    
    	struct ast_lock_track *lt = NULL;
    	int canlog = t->tracking && strcmp(filename, "logger.c");
    
    #ifdef HAVE_BKTR
    	struct ast_bt *bt = NULL;
    #endif
    
    
    	if (t->tracking) {
    		lt = ast_get_reentrancy(&t->track);
    
    		struct ast_bt tmp;
    
    		/* The implementation of backtrace() may have its own locks.
    		 * Capture the backtrace outside of the reentrancy lock to
    		 * avoid deadlocks. See ASTERISK-22455. */
    		ast_bt_get_addresses(&tmp);
    
    
    		if (lt->reentrancy < AST_MAX_REENTRANCY) {
    
    			lt->backtrace[lt->reentrancy] = tmp;
    
    			bt = &lt->backtrace[lt->reentrancy];
    		}
    		ast_reentrancy_unlock(lt);
    
    		ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
    #else
    		ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
    #endif
    	}
    #endif /* DEBUG_THREADS */
    
    #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
    	res = pthread_rwlock_timedwrlock(&t->lock, abs_timeout);
    #else
    	do {
    
    		for (;;) {
    			if (!(res = pthread_rwlock_trywrlock(&t->lock))) {
    				break;
    			}
    
    			_now = ast_tvnow();
    			if (_now.tv_sec > abs_timeout->tv_sec || (_now.tv_sec == abs_timeout->tv_sec && _now.tv_usec * 1000 > abs_timeout->tv_nsec)) {
    
    		ast_reentrancy_lock(lt);
    		if (lt->reentrancy < AST_MAX_REENTRANCY) {
    			lt->file[lt->reentrancy] = filename;
    			lt->lineno[lt->reentrancy] = line;
    			lt->func[lt->reentrancy] = func;
    
    			lt->thread_id[lt->reentrancy] = pthread_self();
    
    			lt->reentrancy++;
    		}
    		ast_reentrancy_unlock(lt);
    
    		ast_mark_lock_acquired(t);
    	} else if (lt) {
    
    #ifdef HAVE_BKTR
    		if (lt->reentrancy) {
    			ast_reentrancy_lock(lt);
    			bt = &lt->backtrace[lt->reentrancy-1];
    			ast_reentrancy_unlock(lt);
    		} else {
    			bt = NULL;
    		}
    
    		__ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
    				filename, line, func, strerror(res));
    		DO_THREAD_CRASH;
    	}
    #endif /* DEBUG_THREADS */
    
    	return res;
    }
    
    
    int __ast_rwlock_tryrdlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
    
    #ifdef HAVE_BKTR
    	struct ast_bt *bt = NULL;
    #endif
    
    
    	if (t->tracking) {
    		lt = ast_get_reentrancy(&t->track);
    
    		struct ast_bt tmp;
    
    		/* The implementation of backtrace() may have its own locks.
    		 * Capture the backtrace outside of the reentrancy lock to
    		 * avoid deadlocks. See ASTERISK-22455. */
    		ast_bt_get_addresses(&tmp);
    
    
    		if (lt->reentrancy < AST_MAX_REENTRANCY) {
    
    			lt->backtrace[lt->reentrancy] = tmp;
    
    			bt = &lt->backtrace[lt->reentrancy];
    		}
    		ast_reentrancy_unlock(lt);
    
    		ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
    #else
    		ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
    #endif
    	}
    #endif /* DEBUG_THREADS */
    
    	res = pthread_rwlock_tryrdlock(&t->lock);
    
    #ifdef DEBUG_THREADS
    
    		ast_reentrancy_lock(lt);
    		if (lt->reentrancy < AST_MAX_REENTRANCY) {
    			lt->file[lt->reentrancy] = filename;
    			lt->lineno[lt->reentrancy] = line;
    			lt->func[lt->reentrancy] = func;
    
    			lt->thread_id[lt->reentrancy] = pthread_self();
    
    			lt->reentrancy++;
    		}
    		ast_reentrancy_unlock(lt);
    
    		ast_mark_lock_acquired(t);
    	} else if (lt) {
    
    		ast_mark_lock_failed(t);
    	}
    #endif /* DEBUG_THREADS */
    
    	return res;
    }
    
    
    int __ast_rwlock_trywrlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
    
    #ifdef HAVE_BKTR
    	struct ast_bt *bt = NULL;
    #endif
    
    
    	if (t->tracking) {
    		lt = ast_get_reentrancy(&t->track);
    
    		struct ast_bt tmp;
    
    		/* The implementation of backtrace() may have its own locks.
    		 * Capture the backtrace outside of the reentrancy lock to
    		 * avoid deadlocks. See ASTERISK-22455. */
    		ast_bt_get_addresses(&tmp);
    
    
    		if (lt->reentrancy < AST_MAX_REENTRANCY) {
    
    			lt->backtrace[lt->reentrancy] = tmp;
    
    			bt = &lt->backtrace[lt->reentrancy];
    		}
    		ast_reentrancy_unlock(lt);
    
    		ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
    #else
    		ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
    #endif
    	}
    #endif /* DEBUG_THREADS */
    
    	res = pthread_rwlock_trywrlock(&t->lock);
    
    #ifdef DEBUG_THREADS
    
    		ast_reentrancy_lock(lt);
    		if (lt->reentrancy < AST_MAX_REENTRANCY) {
    			lt->file[lt->reentrancy] = filename;
    			lt->lineno[lt->reentrancy] = line;
    			lt->func[lt->reentrancy] = func;
    
    			lt->thread_id[lt->reentrancy] = pthread_self();
    
    			lt->reentrancy++;
    		}
    		ast_reentrancy_unlock(lt);
    
    		ast_mark_lock_acquired(t);
    
    		ast_mark_lock_failed(t);
    	}
    #endif /* DEBUG_THREADS */
    
    	return res;
    }