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 * If attr is NULL, the effect is the same as passing the address 21 * of a default condition variable attributes object. 22 23 * The steps are: 24 * -> Create two cond vars, one with NULL attribute and 25 * the other with a default attribute. 26 * -> Compare those two cond vars: 27 * -> If the Thread Process-shared Synchronization is supported, 28 * does both condvars have the same behavior across 29 * different process? (Beware of the spurious wakeups). 30 * (Steps to achieve this goal: 31 * - Have the two cond vars created in shared memory. 32 * - The associated mutex are process-shared and in shared memory also. 33 * - Fork 34 * - One thread in parent process and one thread in child process 35 * wait for the cond. 36 * - Broadcast the cond from the parent process; 37 * then sleep for a while and check if the child process was awaken. 38 * - Do the same with the other condvar; then compare the result. 39 * ) 40 */ 41 42 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 43 #define _POSIX_C_SOURCE 200112L 44 45 /* We need the XSI extention for the mkstemp() routine 46 * - we could rewrite this test without this routine... 47 */ 48#ifndef WITHOUT_XOPEN 49 #define _XOPEN_SOURCE 600 50#endif 51 /********************************************************************************************/ 52/****************************** standard includes *****************************************/ 53/********************************************************************************************/ 54 #include <pthread.h> 55 #include <stdarg.h> 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <unistd.h> 59 60 #include <errno.h> 61 #include <sys/wait.h> 62 #include <sys/mman.h> 63 #include <semaphore.h> 64 #include <string.h> 65 #include <signal.h> 66 67/********************************************************************************************/ 68/****************************** Test framework *****************************************/ 69/********************************************************************************************/ 70 #include "testfrmw.h" 71 #include "testfrmw.c" 72 /* This header is responsible for defining the following macros: 73 * UNRESOLVED(ret, descr); 74 * where descr is a description of the error and ret is an int (error code for example) 75 * FAILED(descr); 76 * where descr is a short text saying why the test has failed. 77 * PASSED(); 78 * No parameter. 79 * 80 * Both three macros shall terminate the calling process. 81 * The testcase shall not terminate in any other maneer. 82 * 83 * The other file defines the functions 84 * void output_init() 85 * void output(char * string, ...) 86 * 87 * Those may be used to output information. 88 */ 89 90/********************************************************************************************/ 91/********************************** Configuration ******************************************/ 92/********************************************************************************************/ 93#ifndef VERBOSE 94#define VERBOSE 1 95#endif 96 97/********************************************************************************************/ 98/*********************************** Test case *****************************************/ 99/********************************************************************************************/ 100#ifndef WITHOUT_XOPEN 101 102/* The data shared between both processes */ 103typedef struct 104{ 105 pthread_mutex_t mtxN; /* Mutex for Null attr condvar */ 106 pthread_mutex_t mtxD; /* Mutex for Default attr condvar */ 107 pthread_mutex_t mtxP; /* Mutex for Pshared condvar */ 108 pthread_cond_t cndN; 109 pthread_cond_t cndD; 110 pthread_cond_t cndP; 111 int cntrN; 112 int cntrD; 113 int cntrP; 114 char bool; 115 sem_t semA; 116 sem_t semB; 117 int result; 118 pid_t child; 119} globaldata_t; 120 121/* The data shared between the threads in the child process */ 122typedef struct 123{ 124 pthread_mutex_t * pmtx; 125 pthread_cond_t * pcnd; 126 int * pcntr; 127 char * pbool; 128 sem_t * psem; 129 pthread_t *pth; 130} datatest_t; 131 132/* The data shared with the signal handlers in the child process */ 133struct 134{ 135 sem_t * psem; 136 pthread_t th[3]; 137} sigdata; 138 139/**** 140 * The child threads signal handler. 141 * 142 */ 143void childsighdl(int sig) 144{ 145 int ret=0; 146 ret = sem_post(sigdata.psem); 147 if (ret != 0) 148 { UNRESOLVED(errno, "[child] Unable to post semaphore in thread signal handler"); } 149} 150 151/**** 152 * The child main signal handler 153 * 154 */ 155void mainsighdl(int sig) 156{ 157 /* We assume this signal handler is never called before the sigdata structure is initialized */ 158 int ret = 0; 159 160 ret = pthread_kill(sigdata.th[0], SIGUSR2); 161 if (ret != 0) 162 { UNRESOLVED(ret, "[child] Unable to kill a child thread"); } 163 ret = pthread_kill(sigdata.th[1], SIGUSR2); 164 if (ret != 0) 165 { UNRESOLVED(ret, "[child] Unable to kill a child thread"); } 166 ret = pthread_kill(sigdata.th[2], SIGUSR2); 167 if (ret != 0) 168 { UNRESOLVED(ret, "[child] Unable to kill a child thread"); } 169} 170 171/**** 172 * child_process_th 173 * Child process's thread function 174 * 175 */ 176void * child_process_th(void * arg) 177{ 178 int ret=0; 179 datatest_t * dt = (datatest_t *) arg; 180 struct sigaction sa; 181 182 /* Register into the signal data structure */ 183 *(dt->pth) = pthread_self(); 184 185 /* Set the signal action and mask for the child thread: Will call childsighdl when SIGUSR2 is received. */ 186 sigemptyset (&sa.sa_mask); 187 sa.sa_flags = 0; 188 sa.sa_handler = childsighdl; 189 ret = sigaction (SIGUSR2, &sa, NULL); 190 if (ret != 0) 191 { UNRESOLVED(ret, "[child] Unable to register action for SIGUSR2"); } 192 193 /* Any signal other than SIGUSR2 is blocked. */ 194 sigfillset(&sa.sa_mask); 195 sigdelset(&sa.sa_mask, SIGUSR2); 196 ret = pthread_sigmask (SIG_SETMASK, &sa.sa_mask, NULL); 197 if (ret != 0) 198 { UNRESOLVED(ret, "[child] Unable to set signal mask in child thread"); } 199 200 201 /* lock the mutex */ 202 ret = pthread_mutex_lock(dt->pmtx); 203 if (ret != 0) 204 { UNRESOLVED(ret, "[child][th] Unable to lock mutex."); } 205 206 /* We can now let the parent thread start its work */ 207 do { ret = sem_post(dt->psem); } 208 while ((ret != 0) && (errno == EINTR)); 209 if (ret != 0) 210 { UNRESOLVED(ret, "[child] Unable to post semaphore"); } 211 212 /* Now, do the actual test: wait for the cond */ 213 do 214 { 215 *(dt->pcntr) += 1; 216 ret = pthread_cond_wait(dt->pcnd, dt->pmtx); 217 *(dt->pcntr) += 1; 218 } while ((ret == 0) && (*(dt->pbool) == 0)); 219 220 if (ret != 0) 221 { 222 #if VERBOSE > 1 223 output("[child][thr] Unable to wait for the cond: %d - %s", ret, strerror(ret) ); 224 #endif 225 *(dt->pcntr) = 0; /* this will signal the parent thread that an error happened */ 226 } 227 228 /* unlock the mutex */ 229 ret = pthread_mutex_unlock(dt->pmtx); 230 if (ret != 0) 231 { UNRESOLVED(ret, "[child][th] Unable to unlock mutex."); } 232 233 return NULL; 234} 235 236/**** 237 * child_process 238 * Child process main thread 239 * This function is called in the child process just after the fork. 240 */ 241int child_process(globaldata_t * gd) 242{ 243 int ret; 244 datatest_t dtN, dtD, dtP; 245 pthread_t thN, thD, thP; 246 247 struct sigaction sa; 248 249 /* Initialize the datatest structures for the sub threads */ 250 dtN.pmtx = &(gd->mtxN); 251 dtN.pcnd = &(gd->cndN); 252 dtN.pcntr = &(gd->cntrN); 253 dtN.pbool = &(gd->bool); 254 dtN.psem = &(gd->semA); 255 dtN.pth = &(sigdata.th[0]); 256 dtD.pmtx = &(gd->mtxD); 257 dtD.pcnd = &(gd->cndD); 258 dtD.pcntr = &(gd->cntrD); 259 dtD.pbool = &(gd->bool); 260 dtD.psem = &(gd->semA); 261 dtD.pth = &(sigdata.th[1]); 262 dtP.pmtx = &(gd->mtxP); 263 dtP.pcnd = &(gd->cndP); 264 dtP.pcntr = &(gd->cntrP); 265 dtP.pbool = &(gd->bool); 266 dtP.psem = &(gd->semA); 267 dtP.pth = &(sigdata.th[2]); 268 269 sigdata.psem = &(gd->semA); 270 271 /* Register the signal handler: mainsighdl will be called when this thread receives SIGUSR1 */ 272 sigemptyset (&sa.sa_mask); 273 sigaddset(&sa.sa_mask, SIGUSR2); 274 sa.sa_flags = 0; 275 sa.sa_handler = mainsighdl; 276 ret = sigaction (SIGUSR1, &sa, NULL); 277 if (ret != 0) 278 { UNRESOLVED(ret, "[child] Unable to register action for SIGUSR1"); } 279 280 /* Set this thread's signal mask: we only accept SIGUSR1 */ 281 sigfillset (&sa.sa_mask); 282 sigdelset(&sa.sa_mask, SIGUSR1); 283 ret = pthread_sigmask (SIG_SETMASK, &sa.sa_mask, NULL); 284 if (ret != 0) 285 { UNRESOLVED(ret, "[child] Unable to set signal mask in child main thread"); } 286 287 /* We start the test threads */ 288 ret = pthread_create(&thN, NULL, child_process_th, &dtN); 289 if (ret != 0) 290 { UNRESOLVED(ret, "[child] Unable to create thread N"); } 291 292 ret = pthread_create(&thD, NULL, child_process_th, &dtD); 293 if (ret != 0) 294 { UNRESOLVED(ret, "[child] Unable to create thread D"); } 295 296 ret = pthread_create(&thP, NULL, child_process_th, &dtP); 297 if (ret != 0) 298 { UNRESOLVED(ret, "[child] Unable to create thread P"); } 299 300 /* We wait for the parent process to let us signal the conditions */ 301 do { ret = sem_wait(&(gd->semB)); } 302 while ((ret != 0) && (errno == EINTR)); 303 if (ret != 0) 304 { UNRESOLVED(errno, "[child] Unable to wait for semaphore B"); } 305 306 /* Now signal both conditions. Changing the boolean was carried on by the parent */ 307 ret = pthread_cond_signal(&(gd->cndN)); 308 if (ret != 0) 309 { UNRESOLVED(ret, "[child] Unable to signal cond N"); } 310 311 ret = pthread_cond_signal(&(gd->cndD)); 312 if (ret != 0) 313 { UNRESOLVED(ret, "[child] Unable to signal cond D"); } 314 315 ret = pthread_cond_signal(&(gd->cndP)); 316 if (ret != 0) 317 { UNRESOLVED(ret, "[child] Unable to signal cond P"); } 318 319 /* Nothing more to do until the threads terminate */ 320 ret = pthread_join(thN, NULL); 321 if (ret != 0) 322 { UNRESOLVED(ret, "[child] Unable to join the thread N"); } 323 324 ret = pthread_join(thD, NULL); 325 if (ret != 0) 326 { UNRESOLVED(ret, "[child] Unable to join the thread D"); } 327 328 ret = pthread_join(thP, NULL); 329 if (ret != 0) 330 { UNRESOLVED(ret, "[child] Unable to join the thread P"); } 331 332 return 0; 333} 334 335/**** 336 * parent_process 337 * This function is called in the parent process just after the fork. 338 * Don't call the UNRESOLVED macro here as it would orphan the child thread! 339 * Instead, the macro LOC_URSLVD(x, s) is provided. The usage is the same. 340 */ 341#define LOC_URSLVD(x,s) \ 342{ \ 343 output("UNRESOLVED:\n Got error %d - %s\n with message %s\n", x, strerror(x), s); \ 344 gd->bool = 1; \ 345 ret = sem_post(&(gd->semB)); \ 346 if (ret != 0) \ 347 { \ 348 kill(gd->child, SIGKILL); \ 349 /* If the call fails, this probably means the process is already dead */ \ 350 } \ 351 return x; \ 352} 353 354int parent_process(globaldata_t * gd) 355{ 356 int ret, tmp, i; 357 358 /* Wait for the child to be ready */ 359 ret = sem_wait(&(gd->semA)); 360 if (ret != 0) 361 { LOC_URSLVD(errno,"[parent] Unable to wait for sem A (1)"); } 362 363 ret = sem_wait(&(gd->semA)); 364 if (ret != 0) 365 { LOC_URSLVD(errno,"[parent] Unable to wait for sem A (2)"); } 366 367 ret = sem_wait(&(gd->semA)); 368 if (ret != 0) 369 { LOC_URSLVD(errno,"[parent] Unable to wait for sem A (3)"); } 370 371 #if VERBOSE > 1 372 output("[parent] Threads are ready...\n"); 373 #endif 374 375 /* Now let the threads either enter the wait or exit if an error occured */ 376 ret = pthread_mutex_lock(&(gd->mtxN)); 377 if (ret != 0) 378 { LOC_URSLVD(ret,"[parent] Unable to lock mutex N"); } 379 380 ret = pthread_mutex_lock(&(gd->mtxD)); 381 if (ret != 0) 382 { LOC_URSLVD(ret,"[parent] Unable to lock mutex D"); } 383 384 ret = pthread_mutex_lock(&(gd->mtxP)); 385 if (ret != 0) 386 { LOC_URSLVD(ret,"[parent] Unable to lock mutex P"); } 387 388 if (gd->cntrP == 0) 389 { 390 /* There was an unexpected error */ 391 LOC_URSLVD(0,"[parent] The pshared condvar reported an error"); 392 } 393 /* Check the threads status */ 394 if ((gd->cntrN == 0) && (gd->cntrD == 0)) /* Both threads got an error */ 395 { 396 /* the test has passed */ 397 gd->result = 0; 398 } 399 if ((gd->cntrN == 0) && (gd->cntrD != 0)) /* thread N got an error */ 400 { 401 /* the test has failed */ 402 gd->result = gd->cntrD; 403 } 404 if ((gd->cntrN != 0) && (gd->cntrD == 0)) /* thread D got an error */ 405 { 406 /* the test has failed */ 407 gd->result = gd->cntrN; 408 } 409 if ((gd->cntrN != 0) && (gd->cntrD != 0)) /* Neither thread got an error - we can test further */ 410 { 411 #if VERBOSE > 1 412 output("[parent] Both threads are waiting for the condition right now.\n"); 413 #endif 414 415 /* We can unlock the mutexs so the threads can go out from pthread_cond_wait */ 416 ret = pthread_mutex_unlock(&(gd->mtxN)); 417 if (ret != 0) 418 { LOC_URSLVD(ret,"[parent] Unable to unlock mutex N"); } 419 420 ret = pthread_mutex_unlock(&(gd->mtxD)); 421 if (ret != 0) 422 { LOC_URSLVD(ret,"[parent] Unable to unlock mutex D"); } 423 424 ret = pthread_mutex_unlock(&(gd->mtxP)); 425 if (ret != 0) 426 { LOC_URSLVD(ret,"[parent] Unable to unlock mutex P"); } 427 428 for (i=0; i<100; i++) 429 { 430 /* We try to signal the conditions */ 431 tmp = pthread_cond_signal(&(gd->cndN)); 432 ret = pthread_cond_signal(&(gd->cndD)); 433 if (ret != tmp) 434 { LOC_URSLVD(ret>tmp?ret:tmp, "[parent] Signaling the conditions give different error codes"); } 435 #if VERBOSE > 1 436 if (i==0) 437 { 438 output("[parent] Signaling the condition returned %d for both condvar\n", ret); 439 } 440 #endif 441 ret = pthread_cond_signal(&(gd->cndP)); 442 if (ret != 0) 443 { LOC_URSLVD(ret, "[parent] Signaling the pshared condition failed"); } 444 445 446 /* Make sure the child process's threads were scheduled */ 447 /* We kill it and wait for both threads to have the signal handled. 448 This will mean the threads were scheduled */ 449 ret = kill(gd->child, SIGUSR1); 450 if (ret != 0) 451 { LOC_URSLVD(errno, "[parent] Killing child thread with USR1 failed"); } 452 453 ret = sem_wait(&(gd->semA)); 454 if (ret != 0) 455 { LOC_URSLVD(errno,"[parent] Unable to wait for sem A (4)"); } 456 457 ret = sem_wait(&(gd->semA)); 458 if (ret != 0) 459 { LOC_URSLVD(errno,"[parent] Unable to wait for sem A (5)"); } 460 461 ret = sem_wait(&(gd->semA)); 462 if (ret != 0) 463 { LOC_URSLVD(errno,"[parent] Unable to wait for sem A (6)"); } 464 465 sched_yield(); 466 467 /* We try to broadcast the conditions */ 468 tmp = pthread_cond_broadcast(&(gd->cndN)); 469 ret = pthread_cond_broadcast(&(gd->cndD)); 470 if (ret != tmp) 471 { LOC_URSLVD(ret>tmp?ret:tmp, "[parent] Broadcasting the conditions give different error codes"); } 472 #if VERBOSE > 1 473 if (i==0) 474 { 475 output("[parent] Broadcasting the condition returned %d for both condvar\n", tmp); 476 } 477 #endif 478 ret = pthread_cond_broadcast(&(gd->cndP)); 479 if (ret != 0) 480 { LOC_URSLVD(ret, "[parent] Broadcasting the pshared conditions failed"); } 481 482 /* Make sure the child process's threads were scheduled */ 483 /* We kill it and wait for both threads to have the signal handled. 484 This will mean the threads were scheduled */ 485 ret = kill(gd->child, SIGUSR1); 486 if (ret != 0) 487 { LOC_URSLVD(errno, "[parent] Killing child thread with USR1 failed"); } 488 489 ret = sem_wait(&(gd->semA)); 490 if (ret != 0) 491 { LOC_URSLVD(errno,"[parent] Unable to wait for sem A (7)"); } 492 493 ret = sem_wait(&(gd->semA)); 494 if (ret != 0) 495 { LOC_URSLVD(errno,"[parent] Unable to wait for sem A (8)"); } 496 497 ret = sem_wait(&(gd->semA)); 498 if (ret != 0) 499 { LOC_URSLVD(errno,"[parent] Unable to wait for sem A (9)"); } 500 501 sched_yield(); 502 } 503 504 505 /* Now we relock the mutexes */ 506 ret = pthread_mutex_lock(&(gd->mtxN)); 507 if (ret != 0) 508 { LOC_URSLVD(ret,"[parent] Unable to lock mutex N"); } 509 510 ret = pthread_mutex_lock(&(gd->mtxD)); 511 if (ret != 0) 512 { LOC_URSLVD(ret,"[parent] Unable to lock mutex D"); } 513 514 ret = pthread_mutex_lock(&(gd->mtxP)); 515 if (ret != 0) 516 { LOC_URSLVD(ret,"[parent] Unable to lock mutex P"); } 517 518 /* We compare the counters values */ 519 if (gd->cntrP == 0) 520 { LOC_URSLVD(0, "[parent] The pshared condvar failed"); } 521 522 if ((gd->cntrN == 0) && (gd->cntrD == 0)) 523 { 524 #if VERBOSE > 1 525 output("[parent] Both cond wait have failed\n"); 526 #endif 527 gd->result = 0; /* The test has passed */ 528 } 529 if ((gd->cntrN == 0) && (gd->cntrD != 0)) 530 { 531 #if VERBOSE > 1 532 output("[parent] cond wait has failed for N\n"); 533 #endif 534 gd->result = gd->cntrD; /* The test has failed */ 535 } 536 if ((gd->cntrN != 0) && (gd->cntrD == 0)) 537 { 538 #if VERBOSE > 1 539 output("[parent] cond wait has failed for D\n"); 540 #endif 541 gd->result = gd->cntrN; /* The test has failed */ 542 } 543 if ((gd->cntrN != 0) && (gd->cntrD != 0)) /* None of the condwait returned an error */ 544 { 545 if (((gd->cntrN & 1) != 1) || ((gd->cntrD & 1) != 1)) 546 { 547 output("N:%d D:%d\n",gd->cntrN,gd->cntrD); 548 LOC_URSLVD((gd->cntrN & 1)?gd->cntrD:gd->cntrN,"[parent] Even counter - pshared mutex failure"); 549 } 550 551 gd->result = 0; 552 553 #if VERBOSE > 1 554 output("[parent] Reports:\n"); 555 output("[parent] Process-shared condvar was awaken : %i times (reference)\n", gd->cntrP >> 1); 556 output("[parent] Null attribute condvar was awaken : %i times\n", gd->cntrN >> 1); 557 output("[parent] Default attr. condvar was awaken : %i times\n", gd->cntrD >> 1); 558 #endif 559 560 if ((gd->cntrN == gd->cntrP) && (gd->cntrD != gd->cntrP)) 561 { 562 #if VERBOSE > 1 563 output("[parent] Null condvar seems to be process-shared while Default condvar seems not\n"); 564 #endif 565 gd->result = gd->cntrD; 566 } 567 if ((gd->cntrN != gd->cntrP) && (gd->cntrD == gd->cntrP)) 568 { 569 #if VERBOSE > 1 570 output("[parent] Default condvar seems to be process-shared while Null condvar seems not\n"); 571 #endif 572 gd->result = gd->cntrN; 573 } 574 575 } 576 } 577 578 #if VERBOSE > 1 579 output("[parent] Threads tests are finished, about to stop them...\n"); 580 #endif 581 gd->bool = 1; /* the threads can now terminate */ 582 583 ret = pthread_mutex_unlock(&(gd->mtxN)); 584 if (ret != 0) 585 { LOC_URSLVD(ret,"[parent] Unable to unlock mutex N"); } 586 587 ret = pthread_mutex_unlock(&(gd->mtxD)); 588 if (ret != 0) 589 { LOC_URSLVD(ret,"[parent] Unable to unlock mutex D"); } 590 591 ret = pthread_mutex_unlock(&(gd->mtxP)); 592 if (ret != 0) 593 { LOC_URSLVD(ret,"[parent] Unable to unlock mutex P"); } 594 595 /* Let the child thread terminate */ 596 ret = sem_post(&(gd->semB)); 597 if (ret != 0) 598 { LOC_URSLVD(errno, "[parent] Failed to post the semaphore B"); } 599 600 return 0; 601} 602 603/**** 604 * do_tps_test 605 * This function will take care of testing the condvars 606 * when shared between processes. 607 */ 608int do_tps_test(void) 609{ 610 int ret=0; 611 globaldata_t * gd; 612 pthread_condattr_t ca; 613 pthread_mutexattr_t ma; 614 pid_t wrc, child; 615 616 size_t sz; 617 char filename[] = "/tmp/cond_init_1-3-XXXXXX"; 618 void * mmaped; 619 char * tmp; 620 int fd; 621 622 int status; 623 int rc2; 624 625 626 /* We now create the temp files */ 627 fd = mkstemp(filename); 628 if (fd == -1) 629 { UNRESOLVED(errno, "Temporary file could not be created"); } 630 631 /* and make sure the file will be deleted when closed */ 632 unlink(filename); 633 634 #if VERBOSE > 1 635 output("Temp file created (%s).\n", filename); 636 #endif 637 638 sz= (size_t)sysconf(_SC_PAGESIZE); 639 640 tmp = calloc(1, sz); 641 if (tmp == NULL) 642 { UNRESOLVED(errno, "Memory allocation failed"); } 643 644 /* Write the data to the file. */ 645 if (write (fd, tmp, sz) != (ssize_t) sz) 646 { UNRESOLVED(sz, "Writting to the file failed"); } 647 648 free(tmp); 649 650 /* Now we can map the file in memory */ 651 mmaped = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 652 if (mmaped == MAP_FAILED) 653 { UNRESOLVED(errno, "mmap failed"); } 654 655 gd = (globaldata_t *) mmaped; 656 657 /* Our datatest structure is now in shared memory */ 658 #if VERBOSE > 1 659 output("Shared memory created successfully.\n"); 660 output("Initializing data...\n"); 661 #endif 662 663 /* Initialize the objects attributes */ 664 ret = pthread_mutexattr_init(&ma); 665 if (ret != 0) 666 { UNRESOLVED(ret, "Unable to initialize mutex attribute object"); } 667 668 ret = pthread_condattr_init(&ca); 669 if (ret != 0) 670 { UNRESOLVED(ret, "Unable to initialize condvar attribute object"); } 671 672 ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); 673 if (ret != 0) 674 { UNRESOLVED(ret, "Unable to set the mutex attribute as process shared"); } 675 676 /* Initialize the synchronization objects */ 677 ret = pthread_mutex_init(&(gd->mtxN), &ma); 678 if (ret != 0) 679 { UNRESOLVED(ret, "Unable to initialize the mutex N in shared memory"); } 680 681 ret = pthread_mutex_init(&(gd->mtxD), &ma); 682 if (ret != 0) 683 { UNRESOLVED(ret, "Unable to initialize the mutex D in shared memory"); } 684 685 ret = pthread_mutex_init(&(gd->mtxP), &ma); 686 if (ret != 0) 687 { UNRESOLVED(ret, "Unable to initialize the mutex P in shared memory"); } 688 689 /* we don't need the mutex attribute object anymore */ 690 ret = pthread_mutexattr_destroy(&ma); 691 if (ret != 0) 692 { UNRESOLVED(ret, "Unable to destroy the mutex attribute object"); } 693 694 /* Now we'll initialize the cond vars */ 695 ret = pthread_cond_init(&(gd->cndN), NULL); 696 if (ret != 0) 697 { UNRESOLVED(ret, "Unable to initialize the Null attribute condvar"); } 698 699 ret = pthread_cond_init(&(gd->cndD), &ca); 700 if (ret != 0) 701 { UNRESOLVED(ret, "Unable to initialize the Default attribute condvar"); } 702 703 ret = pthread_condattr_setpshared(&ca, PTHREAD_PROCESS_SHARED); 704 if (ret != 0) 705 { UNRESOLVED(ret, "Unable to set the cond attribute as process shared"); } 706 707 ret = pthread_cond_init(&(gd->cndP), &ca); 708 if (ret != 0) 709 { UNRESOLVED(ret, "Unable to initialize the Pshared condvar"); } 710 711 ret = pthread_condattr_destroy(&ca); 712 if (ret != 0) 713 { UNRESOLVED(ret, "Unable to destroy the condvar attribute object"); } 714 715 /* We initialize the other values in the test structure */ 716 gd->cntrN = 0; 717 gd->cntrD = 0; 718 gd->cntrP = 0; 719 gd->bool = 0; 720 gd->result = 0; 721 ret = sem_init(&(gd->semA), 1, 0); 722 if (ret != 0) 723 { UNRESOLVED(errno, "Unable to initialize semaphore A"); } 724 725 ret = sem_init(&(gd->semB), 1, 0); 726 if (ret != 0) 727 { UNRESOLVED(errno, "Unable to initialize semaphore B"); } 728 729 /* Initializations are OK */ 730 #if VERBOSE > 1 731 output("All initializations OK, proceed to the test (fork).\n"); 732 #endif 733 734 child = fork(); 735 if (child == -1) 736 { UNRESOLVED(errno, "Fork failed"); } 737 738 if (child == 0) 739 { 740 /* We are the child */ 741 ret = child_process(gd); 742 #if VERBOSE > 1 743 output("[child] Test function returned %d.\n", ret); 744 #endif 745 exit(ret); 746 } 747 748 /* We are the parent */ 749 gd->child = child; 750 rc2 = parent_process(gd); 751 #if VERBOSE > 1 752 output("[parent] Test function returned %d.\n", rc2); 753 #endif 754 755 /* In any case we must wait for the child */ 756 wrc = waitpid(child, &status, 0); 757 if (wrc != child) 758 { 759 output("Expected pid: %i. Got %i\n", (int)child, (int)wrc); 760 UNRESOLVED(errno, "Waitpid failed"); 761 } 762 763 if (WIFSIGNALED(status)) 764 { 765 output("Child process killed with signal %d\n",WTERMSIG(status)); 766 UNRESOLVED( rc2 , "Child process was killed"); 767 } 768 769 if (WIFEXITED(status)) 770 { 771 ret = WEXITSTATUS(status); 772 } 773 else 774 { 775 UNRESOLVED( rc2, "Child process was neither killed nor exited"); 776 } 777 778 #if VERBOSE > 1 779 output("[parent] Successfully waited for child process.\n"); 780 #endif 781 782 /* The return value from the parent is in 'rc2' and 783 * 'ret' contains the child return code. 784 * The test status is in gd->result 785 */ 786 if (rc2 != 0) 787 { 788 UNRESOLVED(ret, "Parent process failed"); 789 } 790 791 if (ret != 0) 792 { 793 UNRESOLVED(ret, "Child process failed"); 794 } 795 796 #if VERBOSE > 1 797 output("Destroying the data.\n"); 798 #endif 799 800 /* We can now destroy all the datas */ 801 ret = sem_destroy(&(gd->semB)); 802 if (ret != 0) 803 { UNRESOLVED(errno, "Unable to destroy the semaphore B"); } 804 805 ret = sem_destroy(&(gd->semA)); 806 if (ret != 0) 807 { UNRESOLVED(errno, "Unable to destroy the semaphore A"); } 808 809 ret = pthread_cond_destroy(&(gd->cndP)); 810 if (ret != 0) 811 { UNRESOLVED(ret, "Unable to destroy the P condvar"); } 812 813 ret = pthread_cond_destroy(&(gd->cndD)); 814 if (ret != 0) 815 { UNRESOLVED(ret, "Unable to destroy the D condvar"); } 816 817 ret = pthread_cond_destroy(&(gd->cndN)); 818 if (ret != 0) 819 { UNRESOLVED(ret, "Unable to destroy the N condvar"); } 820 821 ret = pthread_mutex_destroy(&(gd->mtxP)); 822 if (ret != 0) 823 { UNRESOLVED(ret, "Unable to destroy the P mutex"); } 824 825 ret = pthread_mutex_destroy(&(gd->mtxD)); 826 if (ret != 0) 827 { UNRESOLVED(ret, "Unable to destroy the D mutex"); } 828 829 ret = pthread_mutex_destroy(&(gd->mtxN)); 830 if (ret != 0) 831 { UNRESOLVED(ret, "Unable to destroy the N mutex"); } 832 833 rc2 = gd->result; 834 835 #if VERBOSE > 1 836 output("Unmapping shared memory.\n"); 837 #endif 838 839 ret = munmap(mmaped, sz); 840 if (ret != 0) 841 { UNRESOLVED(errno, "Memory unmapping failed"); } 842 843 return rc2; 844} 845 846/**** 847 * Main function 848 * This one is responsible for executing the previous functions 849 * according to the supported features. 850 */ 851int main(int argc, char * argv[]) 852{ 853 long opt_TPS, opt_MF; 854 int ret=0; 855 856 output_init(); 857 858 #if VERBOSE > 1 859 output("Test starting...\n"); 860 #endif 861 862 opt_MF =sysconf(_SC_MAPPED_FILES); 863 opt_TPS=sysconf(_SC_THREAD_PROCESS_SHARED); 864 865 #if VERBOSE > 1 866 output("Memory Mapped Files option : %li\n", opt_MF); 867 output("Thread Process-shared Synchronization option: %li\n", opt_TPS); 868 #endif 869 870 if ((opt_TPS != -1L) && (opt_MF != -1L)) 871 { 872 #if VERBOSE > 0 873 output("Starting process test\n"); 874 #endif 875 ret = do_tps_test(); 876 } 877 else 878 { 879 UNTESTED("This test requires unsupported features"); 880 } 881 882 if (ret != 0) 883 { FAILED("The cond vars behave differently across processes."); } 884 885 #if VERBOSE > 1 886 output("Test terminated successfully\n"); 887 #endif 888 889 PASSED; 890} 891 892#else /* WITHOUT_XOPEN */ 893int main(int argc, char * argv[]) 894{ 895 output_init(); 896 UNTESTED("This test requires XSI features"); 897} 898#endif 899 900