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//------------------------------------------------------------------------------
8tbthread_key_t key;
9extern int tb_pid;
10void 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//------------------------------------------------------------------------------
20void *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//------------------------------------------------------------------------------
35int 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
92exit:
93 tbthread_key_delete(key);
94 tbthread_finit();
95 return 0;
96}
97