コード例 #1
0
ファイル: pth_str03.c プロジェクト: joyforu/android-ltp-ndk
/*--------------------------------------------------------------------------------*
 * doit
 *
 * Do it.
 *--------------------------------------------------------------------------------*/
void *doit( void *param )
{
        c_info *parent  = (c_info *) param;
	int		rc, child, my_index;
	void		*status;
	c_info 		*info_p;
	struct timespec	timer;

	if (parent != NULL) {
	    /* Synchronize with our siblings so that all the children at
	     * a given level have been created before we allow those children
	     * to spawn new ones (or do anything else for that matter).  */
	    if (debug) {
		printf( "non-root child calling synchronize_children\n" );
		fflush( stdout );
	    }
	    my_index = synchronize_children( parent );
	    if (debug) {
		printf( "non-root child has been assigned index %d\n",
		  my_index );
		fflush( stdout );
	    }
	} else {
	    /* The first thread has no one with which to synchronize, so
	     * set some initial values for things.  */
	    if (debug) {
		printf( "root child\n" );
		fflush( stdout );
	    }
	    cdepth = 1;
	    my_index = 0;
	    node_count = 1;
	}

	/* Figure out our place in the pthread array.  */
	info_p = &child_info[my_index];

	if (debug) {
	    printf( "thread %d getting to heart of doit.\n", my_index );
	    printf( "info_p=%p, cdepth=%d, depth=%d\n", info_p, cdepth, depth );
	    fflush( stdout );
	}

	if (cdepth <= depth)
	{
	    /* Since the tree is not yet complete (it is not yet tall enough),
	     * we need to create another level of children.  */

	    tst_resm(TINFO, "thread %d creating kids, cdepth=%d", my_index, cdepth);

	    /* Create breadth children.  */
	    for (child = 0; child < breadth; child++) {
		if ((rc = pthread_create(&(info_p->threads[child]), &attr, doit, (void *) info_p))) {
		    tst_resm( TINFO, "pthread_create (doit): %s",
		      strerror(rc) );
		    testexit( 3 );
		} else {
		    if (debug) {
			printf( "pthread_create made thread %p\n",
			  &(info_p->threads[child]) );
			fflush( stdout );
		    }
		}
	    }

	    if (debug) {
		printf( "thread %d waits on kids, cdepth=%d\n", my_index,
		    cdepth );
		fflush( stdout );
	    }

	    /* Wait for our children to finish before we exit ourselves.  */
	    for (child = 0; child < breadth; child++) {
		if (debug) {
		    printf( "attempting join on thread %p\n",
		      &(info_p->threads[child]) );
		    fflush( stdout );
		}
		if ((rc = pthread_join((info_p->threads[child]), &status))) {
		    if (debug) {
			printf(
			  "join failed on thread %d, status addr=%p: %s\n",
			  my_index, status, strerror(rc) );
			fflush( stdout );
		    }
		    testexit( 4 );
		} else {
		    if (debug) {
			printf( "thread %d joined child %d ok\n", my_index, child );
			fflush( stdout );
		    }

		    /* Add all childrens indexes to your index value */
		    info_p->sum += info_p->child_ptrs[child]->sum;
		    tst_resm(TINFO, "thread %d adding child thread %d to sum = %ld",
			   my_index, info_p->child_ptrs[child]->index, (long int)info_p->sum);
		}
	    }

	} else {

	    /* This is the leaf node case.  These children don't create
	     * any kids; they just talk amongst themselves.  */
	    tst_resm( TINFO, "thread %d is a leaf node, depth=%d", my_index, cdepth );

	    /* Talk to siblings (children of the same parent node).  */
	    if (breadth > 1) {

		for (child = 0; child < breadth; child++) {
		    /* Don't talk to yourself.  */
		    if (parent->child_ptrs[child] != info_p) {
			if (debug) {
			    printf( "thread %d locking talk_mutex\n",
			      my_index );
			    fflush( stdout );
			}
			pthread_mutex_lock(
			  &(parent->child_ptrs[child]->talk_mutex) );
			if (++parent->child_ptrs[child]->talk_count == (breadth - 1)) {
			    if (debug) {
				printf( "thread %d talk siblings\n", my_index );
				fflush( stdout );
			    }
			    if ((rc = pthread_cond_broadcast(
			      &parent->child_ptrs[child]->talk_condvar))) {
				tst_resm( TINFO, "pthread_cond_broadcast: %s",
				  strerror(rc) );
				testexit( 5 );
			    }
			}
			if (debug) {
			    printf( "thread %d unlocking talk_mutex\n",
			      my_index );
			    fflush( stdout );
			}
			pthread_mutex_unlock(
			  &(parent->child_ptrs[child]->talk_mutex) );
		    }
		}

		/* Wait until the breadth - 1 siblings have contacted us.  */
		if (debug) {
		    printf( "thread %d waiting for talk siblings\n", my_index );
		    fflush( stdout );
		}

		pthread_mutex_lock( &info_p->talk_mutex );
		if (info_p->talk_count < (breadth - 1)) {
		    time( &timer.tv_sec );
		    timer.tv_sec += (unsigned long)timeout * 60;
		    timer.tv_nsec = (unsigned long)0;
		    if ((rc = pthread_cond_timedwait(&info_p->talk_condvar,
		      &info_p->talk_mutex, &timer))) {
			tst_resm( TINFO,
			  "pthread_cond_timedwait (leaf) %d: %s",
			  my_index, strerror(rc) );
			testexit( 6 );
		    }
		}
		pthread_mutex_unlock( &info_p->talk_mutex );

	    }

	}

	/* Our work is done.  We're outta here. */
	tst_resm(TINFO, "thread %d exiting, depth=%d, status=%d, addr=%p", my_index,
	  cdepth, info_p->status, info_p);

	pthread_exit( 0 );
}
コード例 #2
0
ファイル: sfs_c_pnt.c プロジェクト: richwolski/bluesky
/*
 * Parent: wait for kids to get ready, start them, wait for them to
 * finish, read and accumulate results.
 */
