void * threaded (void * arg) { int ret = 0; #if VERBOSE > 4 output("Thread %i starting...\n", sc); #endif /* Alternate stack test */ if (scenarii[sc].bottom != NULL) { #ifdef WITHOUT_XOPEN output("Unable to test the alternate stack feature; need an integer pointer cast\n"); #else intptr_t stack_start, stack_end, current_pos; stack_start = (intptr_t) scenarii[sc].bottom; stack_end = stack_start + (intptr_t)sysconf(_SC_THREAD_STACK_MIN); current_pos = (intptr_t)&ret; #if VERBOSE > 2 output("Stack bottom: %p\n", scenarii[sc].bottom); output("Stack end : %p (stack is 0x%lx bytes)\n", (void *)stack_end, stack_end - stack_start); output("Current pos : %p\n", &ret); #endif if ((stack_start > current_pos) || (current_pos > stack_end)) { FAILED("The specified stack was not used.\n"); } #endif // WITHOUT_XOPEN } /* Guard size test */ if ((scenarii[sc].bottom == NULL) /* no alternative stack was specified */ && (scenarii[sc].guard == 2) /* guard area size is 1 memory page */ && (scenarii[sc].altsize == 1))/* We know the stack size */ { pid_t child, ctrl; int status; child=fork(); /* We'll test the feature in another process as this test may segfault */ if (child == -1) { UNRESOLVED(errno, "Failed to fork()"); } if (child != 0) /* father */ { /* Just wait for the child and check its return value */ ctrl = waitpid(child, &status, 0); if (ctrl != child) { UNRESOLVED(errno, "Failed to wait for process termination"); } if (WIFEXITED(status)) /* The process exited */ { if (WEXITSTATUS(status) == 0) { FAILED("Overflow into the guard area did not fail"); } if (WEXITSTATUS(status) == PTS_UNRESOLVED) { UNRESOLVED(-1, "The child process returned unresolved status"); } #if VERBOSE > 4 else { output("The child process returned: %i\n", WEXITSTATUS(status)); } } else { output("The child process did not returned\n"); if (WIFSIGNALED(status)) output("It was killed with signal %i\n", WTERMSIG(status)); else output("neither was it killed. (status = %i)\n", status); #endif } } if (child == 0) /* this is the new process */ { pthread_t th; ret = pthread_create(&th, &scenarii[sc].ta, overflow, NULL); /* Create a new thread with the same attributes */ if (ret != 0) { UNRESOLVED(ret, "Unable to create another thread with the same attributes in the new process"); } if (scenarii[sc].detached == 0) { ret = pthread_join(th, NULL); if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } } else { /* Just wait for the thread to terminate */ do { ret = sem_wait(&scenarii[sc].sem); } while ((ret == -1) && (errno == EINTR)); if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } } /* Terminate the child process here */ exit(0); } } /* Post the semaphore to unlock the main thread in case of a detached thread */ do { ret = sem_post(&scenarii[sc].sem); } while ((ret == -1) && (errno == EINTR)); if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } return arg; }
/* main function */ int main() { int ret; long rts; struct sigaction sa; /* Initialize output */ output_init(); /* Test the RTS extension */ rts = sysconf(_SC_REALTIME_SIGNALS); if (rts < 0L) { UNTESTED("This test needs the RTS extension"); } /* Set the signal handler */ sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = handler; ret = sigemptyset(&sa.sa_mask); if (ret != 0) { UNRESOLVED(ret, "Failed to empty signal set"); } /* Install the signal handler for SIGQUIT */ ret = sigaction(SIGNAL, &sa, 0); if (ret != 0) { UNRESOLVED(ret, "Failed to set signal handler"); } if (called) { FAILED("The signal handler has been called when no signal was raised"); } ret = raise(SIGNAL); if (ret != 0) { UNRESOLVED(ret, "Failed to raise SIGQUIT"); } if (!called) { FAILED("the sa_handler was not called whereas SA_SIGINFO was not set"); } /* Test passed */ #if VERBOSE > 0 output("Test passed\n"); #endif PASSED; }
/* Main function */ int main (int argc, char * argv[]) { int ret; pthread_t th_work, th_sig1, th_sig2; thestruct arg1, arg2; struct sigaction sa; /* Initialize output routine */ output_init(); /* We need to register the signal handlers for the PROCESS */ sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = sighdl1; if ((ret = sigaction (SIGUSR1, &sa, NULL))) { UNRESOLVED(ret, "Unable to register signal handler1"); } sa.sa_handler = sighdl2; if ((ret = sigaction (SIGUSR2, &sa, NULL))) { UNRESOLVED(ret, "Unable to register signal handler2"); } /* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */ sigemptyset(&usersigs); ret = sigaddset(&usersigs, SIGUSR1); ret |= sigaddset(&usersigs, SIGUSR2); if (ret != 0) { UNRESOLVED(ret, "Unable to add SIGUSR1 or 2 to a signal set"); } /* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */ ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); if (ret != 0) { UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 in main thread"); } #ifdef WITH_SYNCHRO if (sem_init(&semsig1, 0, 1)) { UNRESOLVED(errno, "Semsig1 init"); } if (sem_init(&semsig2, 0, 1)) { UNRESOLVED(errno, "Semsig2 init"); } #endif if ((ret = pthread_create(&th_work, NULL, test, NULL))) { UNRESOLVED(ret, "Worker thread creation failed"); } arg1.sig = SIGUSR1; arg2.sig = SIGUSR2; #ifdef WITH_SYNCHRO arg1.sem = &semsig1; arg2.sem = &semsig2; #endif if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) { UNRESOLVED(ret, "Signal 1 sender thread creation failed"); } if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) { UNRESOLVED(ret, "Signal 2 sender thread creation failed"); } /* Let's wait for a while now */ sleep(1); /* Now stop the threads and join them */ do { do_it=0; } while (do_it); if ((ret = pthread_join(th_sig1, NULL))) { UNRESOLVED(ret, "Signal 1 sender thread join failed"); } if ((ret = pthread_join(th_sig2, NULL))) { UNRESOLVED(ret, "Signal 2 sender thread join failed"); } if ((ret = pthread_join(th_work, NULL))) { UNRESOLVED(ret, "Worker thread join failed"); } #if VERBOSE > 0 output("Test executed successfully.\n"); output(" %d mutex locks.\n", count_ope); #ifdef WITH_SYNCHRO output(" %d signals were sent meanwhile.\n", count_sig); #endif #endif PASSED; }
int main(int argc, char * argv[]) { int ret, i, j; struct sigaction sa; pthread_mutexattr_t ma; pthread_condattr_t ca; clockid_t cid = CLOCK_REALTIME; testdata_t * td; testdata_t alternativ; int do_fork; long pshared, monotonic, cs, mf; pthread_t th[NTOT]; output_init(); pshared = sysconf(_SC_THREAD_PROCESS_SHARED); cs = sysconf(_SC_CLOCK_SELECTION); monotonic = sysconf(_SC_MONOTONIC_CLOCK); mf =sysconf(_SC_MAPPED_FILES); #if VERBOSE > 0 output("Test starting\n"); output("System abilities:\n"); output(" TPS : %li\n", pshared); output(" CS : %li\n", cs); output(" MON : %li\n", monotonic); output(" MF : %li\n", mf); if ((mf < 0) || (pshared < 0)) output("Process-shared attributes won't be tested\n"); if ((cs < 0) || (monotonic < 0)) output("Alternative clock won't be tested\n"); #endif /* We are not interested in testing the clock if we have no other clock available.. */ if (monotonic < 0) cs = -1; #ifndef USE_ALTCLK if (cs > 0) output("Implementation supports the MONOTONIC CLOCK but option is disabled in test.\n"); #endif /********** * Allocate space for the testdata structure */ if (mf < 0) { /* Cannot mmap a file, we use an alternative method */ td = &alternativ; pshared = -1; /* We won't do this testing anyway */ #if VERBOSE > 0 output("Testdata allocated in the process memory.\n"); #endif } else { /* We will place the test data in a mmaped file */ char filename[] = "/tmp/cond_timedwait_st1-XXXXXX"; size_t sz, ps; void * mmaped; int fd; char * tmp; /* We now create the temp files */ fd = mkstemp(filename); if (fd == -1) { UNRESOLVED(errno, "Temporary file could not be created"); } /* and make sure the file will be deleted when closed */ unlink(filename); #if VERBOSE > 1 output("Temp file created (%s).\n", filename); #endif ps = (size_t)sysconf(_SC_PAGESIZE); sz= ((sizeof(testdata_t) / ps) + 1) * ps; /* # pages needed to store the testdata */ tmp = calloc(1 , sz); if (tmp == NULL) { UNRESOLVED(errno, "Memory allocation failed"); } /* Write the data to the file. */ if (write (fd, tmp, sz) != (ssize_t) sz) { UNRESOLVED(sz, "Writting to the file failed"); } free(tmp); /* Now we can map the file in memory */ mmaped = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mmaped == MAP_FAILED) { UNRESOLVED(errno, "mmap failed"); } td = (testdata_t *) mmaped; /* Our datatest structure is now in shared memory */ #if VERBOSE > 1 output("Testdata allocated in shared memory (%ib).\n", sizeof(testdata_t)); #endif } /* Init the signal handler variable */ pBoolean = &(td->boolean); /* Init the structure */ for (i=0; i< NSCENAR ; i++) { #if VERBOSE > 1 output("[parent] Preparing attributes for: %s\n", scenarii[i].descr); #ifdef WITHOUT_XOPEN output("[parent] Mutex attributes DISABLED -> not used\n"); #endif #endif /* set / reset everything */ do_fork=0; ret = pthread_mutexattr_init(&ma); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to initialize the mutex attribute object"); } ret = pthread_condattr_init(&ca); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to initialize the cond attribute object"); } #ifndef WITHOUT_XOPEN /* Set the mutex type */ ret = pthread_mutexattr_settype(&ma, scenarii[i].m_type); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set mutex type"); } #if VERBOSE > 1 output("[parent] Mutex type : %i\n", scenarii[i].m_type); #endif #endif /* Set the pshared attributes, if supported */ if ((pshared > 0) && (scenarii[i].mc_pshared != 0)) { ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set the mutex process-shared"); } ret = pthread_condattr_setpshared(&ca, PTHREAD_PROCESS_SHARED); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set the cond var process-shared"); } #if VERBOSE > 1 output("[parent] Mutex & cond are process-shared\n"); #endif } #if VERBOSE > 1 else { output("[parent] Mutex & cond are process-private\n"); } #endif /* Set the alternative clock, if supported */ #ifdef USE_ALTCLK if ((cs > 0) && (scenarii[i].c_clock != 0)) { ret = pthread_condattr_setclock(&ca, CLOCK_MONOTONIC); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set the monotonic clock for the cond"); } #if VERBOSE > 1 output("[parent] Cond uses the Monotonic clock\n"); #endif } #if VERBOSE > 1 else { output("[parent] Cond uses the default clock\n"); } #endif ret = pthread_condattr_getclock(&ca, &cid); if (ret != 0) { UNRESOLVED(ret, "Unable to get clock from cond attr"); } #endif /* Tell whether the test will be across processes */ if ((pshared > 0) && (scenarii[i].fork != 0)) { do_fork = 1; #if VERBOSE > 1 output("[parent] Child will be a new process\n"); #endif } #if VERBOSE > 1 else { output("[parent] Child will be a new thread\n"); } #endif /* Initialize all the mutex and condvars which uses those attributes */ for (j=0; j < SCALABILITY_FACTOR * NCHILDREN; j++) { #define CD (td->cd[i+(j*NSCENAR)]) CD.pBool = &(td->boolean); CD.fork = do_fork; CD.cid = cid; /* initialize the condvar */ ret = pthread_cond_init(&(CD.cnd), &ca); if (ret != 0) { UNRESOLVED(ret, "[parent] Cond init failed"); } /* initialize the mutex */ ret = pthread_mutex_init(&(CD.mtx), &ma); if (ret != 0) { UNRESOLVED(ret, "[parent] Mutex init failed"); } #undef CD } ret = pthread_condattr_destroy(&ca); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the cond var attribute object"); } ret = pthread_mutexattr_destroy(&ma); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the mutex attribute object"); } } #if VERBOSE > 1 output("[parent] All condvars & mutex are ready\n"); #endif ret = pthread_attr_init(&ta); if (ret != 0) { UNRESOLVED(ret, "[parent] Failed to initialize a thread attribute object"); } ret = pthread_attr_setstacksize(&ta, sysconf(_SC_THREAD_STACK_MIN)); if (ret != 0) { UNRESOLVED(ret, "[parent] Failed to set thread stack size"); } sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = sighdl; if ((ret = sigaction (SIGUSR1, &sa, NULL))) { UNRESOLVED(ret, "Unable to register signal handler"); } if ((ret = sigaction (SIGALRM, &sa, NULL))) { UNRESOLVED(ret, "Unable to register signal handler"); } #if VERBOSE > 1 output("[parent] Signal handler registered\n"); #endif for (i=0; i<NTOT; i++) { ret = pthread_create(&th[i], &ta, threaded_A, &(td->cd[i])); /* In case of failure we can exit; the child processes will die after a while */ if (ret != 0) { UNRESOLVED(ret, "[Parent] Failed to create a thread"); } #if VERBOSE > 1 if ((i % 10) == 0) output("[parent] %i threads created...\n", i+1); #endif } #if VERBOSE > 1 output("[parent] All %i threads are running...\n", NTOT); #endif for (i=0; i<NTOT; i++) { ret = pthread_join(th[i], NULL); if (ret != 0) { UNRESOLVED(ret, "[Parent] Failed to join a thread"); } } /* Destroy everything */ for (i=0; i< NTOT ; i++) { /* destroy the condvar */ ret = pthread_cond_destroy(&(td->cd[i].cnd)); if (ret != 0) { UNRESOLVED(ret, "[parent] Cond destroy failed"); } /* destroy the mutex */ ret = pthread_mutex_init(&(td->cd[i].mtx), &ma); if (ret != 0) { UNRESOLVED(ret, "[parent] Mutex destroy failed"); } } #if VERBOSE > 0 output("Test passed\n"); #endif PASSED; }
/* Main routine */ int main(int argc, char *argv[]) { int ret = 0; pthread_t child; mf = sysconf(_SC_MAPPED_FILES); output_init(); scenar_init(); /* We want to share some memory with the child process */ if (mf > 0) { /* We will place the test data in a mmaped file */ char filename[] = "/tmp/pthread_exit_6-1-XXXXXX"; size_t sz; void *mmaped; int fd; char *tmp; /* We now create the temp files */ fd = mkstemp(filename); if (fd == -1) { UNRESOLVED(errno, "Temporary file could not be created"); } /* and make sure the file will be deleted when closed */ unlink(filename); #if VERBOSE > 1 output("Temp file created (%s).\n", filename); #endif sz = (size_t) sysconf(_SC_PAGESIZE); tmp = calloc(1, sz); if (tmp == NULL) { UNRESOLVED(errno, "Memory allocation failed"); } /* Write the data to the file. */ if (write(fd, tmp, sz) != (ssize_t) sz) { UNRESOLVED(sz, "Writting to the file failed"); } free(tmp); /* Now we can map the file in memory */ mmaped = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mmaped == MAP_FAILED) { UNRESOLVED(errno, "mmap failed"); } ctl = (int *)mmaped; /* Our datatest structure is now in shared memory */ #if VERBOSE > 1 output("Testdata allocated in shared memory.\n"); #endif } for (sc = 0; sc < NSCENAR; sc++) { #if VERBOSE > 0 output("-----\n"); output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); #endif ret = pthread_create(&child, &scenarii[sc].ta, threaded, &ctl); switch (scenarii[sc].result) { case 0: /* Operation was expected to succeed */ if (ret != 0) { UNRESOLVED(ret, "Failed to create this thread"); } break; case 1: /* Operation was expected to fail */ if (ret == 0) { UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); } break; case 2: /* We did not know the expected result */ default: #if VERBOSE > 0 if (ret == 0) { output ("Thread has been created successfully for this scenario\n"); } else { output ("Thread creation failed with the error: %s\n", strerror(ret)); } #endif } if (ret == 0) { /* The new thread is running */ if (scenarii[sc].detached == 0) { ret = pthread_join(child, NULL); if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } } else { /* Just wait for the thread to terminate */ do { ret = sem_wait(&scenarii[sc].sem); } while ((ret == -1) && (errno == EINTR)); if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } } } } scenar_fini(); #if VERBOSE > 0 output("-----\n"); output("All test data destroyed\n"); output("Test PASSED\n"); #endif PASSED; }
/* The main test function. */ int main( int argc, char *argv[] ) { int ret = 0; pthread_t child; pthread_attr_t ta; pthread_barrier_t bar; struct sched_param sp; /* Initialize output routine */ output_init(); ret = pthread_barrier_init( &bar, NULL, 2 ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to init barrier" ); } /* Create the attribute object with a known scheduling policy */ ret = pthread_attr_init( &ta ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to initialize thread attribute" ); } ret = pthread_attr_setinheritsched( &ta, PTHREAD_EXPLICIT_SCHED ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to set inherit sched" ); } sp.sched_priority = sched_get_priority_min( SCHED_RR ); if ( sp.sched_priority == -1 ) { UNRESOLVED( errno, "Failed to get min priority" ); } ret = pthread_attr_setschedparam( &ta, &sp ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to set attribute param" ); } ret = pthread_attr_setschedpolicy( &ta, SCHED_RR ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to set attribute policy" ); } /* Create the thread with this attribute */ ret = pthread_create( &child, &ta, threaded, &bar ); if ( ret != 0 ) { UNRESOLVED( ret, "thread creation failed (you may need more priviledges)" ); } /* Wait while the thread checks its policy (we only check what is reported, not the real behavior) */ check_param( child, SCHED_RR, sched_get_priority_min( SCHED_RR ) ); ret = pthread_barrier_wait( &bar ); if ( ( ret != 0 ) && ( ret != PTHREAD_BARRIER_SERIAL_THREAD ) ) { UNRESOLVED( ret, "barrier wait failed" ); } /* Change the threads policy */ sp.sched_priority = sched_get_priority_min( SCHED_FIFO ); if ( sp.sched_priority == -1 ) { UNRESOLVED( errno, "Failed to get min priority" ); } ret = pthread_setschedparam( child, SCHED_FIFO, &sp ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to change running thread's policy" ); } ret = pthread_barrier_wait( &bar ); if ( ( ret != 0 ) && ( ret != PTHREAD_BARRIER_SERIAL_THREAD ) ) { UNRESOLVED( ret, "barrier wait failed" ); } /* Wait while the thread checks its policy (we only check what is reported, not the real behavior) */ check_param( child, SCHED_FIFO, sched_get_priority_min( SCHED_FIFO ) ); ret = pthread_barrier_wait( &bar ); if ( ( ret != 0 ) && ( ret != PTHREAD_BARRIER_SERIAL_THREAD ) ) { UNRESOLVED( ret, "barrier wait failed" ); } /* Change the thread priority */ sp.sched_priority = sched_get_priority_max( SCHED_FIFO ); if ( sp.sched_priority == -1 ) { UNRESOLVED( errno, "Failed to get max priority" ); } ret = pthread_setschedprio( child, sp.sched_priority ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to raise thread's priority" ); } ret = pthread_barrier_wait( &bar ); if ( ( ret != 0 ) && ( ret != PTHREAD_BARRIER_SERIAL_THREAD ) ) { UNRESOLVED( ret, "barrier wait failed" ); } /* The thread checks its priority (we only check what is reported, not the real behavior) */ check_param( child, SCHED_FIFO, sched_get_priority_max( SCHED_FIFO ) ); ret = pthread_barrier_wait( &bar ); if ( ( ret != 0 ) && ( ret != PTHREAD_BARRIER_SERIAL_THREAD ) ) { UNRESOLVED( ret, "barrier wait failed" ); } ret = pthread_join( child, NULL ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to join the thread" ); } PASSED; }
/* main function */ int main() { int ret; pthread_t child; struct sigaction sa; /* Initialize output */ output_init(); /* Set the signal handler */ sa.sa_flags = SA_RESTART; sa.sa_handler = handler; ret = sigemptyset( &sa.sa_mask ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to empty signal set" ); } /* Install the signal handler for SIGNAL */ ret = sigaction( SIGNAL, &sa, 0 ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to set signal handler" ); } /* Initialize the semaphore */ ret = sem_init( &sem, 0, 0 ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to init a semaphore" ); } /* Create the child thread */ ret = pthread_create( &child, NULL, threaded, NULL ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to create a child thread" ); } /* Let the child thread enter the wait routine... we use sched_yield as there is no certain way to test that the child is waiting for the semaphore... */ sched_yield(); sched_yield(); sched_yield(); /* Ok, now kill the child */ ret = pthread_kill( child, SIGNAL ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to kill the child thread" ); } /* wait that the child receives the signal */ while ( !caught ) sched_yield(); /* Now let the child run and terminate */ ret = sem_post( &sem ); if ( ret != 0 ) { UNRESOLVED( errno, "Failed to post the semaphore" ); } ret = pthread_join( child, NULL ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to join the thread" ); } /* terminate */ ret = sem_destroy( &sem ); if ( ret != 0 ) { UNRESOLVED( ret, "Failed to destroy the semaphore" ); } /* Test passed */ #if VERBOSE > 0 output( "Test passed\n" ); #endif PASSED; }
void *threaded(void *arg) { pthread_mutexattr_t ma[4], *pma[5]; pthread_mutex_t m[5]; int i; int ret; /* We need to register the signal handlers */ struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = sighdl1; if ((ret = sigaction(SIGUSR1, &sa, NULL))) { UNRESOLVED(ret, "Unable to register signal handler1"); } sa.sa_handler = sighdl2; if ((ret = sigaction(SIGUSR2, &sa, NULL))) { UNRESOLVED(ret, "Unable to register signal handler2"); } if ((sem_post(&semsync2))) { UNRESOLVED(errno, "could not post semsync2"); } /* Initialize the different mutex */ pma[4] = NULL; for (i = 0; i < 4; i++) { pma[i] = &ma[i]; if ((ret = pthread_mutexattr_init(pma[i]))) { UNRESOLVED(ret, "pthread_mutexattr_init"); } } #ifndef WITHOUT_XOPEN if ((ret = pthread_mutexattr_settype(pma[0], PTHREAD_MUTEX_NORMAL))) { UNRESOLVED(ret, "pthread_mutexattr_settype (normal)"); } if ((ret = pthread_mutexattr_settype(pma[1], PTHREAD_MUTEX_ERRORCHECK))) { UNRESOLVED(ret, "pthread_mutexattr_settype (errorcheck)"); } if ((ret = pthread_mutexattr_settype(pma[2], PTHREAD_MUTEX_RECURSIVE))) { UNRESOLVED(ret, "pthread_mutexattr_settype (recursive)"); } if ((ret = pthread_mutexattr_settype(pma[3], PTHREAD_MUTEX_DEFAULT))) { UNRESOLVED(ret, "pthread_mutexattr_settype (default)"); } #if VERBOSE >1 output ("Mutex attributes NORMAL,ERRORCHECK,RECURSIVE,DEFAULT initialized\n"); #endif #else #if VERBOSE > 0 output ("Mutex attributes NORMAL,ERRORCHECK,RECURSIVE,DEFAULT unavailable\n"); #endif #endif for (i = 0; i < 5; i++) { ret = pthread_mutex_init(&m[i], pma[i]); if (ret == EINTR) { FAILED("pthread_mutex_init returned EINTR"); } if (ret != 0) { UNRESOLVED(ret, "pthread_mutex_init failed"); } } /* The mutex are ready, we will loop on lock/unlock now */ while (do_it) { for (i = 0; i < 5; i++) { ret = pthread_mutex_lock(&m[i]); if (ret == EINTR) { FAILED("pthread_mutex_lock returned EINTR"); } if (ret != 0) { UNRESOLVED(ret, "pthread_mutex_lock failed"); } ret = pthread_mutex_unlock(&m[i]); if (ret == EINTR) { FAILED("pthread_mutex_unlock returned EINTR"); } if (ret != 0) { UNRESOLVED(ret, "pthread_mutex_unlock failed"); } } ret = pthread_mutex_lock(&count_protect); if (ret == EINTR) { FAILED("pthread_mutex_lock returned EINTR"); } if (ret != 0) { UNRESOLVED(ret, "pthread_mutex_lock failed"); } count_ope++; pthread_mutex_unlock(&count_protect); if (ret == EINTR) { FAILED("pthread_mutex_unlock returned EINTR"); } if (ret != 0) { UNRESOLVED(ret, "pthread_mutex_unlock failed"); } } /* Now we can destroy the mutex objects */ for (i = 0; i < 4; i++) { if ((ret = pthread_mutexattr_destroy(pma[i]))) { UNRESOLVED(ret, "pthread_mutexattr_init"); } } for (i = 0; i < 5; i++) { ret = pthread_mutex_destroy(&m[i]); if (ret == EINTR) { FAILED("pthread_mutex_destroy returned EINTR"); } if (ret != 0) { UNRESOLVED(ret, "pthread_mutex_destroy failed"); } } do { ret = sem_wait(&semsync); } while (ret && (errno == EINTR)); if (ret) { UNRESOLVED(errno, "Could not wait for sig senders termination"); } return NULL; }
/* At last (but not least) we need a main */ int main(int argc, char *argv[]) { int ret; pthread_t th_work, th_sig1, th_sig2; thestruct arg1, arg2; output_init(); #ifdef WITH_SYNCHRO #if VERBOSE >1 output("Running in synchronized mode\n"); #endif if ((sem_init(&semsig1, 0, 1))) { UNRESOLVED(errno, "Semsig1 init"); } if ((sem_init(&semsig2, 0, 1))) { UNRESOLVED(errno, "Semsig2 init"); } #endif if ((sem_init(&semsync, 0, 0))) { UNRESOLVED(errno, "semsync init"); } if ((sem_init(&semsync2, 0, 0))) { UNRESOLVED(errno, "semsync2 init"); } #if VERBOSE >1 output("Starting the worker thread\n"); #endif if ((ret = pthread_create(&th_work, NULL, threaded, NULL))) { UNRESOLVED(ret, "Worker thread creation failed"); } do { ret = sem_wait(&semsync2); } while (ret && (errno == EINTR)); arg1.thr = &th_work; arg2.thr = &th_work; arg1.sig = SIGUSR1; arg2.sig = SIGUSR2; #ifdef WITH_SYNCHRO arg1.sem = &semsig1; arg2.sem = &semsig2; #endif #if VERBOSE >1 output("Starting the signal sources\n"); #endif if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) { UNRESOLVED(ret, "Signal 1 sender thread creation failed"); } if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) { UNRESOLVED(ret, "Signal 2 sender thread creation failed"); } /* Let's wait for a while now */ #if VERBOSE >1 output("Let the worker be killed for a second\n"); #endif sleep(1); /* Now stop the threads and join them */ #if VERBOSE >1 output("Stop everybody\n"); #endif do { do_it = 0; } while (do_it); if ((ret = pthread_join(th_sig1, NULL))) { UNRESOLVED(ret, "Signal 1 sender thread join failed"); } if ((ret = pthread_join(th_sig2, NULL))) { UNRESOLVED(ret, "Signal 2 sender thread join failed"); } #if VERBOSE >1 output("Signal sources are stopped, we can stop the worker\n"); #endif if ((sem_post(&semsync))) { UNRESOLVED(errno, "could not post semsync"); } if ((ret = pthread_join(th_work, NULL))) { UNRESOLVED(ret, "Worker thread join failed"); } #if VERBOSE > 0 output("Test executed successfully.\n"); output(" %d mutex lock and unlock were done.\n", count_ope); #ifdef WITH_SYNCHRO output(" %d signals were sent meanwhile.\n", count_sig); #endif #endif PASSED; }
/* The main test function. */ int main(int argc, char * argv[]) { int ret, status; pid_t child, ctl; int fd; void *buf; sem_t * sem; /* Initialize output */ output_init(); /* Create the shared memory segment */ fd = shm_open("/sem_init_3-2", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (fd == -1) { UNRESOLVED(errno, "Failed to open shared memory segment"); } /* Size the memory segment to 1 page size. */ ret = ftruncate(fd, sysconf(_SC_PAGESIZE)); if (ret != 0) { UNRESOLVED(errno, "Failed to size the shared memory segment"); } /* Map these sengments in the process memory space */ buf = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { UNRESOLVED(errno, "Failed to mmap the shared memory segment"); } sem = (sem_t *) buf; /* Initialize the semaphore */ ret = sem_init(sem, 1, 0); if (ret != 0) { UNRESOLVED(errno, "Failed to init the semaphore"); } /* Create the child */ child = fork(); if (child == -1) { UNRESOLVED(errno, "Failed to fork"); } /* child */ if (child == 0) { /* Post the sempahore */ ret = sem_post(sem); if (ret != 0) { UNRESOLVED(errno, "Failed to post the semaphore"); } /* We're done */ exit(PTS_PASS); } /* Wait the sempahore */ do { ret = sem_wait(sem); } while (ret != 0 && errno == EINTR); if (ret != 0) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } /* Parent joins the child */ ctl = waitpid(child, &status, 0); if (ctl != child) { UNRESOLVED(errno, "Waitpid returned the wrong PID"); } if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) { FAILED("Child exited abnormally"); } /* Clean things */ ret = sem_destroy(sem); if (ret != 0) { UNRESOLVED(errno, "Failed to destroy the semaphore"); } ret = shm_unlink("/sem_init_3-2"); if (ret != 0) { UNRESOLVED(errno, "Failed to unlink shared memory"); } /* Test passed */ #if VERBOSE > 0 output("Test passed\n"); #endif PASSED; }
/* The main test function. */ int main(int argc, char *argv[]) { int ret, i; sem_t *sems; sem_t sem_last; long max; /* Initialize output */ output_init(); max = sysconf(_SC_SEM_NSEMS_MAX); if (max <= 0) { output("sysconf(_SC_SEM_NSEMS_MAX) = %ld\n", max); UNTESTED("There is no constraint on SEM_NSEMS_MAX"); } sems = (sem_t *) calloc(max, sizeof(sem_t)); if (sems == NULL) { UNRESOLVED(errno, "Failed to alloc space"); } for (i = 0; i < max; i++) { ret = sem_init(&sems[i], 0, 0); if (ret != 0) { output ("sem_init failed to initialize the %d nth semaphore.\n", i); output("Tryed to initialize %ld.\n", max); output("Error is %d: %s\n", errno, strerror(errno)); for (; i > 0; i--) sem_destroy(&sems[i - 1]); free(sems); PASSED; } } ret = sem_init(&sem_last, 0, 1); if (ret == 0) { FAILED ("We were able to sem_init more than SEM_NSEMS_MAX semaphores"); } if (errno != ENOSPC) { output("Error is %d: %s\n", errno, strerror(errno)); } for (i = 0; i < max; i++) sem_destroy(&sems[i]); free(sems); /* Test passed */ #if VERBOSE > 0 output("Test passed\n"); #endif PASSED; }
int main (int argc, char * argv[]) { int ret; pthread_mutexattr_t ma; pthread_condattr_t ca; int scenar; long pshared, monotonic, cs, mf; pid_t p_child[NTHREADS]; pthread_t t_child[NTHREADS]; int ch; pid_t pid; int status; pthread_t t_timer; testdata_t alternativ; output_init(); /* check the system abilities */ pshared = sysconf(_SC_THREAD_PROCESS_SHARED); cs = sysconf(_SC_CLOCK_SELECTION); monotonic = sysconf(_SC_MONOTONIC_CLOCK); mf =sysconf(_SC_MAPPED_FILES); #if VERBOSE > 0 output("Test starting\n"); output("System abilities:\n"); output(" TPS : %li\n", pshared); output(" CS : %li\n", cs); output(" MON : %li\n", monotonic); output(" MF : %li\n", mf); if ((mf < 0) || (pshared < 0)) output("Process-shared attributes won't be tested\n"); if ((cs < 0) || (monotonic < 0)) output("Alternative clock won't be tested\n"); #endif /* We are not interested in testing the clock if we have no other clock available.. */ if (monotonic < 0) cs = -1; #ifndef USE_ALTCLK if (cs > 0) output("Implementation supports the MONOTONIC CLOCK but option is disabled in test.\n"); #endif /********** * Allocate space for the testdata structure */ if (mf < 0) { /* Cannot mmap a file, we use an alternative method */ td = &alternativ; pshared = -1; /* We won't do this testing anyway */ #if VERBOSE > 0 output("Testdata allocated in the process memory.\n"); #endif } else { /* We will place the test data in a mmaped file */ char filename[] = "/tmp/cond_destroy-XXXXXX"; size_t sz, ps; void * mmaped; int fd; char * tmp; /* We now create the temp files */ fd = mkstemp(filename); if (fd == -1) { UNRESOLVED(errno, "Temporary file could not be created"); } /* and make sure the file will be deleted when closed */ unlink(filename); #if VERBOSE > 1 output("Temp file created (%s).\n", filename); #endif ps = (size_t)sysconf(_SC_PAGESIZE); sz= ((sizeof(testdata_t) / ps) + 1) * ps; /* # pages needed to store the testdata */ tmp = calloc(1 , sz); if (tmp == NULL) { UNRESOLVED(errno, "Memory allocation failed"); } /* Write the data to the file. */ if (write (fd, tmp, sz) != (ssize_t) sz) { UNRESOLVED(sz, "Writting to the file failed"); } free(tmp); /* Now we can map the file in memory */ mmaped = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mmaped == MAP_FAILED) { UNRESOLVED(errno, "mmap failed"); } td = (testdata_t *) mmaped; /* Our datatest structure is now in shared memory */ #if VERBOSE > 1 output("Testdata allocated in shared memory (%ib).\n", sizeof(testdata_t)); #endif } /* Do the test for each test scenario */ for (scenar=0; scenar < NSCENAR; scenar++) { /* set / reset everything */ td->fork=0; ret = pthread_mutexattr_init(&ma); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to initialize the mutex attribute object"); } ret = pthread_condattr_init(&ca); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to initialize the cond attribute object"); } #ifndef WITHOUT_XOPEN /* Set the mutex type */ ret = pthread_mutexattr_settype(&ma, scenarii[scenar].m_type); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set mutex type"); } #endif /* Set the pshared attributes, if supported */ if ((pshared > 0) && (scenarii[scenar].mc_pshared != 0)) { ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set the mutex process-shared"); } ret = pthread_condattr_setpshared(&ca, PTHREAD_PROCESS_SHARED); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set the cond var process-shared"); } } /* Set the alternative clock, if supported */ #ifdef USE_ALTCLK if ((cs > 0) && (scenarii[scenar].c_clock != 0)) { ret = pthread_condattr_setclock(&ca, CLOCK_MONOTONIC); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set the monotonic clock for the cond"); } } ret = pthread_condattr_getclock(&ca, &td->cid); if (ret != 0) { UNRESOLVED(ret, "Unable to get clock from cond attr"); } #else td->cid = CLOCK_REALTIME; #endif /* Tell whether the test will be across processes */ if ((pshared > 0) && (scenarii[scenar].fork != 0)) { td->fork = 1; } /* Proceed to testing */ /* initialize the mutex */ ret = pthread_mutex_init(&td->mtx1, &ma); if (ret != 0) { UNRESOLVED(ret, "Mutex init failed"); } ret = pthread_mutex_init(&td->mtx2, &ma); if (ret != 0) { UNRESOLVED(ret, "Mutex init failed"); } ret = pthread_mutex_lock(&td->mtx2); if (ret != 0) { UNRESOLVED(ret, "Mutex lock failed"); } /* initialize the condvar */ ret = pthread_cond_init(&td->cnd, &ca); if (ret != 0) { UNRESOLVED(ret, "Cond init failed"); } #if VERBOSE > 2 output("[parent] Starting 1st pass of test %s\n", scenarii[scenar].descr); #endif td->count1=0; td->count2=0; td->predicate1=0; td->predicate2=0; /* Create all the children */ for (ch=0; ch < NTHREADS; ch++) { if (td->fork==0) { ret = pthread_create(&t_child[ch], NULL, child, NULL); if (ret != 0) { UNRESOLVED(ret, "Failed to create a child thread"); } } else { p_child[ch]=fork(); if (p_child[ch] == -1) { ret = errno; for (--ch; ch>=0; ch--) kill(p_child[ch], SIGKILL); UNRESOLVED(ret, "Failed to create a child process"); } if (p_child[ch] == 0) /* We are the child */ { child(NULL); exit(0); } } } #if VERBOSE > 4 output("[parent] All children are running\n"); #endif /* Make sure all children are waiting */ ret = pthread_mutex_lock(&td->mtx1); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to lock mutex", p_child); } ch = td->count1; while (ch < NTHREADS) { ret = pthread_mutex_unlock(&td->mtx1); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to unlock mutex",p_child); } sched_yield(); ret = pthread_mutex_lock(&td->mtx1); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to lock mutex",p_child); } ch = td->count1; } #if VERBOSE > 4 output("[parent] All children are waiting\n"); #endif /* create the timeout thread */ ret = pthread_create(&t_timer, NULL, timer, p_child); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Unable to create timer thread",p_child); } /* Wakeup the children */ td->predicate1=1; ret = pthread_cond_broadcast(&td->cnd); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to signal the condition.", p_child); } ret = pthread_mutex_unlock(&td->mtx1); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to unlock mutex",p_child); } /* Destroy the condvar (this must be safe) */ ret = pthread_cond_destroy(&td->cnd); if (ret != 0) { FAILED_KILLALL("Unable to destroy the cond while no thread is blocked inside", p_child); } /* Reuse the cond memory */ memset(&td->cnd, 0xFF, sizeof(pthread_cond_t)); #if VERBOSE > 4 output("[parent] Condition was broadcasted, and condvar destroyed.\n"); #endif /* Make sure all children have exited the first wait */ ret = pthread_mutex_lock(&td->mtx1); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to lock mutex",p_child); } ch = td->count1; while (ch > 0) { ret = pthread_mutex_unlock(&td->mtx1); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to unlock mutex",p_child); } sched_yield(); ret = pthread_mutex_lock(&td->mtx1); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to lock mutex",p_child); } ch = td->count1; } ret = pthread_mutex_unlock(&td->mtx1); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to unlock mutex",p_child); } /* Go toward the 2nd pass */ /* Now, all children are waiting to lock the 2nd mutex, which we own here. */ /* reinitialize the condvar */ ret = pthread_cond_init(&td->cnd, &ca); if (ret != 0) { UNRESOLVED(ret, "Cond init failed"); } #if VERBOSE > 2 output("[parent] Starting 2nd pass of test %s\n", scenarii[scenar].descr); #endif /* Make sure all children are waiting */ ch = td->count2; while (ch < NTHREADS) { ret = pthread_mutex_unlock(&td->mtx2); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to unlock mutex",p_child); } sched_yield(); ret = pthread_mutex_lock(&td->mtx2); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to lock mutex",p_child); } ch = td->count2; } #if VERBOSE > 4 output("[parent] All children are waiting\n"); #endif /* Wakeup the children */ td->predicate2=1; ret = pthread_cond_broadcast(&td->cnd); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to signal the condition.", p_child); } /* Allow the children to terminate */ ret = pthread_mutex_unlock(&td->mtx2); if (ret != 0) { UNRESOLVED_KILLALL(ret, "Failed to unlock mutex",p_child); } /* Destroy the condvar (this must be safe) */ ret = pthread_cond_destroy(&td->cnd); if (ret != 0) { FAILED_KILLALL("Unable to destroy the cond while no thread is blocked inside", p_child); } /* Reuse the cond memory */ memset(&td->cnd, 0x00, sizeof(pthread_cond_t)); #if VERBOSE > 4 output("[parent] Condition was broadcasted, and condvar destroyed.\n"); #endif #if VERBOSE > 4 output("[parent] Joining the children\n"); #endif /* join the children */ for (ch=(NTHREADS - 1); ch >= 0 ; ch--) { if (td->fork==0) { ret = pthread_join(t_child[ch], NULL); if (ret != 0) { UNRESOLVED(ret, "Failed to join a child thread"); } } else { pid = waitpid(p_child[ch], &status, 0); if (pid != p_child[ch]) { ret = errno; output("Waitpid failed (expected: %i, got: %i)\n", p_child[ch], pid); for (; ch>=0; ch--) { kill(p_child[ch], SIGKILL); } UNRESOLVED(ret, "Waitpid failed"); } if (WIFEXITED(status)) { /* the child should return only failed or unresolved or passed */ if (ret != PTS_FAIL) ret |= WEXITSTATUS(status); } } } if (ret != 0) { output_fini(); exit(ret); } #if VERBOSE > 4 output("[parent] All children terminated\n"); #endif /* cancel the timeout thread */ ret = pthread_cancel(t_timer); if (ret != 0) { /* Strange error here... the thread cannot be terminated (app would be killed) */ UNRESOLVED(ret, "Failed to cancel the timeout handler"); } /* join the timeout thread */ ret = pthread_join(t_timer, NULL); if (ret != 0) { UNRESOLVED(ret, "Failed to join the timeout handler"); } /* Destroy the datas */ ret = pthread_cond_destroy(&td->cnd); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the condvar"); } ret = pthread_mutex_destroy(&td->mtx1); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the mutex"); } ret = pthread_mutex_destroy(&td->mtx2); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the mutex"); } /* Destroy the attributes */ ret = pthread_condattr_destroy(&ca); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the cond var attribute object"); } ret = pthread_mutexattr_destroy(&ma); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the mutex attribute object"); } } /* exit */ PASSED; }
/* Child function (either in a thread or in a process) */ void * child(void * arg) { int ret=0; struct timespec ts; char timed; /* lock the 1st mutex */ ret = pthread_mutex_lock(&td->mtx1); if (ret != 0) { UNRESOLVED(ret, "Failed to lock mutex in child"); } /* increment count */ td->count1++; timed=td->count1 & 1; if (timed) { /* get current time if we are a timedwait */ ret = clock_gettime(td->cid, &ts); if (ret != 0) { UNRESOLVED(errno, "Unable to read clock"); } ts.tv_sec += TIMEOUT; } do { /* Wait while the predicate is false */ if (timed) ret = pthread_cond_timedwait(&td->cnd, &td->mtx1, &ts); else ret = pthread_cond_wait(&td->cnd, &td->mtx1); } while ((ret == 0) && (td->predicate1==0)); if ((ret != 0) && (td->predicate1 != 0)) { output("Wakening the cond failed with error %i (%s)\n", ret, strerror(ret)); FAILED("Destroying the cond var while threads were awaken but inside wait routine failed."); } if (ret != 0) { UNRESOLVED(ret, "Failed to wait for the cond"); } td->count1--; /* unlock the mutex */ ret = pthread_mutex_unlock(&td->mtx1); if (ret != 0) { UNRESOLVED(ret, "Failed to unlock the mutex."); } /* Second pass */ /* lock the mutex */ ret = pthread_mutex_lock(&td->mtx2); if (ret != 0) { UNRESOLVED(ret, "Failed to lock mutex in child"); } /* increment count */ td->count2++; timed=td->count2 & 1; if (timed) { /* get current time if we are a timedwait */ ret = clock_gettime(td->cid, &ts); if (ret != 0) { UNRESOLVED(errno, "Unable to read clock"); } ts.tv_sec += TIMEOUT; } do { /* Wait while the predicate is false */ if (timed) ret = pthread_cond_timedwait(&td->cnd, &td->mtx2, &ts); else ret = pthread_cond_wait(&td->cnd, &td->mtx2); } while ((ret == 0) && (td->predicate2==0)); if ((ret != 0) && (td->predicate2 != 0)) { output("Wakening the cond failed with error %i (%s)\n", ret, strerror(ret)); FAILED("Destroying the cond var while threads were awaken but inside wait routine failed."); } if (ret != 0) { UNRESOLVED(ret, "Failed to wait for the cond"); } /* unlock the mutex */ ret = pthread_mutex_unlock(&td->mtx2); if (ret != 0) { UNRESOLVED(ret, "Failed to unlock the mutex."); } return NULL; }
/* The main test function. */ int main(void) { int ret, i; char *name = "/sem_open_15_1"; sem_t *sems[4]; /* Initialize output */ output_init(); /* Initialize all semaphores */ for (i = 0; i < 4; i++) { sems[i] = sem_open(name, O_CREAT, 0777, 1); if (sems[i] == SEM_FAILED) { UNRESOLVED(errno, "Failed to sem_open"); } } /* Check all calls returned the same @ */ for (i = 0; i < 3; i++) { if (sems[i] != sems[i + 1]) { FAILED("sem_open returned a different address"); } /* Close some semaphores */ ret = sem_close(sems[i]); if (ret != 0) { UNRESOLVED(errno, "Failed to sem_close"); } } /* Now, reopen, we should still get the same address */ for (i = 0; i < 3; i++) { sems[i] = sem_open(name, O_CREAT, 0777, 1); if (sems[i] == SEM_FAILED) { UNRESOLVED(errno, "Failed to sem_open"); } } /* Check all calls returned the same @ */ for (i = 0; i < 3; i++) { if (sems[i] != sems[i + 1]) { FAILED("sem_open returned a different address"); } } /* Close all semaphores */ for (i = 0; i < 4; i++) { ret = sem_close(sems[i]); if (ret != 0) { UNRESOLVED(errno, "Failed to sem_close"); } } sem_unlink(name); /* Test passed */ #if VERBOSE > 0 output("Test passed\n"); #endif PASSED; }
void * threaded(void * arg) { pthread_condattr_t ca[4], *pca[5]; pthread_cond_t c[5]; int i; int ret; /* We need to register the signal handlers */ struct sigaction sa; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = sighdl1; if ((ret = sigaction (SIGUSR1, &sa, NULL))) { UNRESOLVED(ret, "Unable to register signal handler1"); } sa.sa_handler = sighdl2; if ((ret = sigaction (SIGUSR2, &sa, NULL))) { UNRESOLVED(ret, "Unable to register signal handler2"); } /* Initialize the different cond attributes */ pca[4]=NULL; for (i=0; i<4; i++) { pca[i]=&ca[i]; if ((ret = pthread_condattr_init(pca[i]))) { UNRESOLVED(ret, "pthread_condattr_init"); } } ret = pthread_condattr_setpshared(pca[0], PTHREAD_PROCESS_SHARED); if (ret != 0) { UNRESOLVED(ret, "Cond attribute PSHARED failed"); } ret = pthread_condattr_setpshared(pca[1], PTHREAD_PROCESS_SHARED); if (ret != 0) { UNRESOLVED(ret, "Cond attribute PSHARED failed"); } #if VERBOSE >1 output("PShared condvar attributes initialized\n"); #endif if (sysconf(_SC_MONOTONIC_CLOCK) > 0) { ret = pthread_condattr_setclock(pca[1], CLOCK_MONOTONIC); if (ret != 0) { UNRESOLVED(ret, "Cond set monotonic clock failed"); } ret = pthread_condattr_setclock(pca[2], CLOCK_MONOTONIC); if (ret != 0) { UNRESOLVED(ret, "Cond set monotonic clock failed"); } #if VERBOSE >1 output("Alternative clock condvar attributes initialized\n"); #endif } /* We are ready to proceed */ while (do_it) { for (i=0; i<5; i++) { ret = pthread_cond_init(&c[i], pca[i]); if (ret == EINTR) { FAILED("pthread_cond_init returned EINTR"); } if (ret != 0) { UNRESOLVED(ret, "pthread_cond_init failed"); } ret = pthread_cond_destroy(&c[i]); if (ret == EINTR) { FAILED("pthread_cond_destroy returned EINTR"); } if (ret != 0) { UNRESOLVED(ret, "pthread_cond_destroy failed"); } pthread_mutex_lock(&count_protect); count_ope++; pthread_mutex_unlock(&count_protect); } } /* Now we can destroy the mutex attributes objects */ for (i=0; i<4; i++) { if ((ret = pthread_condattr_destroy(pca[i]))) { UNRESOLVED(ret, "pthread_condattr_init"); } } do { ret = sem_wait(&semsync); } while (ret && (errno == EINTR)); if (ret) { UNRESOLVED(errno, "Could not wait for sig senders termination"); } return NULL; }
int main(int argc, char *argv[]) { int ret; pthread_t th_work, th_sig1, th_sig2; struct thestruct arg1, arg2; struct sigaction sa; output_init(); sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = sighdl1; ret = sigaction(SIGUSR1, &sa, NULL); if (ret == -1) UNRESOLVED(ret, "Unable to register signal handler1"); sa.sa_handler = sighdl2; ret = sigaction(SIGUSR2, &sa, NULL); if (ret == -1) UNRESOLVED(ret, "Unable to register signal handler2"); /* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */ sigemptyset(&usersigs); ret = sigaddset(&usersigs, SIGUSR1); ret |= sigaddset(&usersigs, SIGUSR2); if (ret != 0) UNRESOLVED(ret, "Unable to add SIGUSR1 or 2 to a signal set"); /* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */ ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); if (ret != 0) UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 " "in main thread"); #ifdef WITH_SYNCHRO if (sem_init(&semsig1, 0, 1)) UNRESOLVED(errno, "Semsig1 init"); if (sem_init(&semsig2, 0, 1)) UNRESOLVED(errno, "Semsig2 init"); #endif /* Initialize thread attribute objects */ scenar_init(); ret = pthread_create(&th_work, NULL, test, NULL); if (ret) UNRESOLVED(ret, "Worker thread creation failed"); arg1.sig = SIGUSR1; arg2.sig = SIGUSR2; #ifdef WITH_SYNCHRO arg1.sem = &semsig1; arg2.sem = &semsig2; #endif ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1); if (ret) UNRESOLVED(ret, "Signal 1 sender thread creation failed"); ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2); if (ret) UNRESOLVED(ret, "Signal 2 sender thread creation failed"); /* Now stop the threads and join them */ do { do_it1 = 0; } while (do_it1); sleep(1); do { do_it2 = 0; } while (do_it2); ret = pthread_join(th_sig1, NULL); if (ret) UNRESOLVED(ret, "Signal 1 sender thread join failed"); ret = pthread_join(th_sig2, NULL); if (ret) UNRESOLVED(ret, "Signal 2 sender thread join failed"); ret = pthread_join(th_work, NULL); if (ret) UNRESOLVED(ret, "Worker thread join failed"); scenar_fini(); #if VERBOSE > 0 output("Test executed successfully.\n"); output(" %d pthread_join calls.\n", count_ope); #ifdef WITH_SYNCHRO output(" %d signals were sent meanwhile.\n", count_sig); #endif #endif PASSED; }
/* Main function */ int main (int argc, char * argv[]) { int ret; pthread_t th_work, th_sig1, th_sig2; thestruct arg1, arg2; output_init(); #ifdef WITH_SYNCHRO if (sem_init(&semsig1, 0, 1)) { UNRESOLVED(errno, "Semsig1 init"); } if (sem_init(&semsig2, 0, 1)) { UNRESOLVED(errno, "Semsig2 init"); } #endif if (sem_init(&semsync, 0, 0)) { UNRESOLVED(errno, "semsync init"); } if ((ret = pthread_create(&th_work, NULL, threaded, NULL))) { UNRESOLVED(ret, "Worker thread creation failed"); } arg1.thr = &th_work; arg2.thr = &th_work; arg1.sig = SIGUSR1; arg2.sig = SIGUSR2; #ifdef WITH_SYNCHRO arg1.sem = &semsig1; arg2.sem = &semsig2; #endif if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) { UNRESOLVED(ret, "Signal 1 sender thread creation failed"); } if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) { UNRESOLVED(ret, "Signal 2 sender thread creation failed"); } /* Let's wait for a while now */ sleep(1); /* Now stop the threads and join them */ do { do_it=0; } while (do_it); if ((ret = pthread_join(th_sig1, NULL))) { UNRESOLVED(ret, "Signal 1 sender thread join failed"); } if ((ret = pthread_join(th_sig2, NULL))) { UNRESOLVED(ret, "Signal 2 sender thread join failed"); } if (sem_post(&semsync)) { UNRESOLVED(errno, "could not post semsync"); } if ((ret = pthread_join(th_work, NULL))) { UNRESOLVED(ret, "Worker thread join failed"); } #if VERBOSE > 0 output("Test executed successfully.\n"); output(" %d condvars initialization and destruction were done.\n", count_ope); #ifdef WITH_SYNCHRO output(" %d signals were sent meanwhile.\n", count_sig); #endif #endif PASSED; }
/* The main test function. */ int main(int argc, char *argv[]) { int ret, value; sem_t *sem1, *sem2; /* Initialize output */ output_init(); /* Create the semaphore */ sem1 = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0777, 1); if ((sem1 == SEM_FAILED) && (errno == EEXIST)) { sem_unlink(SEM_NAME); sem1 = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0777, 1); } if (sem1 == SEM_FAILED) { UNRESOLVED(errno, "Failed to create the semaphore"); } /* Unlink */ ret = sem_unlink(SEM_NAME); if (ret != 0) { UNRESOLVED(errno, "Failed to unlink the semaphore"); } /* Try reconnect */ sem2 = sem_open(SEM_NAME, 0); if (sem2 != SEM_FAILED) { FAILED("Reconnecting the unlinked semaphore did not failed"); } if (errno != ENOENT) { output("Error %d: %s\n", errno, strerror(errno)); FAILED ("Reconnecting the unlinked semaphore failed with a wrong error"); } /* Reopen the semaphore */ sem2 = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0777, 3); if (sem2 == SEM_FAILED) { output("Gor error %d: %s\n", errno, strerror(errno)); FAILED("Failed to recreate the semaphore"); } /* Check the semaphore have different values */ ret = sem_getvalue(sem1, &value); if (ret != 0) { UNRESOLVED(errno, "Failed to read sem1 value"); } if (value != 1) { output("Read: %d\n", value); FAILED("Semaphore value is not as expected"); } ret = sem_getvalue(sem2, &value); if (ret != 0) { UNRESOLVED(errno, "Failed to read sem1 value"); } if (value != 3) { output("Read: %d\n", value); FAILED("Semaphore value is not as expected"); } /* Unlink */ ret = sem_unlink(SEM_NAME); if (ret != 0) { UNRESOLVED(errno, "Failed to unlink the semaphore"); } /* close both */ ret = sem_close(sem1); if (ret != 0) { UNRESOLVED(errno, "Failed to close the semaphore"); } ret = sem_close(sem2); if (ret != 0) { UNRESOLVED(errno, "Failed to close the semaphore"); } /* Test passed */ #if VERBOSE > 0 output("Test passed\n"); #endif PASSED; }
/***** main program *****/ int main(int argc, char *argv[]) { pthread_mutex_t mtx_null, mtx_def; pthread_mutexattr_t mattr; pthread_t thr; pthread_mutex_t * tab_mutex[2]={&mtx_null, &mtx_def}; int tab_res[2][3]={{0,0,0},{0,0,0}}; int ret; void * th_ret; int i; output_init(); #if VERBOSE >1 output("Test starting...\n"); #endif /* We first initialize the two mutexes. */ if ((ret=pthread_mutex_init(&mtx_null, NULL))) { UNRESOLVED(ret, "NULL mutex init"); } if ((ret=pthread_mutexattr_init(&mattr))) { UNRESOLVED(ret, "Mutex attribute init"); } if ((ret=pthread_mutex_init(&mtx_def, &mattr))) { UNRESOLVED(ret, "Default attribute mutex init"); } if ((ret=pthread_mutexattr_destroy(&mattr))) { UNRESOLVED(ret, "Mutex attribute destroy"); } if ((ret=sem_init(&semA, 0, 0))) { UNRESOLVED(errno, "Sem A init"); } if ((ret=sem_init(&semB, 0, 0))) { UNRESOLVED(errno, "Sem B init"); } #if VERBOSE >1 output("Data initialized...\n"); #endif /* OK let's go for the first part of the test : abnormals unlocking */ /* We first check if unlocking an unlocked mutex returns an error. */ retval = pthread_mutex_unlock(tab_mutex[0]); ret = pthread_mutex_unlock(tab_mutex[1]); #if VERBOSE >0 output("Results for unlock issue #1:\n mutex 1 unlocking returned %i\n mutex 2 unlocking returned %i\n", retval, ret); #endif if (ret != retval) { FAILED("Unlocking an unlocked mutex behaves differently."); } /* Now we focus on unlocking a mutex lock by another thread */ for (i=0; i<2; i++) { p_mtx = tab_mutex[i]; tab_res[i][0]=0; tab_res[i][1]=0; tab_res[i][2]=0; #if VERBOSE >1 output("Creating thread (unlock)...\n"); #endif if ((ret = pthread_create(&thr, NULL, unlock_issue, NULL))) { UNRESOLVED(ret, "Unlock issue thread create"); } if ((ret = sem_wait(&semA))) { UNRESOLVED(errno, "Sem A wait failed for unlock issue."); } #if VERBOSE >1 output("Unlocking in parent...\n"); #endif retval = pthread_mutex_unlock(p_mtx); if ((ret = sem_post(&semB))) { UNRESOLVED(errno, "Sem B post failed for unlock issue."); } if ((ret=pthread_join(thr, &th_ret))) { UNRESOLVED(ret, "Join thread"); } #if VERBOSE >1 output("Thread joined successfully...\n"); #endif tab_res[i][0] = retval; } #if VERBOSE >0 output("Results for unlock issue #2:\n mutex 1 returned %i\n mutex 2 returned %i\n", tab_res[0][0],tab_res[1][0]); #endif if (tab_res[0][0] != tab_res[1][0]) { FAILED("Unlocking an unowned mutex behaves differently."); } /* We now are going to test the deadlock issue */ /* We start with testing the NULL mutex features */ for (i=0; i<2; i++) { p_mtx = tab_mutex[i]; tab_res[i][0]=0; tab_res[i][1]=0; tab_res[i][2]=0; #if VERBOSE >1 output("Creating thread (deadlk)...\n"); #endif if ((ret = pthread_create(&thr, NULL, deadlk_issue, NULL))) { UNRESOLVED(ret, "Deadlk_issue thread create"); } /* Now we are waiting the thread is ready to relock the mutex. */ if ((ret=sem_wait(&semA))) { UNRESOLVED(errno, "Sem wait"); } /* To ensure thread runs until second lock, we yield here */ sched_yield(); /* OK, now we cancel the thread */ canceled=0; #if VERBOSE >1 output("Cancel thread...\n"); #endif if (returned ==0) if ((ret=pthread_cancel(thr))) { UNRESOLVED(ret, "Cancel thread (deadlk_issue)"); } #if VERBOSE >1 output("Thread canceled...\n"); #endif if ((ret=pthread_join(thr, &th_ret))) { UNRESOLVED(ret, "Join thread"); } #if VERBOSE >1 output("Thread joined successfully...\n"); #endif tab_res[i][2] = retval; tab_res[i][1] = returned; tab_res[i][0] = canceled; } /* Now we parse the results */ #if VERBOSE >0 output("Results for deadlock issue:\n mutex 1 \t%s\t%s%i\n mutex 2 \t%s\t%s%i\n", tab_res[0][0]?"deadlock" : "no deadlock", tab_res[0][1]?"returned " : "did not return ", tab_res[0][2], tab_res[1][0]?"deadlock" : "no deadlock", tab_res[1][1]?"returned " : "did not return ", tab_res[1][2]); #endif if (tab_res[0][0] != tab_res[1][0]) { FAILED("One mutex deadlocks, not the other"); } if (tab_res[0][1] != tab_res[1][1]) { UNRESOLVED(tab_res[0][1], "Abnormal situation!"); } if ((tab_res[0][1] == 1) && (tab_res[0][2] != tab_res[1][2])) { FAILED("The locks returned different error codes."); } PASSED; }
int main(void) { int ret, i; pthread_t th_waiter[5], th_worker, th_sig1, th_sig2; struct thestruct arg1, arg2; struct sigaction sa; output_init(); /* We need to register the signal handlers for the PROCESS */ sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = sighdl1; ret = sigaction(SIGUSR1, &sa, NULL); if (ret) UNRESOLVED(ret, "Unable to register signal handler1"); sa.sa_handler = sighdl2; ret = sigaction(SIGUSR2, &sa, NULL); if (ret) UNRESOLVED(ret, "Unable to register signal handler2"); /* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */ sigemptyset(&usersigs); ret = sigaddset(&usersigs, SIGUSR1); ret |= sigaddset(&usersigs, SIGUSR2); if (ret != 0) UNRESOLVED(ret, "Unable to add SIGUSR1 or 2 to a signal set"); /* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */ ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); if (ret != 0) UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 " "in main thread"); #ifdef WITH_SYNCHRO if (sem_init(&semsig1, 0, 1)) UNRESOLVED(errno, "Semsig1 init"); if (sem_init(&semsig2, 0, 1)) UNRESOLVED(errno, "Semsig2 init"); #endif for (i = 0; i < 5; i++) { ret = pthread_create(&th_waiter[i], NULL, waiter, NULL); if (ret) UNRESOLVED(ret, "Waiter thread creation failed"); } ret = pthread_create(&th_worker, NULL, worker, NULL); if (ret) UNRESOLVED(ret, "Worker thread creation failed"); arg1.sig = SIGUSR1; arg2.sig = SIGUSR2; #ifdef WITH_SYNCHRO arg1.sem = &semsig1; arg2.sem = &semsig2; #endif ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1); if (ret) UNRESOLVED(ret, "Signal 1 sender thread creation failed"); ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2); if (ret) UNRESOLVED(ret, "Signal 2 sender thread creation failed"); /* Let's wait for a while now */ sleep(1); /* Now stop the threads and join them */ do { do_it = 0; } while (do_it); ret = pthread_join(th_sig1, NULL); if (ret) UNRESOLVED(ret, "Signal 1 sender thread join failed"); ret = pthread_join(th_sig2, NULL); if (ret) UNRESOLVED(ret, "Signal 2 sender thread join failed"); for (i = 0; i < 5; i++) { ret = pthread_join(th_waiter[i], NULL); if (ret) UNRESOLVED(ret, "Waiter thread join failed"); } ret = pthread_join(th_worker, NULL); if (ret) UNRESOLVED(ret, "Worker thread join failed"); #if VERBOSE > 0 output("Test executed successfully.\n"); output(" Condition was signaled %d times.\n", count_cnd_sig); output(" pthread_cond_wait exited %d times.\n", count_cnd_wup); #ifdef WITH_SYNCHRO output(" %d signals were sent meanwhile.\n", count_sig); #endif #endif PASSED; }
/*** * The child function (always in the main process) */ void * threaded_A (void * arg) { struct childdata * cd = (struct childdata *)arg; int ret, status; pid_t child_p=0, wrc; pthread_t child_t; ret = pthread_mutex_lock(&(cd->mtx)); if (ret != 0) { UNRESOLVED(ret, "[child] Unable to lock mutex"); } /* Create the grand child */ if (cd->fork == 0) { ret = pthread_create(&child_t, &ta, threaded_B, arg); if (ret != 0) { UNRESOLVED(ret, "[child] Failed to create a grand child thread"); } } else { child_p= fork(); if (child_p == -1) { UNRESOLVED(ret, "[child] Failed to create a grand child proces"); } if (child_p == 0) /* grand child */ { threaded_B(arg); exit(0); } } while (*(cd->pBool) == 0) { alarm(TIMEOUT); ret = pthread_cond_wait(&(cd->cnd), &(cd->mtx)); if (ret != 0) { UNRESOLVED(ret, "[child] Failed to wait the cond"); } ret = pthread_cond_signal(&(cd->cnd)); if (ret != 0) { UNRESOLVED(ret, "[child] Signal failed"); } } ret = pthread_mutex_unlock(&(cd->mtx)); if (ret != 0) { UNRESOLVED(ret, "[gchild] Failed to finally release the mutex"); } /* Wait for the grand child termination */ if (cd->fork == 0) { ret = pthread_join(child_t, NULL); if (ret != 0) { UNRESOLVED(ret, "[child] Failed to join a grand child thread"); } } else { wrc = waitpid(child_p, &status, 0); if (wrc != child_p) { output("Expected pid: %i. Got %i\n", (int)child_p, (int)wrc); UNRESOLVED(errno, "Waitpid failed"); } if (WIFSIGNALED(status)) { output("Child process killed with signal %d\n",WTERMSIG(status)); UNRESOLVED(0 , "Child process was killed"); } if (WIFEXITED(status)) { ret = WEXITSTATUS(status); } else { UNRESOLVED(0, "Child process was neither killed nor exited"); } } /* the end */ return NULL; }
int main (int argc, char *argv[]) { int ret=0; pthread_t child; output_init(); scenar_init(); for (sc=0; sc < NSCENAR; sc++) { #if VERBOSE > 0 output("-----\n"); output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); #endif if (scenarii[sc].detached != 0) /* only joinable threads can be detached */ { ret = pthread_attr_setdetachstate(&scenarii[sc].ta, PTHREAD_CREATE_JOINABLE); if (ret != 0) { UNRESOLVED(ret, "Unable to set detachstate back to joinable"); } } /* for detached scenarii, we will call pthread_detach from inside the thread. for joinable scenarii, we'll call pthread_detach from this thread. */ ret = pthread_create(&child, &scenarii[sc].ta, threaded, (scenarii[sc].detached != 0)?&ret:NULL); switch (scenarii[sc].result) { case 0: /* Operation was expected to succeed */ if (ret != 0) { UNRESOLVED(ret, "Failed to create this thread"); } break; case 1: /* Operation was expected to fail */ if (ret == 0) { UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); } #if VERBOSE > 0 break; case 2: /* We did not know the expected result */ default: if (ret == 0) { output("Thread has been created successfully for this scenario\n"); } else { output("Thread creation failed with the error: %s\n", strerror(ret)); } #endif } if (ret == 0) /* The new thread is running */ { /* Just wait for the thread to terminate */ do { ret = sem_wait(&(scenarii[sc].sem)); } while ((ret == -1) && (errno == EINTR)); if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } /* If we must detach from here, we do it now. */ if (scenarii[sc].detached == 0) { ret = pthread_detach(child); if (ret != 0) { UNRESOLVED(ret, "Failed to detach the child thread."); } } /* now check that the thread resources are freed. */ ret = pthread_join(child, NULL); if (ret == 0) { FAILED("We were able to join a detached thread."); } /* Let the thread an additionnal row to cleanup */ sched_yield(); } } scenar_fini(); #if VERBOSE > 0 output("-----\n"); output("All test data destroyed\n"); output("Test PASSED\n"); #endif PASSED; }
/* Thread routine */ void *threaded(void *arg) { int ret = 0; pid_t pid, chk; int status; if (mf > 0) *ctl = 0; pid = fork(); if (pid == (pid_t) - 1) { UNRESOLVED(errno, "Failed to fork()"); } if (pid == 0) { /* children */ if (mf > 0) { ret = atexit(clnp); if (ret != 0) { UNRESOLVED(ret, "Failed to register atexit function"); } } /* exit the last (and only) thread */ pthread_exit(&ret); FAILED ("pthread_exit() did not terminate the process when there was only 1 thread"); } /* Only the parent process goes this far */ chk = waitpid(pid, &status, 0); if (chk != pid) { output("Expected pid: %i. Got %i\n", (int)pid, (int)chk); UNRESOLVED(errno, "Waitpid failed"); } if (WIFSIGNALED(status)) { output("Child process killed with signal %d\n", WTERMSIG(status)); UNRESOLVED(-1, "Child process was killed"); } if (WIFEXITED(status)) { ret = WEXITSTATUS(status); } else { UNRESOLVED(-1, "Child process was neither killed nor exited"); } if (ret != 0) { output("Exit status was: %i\n", ret); FAILED("The child process did not exit with 0 status."); } if (mf > 0) if (*ctl != 1) FAILED ("pthread_exit() in the last thread did not execute atexit() routines"); /* Signal we're done (especially in case of a detached thread) */ do { ret = sem_post(&scenarii[sc].sem); } while ((ret == -1) && (errno == EINTR)); if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } return NULL; }
/* Test function -- creates the threads and check that EINTR is never returned. */ void * test(void * arg) { int ret=0; pthread_t child; /* We don't block the signals SIGUSR1 and SIGUSR2 for this THREAD */ ret = pthread_sigmask(SIG_UNBLOCK, &usersigs, NULL); if (ret != 0) { UNRESOLVED(ret, "Unable to unblock SIGUSR1 and SIGUSR2 in worker thread"); } sc = 0; while (do_it) { #if VERBOSE > 5 output("-----\n"); output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); #endif count_ope++; ret = pthread_create(&child, &scenarii[sc].ta, threaded, NULL); if (ret == EINTR) { FAILED("pthread_create returned EINTR"); } switch (scenarii[sc].result) { case 0: /* Operation was expected to succeed */ if (ret != 0) { UNRESOLVED(ret, "Failed to create this thread"); } break; case 1: /* Operation was expected to fail */ if (ret == 0) { UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); } break; case 2: /* We did not know the expected result */ default: #if VERBOSE > 5 if (ret == 0) { output("Thread has been created successfully for this scenario\n"); } else { output("Thread creation failed with the error: %s\n", strerror(ret)); } #endif ; } if (ret == 0) /* The new thread is running */ { if (scenarii[sc].detached == 0) { ret = pthread_join(child, NULL); if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } } else { /* Just wait for the thread to terminate */ do { ret = sem_wait(&scenarii[sc].sem); } while ((ret == -1) && (errno == EINTR)); if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } } } /* Change thread attribute for the next loop */ sc++; sc %= NSCENAR; } return NULL; }
/* main function */ int main() { int ret; struct sigaction sa, save; /* Initialize output */ output_init(); /* Register the signal handler with signal */ if (SIG_ERR == signal(SIGNAL, handler_1)) { UNRESOLVED(errno, "Failed to register signal handler with signal()"); } /* As whether signal handler is restored to default when executed is implementation defined, we cannot check it was registered here. */ /* Set the new signal handler with sigaction*/ sa.sa_flags = 0; sa.sa_handler = handler_2; ret = sigemptyset(&sa.sa_mask); if (ret != 0) { UNRESOLVED(ret, "Failed to empty signal set"); } /* Install the signal handler for SIGUSR1 */ ret = sigaction(SIGNAL, &sa, &save); if (ret != 0) { UNRESOLVED(ret, "Failed to set signal handler"); } /* Check the signal handler has been set up */ ret = raise(SIGNAL); if (ret != 0) { UNRESOLVED(ret , "Failed to raise the signal"); } if (called != 0) { FAILED("handler not executed"); } /* Restore the first signal handler */ ret = sigaction(SIGNAL, &save, 0); if (ret != 0) { UNRESOLVED(ret, "Failed to set signal handler"); } /* Check the signal handler has been set up */ ret = raise(SIGNAL); if (ret != 0) { UNRESOLVED(ret , "Failed to raise the signal"); } if (called != 1) { FAILED("handler not executed"); } /* Test passed */ #if VERBOSE > 0 output("Test passed\n"); #endif PASSED; }
int main (int argc, char *argv[]) { int ret=0; pthread_t child; pthread_t *th; int nthreads, ctl, i, tmp; struct timespec ts_ref, ts_fin; mes_t sentinel; mes_t *m_cur, *m_tmp; long PTHREAD_THREADS_MAX = sysconf(_SC_THREAD_THREADS_MAX); long my_max = 1000 * SCALABILITY_FACTOR ; /* Initialize the measure list */ m_cur = &sentinel; m_cur->next = NULL; /* Initialize output routine */ output_init(); if (PTHREAD_THREADS_MAX > 0) my_max = PTHREAD_THREADS_MAX; th = (pthread_t *)calloc(1 + my_max, sizeof(pthread_t)); if (th == NULL) { UNRESOLVED(errno, "Not enough memory for thread storage"); } /* Initialize thread attribute objects */ scenar_init(); #ifdef PLOT_OUTPUT printf("# COLUMNS %d #threads", NSCENAR + 1); for (sc=0; sc<NSCENAR; sc++) printf(" %i", sc); printf("\n"); #endif for (sc=0; sc < NSCENAR; sc++) { if (scenarii[sc].bottom == NULL) /* skip the alternate stacks as we could create only 1 */ { #if VERBOSE > 0 output("-----\n"); output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); #endif /* Block every (about to be) created threads */ ret = pthread_mutex_lock(&m_synchro); if (ret != 0) { UNRESOLVED(ret, "Mutex lock failed"); } ctl=0; nthreads=0; m_cur = &sentinel; /* Create 1 thread for testing purpose */ ret = pthread_create(&child, &scenarii[sc].ta, threaded, &ctl); switch (scenarii[sc].result) { case 0: /* Operation was expected to succeed */ if (ret != 0) { UNRESOLVED(ret, "Failed to create this thread"); } break; case 1: /* Operation was expected to fail */ if (ret == 0) { UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); } break; case 2: /* We did not know the expected result */ default: #if VERBOSE > 0 if (ret == 0) { output("Thread has been created successfully for this scenario\n"); } else { output("Thread creation failed with the error: %s\n", strerror(ret)); } #endif ; } if (ret == 0) /* The new thread is running */ { while (1) /* we will break */ { /* read clock */ ret = clock_gettime(CLOCK_REALTIME, &ts_ref); if (ret != 0) { UNRESOLVED(errno, "Unable to read clock"); } /* create a new thread */ ret = pthread_create(&th[nthreads], &scenarii[sc].ta, threaded, &ctl); /* stop here if we've got EAGAIN */ if (ret == EAGAIN) break; // temporary hack if (ret == ENOMEM) break; nthreads++; /* FAILED if error is != EAGAIN or nthreads > PTHREAD_THREADS_MAX */ if (ret != 0) { output("pthread_create returned: %i (%s)\n", ret, strerror(ret)); FAILED("pthread_create did not return EAGAIN on a lack of resource"); } if (nthreads > my_max) { if (PTHREAD_THREADS_MAX > 0) { FAILED("We were able to create more than PTHREAD_THREADS_MAX threads"); } else { break; } } /* wait for the semaphore */ do { ret = sem_wait(&scenarii[sc].sem); } while ((ret == -1) && (errno == EINTR)); if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } /* read clock */ ret = clock_gettime(CLOCK_REALTIME, &ts_fin); if (ret != 0) { UNRESOLVED(errno, "Unable to read clock"); } /* add to the measure list if nthreads % resolution == 0 */ if ((nthreads % RESOLUTION) == 0) { if (m_cur->next == NULL) { /* Create an empty new element */ m_tmp = (mes_t *) malloc(sizeof(mes_t)); if (m_tmp == NULL) { UNRESOLVED(errno, "Unable to alloc memory for measure saving"); } m_tmp->nthreads = nthreads; m_tmp->next = NULL; for (tmp=0; tmp<NSCENAR; tmp++) m_tmp->_data[tmp]= 0; m_cur->next = m_tmp; } /* Add this measure to the next element */ m_cur = m_cur->next; m_cur->_data[sc] = ((ts_fin.tv_sec - ts_ref.tv_sec) * 1000000) + ((ts_fin.tv_nsec - ts_ref.tv_nsec) / 1000) ; #if VERBOSE > 5 output("Added the following measure: sc=%i, n=%i, v=%li\n", sc, nthreads, m_cur->_data[sc]); #endif } } #if VERBOSE > 3 output("Could not create anymore thread. Current count is %i\n", nthreads); #endif /* Unblock every created threads */ ret = pthread_mutex_unlock(&m_synchro); if (ret != 0) { UNRESOLVED(ret, "Mutex unlock failed"); } if (scenarii[sc].detached == 0) { #if VERBOSE > 3 output("Joining the threads\n"); #endif for (i = 0; i < nthreads; i++) { ret = pthread_join(th[i], NULL); if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } } ret = pthread_join(child, NULL); if (ret != 0) { UNRESOLVED(ret, "Unalbe to join a thread"); } } #if VERBOSE > 3 output("Waiting for threads (almost) termination\n"); #endif do { ret = pthread_mutex_lock(&m_synchro); if (ret != 0) { UNRESOLVED(ret, "Mutex lock failed"); } tmp = ctl; ret = pthread_mutex_unlock(&m_synchro); if (ret != 0) { UNRESOLVED(ret, "Mutex unlock failed"); } } while (tmp != nthreads + 1); } /* The thread was created */ } } /* next scenario */ /* Free some memory before result parsing */ free(th); /* Compute the results */ ret = parse_measure(&sentinel); /* Free the resources and output the results */ #if VERBOSE > 5 printf("Dump : \n"); printf("%8.8s", "nth"); for (i = 0; i<NSCENAR; i++) printf("| %2.2i ", i); printf("\n"); #endif while (sentinel.next != NULL) { m_cur = sentinel.next; #if (VERBOSE > 5) || defined(PLOT_OUTPUT) printf("%8.8i", m_cur->nthreads); for (i=0; i<NSCENAR; i++) printf(" %1.1li.%6.6li", m_cur->_data[i] / 1000000, m_cur->_data[i] % 1000000); printf("\n"); #endif sentinel.next = m_cur->next; free(m_cur); } scenar_fini(); #if VERBOSE > 0 output("-----\n"); output("All test data destroyed\n"); output("Test PASSED\n"); #endif PASSED; }
/* Test function -- This one calls pthread_mutex_trylock and check that no EINTR is returned. */ void * test(void * arg) { int ret=0; int i; long pshared; pthread_mutex_t mtx[NSCENAR+2]; pthread_mutexattr_t ma[NSCENAR+1]; /* We don't block the signals SIGUSR1 and SIGUSR2 for this THREAD */ ret = pthread_sigmask(SIG_UNBLOCK, &usersigs, NULL); if (ret != 0) { UNRESOLVED(ret, "Unable to unblock SIGUSR1 and SIGUSR2 in worker thread"); } /* System abilities */ pshared = sysconf(_SC_THREAD_PROCESS_SHARED); /* Initialize the mutex objects according to the scenarii */ for (i=0; i<NSCENAR; i++) { ret = pthread_mutexattr_init(&ma[i]); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to initialize the mutex attribute object"); } #ifndef WITHOUT_XOPEN /* Set the mutex type */ ret = pthread_mutexattr_settype(&ma[i], scenarii[i].m_type); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set mutex type"); } #endif /* Set the pshared attributes, if supported */ if ((pshared > 0) && (scenarii[i].m_pshared != 0)) { ret = pthread_mutexattr_setpshared(&ma[i], PTHREAD_PROCESS_SHARED); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to set the mutex process-shared"); } } /* Initialize the mutex */ ret = pthread_mutex_init(&mtx[i], &ma[i]); if (ret != 0) { UNRESOLVED(ret, "[parent] Mutex init failed"); } } /* Default mutexattr object */ ret = pthread_mutexattr_init(&ma[i]); if (ret != 0) { UNRESOLVED(ret, "[parent] Unable to initialize the mutex attribute object"); } ret = pthread_mutex_init(&mtx[i], &ma[i]); if (ret != 0) { UNRESOLVED(ret, "[parent] Mutex init failed"); } /* Default mutex */ ret = pthread_mutex_init(&mtx[i+1], NULL); if (ret != 0) { UNRESOLVED(ret, "[parent] Mutex init failed"); } /* do the real testing */ while (do_it) { count_ope++; ret = pthread_mutex_trylock(&mtx[count_ope % (NSCENAR+2)]); if (ret == EINTR) { FAILED("EINTR was returned"); } if (ret != 0) { UNRESOLVED(ret, "1st trylock failed"); } ret = pthread_mutex_trylock(&mtx[count_ope % (NSCENAR+2)]); if (ret == EINTR) { FAILED("EINTR was returned"); } if (ret == 0) { ret = pthread_mutex_unlock(&mtx[count_ope % (NSCENAR+2)]); if (ret != 0) { UNRESOLVED(ret, "Unlocking the mutex failed"); } ret = EBUSY; } if (ret != EBUSY) { UNRESOLVED(ret, "Unexpected error was returned."); } ret = pthread_mutex_unlock(&mtx[count_ope % (NSCENAR+2)]); if (ret != 0) { UNRESOLVED(ret, "Failed to unlock the mutex"); } } /* Destroy everything */ for (i=0; i <= NSCENAR; i++) { ret = pthread_mutex_destroy(&mtx[i]); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the mutex"); } ret = pthread_mutexattr_destroy(&ma[i]); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the mutex attr object"); } } ret = pthread_mutex_destroy(&mtx[i]); if (ret != 0) { UNRESOLVED(ret, "Failed to destroy the mutex"); } return NULL; }
int parse_measure(mes_t * measures) { int ret, i, r; mes_t *cur; double Xavg[NSCENAR], Yavg[NSCENAR]; double LnXavg[NSCENAR], LnYavg[NSCENAR]; int N; double r1[NSCENAR], r2[NSCENAR], r3[NSCENAR], r4[NSCENAR]; /* Some more intermediate vars */ long double _q[3][NSCENAR]; long double _d[3][NSCENAR]; long double t; /* temp value */ struct row *Table = NULL; /* This array contains the last element of each serie */ int array_max[NSCENAR]; /* Initialize the datas */ for (i=0; i<NSCENAR; i++) { array_max[i] = -1; /* means no data */ Xavg[i] = 0.0; LnXavg[i] = 0.0; Yavg[i] = 0.0; LnYavg[i] = 0.0; r1[i] = 0.0; r2[i] = 0.0; r3[i] = 0.0; r4[i] = 0.0; _q[0][i]=0.0; _q[1][i]=0.0; _q[2][i]=0.0; _d[0][i]=0.0; _d[1][i]=0.0; _d[2][i]=0.0; } N=0; cur = measures; #if VERBOSE > 1 output("Data analysis starting\n"); #endif /* We start with reading the list to find: * -> number of elements, to assign an array. * -> average values */ while (cur->next != NULL) { cur = cur->next; N++; for (i=0; i<NSCENAR; i++) { if (cur->_data[i] != 0) { array_max[i]=N; Xavg[i] += (double) cur->nthreads; LnXavg[i] += log((double) cur->nthreads); Yavg[i] += (double) cur->_data[i]; LnYavg[i] += log((double) cur->_data[i]); } } } /* We have the sum; we can divide to obtain the average values */ for (i=0; i<NSCENAR; i++) { if (array_max[i] != -1) { Xavg[i] /= array_max[i]; LnXavg[i] /= array_max[i]; Yavg[i] /= array_max[i]; LnYavg[i] /= array_max[i]; } } #if VERBOSE > 1 output(" Found %d rows and %d columns\n", N, NSCENAR); #endif /* We will now alloc the array ... */ Table = calloc(N, sizeof(struct row)); if (Table == NULL) { UNRESOLVED(errno, "Unable to alloc space for results parsing"); } /* ... and fill it */ N = 0; cur = measures; while (cur->next != NULL) { cur = cur->next; Table[N].X = (long) cur->nthreads; Table[N].LnX = log((double) cur->nthreads); for (i=0; i<NSCENAR; i++) { if (array_max[i] > N) { Table[N]._x[i] = Table[N].X - Xavg[i] ; Table[N]._lnx[i] = Table[N].LnX - LnXavg[i]; Table[N].Y[i] = cur->_data[i]; Table[N]._y[i] = Table[N].Y[i] - Yavg[i] ; Table[N].LnY[i] = log((double) cur->_data[i]); Table[N]._lny[i] = Table[N].LnY[i] - LnYavg[i]; } } N++; } /* We won't need the list anymore -- we'll work with the array which should be faster. */ #if VERBOSE > 1 output(" Data was stored in an array.\n"); #endif /* We need to read the full array at least twice to compute all the error factors */ /* In the first pass, we'll compute: * -> r1 for each scenar. * -> "a" factor for linear (0), power (1) and exponential (2) approximations -- with using the _d and _q vars. */ #if VERBOSE > 1 output("Starting first pass...\n"); #endif for (i=0; i<NSCENAR; i++) { for (r=0; r<array_max[i]; r++) { r1[i] += ((double)Table[r]._y[i] / array_max[i]) * (double)Table[r]._y[i]; _q[0][i] += Table[r]._y[i] * Table[r]._x[i]; _d[0][i] += Table[r]._x[i] * Table[r]._x[i]; _q[1][i] += Table[r]._lny[i] * Table[r]._lnx[i]; _d[1][i] += Table[r]._lnx[i] * Table[r]._lnx[i]; _q[2][i] += Table[r]._lny[i] * Table[r]._x[i]; _d[2][i] += Table[r]._x[i] * Table[r]._x[i]; } } /* First pass is terminated; a2 = _q[0]/_d[0]; a3 = _q[1]/_d[1]; a4 = _q[2]/_d[2] */ /* In the first pass, we'll compute: * -> r2, r3, r4 for each scenar. */ #if VERBOSE > 1 output("Starting second pass...\n"); #endif for (i=0; i<NSCENAR; i++) { for (r=0; r<array_max[i]; r++) { /* r2 = avg((y - ax -b)²); t = (y - ax - b) = (y - yavg) - a (x - xavg); */ t = (Table[r]._y[i] - ((_q[0][i] * Table[r]._x[i]) / _d[0][i])); r2[i] += t * t / array_max[i] ; /* r3 = avg((y - c.x^a) ²); t = y - c * x ^ a = y - log (LnYavg - (_q[1]/_d[1]) * LnXavg) * x ^ (_q[1]/_d[1]) */ t = ( Table[r].Y[i] - (logl (LnYavg[i] - (_q[1][i] / _d[1][i]) * LnXavg[i]) * powl(Table[r].X, (_q[1][i] / _d[1][i])) ) ); r3[i] += t * t / array_max[i] ; /* r4 = avg((y - exp(ax+b))²); t = y - exp(ax+b) = y - exp(_q[2]/_d[2] * x + (LnYavg - (_q[2]/_d[2] * Xavg))); = y - exp(_q[2]/_d[2] * (x - Xavg) + LnYavg); */ t = ( Table[r].Y[i] - expl((_q[2][i] / _d[2][i]) * Table[r]._x[i] + LnYavg[i])); r4[i] += t * t / array_max[i] ; } } #if VERBOSE > 1 output("All computing terminated.\n"); #endif ret = 0; for (i=0; i<NSCENAR; i++) { #if VERBOSE > 1 output("\nScenario: %s\n", scenarii[i].descr); output(" # of data: %i\n", array_max[i]); output(" Model: Y = k\n"); output(" k = %g\n", Yavg[i]); output(" Divergence %g\n", r1[i]); output(" Model: Y = a * X + b\n"); output(" a = %Lg\n", _q[0][i] / _d[0][i]); output(" b = %Lg\n", Yavg[i] - ((_q[0][i] / _d[0][i]) * Xavg[i])); output(" Divergence %g\n", r2[i]); output(" Model: Y = c * X ^ a\n"); output(" a = %Lg\n", _q[1][i] / _d[1][i]); output(" c = %Lg\n", logl (LnYavg[i] - (_q[1][i] / _d[1][i]) * LnXavg[i])); output(" Divergence %g\n", r2[i]); output(" Model: Y = exp(a * X + b)\n"); output(" a = %Lg\n", _q[2][i] / _d[2][i]); output(" b = %Lg\n", LnYavg[i] - ((_q[2][i] / _d[2][i]) * Xavg[i])); output(" Divergence %g\n", r2[i]); #endif if (array_max[i] != -1) { /* Compare r1 to other values, with some ponderations */ if ((r1[i] > 1.1 * r2[i]) || (r1[i] > 1.2 * r3[i]) || (r1[i] > 1.3 * r4[i])) ret++; #if VERBOSE > 1 else output(" Sanction: OK\n"); #endif } } /* We need to free the array */ free(Table); /* We're done */ return ret; }
/* The main test function. */ int main(int argc, char * argv[]) { int ret, status; pid_t child, ctl; sigset_t mask, pending; /* Initialize output */ output_init(); /* block SIGUSR1 and SIGUSR2 */ ret = sigemptyset(&mask); if (ret != 0) { UNRESOLVED(errno, "Failed to initialize signal set"); } ret = sigaddset(&mask, SIGUSR1); if (ret != 0) { UNRESOLVED(errno, "Failed to add SIGUSR1 to signal set"); } ret = sigaddset(&mask, SIGUSR2); if (ret != 0) { UNRESOLVED(errno, "Failed to add SIGUSR2 to signal set"); } ret = sigprocmask(SIG_BLOCK, &mask, NULL); if (ret != 0) { UNRESOLVED(errno, "Sigprocmask failed"); } /* Make the signals pending */ ret = kill(getpid(), SIGUSR1); if (ret != 0) { UNRESOLVED(errno, "failed to kill with SIGUSR1"); } ret = kill(getpid(), SIGUSR2); if (ret != 0) { UNRESOLVED(errno, "failed to kill with SIGUSR2"); } do { ret = sigpending(&pending); if (ret != 0) { UNRESOLVED(errno, "failed to examine pending signal set"); } ret = sigismember(&pending, SIGUSR1); if (ret < 0) { UNRESOLVED(errno, "Unable to check signal USR1 presence"); } if (ret == 1) { ret = sigismember(&pending, SIGUSR2); if (ret < 0) { UNRESOLVED(errno, "Unable to check signal USR2 presence"); } } } while (ret != 1); #if VERBOSE > 0 output("SIGUSR1 and SIGUSR2 are pending, we can fork\n"); #endif /* Create the child */ child = fork(); if (child == -1) { UNRESOLVED(errno, "Failed to fork"); } /* child */ if (child == 0) { /* Examine the current blocked signal set. USR1 & USR2 shall be present */ ret = sigprocmask(0, NULL, &mask); if (ret != 0) { UNRESOLVED(errno, "Sigprocmask failed in child"); } ret = sigismember(&mask, SIGUSR1); if (ret < 0) { UNRESOLVED(errno, "Unable to check signal USR1 presence"); } if (ret == 0) { FAILED("The new process does not mask SIGUSR1 as its parent"); } ret = sigismember(&mask, SIGUSR2); if (ret < 0) { UNRESOLVED(errno, "Unable to check signal USR2 presence"); } if (ret == 0) { FAILED("The new process does not mask SIGUSR2 as its parent"); } #if VERBOSE > 0 output("SIGUSR1 and SIGUSR2 are blocked in child\n"); #endif /* Examine pending signals */ ret = sigpending(&pending); if (ret != 0) { UNRESOLVED(errno, "failed to examine pending signal set in child"); } ret = sigismember(&pending, SIGUSR1); if (ret < 0) { UNRESOLVED(errno, "Unable to check signal USR1 presence"); } if (ret != 0) { FAILED("The new process was created with SIGUSR1 pending"); } ret = sigismember(&pending, SIGUSR2); if (ret < 0) { UNRESOLVED(errno, "Unable to check signal USR2 presence"); } if (ret != 0) { FAILED("The new process was created with SIGUSR2 pending"); } #if VERBOSE > 0 output("SIGUSR1 and SIGUSR2 are not pending in child\n"); #endif /* We're done */ exit(PTS_PASS); } /* Parent joins the child */ ctl = waitpid(child, &status, 0); if (ctl != child) { UNRESOLVED(errno, "Waitpid returned the wrong PID"); } if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) { FAILED("Child exited abnormally"); } /* Test passed */ #if VERBOSE > 0 output("Test passed\n"); #endif PASSED; }
/* The main test function. */ int main(int argc, char *argv[]) { int ret, status; pid_t child, ctl; struct itimerval it; /* Initialize output */ output_init(); /* Create the interval timer */ it.it_interval.tv_sec = 15; it.it_interval.tv_usec = 0; it.it_value.tv_sec = 10; it.it_value.tv_usec = 0; ret = setitimer(ITIMER_REAL, &it, NULL); if (ret != 0) { UNRESOLVED(errno, "Failed to set interval timer for ITIMER_REAL"); } ret = setitimer(ITIMER_VIRTUAL, &it, NULL); if (ret != 0) { UNRESOLVED(errno, "Failed to set interval timer for ITIMER_VIRTUAL"); } ret = setitimer(ITIMER_PROF, &it, NULL); if (ret != 0) { UNRESOLVED(errno, "Failed to set interval timer for ITIMER_PROF"); } #if VERBOSE > 0 output("All interval timers are set.\n"); #endif /* Create the child */ child = fork(); if (child == -1) { UNRESOLVED(errno, "Failed to fork"); } /* child */ if (child == 0) { /* Check we get the correct information: timer is reset */ ret = getitimer(ITIMER_REAL, &it); if (ret != 0) { UNRESOLVED(errno, "Failed to read ITIMER_REAL in child"); } if (it.it_value.tv_sec != 0) { FAILED("Timer ITIMER_REAL was not reset in child"); } ret = getitimer(ITIMER_VIRTUAL, &it); if (ret != 0) { UNRESOLVED(errno, "Failed to read ITIMER_VIRTUAL in child"); } if (it.it_value.tv_sec != 0) { FAILED("Timer ITIMER_VIRTUAL was not reset in child"); } ret = getitimer(ITIMER_PROF, &it); if (ret != 0) { UNRESOLVED(errno, "Failed to read ITIMER_PROF in child"); } if (it.it_value.tv_sec != 0) { FAILED("Timer ITIMER_PROF was not reset in child"); } /* We're done */ exit(PTS_PASS); } /* Parent joins the child */ ctl = waitpid(child, &status, 0); if (ctl != child) { UNRESOLVED(errno, "Waitpid returned the wrong PID"); } if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) { FAILED("Child exited abnormally"); } /* Test passed */ #if VERBOSE > 0 output("Test passed\n"); #endif PASSED; }