1/* 2 * Copyright (c) 2004, Bull S.A.. All rights reserved. 3 * Created by: Sebastien Decugis 4 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write the Free Software Foundation, Inc., 59 15 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 16 17 18 * This sample test aims to check the following assertion: 19 * 20 * pthread_create creates a new thread within the process 21 22 * The steps are: 23 * 24 * -> get the thread ID and the process ID of the main thread. 25 * -> create a new thread, get the thread & process ID. 26 * -> check that the thread IDs are different but process IDs are the same 27 28 * The test fails if the thread IDs are the same or the proces IDs are different. 29 30 */ 31 32 33 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 34 #define _POSIX_C_SOURCE 200112L 35 36 /* Some routines are part of the XSI Extensions */ 37#ifndef WITHOUT_XOPEN 38 #define _XOPEN_SOURCE 600 39#endif 40/********************************************************************************************/ 41/****************************** standard includes *****************************************/ 42/********************************************************************************************/ 43 #include <pthread.h> 44 #include <stdarg.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include <sched.h> 51 #include <semaphore.h> 52 #include <errno.h> 53 #include <assert.h> 54/********************************************************************************************/ 55/****************************** Test framework *****************************************/ 56/********************************************************************************************/ 57 #include "testfrmw.h" 58 #include "testfrmw.c" 59 /* This header is responsible for defining the following macros: 60 * UNRESOLVED(ret, descr); 61 * where descr is a description of the error and ret is an int (error code for example) 62 * FAILED(descr); 63 * where descr is a short text saying why the test has failed. 64 * PASSED(); 65 * No parameter. 66 * 67 * Both three macros shall terminate the calling process. 68 * The testcase shall not terminate in any other maneer. 69 * 70 * The other file defines the functions 71 * void output_init() 72 * void output(char * string, ...) 73 * 74 * Those may be used to output information. 75 */ 76 77/********************************************************************************************/ 78/********************************** Configuration ******************************************/ 79/********************************************************************************************/ 80#ifndef VERBOSE 81#define VERBOSE 1 82#endif 83 84/********************************************************************************************/ 85/*********************************** Test cases *****************************************/ 86/********************************************************************************************/ 87 88#include "threads_scenarii.c" 89 90/* This file will define the following objects: 91 * scenarii: array of struct __scenario type. 92 * NSCENAR : macro giving the total # of scenarii 93 * scenar_init(): function to call before use the scenarii array. 94 * scenar_fini(): function to call after end of use of the scenarii array. 95 */ 96 97/********************************************************************************************/ 98/*********************************** Real Test *****************************************/ 99/********************************************************************************************/ 100 101struct testdata 102{ 103 pthread_t tid; 104 pid_t pid; 105 sem_t * sem; 106}; 107 108int global; /* This value is used to check both threads share the same process memory (and not a copy) */ 109 110void * threaded (void * arg) 111{ 112 struct testdata * td=(struct testdata *) arg; 113 pthread_t mytid; 114 pid_t mypid; 115 int ret = 0; 116 117 /* Compare the process IDs */ 118 mypid=getpid(); 119 #if VERBOSE > 0 120 output(" Main pid: %i thread pid: %i\n", td->pid, mypid); 121 #endif 122 123 if (mypid != td->pid) 124 { 125 FAILED("New thread does not belong to the same process as its parent thread"); 126 } 127 128 /* Compare the threads IDs */ 129 mytid = pthread_self(); 130 #if VERBOSE > 0 131 /* pthread_t is a pointer with Linux/nptl. This output can be erroneous for other arcs */ 132 output(" Main tid: %p thread tid: %p\n", td->tid, mytid); 133 #endif 134 135 if (pthread_equal(mytid, td->tid) != 0) 136 { 137 FAILED("The created thread has the same thread ID as its parent"); 138 } 139 140 /* Change the global value */ 141 global++; 142 143 /* Post the semaphore to unlock the main thread in case of a detached thread */ 144 do { ret = sem_post(td->sem); } 145 while ((ret == -1) && (errno == EINTR)); 146 if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } 147 148 return arg; 149} 150 151int main (int argc, char *argv[]) 152{ 153 int ret=0; 154 struct testdata td; 155 void * rval; 156 pthread_t child; 157 int i; 158 159 output_init(); 160 161 td.tid=pthread_self(); 162 td.pid=getpid(); 163 164 scenar_init(); 165 166 for (i=0; i < NSCENAR; i++) 167 { 168 #if VERBOSE > 0 169 output("-----\n"); 170 output("Starting test with scenario (%i): %s\n", i, scenarii[i].descr); 171 #endif 172 173 td.sem = &scenarii[i].sem; 174 175 global = 2*i; 176 177 ret = pthread_create(&child, &scenarii[i].ta, threaded, &td); 178 switch (scenarii[i].result) 179 { 180 case 0: /* Operation was expected to succeed */ 181 if (ret != 0) { UNRESOLVED(ret, "Failed to create this thread"); } 182 break; 183 184 case 1: /* Operation was expected to fail */ 185 if (ret == 0) { UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); } 186 break; 187 188 case 2: /* We did not know the expected result */ 189 default: 190 #if VERBOSE > 0 191 if (ret == 0) 192 { output("Thread has been created successfully for this scenario\n"); } 193 else 194 { output("Thread creation failed with the error: %s\n", strerror(ret)); } 195 #endif 196 } 197 if (ret == 0) /* The new thread is running */ 198 { 199 if (scenarii[i].detached == 0) 200 { 201 ret = pthread_join(child, &rval); 202 if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } 203 204 if (rval != &td) 205 { 206 FAILED("Could not get the thread return value. Did it execute?"); 207 } 208 } 209 else 210 { 211 /* Just wait for the thread terminate */ 212 do { ret = sem_wait(td.sem); } 213 while ((ret == -1) && (errno == EINTR)); 214 if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } 215 } 216 217 if (global != (2*i + 1)) 218 { 219 /* Maybe a possible issue with CPU memory-caching here? */ 220 FAILED("The threads do not share the same process memory."); 221 } 222 } 223 } 224 225 scenar_fini(); 226 #if VERBOSE > 0 227 output("-----\n"); 228 output("All test data destroyed\n"); 229 output("Test PASSED\n"); 230 #endif 231 232 PASSED; 233} 234 235