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;
>   }
>   
>   

Reply via email to