1//------------------------------------------------------------------------------
2// Copyright (c) 2016 by Lukasz Janyst <lukasz@jany.st>
3//------------------------------------------------------------------------------
4// This file is part of thread-bites.
5//
6// thread-bites is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// thread-bites is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with thread-bites. If not, see <http://www.gnu.org/licenses/>.
18//------------------------------------------------------------------------------
19
20#include <tb.h>
21#include <string.h>
22
23//------------------------------------------------------------------------------
24// TLS keys
25//------------------------------------------------------------------------------
26tbthread_key_t key1;
27tbthread_key_t key2;
28tbthread_key_t key3;
29
30//------------------------------------------------------------------------------
31// TLS destructors
32//------------------------------------------------------------------------------
33void dest1(void *data)
34{
35 tbprint("[thread 0x%llx] Error: calling dest1\n", tbthread_self());
36}
37
38void dest2(void *data)
39{
40 tbprint("[thread 0x%llx] Error: calling dest2\n", tbthread_self());
41}
42
43void dest3(void *data)
44{
45 tbprint("[thread 0x%llx] Calling dest3\n", tbthread_self());
46 free(data);
47}
48
49//------------------------------------------------------------------------------
50// Thread function
51//------------------------------------------------------------------------------
52void *thread_func(void *arg)
53{
54 int num = *(int*)arg;
55 int i;
56 tbthread_t self = tbthread_self();
57 tbprint("[thread 0x%llx] Hello from thread #%d\n", self, num);
58 tbprint("[thread 0x%llx] Allocating the TLS data\n", self);
59 void *data1 = malloc(20);
60 void *data2 = malloc(20);
61 void *data3 = malloc(20);
62 tbthread_setspecific(key1, data1);
63 tbthread_setspecific(key2, data2);
64 tbthread_setspecific(key3, data3);
65
66 tbprint("[thread 0x%llx] Sleeping 3 seconds\n", self);
67 tbsleep(3);
68 void *data1r = tbthread_getspecific(key1);
69 void *data2r = tbthread_getspecific(key2);
70 void *data3r = tbthread_getspecific(key3);
71 if(data1r != data1)
72 tbprint("[thread 0x%llx] Error: datar != data\n", self);
73 if(data2r != 0)
74 tbprint("[thread 0x%llx] Error: data2r != 0\n", self);
75 if(data3r != data3)
76 tbprint("[thread 0x%llx] Error: data3r != data3\n", self);
77 free(data2);
78 free(data1);
79 tbthread_setspecific(key1, 0);
80 tbprint("[thread 0x%llx] Sleeping 1 second\n", self);
81 tbsleep(1);
82 return 0;
83}
84
85//------------------------------------------------------------------------------
86// Start the show
87//------------------------------------------------------------------------------
88int main(int argc, char **argv)
89{
90 tbthread_init();
91
92 tbthread_t thread[5];
93 int targ[5];
94 tbthread_attr_t attr;
95 void *ret;
96 int st = 0;
97
98 //----------------------------------------------------------------------------
99 // Allocate the keys
100 //----------------------------------------------------------------------------
101 tbthread_key_create(&key1, dest1);
102 tbthread_key_create(&key2, dest2);
103 tbthread_key_create(&key3, dest3);
104 tbthread_key_delete(key1);
105 tbthread_key_delete(key3);
106 tbthread_key_create(&key3, dest3);
107 tbthread_key_create(&key1, dest1);
108 tbprint("[thread main] TLS keys: %u, %u, %u\n", key1, key2, key3);
109
110 //----------------------------------------------------------------------------
111 // Spawn the threads
112 //----------------------------------------------------------------------------
113 tbthread_attr_init(&attr);
114 for(int i = 0; i < 5; ++i) {
115 targ[i] = i;
116 st = tbthread_create(&thread[i], &attr, thread_func, &targ[i]);
117 if(st != 0) {
118 tbprint("Failed to spawn thread %d: %s\n", i, strerror(-st));
119 goto exit;
120 }
121 tbthread_detach(thread[i]);
122 }
123
124 tbprint("[thread main] Threads spawned successfully\n");
125 tbprint("[thread main] Sleeping 1 second\n");
126 tbsleep(1);
127 tbprint("[thread main] Destroying key2\n");
128 tbthread_key_delete(key2);
129 tbprint("[thread main] Sleeping 10 seconds\n");
130 tbsleep(10);
131
132exit:
133 tbthread_finit();
134 return st;
135};
136