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 * When the cancelation is acted on, the cancelation cleanup handlers for 10 * 'thread' shall be called "asynchronously" 11 * 12 * STEPS: 13 * 1. Change main thread to a real-time thread with a high priority 14 * 1. Create a lower priority thread 15 * 2. In the thread function, push a cleanup function onto the stack 16 * 3. Cancel the thread from main and get timestamp, then block. 17 * 4. The cleanup function should be automatically 18 * executed, else the test will fail. 19 */ 20 21#include <pthread.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <errno.h> 25#include <unistd.h> 26#include "posixtest.h" 27#include <time.h> 28 29#define TEST "3-1" 30#define FUNCTION "pthread_cancel" 31#define ERROR_PREFIX "unexpected error: " FUNCTION " " TEST ": " 32 33#define FIFOPOLICY SCHED_FIFO 34#define MAIN_PRIORITY 30 35#define TIMEOUT_IN_SECS 10 36 37/* Manual semaphore */ 38int sem; 39 40/* Made global so that the cleanup function 41 * can manipulate the value as well. 42 */ 43int cleanup_flag; 44struct timespec main_time, cleanup_time; 45 46/* A cleanup function that sets the cleanup_flag to 1, meaning that the 47 * cleanup function was reached. 48 */ 49void a_cleanup_func() 50{ 51 clock_gettime(CLOCK_REALTIME, &cleanup_time); 52 cleanup_flag = 1; 53 sem = 0; 54 return; 55} 56 57/* A thread function called at the creation of the thread. It will push 58 * the cleanup function onto it's stack, then go into a continuous 'while' 59 * loop, never reaching the cleanup_pop function. So the only way the cleanup 60 * function can be called is when the thread is canceled and all the cleanup 61 * functions are supposed to be popped. 62 */ 63void *a_thread_func() 64{ 65 int rc = 0; 66 67 /* To enable thread immediate cancelation, since the default 68 * is PTHREAD_CANCEL_DEFERRED. 69 */ 70 rc = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 71 if(rc != 0) { 72 printf(ERROR_PREFIX "pthread_setcanceltype\n"); 73 exit(PTS_UNRESOLVED); 74 } 75 pthread_cleanup_push(a_cleanup_func, NULL); 76 77 sem=1; 78 while(sem == 1) 79 sleep(1); 80 sleep(5); 81 sem=0; 82 83 /* Should never be reached, but is required to be in the code 84 * since pthread_cleanup_push is in the code. Else a compile error 85 * will result. 86 */ 87 pthread_cleanup_pop(0); 88 pthread_exit(0); 89 return NULL; 90} 91 92int main() 93{ 94 pthread_t new_th; 95 int i; 96 double diff ; 97 struct sched_param param; 98 int rc = 0; 99 100 /* Initializing the cleanup flag. */ 101 cleanup_flag = 0; 102 sem = 0; 103 param.sched_priority = MAIN_PRIORITY; 104 105 /* Increase priority of main, so the new thread doesn't get to run */ 106 rc = pthread_setschedparam(pthread_self(), FIFOPOLICY, ¶m); 107 if(rc != 0) { 108 printf(ERROR_PREFIX "pthread_setschedparam\n"); 109 exit(PTS_UNRESOLVED); 110 } 111 112 /* Create a new thread. */ 113 rc = pthread_create(&new_th, NULL, a_thread_func, NULL); 114 if(rc != 0) { 115 printf(ERROR_PREFIX "pthread_create\n"); 116 return PTS_UNRESOLVED; 117 } 118 119 /* Make sure thread is created and executed before we cancel it. */ 120 while(sem == 0) 121 sleep(1); 122 123 rc = pthread_cancel(new_th); 124 if(rc != 0) { 125 printf(ERROR_PREFIX "pthread_cancel\n"); 126 exit(PTS_FAIL); 127 } 128 129 /* Get the time after canceling the thread */ 130 clock_gettime(CLOCK_REALTIME, &main_time); 131 i = 0; 132 while(sem == 1) { 133 sleep(1); 134 if(i == TIMEOUT_IN_SECS) { 135 printf(ERROR_PREFIX "Cleanup handler was not called\n"); 136 exit(PTS_FAIL); 137 } 138 i++; 139 } 140 141 /* If the cleanup function was not reached by calling the 142 * pthread_cancel function, then the test fails. 143 */ 144 if(cleanup_flag != 1) { 145 printf(ERROR_PREFIX "Cleanup handler was not called\n"); 146 exit(PTS_FAIL); 147 } 148 149 diff = cleanup_time.tv_sec - main_time.tv_sec; 150 diff += (double)(cleanup_time.tv_nsec - main_time.tv_nsec)/1000000000.0; 151 if(diff < 0) { 152 printf(ERROR_PREFIX "Cleanup function was called before main continued\n"); 153 exit(PTS_FAIL); 154 } 155 printf("Test PASS\n"); 156 exit(PTS_PASS); 157} 158