• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2004, QUALCOMM Inc. All rights reserved.
3  * Created by:  abisain REMOVE-THIS AT qualcomm DOT com
4  * This file is licensed under the GPL license.  For the full content
5  * of this license, see the COPYING file at the top level of this
6  * source tree.
7 
8  * Test pthread_cancel()
9  *
10  * Any destructors for thread_specific data will be called after
11  * all cleanup handlers return
12  *
13  * Steps:
14  * 1.  Create a new thread.
15  * 2.  Create a thread specific object in the thread with a destructor
16  * 3.  Add a cleanup function in the thread
17  * 4.  Call pthread_cancel on the thread.
18  * 5.  Make sure that the destructor was called after the cleanup handler
19  *
20  */
21 
22 #include <pthread.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include "posixtest.h"
27 
28 #define TEST "2-3"
29 #define FUNCTION "pthread_cancel"
30 #define ERROR_PREFIX "unexpected error: " FUNCTION " " TEST ": "
31 
32 int cleanup_flag = 0;
33 int destructor_flag = 0;
34 int sem = 0;			/* manual semaphore */
35 struct timespec destructor_time, cleanup_time;
36 
37 /*
38    Destructor for the Thread Specific Data
39  */
destructor(void * tmp)40 void destructor(void *tmp)
41 {
42 	clock_gettime(CLOCK_REALTIME, &destructor_time);
43 	destructor_flag = 1;
44 }
45 
46 /*
47    Cleanup Handler for the Thread
48  */
cleanup_function()49 void cleanup_function()
50 {
51 	clock_gettime(CLOCK_REALTIME, &cleanup_time);
52 	cleanup_flag = 1;
53 }
54 
55 /* Thread's function. */
a_thread_func(void * tmp)56 void *a_thread_func(void *tmp)
57 {
58 	pthread_key_t key;
59 	int value = 1;
60 	int rc = 0;
61 
62 	/* To enable thread immediate cancelation, since the default
63 	 * is PTHREAD_CANCEL_DEFERRED. */
64 	rc = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
65 	if (rc != 0) {
66 		printf(ERROR_PREFIX "pthread_setcanceltype\n");
67 		exit(PTS_UNRESOLVED);
68 	}
69 
70 	rc = pthread_key_create(&key, destructor);
71 	if (rc != 0) {
72 		printf(ERROR_PREFIX "pthread_key_create\n");
73 		exit(PTS_UNRESOLVED);
74 	}
75 
76 	rc = pthread_setspecific(key, &value);
77 	if (rc != 0) {
78 		printf(ERROR_PREFIX "pthread_setspecific\n");
79 		exit(PTS_UNRESOLVED);
80 	}
81 
82 	pthread_cleanup_push(cleanup_function, NULL);
83 
84 	/* Tell main that the key is created */
85 	sem = 1;
86 
87 	/* Sleep forever */
88 	while (1)
89 		sleep(5);
90 
91 	pthread_cleanup_pop(0);
92 	return NULL;
93 }
94 
main(void)95 int main(void)
96 {
97 	pthread_t new_th;
98 	int rc = 0;
99 	double diff;
100 	sem = 0;
101 
102 	/* Create a new thread. */
103 	rc = pthread_create(&new_th, NULL, a_thread_func, NULL);
104 	if (rc != 0) {
105 		printf(ERROR_PREFIX "pthread_create\n");
106 		exit(PTS_UNRESOLVED);
107 	}
108 
109 	/* Wait for the thread to be ready */
110 	while (sem == 0)
111 		sleep(1);
112 
113 	/* Cancel the thread. */
114 	rc = pthread_cancel(new_th);
115 	if (rc != 0) {
116 		printf(ERROR_PREFIX "pthread_cancel\n");
117 		exit(PTS_UNRESOLVED);
118 	}
119 
120 	/* Delay enough so that the destructor must have been called */
121 	sleep(5);
122 
123 	if (cleanup_flag != 1) {
124 		printf(ERROR_PREFIX
125 		       "Test FAIL: Cleanup handler was not executed.\n");
126 		exit(PTS_FAIL);
127 	}
128 
129 	if (destructor_flag != 1) {
130 		printf(ERROR_PREFIX
131 		       "Test FAIL: Destructor was not executed.\n");
132 		exit(PTS_FAIL);
133 	}
134 
135 	diff = destructor_time.tv_sec - cleanup_time.tv_sec;
136 	diff +=
137 	    (double)(destructor_time.tv_nsec -
138 		     cleanup_time.tv_nsec) / 1000000000.0;
139 	if (diff < 0) {
140 		printf(ERROR_PREFIX
141 		       "Test FAIL: Destructor called before Cleanup Handler\n");
142 		exit(PTS_FAIL);
143 	}
144 
145 	printf("Test PASSED\n");
146 	exit(PTS_PASS);
147 }
148