void
parent(
    int		children,
    int		load,
    char *	mix_file,
    char *	iodist_file)
{
    char	string[80];	/* for interactive startup */
    int		result;
    int		invalid_run;	/* holds INVALID RUN status */
    int		runtime_val;	/* store Runtime value to be printed later */
    int		Saveerrno;
    char	*nameptr;
#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
    struct sigaction sig_act, old_sig_act;
#endif

    /*
     * Setup a SIGCHLD handler in case one of our beloved children dies
     * before its time.
     */
#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
    /* use XOPEN signal handling */

    sig_act.sa_handler = sfs_reaper;
    (void)sigemptyset(&sig_act.sa_mask);
    sig_act.sa_flags = 0;
    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
        perror("sigaction failed: SIGCHLD");
        exit(66);
    }
#else
    (void) signal(SIGCHLD, sfs_reaper);
#endif

    /* Change my name for error logging */
    if ((nameptr = strrchr(sfs_Myname, '/')) != NULL)
        sfs_Myname = ++nameptr;

    /*
     * store the Runtime value; to be printed in results
     */
    if (Prime_client)
	runtime_val = Runtime - MULTICLIENT_OFFSET;
    else runtime_val = Runtime;

    /* print logfile header information */
    (void) fprintf(stdout,"\n");
    (void) fprintf(stdout,
    "************************************************************************");
    (void) fprintf(stdout,"\n");
    (void) fflush(stdout);

    /* print sfs information */
    if (Prime_client) {
	(void) fprintf(stderr,
		"\nSFS NFS Version %d Benchmark Client Logfile, %s\n",
			nfs_version, lad_timestamp());
	(void) fprintf(stderr, "\tClient hostname = %s\n", lad_hostname);
	(void) fprintf(stderr, "\tPrime Client hostname = %s\n",
			Prime_client);
    }

    (void) fprintf(stderr, "\nSPEC SFS Benchmark Version %s, Creation - %s\n",
				SFS_VERSION_NUM, SFS_VERSION_DATE);
    (void) fprintf(stderr, "NFS Protocol Version %d\n", nfs_version);

    /* mount test directories */
    (void) fprintf(stderr, "%s Mounting %d remote test directories.\n",
		lad_timestamp(), children);
    synchronize_children(children);
    (void) fprintf(stderr, "%s Completed.", lad_timestamp());

    /*
     * if multi-client execution then tell Prime-Client I'm done mounting
     * test directories.
     */
    if (Prime_client) {
	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr,
		       "%s Sending DONE-MOUNT message to Prime Client(%s).\n",
			lad_timestamp(), Prime_client);
	if ((result =
	    (int) signal_Prime_Client("CLIENT_SIGNAL", ""))
		== (int) RPC_SUCCESS) {
	    (void) fprintf(stderr, "%s Completed.",lad_timestamp());
	    (void) fflush(stderr);
	} else {
	    (void) fprintf(stderr, "\n");
	    (void) fprintf(stderr,
		"%s:  error %d sending DONE-MOUNT message to Prime Client\n",
		sfs_Myname, result);
	    /* cleanup and exit */
#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
	    sig_act.sa_handler = SIG_DFL;
	    (void)sigemptyset(&sig_act.sa_mask);
	    sig_act.sa_flags = 0;
	    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
	        perror("sigaction failed: SIGCHLD");
	        exit(67);
	    }
#else
	    (void) signal(SIGCHLD, SIG_DFL);
#endif
	    (void) generic_kill(0, SIGINT);
	    exit(68);
	}

	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr,
		    "%s Waiting on DO-INIT message from Prime Client(%s).\n",
		    lad_timestamp(), Prime_client);
	(void) fflush(stderr);

	/*
	 * wait for DO-INIT message from Prime Client
	 * sfs_syncd (rpc server) sends a SIGUSR1 signal;
	 * user can also terminate experiment anytime they wish
	 * with SIGINT or SIGTERM signal
	 */
	(void) pause();
	(void) fprintf(stderr, "%s Received.",lad_timestamp());
	(void) fflush(stderr);

    } /* send DONE-MOUNT and got DO-INIT message */

    /* initialize test directories */
    (void) fprintf(stderr, "\n");
    (void) fprintf(stderr, "%s Initializing test directories.\n",
		    lad_timestamp());

    /* send SIGUSR1 to child processes */
    (void) generic_kill(0, SIGUSR1);
    synchronize_children(children);
    (void) fprintf(stderr, "%s Completed.", lad_timestamp());
    (void) fflush(stderr);

    /*
     * if multi-client execution then tell Prime-Client I'm done initializing
     * and wait for synchronized do warmupmessage.
     */
    if (Prime_client) {
	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr,
		    "%s Sending DONE-INIT message to Prime Client(%s).\n",
			lad_timestamp(), Prime_client);
	if ((result =
	    (int) signal_Prime_Client("CLIENT_SIGNAL",""))
		== (int) RPC_SUCCESS) {
	    (void) fprintf(stderr, "%s Completed.",lad_timestamp());
	    (void) fflush(stderr);
	} else {
	    (void) fprintf(stderr, "\n");
	    (void) fprintf(stderr,
		    "%s:  error %d sending DONE-INIT message to Prime Client\n",
		    sfs_Myname, result);
	    /* cleanup and exit */
#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
	    sig_act.sa_handler = SIG_DFL;
	    (void)sigemptyset(&sig_act.sa_mask);
	    sig_act.sa_flags = 0;
	    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
	        perror("sigaction failed: SIGCHLD");
	        exit(69);
	    }
#else
	    (void) signal(SIGCHLD, SIG_DFL);
#endif
	    (void) generic_kill(0, SIGINT);
	    exit(70);
	}
	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr,
		  "%s Waiting on DO-WARMUP message from Prime Client(%s).\n",
		    lad_timestamp(), Prime_client);
	(void) fflush(stderr);

	/*
	 * wait for DO-WARMUP message from Prime Client
	 * sfs_syncd (rpc server) sends a SIGUSR1 signal;
	 * user can also terminate experiment anytime they wish
	 * with SIGINT or SIGTERM signal
	 */
	(void) pause();
	(void) fprintf(stderr, "%s Received.",lad_timestamp());
	(void) fflush(stderr);

    } /* send DONE-INIT and got DO-WARMUP message */

    if (Populate_only) {
	(void) fprintf(stderr, "\nPopulating directories and exiting.\n");
#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
	sig_act.sa_handler = SIG_DFL;
	(void)sigemptyset(&sig_act.sa_mask);
	sig_act.sa_flags = 0;
	if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
	    perror("sigaction failed: SIGCHLD");
	    exit(71);
	}
#else
	(void) signal(SIGCHLD, SIG_DFL);
#endif
	(void) generic_kill(0, SIGUSR1);
	while (wait((int *) 0) != -1) {
	    /* nop */
	}
	return;
    }

    /* do warm-up */
    if (Warmuptime) {
	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr, "%s Performing %d seconds pretest warmup.\n",
		lad_timestamp(), Warmuptime);
	(void) generic_kill(0, SIGUSR1);
	(void) sleep(Warmuptime);
	(void) fprintf(stderr, "%s Completed.", lad_timestamp());
	(void) fflush(stderr);
    }

    if (Interactive) {
	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr, "Hit <return> when ready to start test ...");
	(void) fgets(string,10,stdin);
    }

    /*
     * if multi-client execution then tell Prime-Client I'm done warm-up
     * and wait for synchronized Start message.
     */
    if (Prime_client) {
	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr,
			"%s Sending READY message to Prime Client(%s).\n",
			lad_timestamp(), Prime_client);
	if ((result =
	    (int) signal_Prime_Client("CLIENT_SIGNAL",""))
		== (int) RPC_SUCCESS) {
	    (void) fprintf(stderr, "%s Completed.",lad_timestamp());
	    (void) fflush(stderr);
	} else {
	    (void) fprintf(stderr, "\n");
	    (void) fprintf(stderr,
		    "%s:  error %d sending READY message to Prime Client\n",
		    sfs_Myname, result);
	    /* cleanup and exit */
#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
	    sig_act.sa_handler = SIG_DFL;
	    (void)sigemptyset(&sig_act.sa_mask);
	    sig_act.sa_flags = 0;
	    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
	        perror("sigaction failed: SIGCHLD");
	        exit(72);
	    }
#else
	    (void) signal(SIGCHLD, SIG_DFL);
#endif
	    (void) generic_kill(0, SIGINT);
	    exit(73);
	}

	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr,
		    "%s Waiting on START message from Prime Client(%s).\n",
		    lad_timestamp(), Prime_client);
	(void) fflush(stderr);

	/*
	 * wait for START message from Prime Client
	 * sfs_syncd (rpc server) sends a SIGUSR1 signal;
	 * user can also terminate experiment anytime they wish
	 * with SIGINT or SIGTERM signal
	 */
	(void) pause();
	(void) fprintf(stderr, "%s Received.",lad_timestamp());
	(void) fflush(stderr);

    } /* send READY and got START message */

    (void) fprintf(stderr, "\n");
    if (Timed_run) {
	if (Prime_client) {
	    (void) fprintf(stderr, "%s Starting %d seconds test run.\n",
		    lad_timestamp(), Runtime - MULTICLIENT_OFFSET);
	} else {
	    (void) fprintf(stderr, "%s Starting %d seconds test run.\n",
		    lad_timestamp(), Runtime);
	}
    } else {
	(void) fprintf(stderr, "%s Starting %d call test run.\n",
		lad_timestamp(), Ops[TOTAL].target_calls);
    }
    (void) fflush(stderr);

    /* signal child processes to go */
    (void) generic_kill(0, SIGUSR1);

    if (Timed_run)
	(void) sleep(Runtime);

#if (defined(_XOPEN_SOURCE) || defined(USE_POSIX_SIGNALS))
    sig_act.sa_handler = SIG_DFL;
    (void)sigemptyset(&sig_act.sa_mask);
    sig_act.sa_flags = 0;
    if (sigaction(SIGCHLD,&sig_act,&old_sig_act) == -1) {
        perror("sigaction failed: SIGCHLD");
        exit(74);
    }
#else
    (void) signal(SIGCHLD, SIG_DFL);
#endif

    if (Timed_run) {
	/*
	 * The parent and the prime are both sleeping for Runtime.
	 * If the parent wakes up first, he'll tell the children to stop.
	 * If the prime wakes up first, he'll send an SIGALRM (via syncd)
	 * to the parent.  That alarm may arrive while the parent is still
	 * asleep, which is ok, or after he has starting running.  Since
	 * the parent SIGARLM catcher does nothing, there is no harm done
	 * by the extra signal in this case.
	 *
	 * Perhaps, if running multi we should just wait (pause()) for
	 * the STOP signal, like we waited for the start signal.  It would
	 * be more obvious.  The only drawback is the OTW rpc delay in
	 * receiving the stop signal from the prime.
	 */
	(void) generic_kill(0, SIGUSR2); /* tell children to finish */
    }

    /* Wait for all the children to finish/die */
    while (wait((int *) 0) != -1) {
	/* nop */
    }

    (void) fprintf(stderr, "%s Completed.", lad_timestamp());
    (void) fflush(stdout);
    (void) fflush(stderr);

    /* Initialize and sum up counters */
    collect_counters(children);
    if ((invalid_run = check_counters()) == 0)
	invalid_run = check_parameters(iodist_file, mix_file, runtime_val);

    /* print test results */
    print_results(children, load, mix_file,
		  invalid_run, runtime_val, iodist_file);

    /*
     * if multi-client execution then tell Prime client that
     * I'm done with 'real' work and wait for move-data message
     * and send data across
     */
    if (Prime_client) {
	(void) fprintf(stderr,
			"%s Sending DONE-TEST message to Prime Client(%s).\n",
			lad_timestamp(), Prime_client);
	if ((result =
	    (int) signal_Prime_Client("CLIENT_SIGNAL",""))
		== (int) RPC_SUCCESS) {
	    (void) fprintf(stderr, "%s Completed.", lad_timestamp());
	    (void) fflush(stderr);
	} else {
	    Saveerrno = errno;
	    (void) fprintf(stderr, "\n");
	    (void) fprintf(stderr,
		    "%s:  error %d sending DONE-TEST message to Prime Client\n",
		    sfs_Myname, result);
	    errno = Saveerrno;
	    perror("signal_Prime_Client");
	    /* cleanup and exit */
	    (void) generic_kill(0, SIGINT);
	    exit(75);
	}

	/*
	 * wait for MOVE-DATA message from Prime Client before
	 * sending send results.
	 */
	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr,
		"%s Waiting on MOVE-DATA message from Prime Client(%s).\n",
		lad_timestamp(), Prime_client);
	(void) fflush(stderr);
	(void) pause();
	(void) fprintf(stderr, "%s Received.", lad_timestamp());
	(void) fprintf(stderr, "\n");
	(void) fprintf(stderr, "%s Sending results to Prime Client(%s)\n",
		lad_timestamp(), Prime_client);
	(void) fflush(stderr);


	if ((result = (int) signal_Prime_Client("CLIENT_DATA",
	    Client_results)) == (int) RPC_SUCCESS) {
	    (void) fprintf(stderr, "%s Completed.\n", lad_timestamp());
	    (void) fflush(stderr);
	} else {
	    Saveerrno = errno;
	    (void) fprintf(stderr, "\n");
	    (void) fprintf(stderr,
		    "%s: error %d sending client's result to Prime Client\n",
		    sfs_Myname, result);
	    errno = Saveerrno;
	    perror("signal_Prime_Client");
	    /* cleanup and exit */
	    (void) generic_kill(0, SIGINT);
	    exit(76);
	}
    } /* sent done, got move-data and sent data */

    (void) fprintf(stdout,"\n");
    (void) fprintf(stdout,
    "************************************************************************");
    (void) fprintf(stdout,"\n");

} /* parent */