📄 thd_dbg.c
字号:
/* $Header: /usr/cvsroot/target/src/wrn/wm/common/lib/thd_dbg.c,v 1.3 2003/01/16 18:18:58 josh Exp $ *//* * Copyright (C) 1999-2005 Wind River Systems, Inc. * All rights reserved. Provided under license only. * Distribution or other use of this software is only * permitted pursuant to the terms of a license agreement * from Wind River Systems (and is otherwise prohibited). * Refer to that license agreement for terms of use. *//**************************************************************************** * Copyright 1998-1999 Integrated Systems, Inc. * All rights reserved. ****************************************************************************//* * $Log: thd_dbg.c,v $ * Revision 1.3 2003/01/16 18:18:58 josh * directory structure shifting * * Revision 1.2 2001/11/06 22:15:56 tneale * Fixed for newest file layout * * Revision 1.1.1.1 2001/11/05 17:48:40 tneale * Tornado shuffle * * Revision 1.12 2001/06/12 08:06:07 paul * Mutex priorities are unsigned. * Added debugging to condition variable routines. * * Revision 1.11 2001/03/22 16:54:08 paul * Mutex and condition variable functions now return errors. * * Revision 1.10 2001/03/20 17:11:38 paul * Removed unused local variable. * * Revision 1.9 2001/01/19 22:21:32 paul * Update copyright. * * Revision 1.8 2000/10/16 19:22:06 paul * Restore sockets and mempool code. * * Revision 1.6 2000/03/17 00:16:59 meister * Update copyright message * * Revision 1.5 1999/09/02 20:58:18 wes * Create a new memory pool for thread debug state, and use it instead of * using malloc/free. * * Revision 1.4 1999/05/20 19:44:32 wes * Print out more info for thread assertion failures * * Revision 1.3 1999/05/19 21:27:33 wes * Fix signed vs unsigned comparison glitch * * Revision 1.2 1999/04/21 20:05:18 wes * Silence DIAB compiler warnings * * Revision 1.1 1999/02/18 17:45:57 wes * 8.3ize thread_debug.c to thd_dbg.c * * Revision 1.2 1999/02/18 04:41:23 wes * Sockets merge: Everything Else * - memory pools * - thread support * - port-specific headers * * Revision 1.1.6.10 1999/02/05 18:33:57 paul * Changed the way we identify the thread for trace statements, due to * differences between various pthreads implementations. * * Revision 1.1.6.9 1999/01/22 19:49:15 paul * Added this_thread() to allow other parts of the code to print the * current thread. * Added copyright notice. * *//* [clearcase]modification history-------------------01b,20apr05,job update copyright notices01a,11dec03,job fix copyright statements*/#include <wrn/wm/common/install.h>#include <wrn/wm/common/config.h>#include <wrn/wm/common/thread.h>#include <wrn/attache/config.h> /* !!!??? */#include <wrn/attache/glue.h> /* !!!??? */#include <wrn/wm/common/bug.h>#define ASSERT1(cond, lock, file, line) \ do {if (!(cond)) { thread_preabort(file, line, lock); \ BUG(BUG_ASSERTION_FAILED, BUG_FATAL, 0, \ (BUG_OUT, "Lock assertion \"%s\" failed, file %s, line %d", \ #cond, file, line)); } } while (0)glue_mutex_t etc_meta_mutex;enum thread_debug_state { THREAD_DEBUG_RUNNABLE, THREAD_DEBUG_MUTEX_WAIT, THREAD_DEBUG_COND_WAIT};typedef struct _tdit thread_debug_info_t;struct _tdit { thread_debug_info_t *next_thread; char *thread_name; enum thread_debug_state thread_state; etc_mutex_t *thread_held_locks; etc_mutex_t *thread_wanted_lock; etc_cond_t *thread_wanted_cond; glue_thread_t tid;};size_t thd_debug_size = sizeof(thread_debug_info_t);void debug_state_free(void *debug){ BUG(BUG_THREAD_TRACE, BUG_CONTINUABLE, 0, (BUG_OUT, "Freeing thread state %p", debug)); GLUE_FREE_TO_POOL(debug, MEMPOOL_THD_DBG);}void common_thread_init(void){ GLUE_THREAD_INIT(); GLUE_MUTEX_INIT_MAGIC(&etc_meta_mutex); GLUE_THD_COOKIE_INIT(debug_state_free); BUG(BUG_THREAD_TRACE, BUG_CONTINUABLE, 0, (BUG_OUT, "Threading!"));}thread_debug_info_t *thread_debug_state(void){ thread_debug_info_t *dip; GLUE_THD_COOKIE_GET(&dip); if (dip == NULL) { dip = GLUE_ALLOC_FROM_POOL(sizeof(*dip), MEMPOOL_THD_DBG); BUG_ASSERT(dip != NULL); dip->tid = GLUE_THD_SELF(); dip->next_thread = NULL; dip->thread_name = NULL; dip->thread_state = THREAD_DEBUG_RUNNABLE; dip->thread_held_locks = NULL; dip->thread_wanted_lock = NULL; dip->thread_wanted_cond = NULL; GLUE_THD_COOKIE_SET(dip); } return dip;}static unsigned compute_lock_prio(thread_debug_info_t *tdi){ unsigned prio = 0; etc_mutex_t *lock; for (lock = tdi->thread_held_locks; lock != NULL; lock = lock->next_lock) { if (lock->lock_prio > prio) prio = lock->lock_prio; } return prio;}#if INSTALL_BUGstatic char *indent_string(int level){ static char indentfu[10]="\t\t\t\t\t\t\t\t\t\t"; if (level < 0) level=0; if (level > (int)sizeof(indentfu)) level = sizeof(indentfu); return &indentfu[sizeof(indentfu) - level];}#endifvoid print_proc (int level, char *tag, thread_debug_info_t *tdi){ BUG(BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "%s%s: %p", indent_string(level), tag, tdi));}void print_lock(int level, char *tag, etc_mutex_t *lock) { BUG(BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "%s%s: %s (%p) (pri %u)", indent_string(level), tag, lock->lock_name, lock, lock->lock_prio)); BUG(BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "%slock last locked in %s, line %d", indent_string(level+1), lock->last_lock_file, lock->last_lock_line)); BUG(BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "%slock last unlocked in %s, line %d", indent_string(level+1), lock->last_unlock_file, lock->last_unlock_line)); if (lock->lock_owner != NULL) { print_proc(level+1, "Held by", lock->lock_owner); }}void thread_preabort(char *file, int line, etc_mutex_t *errlock) { thread_debug_info_t *tdi = thread_debug_state(); etc_mutex_t *lock; BUG(BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "locking error detected on lock %p at %s, line %d", errlock, file, line)); print_lock(0, "bad lock", errlock); if (tdi->thread_wanted_lock == NULL) { BUG(BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "No locks wanted")); } else { print_lock(0, "waiting for", tdi->thread_wanted_lock); } if (tdi->thread_held_locks == NULL) { BUG(BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "No locks held")); } else { BUG(BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "Held locks:")); for (lock = tdi->thread_held_locks; lock != NULL; lock = lock->next_lock) { BUG(BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "\t%s (%p) (pri %u)", lock->lock_name, lock, lock->lock_prio)); } }}static int etc_mutex_lock_debug (etc_mutex_t *lock, unsigned prio, char *file, int line) { thread_debug_info_t *us = thread_debug_state(); unsigned curlockprio = compute_lock_prio(us); int ret; ASSERT1((lock->magic == ETC_LOCK_MAGIC), lock, file, line); us->thread_state = THREAD_DEBUG_MUTEX_WAIT; us->thread_wanted_lock = lock; ASSERT1((lock->lock_owner != us), lock, file, line); ASSERT1((lock->lock_prio > curlockprio), lock, file, line); BUG(BUG_THREAD_TRACE, BUG_CONTINUABLE, 0, (BUG_OUT, "waiting to lock %s (%p) at %s, line %d", lock->lock_name, lock, file, line)); if (GLUE_MUTEX_TRYLOCK(&(lock)->m, prio)) { ETC_META_UNLOCK(); ret = (int)GLUE_MUTEX_LOCK(&(lock)->m, prio); ETC_META_LOCK(); if (ret) { BUG(BUG_THREAD_TRACE, BUG_CONTINUABLE, 0, (BUG_OUT, "!!failed to lock %s (%p) at %s, line %d", lock->lock_name, lock, file, line)); return ret; } } BUG(BUG_THREAD_TRACE, BUG_CONTINUABLE, 0, (BUG_OUT, "locked %s (%p) at %s, line %d", lock->lock_name, lock, file, line)); us->thread_state = THREAD_DEBUG_RUNNABLE; us->thread_wanted_lock = NULL; ASSERT1((lock->lock_prio == prio), lock, file, line); ASSERT1((lock->lock_owner == NULL), lock, file, line); lock->last_lock_file = file; lock->last_lock_line = line; lock->lock_owner = us; lock->next_lock = us->thread_held_locks; us->thread_held_locks = lock; return 0;}static int etc_mutex_unlock_debug (etc_mutex_t *lock, unsigned prio, char *file, int line){ thread_debug_info_t *us = thread_debug_state(); ASSERT1((lock->magic == ETC_LOCK_MAGIC), lock, file, line); ASSERT1((lock->lock_owner == us), lock, file, line); ASSERT1((lock->lock_prio == prio), lock, file, line); lock->lock_owner = NULL; BUG(BUG_THREAD_TRACE, BUG_CONTINUABLE, 0, (BUG_OUT, "unlocking %s (%p) at %s, line %d", lock->lock_name, lock, file, line)); if (lock == us->thread_held_locks) { us->thread_held_locks = lock->next_lock; lock->next_lock = NULL; } else { etc_mutex_t *l1; for (l1 = us->thread_held_locks; l1 != NULL; l1 = l1->next_lock) { if (l1->next_lock == lock) { l1->next_lock = lock->next_lock; lock->next_lock = NULL; break; } } } ASSERT1((lock->next_lock == NULL), lock, file, line); lock->last_unlock_file = file; lock->last_unlock_line = line; return (int)GLUE_MUTEX_UNLOCK(&(lock)->m, prio);}void etc_mutex_lock_assert (etc_mutex_t *lock, unsigned prio, char *file, int line){ thread_debug_info_t *us = thread_debug_state(); ETC_META_LOCK(); ASSERT1((lock->magic == ETC_LOCK_MAGIC), lock, file, line); ASSERT1((lock->lock_owner == us), lock, file, line); ASSERT1((lock->lock_prio == prio), lock, file, line); ETC_META_UNLOCK();}int etc_mutex_destroy (etc_mutex_t *lock, char *file, int line){ int ret; ETC_META_LOCK(); BUG(BUG_THREAD_TRACE, BUG_CONTINUABLE, 0, (BUG_OUT, "destroying mutex %s (%p)", lock->lock_name, lock)); ASSERT1((lock->magic == ETC_LOCK_MAGIC), lock, file, line); ret = (int)GLUE_MUTEX_DESTROY(&(lock)->m); (lock)->magic = ~ETC_LOCK_MAGIC; lock->last_unlock_file = file; lock->last_unlock_line = line; ETC_META_UNLOCK(); return ret;}void *this_thread(void){ thread_debug_info_t *us = thread_debug_state(); return (void *)us;}int etc_mutex_init(etc_mutex_t *lock, unsigned prio, char *name){ int ret; ETC_META_LOCK(); lock->magic = ETC_LOCK_MAGIC; lock->lock_owner = NULL; lock->lock_name = name; lock->lock_prio = prio; lock->next_lock = NULL; ret = (int)GLUE_MUTEX_INIT(&lock->m, prio); ETC_META_UNLOCK(); return ret;}int etc_mutex_lock(etc_mutex_t *lock, unsigned prio, char *file, int line){ int ret; ETC_META_LOCK(); ret = etc_mutex_lock_debug(lock, prio, file, line); ETC_META_UNLOCK(); return ret;}int etc_mutex_unlock(etc_mutex_t *lock, unsigned prio, char *file, int line){ int ret; ETC_META_LOCK(); ret = etc_mutex_unlock_debug(lock, prio, file, line); ETC_META_UNLOCK(); return ret;}int etc_cond_init(etc_cond_t *cond, etc_mutex_t *mutex, char *file, int line){ int ret; ETC_META_LOCK(); cond->m = mutex; ret = (int)GLUE_COND_INIT(&cond->c, &mutex->m); ETC_META_UNLOCK(); /* pthread_cond_init() and cv_create() both return 0 on success */ BUG_IF((ret != 0), BUG_ASSERTION_FAILED, BUG_CONTINUABLE, 0, (BUG_OUT, "GLUE_COND_INIT returned %d, file %s, line %d", ret, file, line)); return ret;}int etc_cond_wait(etc_cond_t *cond, etc_mutex_t *mutex, char *file, int line){ int ret; ETC_META_LOCK(); etc_mutex_unlock_debug(mutex, mutex->lock_prio, file, line); ret = (int)GLUE_COND_WAIT(&cond->c, &etc_meta_mutex); etc_mutex_lock_debug(mutex, mutex->lock_prio, file, line); ETC_META_UNLOCK(); /* pthread_cond_wait() and cv_wait() both return 0 on success */ BUG_IF((ret != 0), BUG_ASSERTION_FAILED, BUG_FATAL, 0, (BUG_OUT, "GLUE_COND_WAIT returned %d, file %s, line %d", ret, file, line)); return ret;}int etc_cond_wakeup(etc_cond_t *cond, etc_mutex_t *mutex, char *file, int line){ int ret; ETC_META_LOCK(); ret = (int)GLUE_COND_WAKEUP(&cond->c, mutex); ETC_META_UNLOCK(); /* pthread_cond_signal() and cv_signal() both return 0 on success */ BUG_IF((ret != 0), BUG_ASSERTION_FAILED, BUG_FATAL, 0, (BUG_OUT, "GLUE_COND_WAKEUP returned %d, file %s, line %d", ret, file, line)); return ret;}int etc_cond_broadcast(etc_cond_t *cond, etc_mutex_t *mutex, char *file, int line){ int ret; ETC_META_LOCK(); ret = (int)GLUE_COND_BROADCAST(&cond->c, mutex); ETC_META_UNLOCK(); /* pthread_cond_broadcast() and cv_broadcast() both return 0 on success */ BUG_IF((ret != 0), BUG_ASSERTION_FAILED, BUG_FATAL, 0, (BUG_OUT, "GLUE_COND_BROADCAST returned %d, file %s, line %d", ret, file, line)); return ret;}int etc_cond_destroy(etc_cond_t *cond, char *file, int line){ int ret; ETC_META_LOCK(); ret = (int)GLUE_COND_DESTROY(&cond->c); ETC_META_UNLOCK(); /* pthread_cond_destroy() and cv_delete() both return 0 on success */ BUG_IF((ret != 0), BUG_ASSERTION_FAILED, BUG_FATAL, 0, (BUG_OUT, "GLUE_COND_DESTROY returned %d, file %s, line %d", ret, file, line)); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -