From cce8a3ebd3d8e99bb4ef748a8b03ccc5ec678dfe Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Wed, 22 May 2002 13:17:31 +0000 Subject: [PATCH] Implement pthread_yield. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@308 --- coregrind/arch/x86-linux/vg_libpthread.c | 11 +++++ .../arch/x86-linux/vg_libpthread_unimp.c | 2 - coregrind/vg_include.h | 1 + coregrind/vg_libpthread.c | 11 +++++ coregrind/vg_libpthread_unimp.c | 2 - coregrind/vg_scheduler.c | 20 +++++++++ tests/Makefile.am | 2 +- tests/pth_yield.c | 44 +++++++++++++++++++ vg_include.h | 1 + vg_libpthread.c | 11 +++++ vg_libpthread_unimp.c | 2 - vg_scheduler.c | 20 +++++++++ 12 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 tests/pth_yield.c diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c index 572f33aea0..46d1c65a79 100644 --- a/coregrind/arch/x86-linux/vg_libpthread.c +++ b/coregrind/arch/x86-linux/vg_libpthread.c @@ -259,6 +259,17 @@ int pthread_attr_destroy(pthread_attr_t *attr) THREADs ------------------------------------------------ */ +__attribute__((weak)) +int pthread_yield ( void ) +{ + int res; + ensure_valgrind("pthread_yield"); + VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */, + VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0); + return 0; +} + + int pthread_equal(pthread_t thread1, pthread_t thread2) { return thread1 == thread2 ? 1 : 0; diff --git a/coregrind/arch/x86-linux/vg_libpthread_unimp.c b/coregrind/arch/x86-linux/vg_libpthread_unimp.c index 01c299e2a9..1458dc2fa4 100644 --- a/coregrind/arch/x86-linux/vg_libpthread_unimp.c +++ b/coregrind/arch/x86-linux/vg_libpthread_unimp.c @@ -252,8 +252,6 @@ __attribute__((weak)) void pthread_spin_trylock ( void ) { vgPlain_unimp("pthread_spin_trylock"); } __attribute__((weak)) void pthread_spin_unlock ( void ) { vgPlain_unimp("pthread_spin_unlock"); } -__attribute__((weak)) void pthread_yield ( void ) - { vgPlain_unimp("pthread_yield"); } /*--------------------------------------------------------------------*/ diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index cdcd1caa3b..692a48c528 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -436,6 +436,7 @@ extern Bool VG_(is_empty_arena) ( ArenaId aid ); #define VG_USERREQ__PTHREAD_SIGMASK 0x3012 #define VG_USERREQ__SIGWAIT 0x3013 #define VG_USERREQ__PTHREAD_KILL 0x3014 +#define VG_USERREQ__PTHREAD_YIELD 0x3015 /* Cosmetic ... */ #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101 diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c index 572f33aea0..46d1c65a79 100644 --- a/coregrind/vg_libpthread.c +++ b/coregrind/vg_libpthread.c @@ -259,6 +259,17 @@ int pthread_attr_destroy(pthread_attr_t *attr) THREADs ------------------------------------------------ */ +__attribute__((weak)) +int pthread_yield ( void ) +{ + int res; + ensure_valgrind("pthread_yield"); + VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */, + VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0); + return 0; +} + + int pthread_equal(pthread_t thread1, pthread_t thread2) { return thread1 == thread2 ? 1 : 0; diff --git a/coregrind/vg_libpthread_unimp.c b/coregrind/vg_libpthread_unimp.c index 01c299e2a9..1458dc2fa4 100644 --- a/coregrind/vg_libpthread_unimp.c +++ b/coregrind/vg_libpthread_unimp.c @@ -252,8 +252,6 @@ __attribute__((weak)) void pthread_spin_trylock ( void ) { vgPlain_unimp("pthread_spin_trylock"); } __attribute__((weak)) void pthread_spin_unlock ( void ) { vgPlain_unimp("pthread_spin_unlock"); } -__attribute__((weak)) void pthread_yield ( void ) - { vgPlain_unimp("pthread_yield"); } /*--------------------------------------------------------------------*/ diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 57d687d5f8..1c6dfede1d 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -1542,6 +1542,20 @@ void cleanup_after_thread_exited ( ThreadId tid ) } +static +void do_pthread_yield ( ThreadId tid ) +{ + Char msg_buf[100]; + vg_assert(VG_(is_valid_tid)(tid)); + + if (VG_(clo_trace_sched)) { + VG_(sprintf)(msg_buf, "yield"); + print_sched_event(tid, msg_buf); + } + SET_EDX(tid, 0); +} + + static void do_pthread_cancel ( ThreadId tid, pthread_t tid_cancellee ) @@ -2672,6 +2686,12 @@ void do_nontrivial_clientreq ( ThreadId tid ) do_pthread_kill ( tid, arg[1], arg[2] ); break; + case VG_USERREQ__PTHREAD_YIELD: + do_pthread_yield ( tid ); + /* because this is classified as a non-trivial client + request, the scheduler should now select a new thread to + run. */ + break; case VG_USERREQ__MAKE_NOACCESS: case VG_USERREQ__MAKE_WRITABLE: diff --git a/tests/Makefile.am b/tests/Makefile.am index 93a79cfea5..796a0334db 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,4 +28,4 @@ EXTRA_DIST = \ bt_everything.c bt_literal.c \ pth_threadpool.c pth_specific.c pth_mutexspeed.c malloc3.c \ pth_once.c weirdioctl.c pth_signal1.c pth_signal2.c \ - discard.c pth_semaphore1.c new_override.cpp + discard.c pth_semaphore1.c new_override.cpp pth_yield.c diff --git a/tests/pth_yield.c b/tests/pth_yield.c new file mode 100644 index 0000000000..0b708ba063 --- /dev/null +++ b/tests/pth_yield.c @@ -0,0 +1,44 @@ + +#include +#include + +#define __USE_GNU +#include + +void do_one_thing ( void* v ) +{ + int i, j, res; + for (i = 0; i < 10; i++) { + for (j = 0; j < 10; j++) { + printf("a "); fflush(stdout); + } + printf("\naaaaaaa-yielding\n"); + res = pthread_yield(); + assert(res == 0); + } +} + +void do_another_thing ( void* v ) +{ + int i, j, res; + for (i = 0; i < 10; i++) { + for (j = 0; j < 10; j++) { + printf("b "); fflush(stdout); + } + printf("\nbbbbbbb-yielding\n"); + res = pthread_yield(); + assert(res == 0); + } +} + + +int main ( void ) +{ + pthread_t t1, t2; + pthread_create( &t1, NULL, (void*)do_one_thing, NULL ); + pthread_create( &t2, NULL, (void*)do_another_thing, NULL ); + pthread_join(t1, NULL); + pthread_join(t2, NULL); + printf("bye!\n"); + return 0; +} diff --git a/vg_include.h b/vg_include.h index cdcd1caa3b..692a48c528 100644 --- a/vg_include.h +++ b/vg_include.h @@ -436,6 +436,7 @@ extern Bool VG_(is_empty_arena) ( ArenaId aid ); #define VG_USERREQ__PTHREAD_SIGMASK 0x3012 #define VG_USERREQ__SIGWAIT 0x3013 #define VG_USERREQ__PTHREAD_KILL 0x3014 +#define VG_USERREQ__PTHREAD_YIELD 0x3015 /* Cosmetic ... */ #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101 diff --git a/vg_libpthread.c b/vg_libpthread.c index 572f33aea0..46d1c65a79 100644 --- a/vg_libpthread.c +++ b/vg_libpthread.c @@ -259,6 +259,17 @@ int pthread_attr_destroy(pthread_attr_t *attr) THREADs ------------------------------------------------ */ +__attribute__((weak)) +int pthread_yield ( void ) +{ + int res; + ensure_valgrind("pthread_yield"); + VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */, + VG_USERREQ__PTHREAD_YIELD, 0, 0, 0, 0); + return 0; +} + + int pthread_equal(pthread_t thread1, pthread_t thread2) { return thread1 == thread2 ? 1 : 0; diff --git a/vg_libpthread_unimp.c b/vg_libpthread_unimp.c index 01c299e2a9..1458dc2fa4 100644 --- a/vg_libpthread_unimp.c +++ b/vg_libpthread_unimp.c @@ -252,8 +252,6 @@ __attribute__((weak)) void pthread_spin_trylock ( void ) { vgPlain_unimp("pthread_spin_trylock"); } __attribute__((weak)) void pthread_spin_unlock ( void ) { vgPlain_unimp("pthread_spin_unlock"); } -__attribute__((weak)) void pthread_yield ( void ) - { vgPlain_unimp("pthread_yield"); } /*--------------------------------------------------------------------*/ diff --git a/vg_scheduler.c b/vg_scheduler.c index 57d687d5f8..1c6dfede1d 100644 --- a/vg_scheduler.c +++ b/vg_scheduler.c @@ -1542,6 +1542,20 @@ void cleanup_after_thread_exited ( ThreadId tid ) } +static +void do_pthread_yield ( ThreadId tid ) +{ + Char msg_buf[100]; + vg_assert(VG_(is_valid_tid)(tid)); + + if (VG_(clo_trace_sched)) { + VG_(sprintf)(msg_buf, "yield"); + print_sched_event(tid, msg_buf); + } + SET_EDX(tid, 0); +} + + static void do_pthread_cancel ( ThreadId tid, pthread_t tid_cancellee ) @@ -2672,6 +2686,12 @@ void do_nontrivial_clientreq ( ThreadId tid ) do_pthread_kill ( tid, arg[1], arg[2] ); break; + case VG_USERREQ__PTHREAD_YIELD: + do_pthread_yield ( tid ); + /* because this is classified as a non-trivial client + request, the scheduler should now select a new thread to + run. */ + break; case VG_USERREQ__MAKE_NOACCESS: case VG_USERREQ__MAKE_WRITABLE: -- 2.47.2