summaryrefslogtreecommitdiff
path: root/pstack/linuxthreads.c
blob: 8624bd217829e946939993d1962def2dceb74f7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* $Header$ */

/*
 * LinuxThreads specific stuff.
 */

#include	<sys/types.h>

#include	<assert.h>
#include	<limits.h>	/* PTHREAD_THREADS_MAX */
#include	<pthread.h>
#include	<stdio.h>
#include	<unistd.h>
#include	<signal.h>
#include	<sched.h>

#include	"linuxthreads.h"

#define AT_INT(intval)	*((int32_t*)(intval))

/*
 * Internal LinuxThreads variables.
 * Official interface exposed to GDB.
 */
#if 1
extern volatile	int		__pthread_threads_debug;
extern volatile	char		__pthread_handles;
extern char			__pthread_initial_thread;
/*extern volatile	Elf32_Sym*	__pthread_manager_thread;*/
extern const int		__pthread_sizeof_handle;
extern const int		__pthread_offsetof_descr;
extern const int		__pthread_offsetof_pid;
extern volatile	int		__pthread_handles_num;
#endif /* 0 */

/*
 * Notify others.
 */
int
linuxthreads_notify_others(	const int	signotify)
{
	const pid_t			mypid = getpid();
	//const pthread_t			mytid = pthread_self();
	int				i;
	int				threadcount = 0;
	int				threads[PTHREAD_THREADS_MAX];
	int				pid;

	TRACE_FPRINTF((stderr, "theadcount:%d\n", __pthread_handles_num));
	if (__pthread_handles_num==2) {
		/* no threads beside the initial thread */
		return 0;
	}
	/*assert(maxthreads>=3);
	assert(maxthreads>=__pthread_handles_num+2);*/

	// take the initial thread with us
	pid = AT_INT(&__pthread_initial_thread + __pthread_offsetof_pid);
	if (pid!=mypid && pid!=0)
		threads[threadcount++] = pid;
	// don't know why, but always handles[0]==handles[1]
	for (i=1; i<__pthread_handles_num; ++i) {
		const int descr = AT_INT(&__pthread_handles+i*__pthread_sizeof_handle+__pthread_offsetof_descr);
		assert(descr!=0);
		pid = AT_INT(descr+__pthread_offsetof_pid);
		if (pid!=mypid && pid!=0)
			threads[threadcount++] = pid;
	}
	/* TRACE_FPRINTF((stderr, "Stopping threads...")); */
	//for (i=0; i<threadcount; ++i) {
	//	/* TRACE_FPRINTF((stderr, "%d ", threads[i])); */
	//	fflush(stdout);
	//	kill(threads[i], SIGSTOP);	/* Tell thread to stop */
	//}
	/* TRACE_FPRINTF((stderr, " done!\n")); */
	for (i=0; i<threadcount; ++i) {
		TRACE_FPRINTF((stderr, "--- NOTIFYING %d\n", threads[i]));
		kill(threads[i], signotify);	/* Tell to print stack trace */
		/* TRACE_FPRINTF((stderr, "--- WAITING FOR %d\n", threads[i])); */
		/*pause();		 Wait for confirmation. */
	}
	for (i=0; i<threadcount; ++i)
		sched_yield();
	for (i=0; i<threadcount; ++i) {
		TRACE_FPRINTF((stderr, "--- KILLING %d\n", threads[i]));
		kill(threads[i], SIGKILL);	/* Tell thread die :) */
	}
	return __pthread_handles_num;
}