Message ID | 4F47CB30.4070506@redhat.com |
---|---|
State | New |
Headers | show |
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; > } > >
On Feb 24, 2012, at 9:38 AM, Andrew MacLeod wrote: > I've been toying with the simulate-thread framework a bit. > OK for mainline? Ok. Don't know why you ask... I'd ask you if I wanted to make a change to the file... Anyway, I reviewed it, and didn't spot anything bad.
On 02/24/2012 02:10 PM, Mike Stump wrote: > On Feb 24, 2012, at 9:38 AM, Andrew MacLeod wrote: >> I've been toying with the simulate-thread framework a bit. >> OK for mainline? > Ok. > > Don't know why you ask... I'd ask you if I wanted to make a change to the file... Anyway, I reviewed it, and didn't spot anything bad. Just dotting my i's :-) I figured I'd give anyone who had issues earlier with these tests a bit of a chance to make sure it works if they wanted :-) Thanks. 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; }