testsuite: pthread: call sched_yield for non-preemptive targets
Commit Message
Systems without preemptive multi-threading require sched_yield calls
to be placed at points in which a context switch might be needed to
enable the test to complete.
Regstrapped on x86_64-linux-gnu, also tested with a cross to
aarch64-rtems6. Ok to install?
for gcc/testsuite/ChangeLog
* gcc.dg/atomic/c11-atomic-exec-4.c: Call sched_yield.
* gcc.dg/atomic/c11-atomic-exec-5.c: Likewise.
* gcc.dg/atomic/pr80640-2.c: Likewise.
* gcc.dg/atomic/pr80640.c: Likewise.
* gcc.dg/atomic/pr81316.c: Likewise.
* gcc.dg/di-sync-multithread.c: Likewise.
---
gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c | 12 +++++++++---
gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c | 6 +++++-
gcc/testsuite/gcc.dg/atomic/pr80640-2.c | 6 ++++--
gcc/testsuite/gcc.dg/atomic/pr80640.c | 6 ++++--
gcc/testsuite/gcc.dg/atomic/pr81316.c | 9 +++++++--
gcc/testsuite/gcc.dg/di-sync-multithread.c | 8 ++++++++
6 files changed, 37 insertions(+), 10 deletions(-)
Comments
On 6/20/2022 11:51 PM, Alexandre Oliva via Gcc-patches wrote:
> Systems without preemptive multi-threading require sched_yield calls
> to be placed at points in which a context switch might be needed to
> enable the test to complete.
>
> Regstrapped on x86_64-linux-gnu, also tested with a cross to
> aarch64-rtems6. Ok to install?
>
>
> for gcc/testsuite/ChangeLog
>
> * gcc.dg/atomic/c11-atomic-exec-4.c: Call sched_yield.
> * gcc.dg/atomic/c11-atomic-exec-5.c: Likewise.
> * gcc.dg/atomic/pr80640-2.c: Likewise.
> * gcc.dg/atomic/pr80640.c: Likewise.
> * gcc.dg/atomic/pr81316.c: Likewise.
> * gcc.dg/di-sync-multithread.c: Likewise.
OK.
I was hoping this would improve things internally as I know we have
problems with the c11-atomic-exec-{4,5} and pr80640 testcases with one
of our simulators that doesn't handle threads well. But it doesn't seem
to have helped. Too bad, it would have been nice to have those tests
flip to pass consistently.
Jeff
@@ -32,7 +32,10 @@ test_thread_##NAME (void *arg) \
{ \
thread_ready = true; \
for (int i = 0; i < ITER_COUNT; i++) \
- PRE var_##NAME POST; \
+ { \
+ sched_yield (); \
+ PRE var_##NAME POST; \
+ } \
return NULL; \
} \
\
@@ -49,9 +52,12 @@ test_main_##NAME (void) \
return 1; \
} \
while (!thread_ready) \
- ; \
+ sched_yield (); \
for (int i = 0; i < ITER_COUNT; i++) \
- PRE var_##NAME POST; \
+ { \
+ PRE var_##NAME POST; \
+ sched_yield (); \
+ } \
pthread_join (thread_id, NULL); \
if (var_##NAME != (FINAL)) \
{ \
@@ -53,8 +53,11 @@ test_thread_##NAME (void *arg) \
thread_ready = true; \
while (!thread_stop) \
{ \
+ sched_yield (); \
var_##NAME = (INIT1); \
+ sched_yield (); \
var_##NAME = (INIT2); \
+ sched_yield (); \
} \
return NULL; \
} \
@@ -75,13 +78,14 @@ test_main_##NAME (void) \
} \
int num_1_pass = 0, num_1_fail = 0, num_2_pass = 0, num_2_fail = 0; \
while (!thread_ready) \
- ; \
+ sched_yield (); \
for (int i = 0; i < ITER_COUNT; i++) \
{ \
feclearexcept (FE_ALL_EXCEPT); \
feraiseexcept (BEXC); \
LHSTYPE r = (PRE var_##NAME POST); \
int rexc = fetestexcept (TEST_ALL_EXCEPT); \
+ sched_yield (); \
if (VALTEST1 (r)) \
{ \
if (rexc == ((BEXC) | (EXC1))) \
@@ -12,7 +12,8 @@ static void *f(void *va)
void **p = va;
if (*p) return *p;
sem1 = 1;
- while (!__atomic_load_n(&sem2, __ATOMIC_ACQUIRE));
+ while (!__atomic_load_n(&sem2, __ATOMIC_ACQUIRE))
+ sched_yield ();
// GCC used to RTL-CSE this and the first load, causing 0 to be returned
return *p;
}
@@ -23,7 +24,8 @@ int main()
pthread_t thr;
if (pthread_create(&thr, 0, f, &p))
return 2;
- while (!sem1);
+ while (!sem1)
+ sched_yield ();
__atomic_thread_fence(__ATOMIC_ACQUIRE);
p = &p;
__atomic_store_n(&sem2, 1, __ATOMIC_RELEASE);
@@ -12,7 +12,8 @@ static void *f(void *va)
void **p = va;
if (*p) return *p;
sem1 = 1;
- while (!sem2);
+ while (!sem2)
+ sched_yield ();
__atomic_thread_fence(__ATOMIC_ACQUIRE);
// GCC used to RTL-CSE this and the first load, causing 0 to be returned
return *p;
@@ -24,7 +25,8 @@ int main()
pthread_t thr;
if (pthread_create(&thr, 0, f, &p))
return 2;
- while (!sem1);
+ while (!sem1)
+ sched_yield ();
__atomic_thread_fence(__ATOMIC_ACQUIRE);
p = &p;
__atomic_thread_fence(__ATOMIC_RELEASE);
@@ -10,7 +10,8 @@ static _Atomic int sem1;
static void *f(void *va)
{
void **p = va;
- while (!__atomic_load_n(&sem1, __ATOMIC_ACQUIRE));
+ while (!__atomic_load_n(&sem1, __ATOMIC_ACQUIRE))
+ sched_yield ();
exit(!*p);
}
@@ -24,6 +25,10 @@ int main(int argc)
p = &p;
__atomic_store_n(&sem1, 1, __ATOMIC_RELEASE);
int r = -1;
- while (r < 0) asm("":"+r"(r));
+ while (r < 0)
+ {
+ sched_yield ();
+ asm("":"+r"(r));
+ }
return r;
}
@@ -70,6 +70,8 @@ worker (void* data)
case this to carry across the 32bit boundary. */
for (tmp2 = 0; tmp2 < 64; tmp2++)
{
+ sched_yield ();
+
/* Add 2 using the two different adds. */
tmp1 = __sync_add_and_fetch (&workspace, add1bit);
tmp3 = __sync_fetch_and_add (&workspace, add1bit);
@@ -103,6 +105,8 @@ worker (void* data)
for (tmp2 = 0; tmp2 < 64; tmp2++)
{
+ sched_yield ();
+
/* Subtract 2 using the two different subs. */
tmp1=__sync_sub_and_fetch (&workspace, add1bit);
tmp3=__sync_fetch_and_sub (&workspace, add1bit);
@@ -178,6 +182,8 @@ main ()
t, err);
};
+ sched_yield ();
+
#ifdef _WIN32
Sleep (5000);
#else
@@ -187,6 +193,8 @@ main ()
/* Stop please. */
__sync_lock_test_and_set (&doquit, 1ll);
+ sched_yield ();
+
for (t = 0; t < 3; t++)
{
err=pthread_join (threads[t], NULL);