⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctrace.c

📁 linux下的多线程调试c++代码,适合多线程linux下程序的调试
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>#include <stdarg.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <pthread.h>#include <semaphore.h>#include <time.h>#include <ctrace.h>#define TRC_PORT 2013#define SYSFILE(a) ((a == _STDOUT) || (a == _STDERR))  tenable_t _trc = TRC_DISABLED;		/* trace enabled ? */static ton_t _on = TRC_OFF;		/* trace on */	static tlevel_t _tlevel = TRC_NONE;	/* trace levels enabled */static FILE *_fp = NULL;		/* trc msgs output file stream */static tserver_t  _server = 0;		/* run trace library as separate thread */static int _msgs = 0;			/* msgs still being processed by server */static pthread_t _sid;			/* server thread id */static int _serv_sockfd;		/* server socket */static sem_t _startclient;		/* dont start client until server inited */static int _initialised = 0;		/* static trace library initialised *//* trace field sizes */ #define T1	30		/* file name 	*/#define T2	4		/* line number  */#define T3	10		/* thread name  */#define T4	30		/* keyword max 	*/#define T5	1024		/* info max 	*/#define TRACELEN (T1 + T2 + T3 + T4 + T5) /* indented trace fields start at WSPACEMAX + 1 */#define WSPACEMAX (T1 + T2 + T3)	#define WSPACELEN(a) WSPACEMAX - a/* dont create thread data buffers on the fly *//* instead keep them permanently in memory as *//* part of the tthread_t struct *//* trace thread type */typedef struct tthread_t{	tid_t id;	char name[T3];		int on;	tlevel_t level;	char wspace[WSPACEMAX];		char fmt[T5];	char trace[TRACELEN];	struct tthread_t *next;	} tthread_t;#define THRDMAX	307	/* keep this prime - used in hashing fn */ #define HASH(a) a % THRDMAX static tthread_t *_thread[THRDMAX]; 	/* trace thread hash lookup table */static uint_t _numthreads = 0;	static pthread_mutex_t _hashmutex;	/* for _thread hash table integrity */static int _hashreads = 0;static sem_t _hashsem;/* trace unit type */typedef struct tunit_t{	int on;	tlevel_t level;}tunit_t;#define UNITMAX 1000static tunit_t *_unit = NULL;		/* trace unit array */static uint_t _unitmax = 0;		/* size of trace unit array *//* write has exclusive use of hash table *//* muliple reads can occur concurrently */#define HASH_READ_ENTER() \	pthread_mutex_lock(&_hashmutex); \	if(!_hashreads) \		sem_wait(&_hashsem); \	_hashreads++; \	pthread_mutex_unlock(&_hashmutex);#define HASH_READ_EXIT() \	pthread_mutex_lock(&_hashmutex); \	--_hashreads; \	if(!_hashreads) \		sem_post(&_hashsem); \	pthread_mutex_unlock(&_hashmutex);#define HASH_WRITE_ENTER() sem_wait(&_hashsem)#define HASH_WRITE_EXIT() sem_post(&_hashsem)/* functions requiring forward delcarations */int trc_file(cchar_t *file);	void *trc_start_server(void);int trc_stop_server();/* ----------------------------------------------------------------------   int			// 0=success, 1=failure   trc_init(		// function name   cchar_t *file,	// output stream(file, stdout, stderr), NULL=stdout     tenable_t trc,	// trace enabled flag   ton_t on,		// trace on flag   tlevel_t level,	// trace levels to default to   tserver_t server)	// if server=1 run trace as separate server   --------------------------------------------------------------------*/int trc_init(cchar_t *file, tenable_t trc, ton_t on, tlevel_t level, uint_t umax, tserver_t server){	int i, ret = 0;	if(_initialised) return 1;	_trc = trc;	_on = on;	_tlevel = level;	_server = server;	if(trc_file(file))		return 1;		for(i=0; i<THRDMAX; i++)		_thread[i] = NULL;	/* initialise logical software unit array */	if(umax > 0){		_unitmax = umax;		_unit = (tunit_t *)malloc(sizeof(tunit_t)*_unitmax);		for(i=0; i<_unitmax; i++){			_unit[i].on = TRC_OFF;			_unit[i].level = TRC_ALL;		}	}	if(pthread_mutex_init(&_hashmutex, NULL))		return 1;	sem_init(&_hashsem, 0, 1);	sem_init(&_startclient, 0, 1);	/* run trace as separate thread */	if(_server == TRC_SERV_ON){		sem_wait(&_startclient);		if(pthread_create(&_sid, NULL, trc_start_server, NULL)){			trc_end();			return 1;			}		trc_start_client();	}	_initialised = 1;	return 0;}/* ----------------------------------------------------------------------   void			// procedure    trc_end()		// procedure name   --------------------------------------------------------------------*/void trc_end(){	int i;	tthread_t *cur, *next;	_trc = TRC_DISABLED;	if(_server){		trc_stop_server();		pthread_join(_sid, NULL);		trc_stop_client();	}	for(i=0; i<THRDMAX; i++){		for(cur=_thread[i]; cur !=NULL; cur = next){			next = cur->next;			free(cur);		}	}	pthread_mutex_destroy(&_hashmutex);	sem_destroy(&_hashsem);	sem_destroy(&_startclient);	if(!SYSFILE(_fp))		fclose(_fp);	_initialised = 0;}/* ----------------------------------------------------------------------   int			// 0=success, 1=failure   trc_file(		// function name   cchar_t *file)	// output stream(file, stdout, stderr), NULL=stdout     --------------------------------------------------------------------*/int trc_file(cchar_t *file){	if(_fp && !SYSFILE(_fp))		fclose(_fp);		if(!file)		_fp = _STDOUT;	else if(!(_fp = fopen(file, "w")))		return 1; 	return 0;}/* ----------------------------------------------------------------------   tthread_t *		// thread struct of global data      trc_thread(		// function name   tid_t id)		// thread id for index into _threads hash table    --------------------------------------------------------------------*/tthread_t *trc_thread(tid_t id){	tthread_t *t = NULL;		/* if thread already added return thread */	for(t=_thread[HASH((int)id)]; t!=NULL; t=t->next)		if(t->id == id)			break;	return t; }/* ----------------------------------------------------------------------   void			// procedure    trc_print()		// procedure name   desc: Print all current added threads, for debugging purposes.   --------------------------------------------------------------------*/void trc_print_threads(){	int i;	tthread_t *t = NULL;	HASH_WRITE_ENTER();	for(i=0; i<THRDMAX; i++)		for(t=_thread[i]; _thread[i] && t!=NULL; t=t->next)			printf("t->id: %d\t t->name: %s\t t->level: %d\tt->on: %d\n", 				t->id, t->name, t->level, t->on);	HASH_WRITE_EXIT();}/* ----------------------------------------------------------------------   int			// 0=success, 1=failure   trc_add_thread(	// function name   cchar_t *tname,	// trace output thread name    tid_t id)		// thread id   desc: add thread struct to _thread hash table for thread with <id>   --------------------------------------------------------------------*/int trc_add_thread(cchar_t *tname, tid_t id){	uint_t i;	tthread_t *t = NULL;	if(id == 0)		id = pthread_self();	HASH_WRITE_ENTER();	if(t = trc_thread(id)){		//strncpy(t->name, tname, T3);		if(tname)			sprintf(t->name, "%s", tname);		else			sprintf(t->name, "%d", id);	}	else{		t = (tthread_t *)malloc(sizeof(tthread_t));		if(!t){			HASH_WRITE_EXIT();			return 1;		}		i = HASH((int)id);		t->id = id;		//strncpy(t->name, tname, T3);		if(tname)			sprintf(t->name, "%s", tname);		else			sprintf(t->name, "%d", id);		t->on = _on; 		t->level = _tlevel;		memset(t->wspace, ' ', WSPACEMAX);		t->next = _thread[i];		_thread[i] = t;		_numthreads++;	}	HASH_WRITE_EXIT();	return 0;}/* ----------------------------------------------------------------------   int			// 0=success, 1=failure   trc_remove_thread(	// function name   tid_t id)		// thread id   desc: remove thread struct from _thread hash table for thread with <id>   --------------------------------------------------------------------*/int trc_remove_thread(tid_t id){	int i, ret = 1;	tthread_t *cur, *next;	if(id == 0)		id = pthread_self();		HASH_WRITE_ENTER();	i = HASH((int)id);	// if head of list is target, remove head	if(_thread[i] && _thread[i]->id == id){		cur = _thread[i];		_thread[i] = cur->next;		free(cur);		_numthreads--;		ret = 0;	}	// else we need to find and remove target	else{		for(cur=_thread[i]; cur!=NULL; cur=cur->next){			next = cur->next;			if(next && (next->id == id)){				cur->next = next->next;				free(next);				_numthreads--;				ret = 0;			}		}	}	HASH_WRITE_EXIT();	return ret;}/* ----------------------------------------------------------------------   void			// procedure    trc_turn_on()	// procedure name   desc: turn tracing on for all added threads    --------------------------------------------------------------------*/void trc_turn_on(){	uint_t i;	tthread_t *t = NULL;	HASH_WRITE_ENTER();	_on = TRC_ON;	for(i=0; i<THRDMAX; i++)		for(t=_thread[i]; _thread[i] && t!=NULL; t=t->next)			t->on = 1;	HASH_WRITE_EXIT();}/* ----------------------------------------------------------------------   void			// procedure    trc_turn_off()	// procedure name   desc: turn tracing on for all added threads    --------------------------------------------------------------------*/void trc_turn_off(){	uint_t i;	tthread_t *t = NULL;	HASH_WRITE_ENTER();	_on = TRC_OFF;	for(i=0; i<THRDMAX; i++)		for(t=_thread[i]; _thread[i] && t!=NULL; t=t->next)			t->on = 0;	HASH_WRITE_EXIT();}/* ----------------------------------------------------------------------   int			// 0=success, 1=failure   trc_turn_thread_on(	// function name   tid_t id)		// thread id   desc: turn tracing on for thread <id>    --------------------------------------------------------------------*/int trc_turn_thread_on(tid_t id){	int ret = 1;	tthread_t *t = NULL;	if(id == 0)		id = pthread_self();	HASH_READ_ENTER();	if(t = trc_thread(id)){		t->on = TRC_ON;		ret = 0;	}	HASH_READ_EXIT();		return ret;}/* ----------------------------------------------------------------------   int			// 0=success, 1=failure   trc_turn_thread_off(	// function name   tid_t id)		// thread id   desc: turn tracing off for thread <id>    --------------------------------------------------------------------*/int trc_turn_thread_off(tid_t id){	int ret = 1;	tthread_t *t = NULL;	if(id == 0)		id = pthread_self();	HASH_READ_ENTER();	if(t = trc_thread(id)){		t->on = TRC_OFF;		ret = 0;	}	HASH_READ_EXIT();		return ret;}/* ----------------------------------------------------------------------   int			// 0=success, 1=failure    trc_turn_unit_on(	// procedure name   tunit_t *tl)	// unit software section variable   desc: turn tracing on for unit section of software    --------------------------------------------------------------------*/int trc_turn_unit_on(uint_t i){	int ret = 1;	if(_unitmax == 0 || i<0 || i>=_unitmax)		return ret;	/* this wont happen often so just reuse hash table locks */	HASH_WRITE_ENTER();	if(i < UNITMAX){		_unit[i].on = TRC_ON;		ret = 0;	}	HASH_WRITE_EXIT();	return ret;}/* ----------------------------------------------------------------------   int			// 0=success, 1=failure    trc_turn_unit_off(	// procedure name   tunit_t *tl)	// unit software section variable   desc: turn tracing off for unit section of software    --------------------------------------------------------------------*/int trc_turn_unit_off(uint_t i){	int ret = 1;	if(_unitmax == 0 || i<0 || i>=_unitmax)		return ret;	/* this wont happen often so just reuse hash table locks */	HASH_WRITE_ENTER();	if(i < UNITMAX){		_unit[i].on = TRC_OFF;		ret = 0;	}	HASH_WRITE_EXIT();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -