On Fri, Feb 24, 2012 at 12:38:56PM -0500, Andrew MacLeod wrote: > I've been toying with the simulate-thread framework a bit. With the > timeout threshold is back to where it originally was, the spectre of > huge log files when an infinite loop happens is back. > > This patch has the following modifications: > > 1) An instruction count threshold has been added. > This will truly prevent infinite loops which were the original > issue. If the count reaches the threshold value, the test case fails. > I've set the current limit to 10,000, which I would expect to be > sufficient. The highest Ive seen so far is 877, but I'm sure someone > will find something higher :-). A testcase can override this value if > it wishes. If we encounter targets where this is not high enough, we > can raise it further. The main point is to avoid generating 10's of > gigabytes of log files when a fast machine hits an infinite loop and the > time based timeout doesnt kick in quickly enough. > If a test does fail for this reason, the log file will issue a FAIL > message indicating the instruction count threshold was exceeded. > > 2) I tweaked the atomic-load-int128.c testcase to avoid an inadvertent > hostile thread situation that was not intended. > > 3) The speculative-store.c testcase had a bug in it where the verify > function was not returning a value when successful. ThIs resulted in an > UNSUPPORTED result occasionally because the testcase didn't run far > enough to indicate GDB had successfully run, yet no FAIL was issued. > > 4) I lowered the hostile thread threshold by an order of magnitude so > that if a hostile thread is encountered frequently, it wont rapidly > approach the new instruction count threshold. This could happen on > compare_and_swap loop targets. > > I've tried this on x86_64-unknown-linux-gnu and everything seems good. > If anyone wants to try it on their more stressed arch, all you need to > do is apply the patch to the testsuite and run 'make check-gcc > RUNTESTFLAGS=simulate-thread.exp' to see if the results are as expected.
Andrew, Works fine on x86_64 darwin when applied to curren gcc trunk... Native configuration is x86_64-apple-darwin11.3.0 === gcc tests === Schedule of variations: unix/-m32 unix/-m64 Running target unix/-m32 Using /sw/share/dejagnu/baseboards/unix.exp as board description file for target. Using /sw/share/dejagnu/config/unix.exp as generic interface file for target. Using /sw/src/fink.build/gcc47-4.7.0-1/gcc-4.7-20120224/gcc/testsuite/config/default.exp as tool-and-target-specific interface file. Running /sw/src/fink.build/gcc47-4.7.0-1/gcc-4.7-20120224/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.exp ... === gcc Summary for unix/-m32 === # of expected passes 76 # of unsupported tests 8 Running target unix/-m64 Using /sw/share/dejagnu/baseboards/unix.exp as board description file for target. Using /sw/share/dejagnu/config/unix.exp as generic interface file for target. Using /sw/src/fink.build/gcc47-4.7.0-1/gcc-4.7-20120224/gcc/testsuite/config/default.exp as tool-and-target-specific interface file. Running /sw/src/fink.build/gcc47-4.7.0-1/gcc-4.7-20120224/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.exp ... === gcc Summary for unix/-m64 === # of expected passes 88 # of unsupported tests 2 === gcc Summary === # of expected passes 164 # of unsupported tests 10 /sw/src/fink.build/gcc47-4.7.0-1/darwin_objdir/gcc/xgcc version 4.7.0 20120224 (experimental) (GCC > > OK for mainline? > > Andrew > > > > > > * gcc.dg/simulate-thread/simulate-thread.gdb: Use return value from > simulate_thread_wrapper_other_threads > * gcc.dg/simulate-thread/atomic-load-int128.c (simulate_thread_main): > Move initialization of 'value' to main(). > (main): Initialize 'value'; > * gcc.dg/simulate-thread/speculative-store.c > (simulate_thread_step_verify): Return 0 when successful. > * gcc.dg/simulate-thread/simulate-thread.h (HOSTILE_THREAD_THRESHOLD): > Reduce threshold. > (INSN_COUNT_THRESHOLD): New. Instruction limit to terminate test. > (simulate_thread_wrapper_other_threads): Return a success/fail value > and issue an error if the instruction count threshold is exceeded. > > Index: testsuite/gcc.dg/simulate-thread/simulate-thread.gdb > =================================================================== > *** testsuite/gcc.dg/simulate-thread/simulate-thread.gdb (revision > 184447) > --- testsuite/gcc.dg/simulate-thread/simulate-thread.gdb (working copy) > *************** run > *** 5,11 **** > > set $ret = 0 > while (simulate_thread_fini != 1) && (! $ret) > ! call simulate_thread_wrapper_other_threads() > stepi > set $ret |= simulate_thread_step_verify() > end > --- 5,11 ---- > > set $ret = 0 > while (simulate_thread_fini != 1) && (! $ret) > ! set $ret |= simulate_thread_wrapper_other_threads() > stepi > set $ret |= simulate_thread_step_verify() > end > Index: testsuite/gcc.dg/simulate-thread/atomic-load-int128.c > =================================================================== > *** testsuite/gcc.dg/simulate-thread/atomic-load-int128.c (revision > 184447) > --- testsuite/gcc.dg/simulate-thread/atomic-load-int128.c (working copy) > *************** void simulate_thread_main() > *** 105,113 **** > { > int x; > > - /* Make sure value starts with an atomic value now. */ > - __atomic_store_n (&value, ret, __ATOMIC_SEQ_CST); > - > /* Execute loads with value changing at various cyclic values. */ > for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--) > { > --- 105,110 ---- > *************** void simulate_thread_main() > *** 126,131 **** > --- 123,132 ---- > main() > { > fill_table (); > + > + /* Make sure value starts with an atomic value from the table. */ > + __atomic_store_n (&value, table[0], __ATOMIC_SEQ_CST); > + > simulate_thread_main (); > simulate_thread_done (); > return 0; > Index: testsuite/gcc.dg/simulate-thread/speculative-store.c > =================================================================== > *** testsuite/gcc.dg/simulate-thread/speculative-store.c (revision > 184447) > --- testsuite/gcc.dg/simulate-thread/speculative-store.c (working copy) > *************** int simulate_thread_step_verify() > *** 24,29 **** > --- 24,30 ---- > printf("FAIL: global variable was assigned to. \n"); > return 1; > } > + return 0; > } > > int simulate_thread_final_verify() > Index: testsuite/gcc.dg/simulate-thread/simulate-thread.h > =================================================================== > *** testsuite/gcc.dg/simulate-thread/simulate-thread.h (revision > 184447) > --- testsuite/gcc.dg/simulate-thread/simulate-thread.h (working copy) > *************** simulate_thread_done () > *** 37,43 **** > infinite loop to be avoided. > > If the testcase defines HOSTILE_PAUSE_ERROR, then it will be > ! considered an RUNTIME FAILURE if the hostile pause is triggered. > This will allow to test for guaranteed forward progress routines. > > If the default values for HOSTILE_THREAD_THRESHOLD or > --- 37,43 ---- > infinite loop to be avoided. > > If the testcase defines HOSTILE_PAUSE_ERROR, then it will be > ! considered a RUNTIME FAILURE if the hostile pause is triggered. > This will allow to test for guaranteed forward progress routines. > > If the default values for HOSTILE_THREAD_THRESHOLD or > *************** simulate_thread_done () > *** 50,66 **** > hostile condition is interferring. */ > > > ! /* Define the threshold to start pausing the hostile thread. */ > #if !defined (HOSTILE_THREAD_THRESHOLD) > ! #define HOSTILE_THREAD_THRESHOLD 500 > #endif > > /* Define the length of pause in cycles for the hostile thread to pause to > ! allow forward progress to be made. */ > #if !defined (HOSTILE_THREAD_PAUSE) > #define HOSTILE_THREAD_PAUSE 20 > #endif > > void simulate_thread_other_threads (void); > int simulate_thread_final_verify (void); > > --- 50,78 ---- > hostile condition is interferring. */ > > > ! /* Define the threshold instruction count to start pausing the hostile > ! thread. To avoid huge potential log files when things are not going > well, > ! set this number very low. If a test specifically requires that the > forward > ! progress guarantee is made, this number should be raised by the > testcase. */ > #if !defined (HOSTILE_THREAD_THRESHOLD) > ! #define HOSTILE_THREAD_THRESHOLD 50 > #endif > > /* Define the length of pause in cycles for the hostile thread to pause to > ! allow forward progress to be made. If this number is too low, a > ! compare_and_swap loop may not have time to finish, especially on a > ! 128 bit operation. */ > #if !defined (HOSTILE_THREAD_PAUSE) > #define HOSTILE_THREAD_PAUSE 20 > #endif > > + /* Define the number of instructions which are allowed to be executed before > + the testcase is deemed to fail. This is primarily to avoid huge log > files > + when a testcase goes into an infinte loop. */ > + #if !defined (INSN_COUNT_THRESHOLD) > + #define INSN_COUNT_THRESHOLD 10000 > + #endif > + > void simulate_thread_other_threads (void); > int simulate_thread_final_verify (void); > > *************** static int simulate_thread_hostile_pause > *** 71,96 **** > is reached, the other_thread process is paused for > HOSTILE_THREAD_PAUSE cycles before resuming, and the counters start > again. */ > ! void > simulate_thread_wrapper_other_threads() > { > ! static int count = 0; > ! static int pause = 0; > > ! if (++count >= HOSTILE_THREAD_THRESHOLD) > { > if (!simulate_thread_hostile_pause) > simulate_thread_hostile_pause = 1; > > /* Count cycles before calling the hostile thread again. */ > ! if (pause++ < HOSTILE_THREAD_PAUSE) > ! return; > > /* Reset the pause counter, as well as the thread counter. */ > ! pause = 0; > ! count = 0; > } > simulate_thread_other_threads (); > } > > > --- 83,116 ---- > is reached, the other_thread process is paused for > HOSTILE_THREAD_PAUSE cycles before resuming, and the counters start > again. */ > ! int > simulate_thread_wrapper_other_threads() > { > ! static int insn_count = 0; > ! static int hostile_count = 0; > ! static int hostile_pause = 0; > ! > ! if (++insn_count >= INSN_COUNT_THRESHOLD) > ! { > ! printf ("FAIL: Testcase exceeded maximum instruction count > threshold\n"); > ! return 1; > ! } > > ! if (++hostile_count >= HOSTILE_THREAD_THRESHOLD) > { > if (!simulate_thread_hostile_pause) > simulate_thread_hostile_pause = 1; > > /* Count cycles before calling the hostile thread again. */ > ! if (hostile_pause++ < HOSTILE_THREAD_PAUSE) > ! return 0; > > /* Reset the pause counter, as well as the thread counter. */ > ! hostile_pause = 0; > ! hostile_count = 0; > } > simulate_thread_other_threads (); > + return 0; > } > >