Implement pthread_yield.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@308 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c
index 572f33a..46d1c65 100644
--- a/coregrind/arch/x86-linux/vg_libpthread.c
+++ b/coregrind/arch/x86-linux/vg_libpthread.c
@@ -259,6 +259,17 @@
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 01c299e..1458dc2 100644
--- a/coregrind/arch/x86-linux/vg_libpthread_unimp.c
+++ b/coregrind/arch/x86-linux/vg_libpthread_unimp.c
@@ -252,8 +252,6 @@
{ 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 cdcd1ca..692a48c 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -436,6 +436,7 @@
#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 572f33a..46d1c65 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -259,6 +259,17 @@
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 01c299e..1458dc2 100644
--- a/coregrind/vg_libpthread_unimp.c
+++ b/coregrind/vg_libpthread_unimp.c
@@ -252,8 +252,6 @@
{ 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 57d687d..1c6dfed 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -1543,6 +1543,20 @@
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 @@
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 93a79cf..796a033 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -28,4 +28,4 @@
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 0000000..0b708ba
--- /dev/null
+++ b/tests/pth_yield.c
@@ -0,0 +1,44 @@
+
+#include <stdio.h>
+#include <assert.h>
+
+#define __USE_GNU
+#include <pthread.h>
+
+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 cdcd1ca..692a48c 100644
--- a/vg_include.h
+++ b/vg_include.h
@@ -436,6 +436,7 @@
#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 572f33a..46d1c65 100644
--- a/vg_libpthread.c
+++ b/vg_libpthread.c
@@ -259,6 +259,17 @@
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 01c299e..1458dc2 100644
--- a/vg_libpthread_unimp.c
+++ b/vg_libpthread_unimp.c
@@ -252,8 +252,6 @@
{ 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 57d687d..1c6dfed 100644
--- a/vg_scheduler.c
+++ b/vg_scheduler.c
@@ -1543,6 +1543,20 @@
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 @@
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: