From owner-svn-soc-all@FreeBSD.ORG Thu Jun 7 23:33:10 2012 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id A884E1065679 for ; Thu, 7 Jun 2012 23:33:08 +0000 (UTC) (envelope-from gmiller@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Thu, 07 Jun 2012 23:33:08 +0000 Date: Thu, 07 Jun 2012 23:33:08 +0000 From: gmiller@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20120607233308.A884E1065679@hub.freebsd.org> Cc: Subject: socsvn commit: r237279 - soc2012/gmiller/locking-head/lib/libthr/thread X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Jun 2012 23:33:10 -0000 Author: gmiller Date: Thu Jun 7 23:33:07 2012 New Revision: 237279 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237279 Log: Implement _mutex_release(). Modified: soc2012/gmiller/locking-head/lib/libthr/thread/thr_private.h soc2012/gmiller/locking-head/lib/libthr/thread/thr_profile.c Modified: soc2012/gmiller/locking-head/lib/libthr/thread/thr_private.h ============================================================================== --- soc2012/gmiller/locking-head/lib/libthr/thread/thr_private.h Thu Jun 7 22:57:26 2012 (r237278) +++ soc2012/gmiller/locking-head/lib/libthr/thread/thr_private.h Thu Jun 7 23:33:07 2012 (r237279) @@ -748,33 +748,29 @@ int _mutex_owned(struct pthread *, const struct pthread_mutex *) __hidden; int _mutex_reinit(pthread_mutex_t *) __hidden; void _mutex_fork(struct pthread *curthread) __hidden; -void _mutex_obtain_failed(struct pthread_mutex *, struct timespec *waittime) - __hidden; -void _mutex_obtain_success(struct pthread_mutex *, - struct timespec *waittime, const char *, int) +void _mutex_obtain_failed(struct pthread_mutex *, struct timespec *) __hidden; +void _mutex_obtain_success(struct pthread_mutex *, struct timespec *, + const char *, int) __hidden; void _lock_profile_init(void) __hidden; void _lock_profile_exit_thread(struct pthread *curthread) __hidden; void _rwlock_obtain_read_success(struct pthread_rwlock *, - struct timespec *waittime, - const char *file, int line) __hidden; + struct timespec *wait_time, const char *file, int line) __hidden; void _rwlock_obtain_read_failed(struct pthread_rwlock *, - struct timespec *waittime) __hidden; + struct timespec *wait_time) __hidden; void _rwlock_obtain_write_success(struct pthread_rwlock *, - struct timespec *waittime, - const char *file, int line) __hidden; + struct timespec *wait_time, const char *file, int line) __hidden; void _rwlock_obtain_write_failed(struct pthread_rwlock *, - struct timespec *waittime) __hidden; + struct timespec *wait_time) __hidden; void _rwlock_release_read(struct pthread_rwlock *, struct timespec *) __hidden; void _rwlock_release_write(struct pthread_rwlock *, struct timespec *) __hidden; void _mutex_release(struct pthread_mutex *, struct timespec *) __hidden; void _spin_obtain_success(struct pthread_spinlock *, - struct timespec *waittime, - const char *file, int line) __hidden; + struct timespec *wait_time, const char *file, int line) __hidden; void _spin_obtain_failed(struct pthread_spinlock *, - struct timespec *waittime) __hidden; + struct timespec *wait_time) __hidden; void _spin_release(struct pthread_spinlock *, struct timespec *) __hidden; void _libpthread_init(struct pthread *) __hidden; struct pthread *_thr_alloc(struct pthread *) __hidden; Modified: soc2012/gmiller/locking-head/lib/libthr/thread/thr_profile.c ============================================================================== --- soc2012/gmiller/locking-head/lib/libthr/thread/thr_profile.c Thu Jun 7 22:57:26 2012 (r237278) +++ soc2012/gmiller/locking-head/lib/libthr/thread/thr_profile.c Thu Jun 7 23:33:07 2012 (r237279) @@ -29,26 +29,44 @@ #include #include +#include +#include #include "thr_private.h" #define LOCK_PROF_HASH_SIZE (4096) +struct acquisition_point { + SLIST_ENTRY(acquisition_point) acq_point_next; + const char *file; + int line; + struct timespec wait_max; + struct timespec hold_max; + uintmax_t contest_count; + struct timespec wait_time; + struct timespec hold_time; + int acq_count; +}; + +SLIST_HEAD(acq_point_head, acquisition_point); + struct acquisition { - const char *file; - int line; - struct timespec acq_time; - int count; - int ref; - struct timespec waittime; - SLIST_ENTRY(acquisition) acq_next; + LIST_ENTRY(acquisition) acq_next; + void *lock; + const char *file; + int line; + struct timespec acq_time; + int count; + int ref; + struct timespec wait_time; }; -SLIST_HEAD(acq_head, acquisition); +LIST_HEAD(acq_head, acquisition) acq_head = LIST_HEAD_INITIALIZER(acq_head); -struct acq_head mutex_hash[LOCK_PROF_HASH_SIZE]; +struct acq_point_head mutex_hash[LOCK_PROF_HASH_SIZE]; -void _lock_profile_init() +void +_lock_profile_init() { int i; @@ -58,30 +76,53 @@ } static struct acquisition * -mutex_lookup(struct pthread_mutex *m, const char *file, int line) +mutex_lookup_acq(struct pthread_mutex *m, const char *file, int line) { - u_int hash; struct acquisition *acq; - hash = ((uintptr_t)file * 31 + line) & (LOCK_PROF_HASH_SIZE - 1); - - SLIST_FOREACH(acq, &mutex_hash[hash], acq_next) { + LIST_FOREACH(acq, &acq_head, acq_next) { if (acq->file == file && acq->line == line) { return acq; } } acq = malloc(sizeof(struct acquisition)); + bzero(acq, sizeof(*acq)); + acq->lock = m; acq->file = file; acq->line = line; - SLIST_INSERT_HEAD(&mutex_hash[hash], acq, acq_next); + LIST_INSERT_HEAD(&acq_head, acq, acq_next); + + return (acq); +} + +static struct acquisition_point * +mutex_lookup_acq_point(struct pthread_mutex *m, const char *file, int line) +{ + u_int hash; + struct acquisition_point *acq_point; + + hash = ((uintptr_t)file * 31 + line) & (LOCK_PROF_HASH_SIZE - 1); + + SLIST_FOREACH(acq_point, &mutex_hash[hash], acq_point_next) { + if (acq_point->file == file && acq_point->line == line) { + return (acq_point); + } + } + + acq_point = malloc(sizeof(struct acquisition_point)); + bzero(acq_point, sizeof(*acq_point)); + acq_point->file = file; + acq_point->line = line; - return acq; + SLIST_INSERT_HEAD(&mutex_hash[hash], acq_point, acq_point_next); + + return (acq_point); } void -_mutex_obtain_success(struct pthread_mutex *m, struct timespec *waittime, +_mutex_obtain_success(struct pthread_mutex *m, struct timespec *wait_time, const char *file, int line) { struct pthread *curthread = _get_curthread(); @@ -89,19 +130,20 @@ THR_CRITICAL_ENTER(curthread); - acq = mutex_lookup(m, file, line); + acq = mutex_lookup_acq(m, file, line); if (acq != NULL) { acq->count++; acq->ref++; if (acq->ref == 1) { clock_gettime(CLOCK_REALTIME, &acq->acq_time); - if (waittime->tv_sec != 0 || waittime->tv_nsec != 0) { - if (TIMESPEC_GT(&acq->acq_time, waittime)) { - TIMESPEC_SUB(&acq->waittime, + if (wait_time->tv_sec != 0 || + wait_time->tv_nsec != 0) { + if (TIMESPEC_GT(&acq->acq_time, wait_time)) { + TIMESPEC_SUB(&acq->wait_time, &acq->acq_time, &acq->acq_time); } } else { - bzero(&acq->waittime, sizeof(acq->waittime)); + bzero(&acq->wait_time, sizeof(acq->wait_time)); } } } @@ -110,16 +152,69 @@ } void -_mutex_obtain_failed(struct pthread_mutex *m, struct timespec *waittime) +_mutex_obtain_failed(struct pthread_mutex *m, struct timespec *wait_time) { - if (waittime->tv_sec == 0 && waittime->tv_nsec == 0) { - clock_gettime(CLOCK_REALTIME, waittime); + if (wait_time->tv_sec == 0 && wait_time->tv_nsec == 0) { + clock_gettime(CLOCK_REALTIME, wait_time); } } void -_mutex_release(struct pthread_mutex *m, struct timespec *waittime) +_mutex_release(struct pthread_mutex *m, struct timespec *wait_time) { + struct pthread *curthread = _get_curthread(); + struct acquisition *acq; + struct acquisition_point *acq_point; + struct timespec current_time; + struct timespec hold_time; + + THR_CRITICAL_ENTER(curthread); + + LIST_FOREACH(acq, &acq_head, acq_next) { + if (acq->lock == m) { + break; + } + } + + if (acq != NULL) { + acq->ref--; + if (acq->ref == 0) { + acq_point = mutex_lookup_acq_point(m, acq->file, + acq->line); + clock_gettime(CLOCK_REALTIME, ¤t_time); + if (acq_point != NULL && + TIMESPEC_GT(&acq->acq_time, ¤t_time)) { + TIMESPEC_SUB(&hold_time, ¤t_time, + &acq->acq_time); + if (TIMESPEC_GT(&hold_time, + &acq_point->hold_max)) { + memcpy(&acq_point->hold_max, + &hold_time, + sizeof(struct timespec)); + } + if (TIMESPEC_GT(wait_time, + &acq_point->wait_max)) { + memcpy(&acq_point->wait_max, + wait_time, + sizeof(struct timespec)); + } + TIMESPEC_ADD(&acq_point->hold_time, + &acq_point->hold_time, &hold_time); + TIMESPEC_ADD(&acq_point->wait_time, + &acq_point->wait_time, wait_time); + acq_point->acq_count += acq->count; + if (wait_time->tv_sec != 0 || + wait_time->tv_nsec != 0) { + acq_point->contest_count++; + } + } + } + + LIST_REMOVE(acq, acq_next); + free(acq); + } + + THR_CRITICAL_LEAVE(curthread); } void @@ -129,19 +224,20 @@ void _rwlock_obtain_read_success(struct pthread_rwlock *l, - struct timespec *waittime, const char *file, + struct timespec *wait_time, const char *file, int line) { } void -_rwlock_obtain_read_failed(struct pthread_rwlock *l, struct timespec *waittime) +_rwlock_obtain_read_failed(struct pthread_rwlock *l, + struct timespec *wait_time) { } void _rwlock_obtain_write_success(struct pthread_rwlock *l, - struct timespec *waittime, const char *file, + struct timespec *wait_time, const char *file, int line) { } @@ -153,28 +249,28 @@ } void -_rwlock_release_read(struct pthread_rwlock *l, struct timespec *waittime) +_rwlock_release_read(struct pthread_rwlock *l, struct timespec *wait_time) { } void -_rwlock_release_write(struct pthread_rwlock *l, struct timespec *waittime) +_rwlock_release_write(struct pthread_rwlock *l, struct timespec *wait_time) { } void -_spin_obtain_success(struct pthread_spinlock *s, struct timespec *waittime, +_spin_obtain_success(struct pthread_spinlock *s, struct timespec *wait_time, const char *file, int line) { } void -_spin_obtain_failed(struct pthread_spinlock *s, struct timespec *waittime) +_spin_obtain_failed(struct pthread_spinlock *s, struct timespec *wait_time) { } void -_spin_release(struct pthread_spinlock *s, struct timespec *waittime) +_spin_release(struct pthread_spinlock *s, struct timespec *wait_time) { }