1 | |
2 | #include <tb.h> |
3 | #include <string.h> |
4 | |
5 | //------------------------------------------------------------------------------ |
6 | // Signal handler, we don't print anything here because tbprint takes a lock |
7 | //------------------------------------------------------------------------------ |
8 | tbthread_key_t key; |
9 | extern int tb_pid; |
10 | void sigusr_handler(int sig, siginfo_t *si, void *ctx) |
11 | { |
12 | int *sig_status = (int *)tbthread_getspecific(key); |
13 | if (sig == SIGUSR1 && si->si_pid == tb_pid && si->si_code == SI_TKILL) |
14 | *sig_status = 1; |
15 | } |
16 | |
17 | //------------------------------------------------------------------------------ |
18 | // Thread function |
19 | //------------------------------------------------------------------------------ |
20 | void *thread_func(void *arg) |
21 | { |
22 | tbthread_t self = tbthread_self(); |
23 | int sig_status = 0; |
24 | tbthread_setspecific(key, &sig_status); |
25 | for(int i = 0; i < 5; ++i) { |
26 | tbprint("[thread 0x%llx] Hello! Signal status: %d\n" , self, sig_status); |
27 | tbsleep(1); |
28 | } |
29 | return arg; |
30 | } |
31 | |
32 | //------------------------------------------------------------------------------ |
33 | // Start the show |
34 | //------------------------------------------------------------------------------ |
35 | int main(int argc, char **argv) |
36 | { |
37 | tbthread_init(); |
38 | |
39 | //---------------------------------------------------------------------------- |
40 | // Install the signal handler |
41 | //---------------------------------------------------------------------------- |
42 | struct sigaction sa; |
43 | int st = 0; |
44 | memset(&sa, 0, sizeof(struct sigaction)); |
45 | sa.sa_handler = (__sighandler_t)sigusr_handler; |
46 | sa.sa_flags = SA_SIGINFO; |
47 | st = tbsigaction(SIGUSR1, &sa, 0); |
48 | if(st) { |
49 | tbprint("Unable to install sigaction handler: %s\n" , tbstrerror(-st)); |
50 | goto exit; |
51 | } |
52 | |
53 | //---------------------------------------------------------------------------- |
54 | // Spawn the threads |
55 | //---------------------------------------------------------------------------- |
56 | tbthread_key_create(&key, 0); |
57 | tbthread_t thread[5]; |
58 | tbthread_attr_t attr; |
59 | tbthread_attr_init(&attr); |
60 | |
61 | tbprint("[thread main] Spawning threads. PID: %d\n" , tb_pid); |
62 | for(int i = 0; i < 5; ++i) { |
63 | st = tbthread_create(&thread[i], &attr, thread_func, 0); |
64 | if(st != 0) { |
65 | tbprint("Failed to spawn thread %d: %s\n" , i, tbstrerror(-st)); |
66 | goto exit; |
67 | } |
68 | } |
69 | |
70 | tbprint("[thread main] Threads spawned successfully\n" ); |
71 | |
72 | //---------------------------------------------------------------------------- |
73 | // Sending signal to threads |
74 | //---------------------------------------------------------------------------- |
75 | for(int i = 0; i < 5; ++i) { |
76 | tbprint("[thread main] Sending SIGUSR1 to thread #%d\n" , i); |
77 | SYSCALL3(__NR_tgkill, tb_pid, thread[i]->tid, SIGUSR1); |
78 | } |
79 | |
80 | //---------------------------------------------------------------------------- |
81 | // Joining threads |
82 | //---------------------------------------------------------------------------- |
83 | for(int i = 0; i < 5; ++i) { |
84 | void *ret; |
85 | st = tbthread_join(thread[i], &ret); |
86 | if(st != 0) { |
87 | tbprint("Failed to join thread %d: %s\n" , i, tbstrerror(-st)); |
88 | goto exit; |
89 | } |
90 | } |
91 | |
92 | exit: |
93 | tbthread_key_delete(key); |
94 | tbthread_finit(); |
95 | return 0; |
96 | } |
97 | |