mirror of git://gcc.gnu.org/git/gcc.git
simulate-thread.gdb: Call wrappers for *other_threads() and *final_verify().
* gcc.dg/simulate-thread/simulate-thread.gdb: Call wrappers for *other_threads() and *final_verify(). * gcc.dg/simulate-thread/simulate-thread.h (simulate_thread_wrapper_other_threads): New. (simulate_thread_wrapper_final_verify): New. Co-Authored-By: Andrew MacLeod <amacleod@redhat.com> From-SVN: r179768
This commit is contained in:
parent
fa6963330d
commit
13d563f074
|
@ -1,3 +1,12 @@
|
||||||
|
2011-10-10 Aldy Hernandez <aldyh@redhat.com>
|
||||||
|
Andrew Macleod <amacleod@redhat.com>
|
||||||
|
|
||||||
|
* gcc.dg/simulate-thread/simulate-thread.gdb: Call
|
||||||
|
wrappers for *other_threads() and *final_verify().
|
||||||
|
* gcc.dg/simulate-thread/simulate-thread.h
|
||||||
|
(simulate_thread_wrapper_other_threads): New.
|
||||||
|
(simulate_thread_wrapper_final_verify): New.
|
||||||
|
|
||||||
2011-10-10 Uros Bizjak <ubizjak@gmail.com>
|
2011-10-10 Uros Bizjak <ubizjak@gmail.com>
|
||||||
|
|
||||||
* lib/gcc-gdb-test.exp (gdb-test): Delete $cmd_file before return.
|
* lib/gcc-gdb-test.exp (gdb-test): Delete $cmd_file before return.
|
||||||
|
|
|
@ -5,13 +5,13 @@ run
|
||||||
|
|
||||||
set $ret = 0
|
set $ret = 0
|
||||||
while (simulate_thread_fini != 1) && (! $ret)
|
while (simulate_thread_fini != 1) && (! $ret)
|
||||||
call simulate_thread_other_threads()
|
call simulate_thread_wrapper_other_threads()
|
||||||
stepi
|
stepi
|
||||||
set $ret |= simulate_thread_step_verify()
|
set $ret |= simulate_thread_step_verify()
|
||||||
end
|
end
|
||||||
|
|
||||||
if (! $ret)
|
if (! $ret)
|
||||||
set $ret |= simulate_thread_final_verify()
|
set $ret |= simulate_thread_wrapper_final_verify()
|
||||||
end
|
end
|
||||||
continue
|
continue
|
||||||
quit $ret
|
quit $ret
|
||||||
|
|
|
@ -5,3 +5,107 @@ simulate_thread_done ()
|
||||||
{
|
{
|
||||||
simulate_thread_fini = 1;
|
simulate_thread_fini = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A hostile thread is one which changes a memory location so quickly
|
||||||
|
that another thread may never see the same value again. This is
|
||||||
|
simulated when simulate_thread_other_thread() is defined to modify
|
||||||
|
a memory location every cycle.
|
||||||
|
|
||||||
|
A process implementing a dependency on this value can run into
|
||||||
|
difficulties with such a hostile thread. For instance,
|
||||||
|
implementing an add with a compare_and_swap loop goes something
|
||||||
|
like:
|
||||||
|
|
||||||
|
expected = *mem;
|
||||||
|
loop:
|
||||||
|
new = expected += value;
|
||||||
|
if (!succeed (expected = compare_and_swap (mem, expected, new)))
|
||||||
|
goto loop;
|
||||||
|
|
||||||
|
If the content of 'mem' are changed every cycle by
|
||||||
|
simulate_thread_other_thread () this will become an infinite loop
|
||||||
|
since the value *mem will never be 'expected' by the time the
|
||||||
|
compare_and_swap is executed.
|
||||||
|
|
||||||
|
HOSTILE_THREAD_THRESHOLD defines the number of intructions which a
|
||||||
|
program will execute before triggering the hostile thread
|
||||||
|
pause. The pause will last for HOSTILE_THREAD_PAUSE instructions,
|
||||||
|
and then the counter will reset and begin again. During the pause
|
||||||
|
period, simulate_thread_other_thread will not be called.
|
||||||
|
|
||||||
|
This provides a chance for forward progress to be made and the
|
||||||
|
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
|
||||||
|
HOSTILE_THREAD_PAUSE are insufficient, then the testcase may
|
||||||
|
override these by defining the values before including this file.
|
||||||
|
|
||||||
|
Most testcase are intended to run for very short periods of time,
|
||||||
|
so these defaults are considered to be high enough to not trigger
|
||||||
|
on a typical case, but not drag the test time out too much if a
|
||||||
|
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);
|
||||||
|
|
||||||
|
static int simulate_thread_hostile_pause = 0;
|
||||||
|
|
||||||
|
/* This function wraps simulate_thread_other_threads an monitors for
|
||||||
|
an infinite loop. If the threshold value HOSTILE_THREAD_THRESHOLD
|
||||||
|
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 ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* If the test case defines HOSTILE_PAUSE_ERROR, then the test case
|
||||||
|
will fail execution if it had a hostile pause. */
|
||||||
|
int
|
||||||
|
simulate_thread_wrapper_final_verify ()
|
||||||
|
{
|
||||||
|
int ret = simulate_thread_final_verify ();
|
||||||
|
#if defined (HOSTILE_PAUSE_ERROR)
|
||||||
|
if (simulate_thread_hostile_pause)
|
||||||
|
{
|
||||||
|
printf ("FAIL: Forward progress made only by pausing hostile thread\n");
|
||||||
|
ret = ret | 1; /* 0 indicates proper comnpletion. */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue