1/*
2 * Copyright (c) 2002, Intel Corporation. All rights reserved.
3 * Created by:  rolla.n.selbak REMOVE-THIS AT intel 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_setcanceltype
9 * Atomically sets the cancelability type to 'type' and returns the old
10 * cancelability type in the location referenced by 'oldtype'.
11 * 'state' can either be PTHREAD_CANCEL_DEFERRED, or PTHREAD_CANCEL_ASYNCHRONOUS.
12 *
13 * Test when a thread is PTHREAD_CANCEL_DEFERRED
14 *
15 * STEPS:
16 * 1. Setup a mutex and lock it in main()
17 * 2. Create a thread.
18 * 3. In the thread function, set the type to PTHREAD_CANCEL_DEFERRED
19 * 4. Setup a cleanup handler for the thread.
20 * 5. Make the thread block on the locked mutex
21 * 6. Send out a thread cancel request to the new thread, and unlock the mutex allowing the
22 *    thread to continue execution.
23 * 7. If the cancel request was honored immediately, the
24 *    cleanup handler would have been executed, setting the cleanup_flag to -1, making the
25 *    test fail.
26 * 8. If not, the thread will continue execution, pop the cleanup handler, set the cleanup
27 *    flag to 1, and call the cancelation point pthread_testcancel(). The test will pass.
28 * 9. If the thread did not cancel at the cancelation point like it was supposed to, the thread
29 *    will continue execution and set the cleanup_flag to -2, failing the test.
30 */
31
32#include <pthread.h>
33#include <stdio.h>
34#include <errno.h>
35#include <unistd.h>
36#include "posixtest.h"
37
38# define INTHREAD 0 	/* Control going to or is already for Thread */
39# define INMAIN 1	/* Control going to or is already for Main */
40
41int sem1;		/* Manual semaphore */
42int cleanup_flag;	/* Flag to indicate the thread's cleanup handler was called */
43pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;	/* Mutex */
44
45
46/* Cleanup function that the thread executes when it is canceled.  So if
47 * cleanup_flag is 1, it means that the thread was canceled. */
48void a_cleanup_func()
49{
50	cleanup_flag=-1;
51	return;
52}
53
54/* Function that the thread executes upon its creation */
55void *a_thread_func()
56{
57	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
58	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
59
60	pthread_cleanup_push(a_cleanup_func,NULL);
61
62	/* Indicate to main() that the thread has been created. */
63	sem1=INMAIN;
64
65	/* Lock the mutex. It should have already been locked in main, so the thread
66	 * should block. */
67	if(pthread_mutex_lock(&mutex) != 0)
68        {
69		perror("Error in pthread_mutex_lock()\n");
70		pthread_exit((void*)PTS_UNRESOLVED);
71		return (void*)PTS_UNRESOLVED;
72	}
73
74	/* Should get here if the cancel request was deffered. */
75	pthread_cleanup_pop(0);
76	cleanup_flag=1;
77
78	/* Cancelation point.  Cancel request should not be honored here. */
79	pthread_testcancel();
80
81	/* Should not get here if the cancel request was honored at the cancelation point
82	 * pthread_testcancel(). */
83	cleanup_flag=-2;
84	pthread_exit(0);
85	return NULL;
86}
87
88int main()
89{
90	pthread_t new_th;
91
92	/* Initializing values */
93	sem1=INTHREAD;
94	cleanup_flag=0;
95
96	/* Lock the mutex */
97	if(pthread_mutex_lock(&mutex) != 0)
98	{
99		perror("Error in pthread_mutex_lock()\n");
100		return PTS_UNRESOLVED;
101	}
102
103	/* Create a new thread. */
104	if(pthread_create(&new_th, NULL, a_thread_func, NULL) != 0)
105	{
106		perror("Error creating thread\n");
107		return PTS_UNRESOLVED;
108	}
109
110	/* Make sure thread is created before we cancel it. (wait for
111	 * a_thread_func() to set sem1=INMAIN.) */
112	while(sem1==INTHREAD)
113		sleep(1);
114
115	/* Send cancel request to the thread.  */
116	if(pthread_cancel(new_th) != 0)
117	{
118		printf("Test FAILED: Couldn't cancel thread\n");
119		return PTS_FAIL;
120	}
121
122	/* Cancel request has been sent, unlock the mutex */
123	if(pthread_mutex_unlock(&mutex) != 0)
124	{
125		perror("Error in pthread_mutex_unlock()\n");
126		return PTS_UNRESOLVED;
127	}
128
129	/* Wait 'till the thread has been canceled or has ended execution. */
130	if(pthread_join(new_th, NULL) != 0)
131	{
132		perror("Error in pthread_join()\n");
133		return PTS_UNRESOLVED;
134	}
135
136	/* This means that the cleanup function wasn't called, so the cancel
137	 * request was not honord immediately like it should have been. */
138	if(cleanup_flag == -1)
139	{
140		printf("Test FAILED: Cancel request was not deferred.\n");
141		return PTS_FAIL;
142	}
143
144	if(cleanup_flag == -2)
145	{
146		printf("Test FAILED: (1) Cancel request not honored at cancelation point pthread_testcancel() OR (2) pthread_testcancel() not treated as a cancelation point.\n");
147		return PTS_FAIL;
148	}
149
150	printf("Test PASSED\n");
151	return PTS_PASS;
152}
153
154
155