24 private_t *private = (private_t*)value;
25 int status;
26
27 printf ('thread '%s' exiting...
', private->string);
28 free (value);
29 status = pthread_mutex_lock (&identity_key_mutex);
30 if (status != 0)
31 err_abort (status, 'Lock key mutex');
32 identity_key_counter--;
33 if (identity_key_counter <= 0) {
34 status = pthread_key_delete (identity_key);
35 if (status != 0)
36 err_abort (status, 'Delete key');
37 printf ('key deleted...
');
38 }
39 status = pthread_mutex_unlock (&identity_key_mutex);
40 if (status != 0)
41 err_abort (status, 'Unlock key mutex');
42 }
43
44 /*
45 * Helper routine to allocate a new value for thread-specific
46 * data key if the thread doesn't already have one.
47 */
48 void *identity_key_get (void)
49 {
50 void *value;
51 int status; 52
53 value = pthread_getspecific (identity_key);
54 if (value == NULL) {
55 value = malloc (sizeof (private_t));
56 if (value == NULL)
57 errno_abort ('Allocate key value');
58 status = pthread_setspecific (identity_key, (void*)value);
59 if (status != 0)
60 err_abort (status, 'Set TSD');
61 }
62 return value;
63 }
64
65 /*
66 * Thread start routine to use thread-specific data.
67 */
68 void *thread_routine (void *arg)
69 {
70 private_t *value; 71
72 value = (private_t*)identity_key_get ();
73 value->thread_id = pthread_self ();
74 value->string = (char*)arg;
75 printf ('thread '%s' starting...
', value->string);
76 sleep (2);
77 return NULL;
78 }
79
80 void main (int argc, char *argv[])
81 {
82 pthread_t thread_l, thread_2;
83 private_t *value;
84 int status;
85
86 /*
87 * Create the TSD key, and set the reference counter to
88 * the number of threads that will use it (two thread_routine
89 * threads plus main). This must be done before creating
90 * the threads! Otherwise, if one thread runs the key's
91 * destructor before any other thread uses the key, it will
92 * be deleted.
93 *
94 * Note that there's rarely any good reason to delete a
95 * thread-specific data key.
96 */
97 status = pthread_key_create (
98 &identity_key, identity_key_destructor);
99 if (status != 0)
100 err_abort (status, 'Create key');
101 identity_key_counter = 3;
102 value = (private_t*)identity_key_get ();
103 value->thread_id = pthread_self ();
104 value->string = 'Main thread';
105 status = pthread_create (&thread_1, NULL,
106 thread_routine, 'Thread 1');
107 if (status != 0)
108 err_abort (status, 'Create thread 1');
109 status = pthread_create (&thread_2, NULL,
110 thread_routine, 'Thread 2');
111 if (status != 0)
112 err_abort (status, 'Create thread 2');
113 pthread_exit (NULL);
114 }
5.5 Realtime scheduling