Fix various bugs getting in the way of licq starting up.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@150 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c
index 370acec..2715953 100644
--- a/coregrind/arch/x86-linux/vg_libpthread.c
+++ b/coregrind/arch/x86-linux/vg_libpthread.c
@@ -259,6 +259,13 @@
 }
 
 
+int pthread_detach(pthread_t th)
+{
+   ignored("pthread_detach");
+   return 0;
+}
+
+
 /* ---------------------------------------------------
    MUTEX ATTRIBUTES
    ------------------------------------------------ */
@@ -493,13 +500,18 @@
    CANCELLATION
    ------------------------------------------------ */
 
+int pthread_setcancelstate(int state, int *oldstate)
+{
+   ignored("pthread_setcancelstate");
+   return 0;
+}
+
 int pthread_setcanceltype(int type, int *oldtype)
 {
    ignored("pthread_setcanceltype");
    return 0;
 }
 
-
 int pthread_cancel(pthread_t thread)
 {
    int res;
@@ -510,6 +522,27 @@
    return res;
 }
 
+void pthread_testcancel(void)
+{
+}
+
+/*-------------------*/
+static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
+
+void __pthread_kill_other_threads_np ( void )
+{
+   int i, res, me;
+   pthread_mutex_lock(&massacre_mx);
+   me = pthread_self();
+   for (i = 1; i < VG_N_THREADS; i++) {
+      if (i == me) continue;
+      res = pthread_cancel(i);
+      if (res == 0)
+         printf("----------- NUKED %d\n", i);
+   }
+   pthread_mutex_unlock(&massacre_mx);
+}
+
 
 /* ---------------------------------------------------
    THREAD-SPECIFICs
@@ -584,6 +617,19 @@
 
 
 /* ---------------------------------------------------
+   MISC
+   ------------------------------------------------ */
+
+int pthread_atfork ( void (*prepare)(void),
+                     void (*parent)(void),
+                     void (*child)(void) )
+{
+   ignored("pthread_atfork");
+   return 0;
+}
+
+
+/* ---------------------------------------------------
    LIBRARY-PRIVATE THREAD SPECIFIC STATE
    ------------------------------------------------ */
 
@@ -698,18 +744,18 @@
 
  
 extern
-int __libc_open64(const char *pathname, int flags, ...);
-int open64(const char *pathname, int flags, ...)
+int __libc_open64(const char *pathname, int flags, mode_t mode);
+int open64(const char *pathname, int flags, mode_t mode)
 {
-   return __libc_open64(pathname, flags);
+   return __libc_open64(pathname, flags, mode);
 }
 
 
 extern
-int __libc_open(const char *pathname, int flags);
-int open(const char *pathname, int flags)
+int __libc_open(const char *pathname, int flags, mode_t mode);
+int open(const char *pathname, int flags, mode_t mode)
 {
-   return __libc_open(pathname, flags);
+   return __libc_open(pathname, flags, mode);
 }
 
 
@@ -1142,6 +1188,7 @@
   extern __typeof (name) aliasname __attribute__ ((alias (#name)));
 
 strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
+strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
 strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
 strong_alias(pthread_mutexattr_init, __pthread_mutexattr_init)
 strong_alias(pthread_mutexattr_settype, __pthread_mutexattr_settype)
@@ -1149,7 +1196,9 @@
 strong_alias(pthread_mutexattr_destroy, __pthread_mutexattr_destroy)
 strong_alias(pthread_mutex_destroy, __pthread_mutex_destroy)
 strong_alias(pthread_once, __pthread_once)
+strong_alias(pthread_atfork, __pthread_atfork)
 
+strong_alias(fork, __fork)
 strong_alias(close, __close)
 strong_alias(write, __write)
 strong_alias(read, __read)
@@ -1171,16 +1220,18 @@
 #undef _IO_flockfile
 void _IO_flockfile ( _IO_FILE * file )
 {
-   //   char* str = "_IO_flockfile\n";
-   //   write(2, str, strlen(str));
+   //char* str = "_IO_flockfile\n";
+   //write(2, str, strlen(str));
+   pthread_mutex_lock(file->_lock);
    //  barf("_IO_flockfile");
 }
 
 #undef _IO_funlockfile
 void _IO_funlockfile ( _IO_FILE * file )
 {
-   //   char* str = "_IO_funlockfile\n";
-   //   write(2, str, strlen(str));
+   //char* str = "_IO_funlockfile\n";
+   //write(2, str, strlen(str));
+   pthread_mutex_unlock(file->_lock);
    //  barf("_IO_funlockfile");
 }
 
diff --git a/coregrind/arch/x86-linux/vg_libpthread_unimp.c b/coregrind/arch/x86-linux/vg_libpthread_unimp.c
index 24c154c..d01dc5b 100644
--- a/coregrind/arch/x86-linux/vg_libpthread_unimp.c
+++ b/coregrind/arch/x86-linux/vg_libpthread_unimp.c
@@ -13,7 +13,7 @@
 //void __connect ( void )  { unimp("__connect"); }
 //void __errno_location ( void )  { unimp("__errno_location"); }
 //void __fcntl ( void )  { unimp("__fcntl"); }
-void __fork ( void )  { unimp("__fork"); }
+//void __fork ( void )  { unimp("__fork"); }
 //void __h_errno_location ( void )  { unimp("__h_errno_location"); }
 void __libc_allocate_rtsig ( void )  { unimp("__libc_allocate_rtsig"); }
 void __libc_current_sigrtmax ( void )  { unimp("__libc_current_sigrtmax"); }
@@ -22,14 +22,14 @@
 //void __open ( void )  { unimp("__open"); }
 //void __open64 ( void )  { unimp("__open64"); }
 void __pread64 ( void )  { unimp("__pread64"); }
-void __pthread_atfork ( void )  { unimp("__pthread_atfork"); }
+//void __pthread_atfork ( void )  { unimp("__pthread_atfork"); }
 //void __pthread_getspecific ( void )  { unimp("__pthread_getspecific"); }
 //void __pthread_key_create ( void )  { unimp("__pthread_key_create"); }
-void __pthread_kill_other_threads_np ( void )  { unimp("__pthread_kill_other_threads_np"); }
+//void __pthread_kill_other_threads_np ( void )  { unimp("__pthread_kill_other_threads_np"); }
 //void __pthread_mutex_destroy ( void )  { unimp("__pthread_mutex_destroy"); }
 //void __pthread_mutex_init ( void )  { unimp("__pthread_mutex_init"); }
 //void __pthread_mutex_lock ( void )  { unimp("__pthread_mutex_lock"); }
-void __pthread_mutex_trylock ( void )  { unimp("__pthread_mutex_trylock"); }
+//void __pthread_mutex_trylock ( void )  { unimp("__pthread_mutex_trylock"); }
 //void __pthread_mutex_unlock ( void )  { unimp("__pthread_mutex_unlock"); }
 //void __pthread_mutexattr_destroy ( void )  { unimp("__pthread_mutexattr_destroy"); }
 //void __pthread_mutexattr_init ( void )  { unimp("__pthread_mutexattr_init"); }
@@ -49,7 +49,7 @@
 void _pthread_cleanup_push ( void )  { unimp("_pthread_cleanup_push"); }
 //void _pthread_cleanup_push_defer ( void )  { unimp("_pthread_cleanup_push_defer"); }
 //void longjmp ( void )  { unimp("longjmp"); }
-void pthread_atfork ( void )  { unimp("pthread_atfork"); }
+//void pthread_atfork ( void )  { unimp("pthread_atfork"); }
 //void pthread_attr_destroy ( void )  { unimp("pthread_attr_destroy"); }
 void pthread_attr_getdetachstate ( void )  { unimp("pthread_attr_getdetachstate"); }
 void pthread_attr_getinheritsched ( void )  { unimp("pthread_attr_getinheritsched"); }
@@ -79,7 +79,7 @@
 void pthread_condattr_getpshared ( void )  { unimp("pthread_condattr_getpshared"); }
 //void pthread_condattr_init ( void )  { unimp("pthread_condattr_init"); }
 void pthread_condattr_setpshared ( void )  { unimp("pthread_condattr_setpshared"); }
-void pthread_detach ( void )  { unimp("pthread_detach"); }
+//void pthread_detach ( void )  { unimp("pthread_detach"); }
 //void pthread_equal ( void )  { unimp("pthread_equal"); }
 //void pthread_exit ( void )  { unimp("pthread_exit"); }
 void pthread_getattr_np ( void )  { unimp("pthread_getattr_np"); }
@@ -115,12 +115,12 @@
 void pthread_rwlockattr_setkind_np ( void )  { unimp("pthread_rwlockattr_setkind_np"); }
 void pthread_rwlockattr_setpshared ( void )  { unimp("pthread_rwlockattr_setpshared"); }
 //void pthread_self ( void )  { unimp("pthread_self"); }
-void pthread_setcancelstate ( void )  { unimp("pthread_setcancelstate"); }
+//void pthread_setcancelstate ( void )  { unimp("pthread_setcancelstate"); }
 //void pthread_setcanceltype ( void )  { unimp("pthread_setcanceltype"); }
 //void pthread_setschedparam ( void )  { unimp("pthread_setschedparam"); }
 //void pthread_setspecific ( void )  { unimp("pthread_setspecific"); }
 void pthread_sigmask ( void )  { unimp("pthread_sigmask"); }
-void pthread_testcancel ( void )  { unimp("pthread_testcancel"); }
+//void pthread_testcancel ( void )  { unimp("pthread_testcancel"); }
 void raise ( void )  { unimp("raise"); }
 void sem_close ( void )  { unimp("sem_close"); }
 void sem_open ( void )  { unimp("sem_open"); }
diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c
index 370acec..2715953 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -259,6 +259,13 @@
 }
 
 
+int pthread_detach(pthread_t th)
+{
+   ignored("pthread_detach");
+   return 0;
+}
+
+
 /* ---------------------------------------------------
    MUTEX ATTRIBUTES
    ------------------------------------------------ */
@@ -493,13 +500,18 @@
    CANCELLATION
    ------------------------------------------------ */
 
+int pthread_setcancelstate(int state, int *oldstate)
+{
+   ignored("pthread_setcancelstate");
+   return 0;
+}
+
 int pthread_setcanceltype(int type, int *oldtype)
 {
    ignored("pthread_setcanceltype");
    return 0;
 }
 
-
 int pthread_cancel(pthread_t thread)
 {
    int res;
@@ -510,6 +522,27 @@
    return res;
 }
 
+void pthread_testcancel(void)
+{
+}
+
+/*-------------------*/
+static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
+
+void __pthread_kill_other_threads_np ( void )
+{
+   int i, res, me;
+   pthread_mutex_lock(&massacre_mx);
+   me = pthread_self();
+   for (i = 1; i < VG_N_THREADS; i++) {
+      if (i == me) continue;
+      res = pthread_cancel(i);
+      if (res == 0)
+         printf("----------- NUKED %d\n", i);
+   }
+   pthread_mutex_unlock(&massacre_mx);
+}
+
 
 /* ---------------------------------------------------
    THREAD-SPECIFICs
@@ -584,6 +617,19 @@
 
 
 /* ---------------------------------------------------
+   MISC
+   ------------------------------------------------ */
+
+int pthread_atfork ( void (*prepare)(void),
+                     void (*parent)(void),
+                     void (*child)(void) )
+{
+   ignored("pthread_atfork");
+   return 0;
+}
+
+
+/* ---------------------------------------------------
    LIBRARY-PRIVATE THREAD SPECIFIC STATE
    ------------------------------------------------ */
 
@@ -698,18 +744,18 @@
 
  
 extern
-int __libc_open64(const char *pathname, int flags, ...);
-int open64(const char *pathname, int flags, ...)
+int __libc_open64(const char *pathname, int flags, mode_t mode);
+int open64(const char *pathname, int flags, mode_t mode)
 {
-   return __libc_open64(pathname, flags);
+   return __libc_open64(pathname, flags, mode);
 }
 
 
 extern
-int __libc_open(const char *pathname, int flags);
-int open(const char *pathname, int flags)
+int __libc_open(const char *pathname, int flags, mode_t mode);
+int open(const char *pathname, int flags, mode_t mode)
 {
-   return __libc_open(pathname, flags);
+   return __libc_open(pathname, flags, mode);
 }
 
 
@@ -1142,6 +1188,7 @@
   extern __typeof (name) aliasname __attribute__ ((alias (#name)));
 
 strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
+strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
 strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
 strong_alias(pthread_mutexattr_init, __pthread_mutexattr_init)
 strong_alias(pthread_mutexattr_settype, __pthread_mutexattr_settype)
@@ -1149,7 +1196,9 @@
 strong_alias(pthread_mutexattr_destroy, __pthread_mutexattr_destroy)
 strong_alias(pthread_mutex_destroy, __pthread_mutex_destroy)
 strong_alias(pthread_once, __pthread_once)
+strong_alias(pthread_atfork, __pthread_atfork)
 
+strong_alias(fork, __fork)
 strong_alias(close, __close)
 strong_alias(write, __write)
 strong_alias(read, __read)
@@ -1171,16 +1220,18 @@
 #undef _IO_flockfile
 void _IO_flockfile ( _IO_FILE * file )
 {
-   //   char* str = "_IO_flockfile\n";
-   //   write(2, str, strlen(str));
+   //char* str = "_IO_flockfile\n";
+   //write(2, str, strlen(str));
+   pthread_mutex_lock(file->_lock);
    //  barf("_IO_flockfile");
 }
 
 #undef _IO_funlockfile
 void _IO_funlockfile ( _IO_FILE * file )
 {
-   //   char* str = "_IO_funlockfile\n";
-   //   write(2, str, strlen(str));
+   //char* str = "_IO_funlockfile\n";
+   //write(2, str, strlen(str));
+   pthread_mutex_unlock(file->_lock);
    //  barf("_IO_funlockfile");
 }
 
diff --git a/coregrind/vg_libpthread_unimp.c b/coregrind/vg_libpthread_unimp.c
index 24c154c..d01dc5b 100644
--- a/coregrind/vg_libpthread_unimp.c
+++ b/coregrind/vg_libpthread_unimp.c
@@ -13,7 +13,7 @@
 //void __connect ( void )  { unimp("__connect"); }
 //void __errno_location ( void )  { unimp("__errno_location"); }
 //void __fcntl ( void )  { unimp("__fcntl"); }
-void __fork ( void )  { unimp("__fork"); }
+//void __fork ( void )  { unimp("__fork"); }
 //void __h_errno_location ( void )  { unimp("__h_errno_location"); }
 void __libc_allocate_rtsig ( void )  { unimp("__libc_allocate_rtsig"); }
 void __libc_current_sigrtmax ( void )  { unimp("__libc_current_sigrtmax"); }
@@ -22,14 +22,14 @@
 //void __open ( void )  { unimp("__open"); }
 //void __open64 ( void )  { unimp("__open64"); }
 void __pread64 ( void )  { unimp("__pread64"); }
-void __pthread_atfork ( void )  { unimp("__pthread_atfork"); }
+//void __pthread_atfork ( void )  { unimp("__pthread_atfork"); }
 //void __pthread_getspecific ( void )  { unimp("__pthread_getspecific"); }
 //void __pthread_key_create ( void )  { unimp("__pthread_key_create"); }
-void __pthread_kill_other_threads_np ( void )  { unimp("__pthread_kill_other_threads_np"); }
+//void __pthread_kill_other_threads_np ( void )  { unimp("__pthread_kill_other_threads_np"); }
 //void __pthread_mutex_destroy ( void )  { unimp("__pthread_mutex_destroy"); }
 //void __pthread_mutex_init ( void )  { unimp("__pthread_mutex_init"); }
 //void __pthread_mutex_lock ( void )  { unimp("__pthread_mutex_lock"); }
-void __pthread_mutex_trylock ( void )  { unimp("__pthread_mutex_trylock"); }
+//void __pthread_mutex_trylock ( void )  { unimp("__pthread_mutex_trylock"); }
 //void __pthread_mutex_unlock ( void )  { unimp("__pthread_mutex_unlock"); }
 //void __pthread_mutexattr_destroy ( void )  { unimp("__pthread_mutexattr_destroy"); }
 //void __pthread_mutexattr_init ( void )  { unimp("__pthread_mutexattr_init"); }
@@ -49,7 +49,7 @@
 void _pthread_cleanup_push ( void )  { unimp("_pthread_cleanup_push"); }
 //void _pthread_cleanup_push_defer ( void )  { unimp("_pthread_cleanup_push_defer"); }
 //void longjmp ( void )  { unimp("longjmp"); }
-void pthread_atfork ( void )  { unimp("pthread_atfork"); }
+//void pthread_atfork ( void )  { unimp("pthread_atfork"); }
 //void pthread_attr_destroy ( void )  { unimp("pthread_attr_destroy"); }
 void pthread_attr_getdetachstate ( void )  { unimp("pthread_attr_getdetachstate"); }
 void pthread_attr_getinheritsched ( void )  { unimp("pthread_attr_getinheritsched"); }
@@ -79,7 +79,7 @@
 void pthread_condattr_getpshared ( void )  { unimp("pthread_condattr_getpshared"); }
 //void pthread_condattr_init ( void )  { unimp("pthread_condattr_init"); }
 void pthread_condattr_setpshared ( void )  { unimp("pthread_condattr_setpshared"); }
-void pthread_detach ( void )  { unimp("pthread_detach"); }
+//void pthread_detach ( void )  { unimp("pthread_detach"); }
 //void pthread_equal ( void )  { unimp("pthread_equal"); }
 //void pthread_exit ( void )  { unimp("pthread_exit"); }
 void pthread_getattr_np ( void )  { unimp("pthread_getattr_np"); }
@@ -115,12 +115,12 @@
 void pthread_rwlockattr_setkind_np ( void )  { unimp("pthread_rwlockattr_setkind_np"); }
 void pthread_rwlockattr_setpshared ( void )  { unimp("pthread_rwlockattr_setpshared"); }
 //void pthread_self ( void )  { unimp("pthread_self"); }
-void pthread_setcancelstate ( void )  { unimp("pthread_setcancelstate"); }
+//void pthread_setcancelstate ( void )  { unimp("pthread_setcancelstate"); }
 //void pthread_setcanceltype ( void )  { unimp("pthread_setcanceltype"); }
 //void pthread_setschedparam ( void )  { unimp("pthread_setschedparam"); }
 //void pthread_setspecific ( void )  { unimp("pthread_setspecific"); }
 void pthread_sigmask ( void )  { unimp("pthread_sigmask"); }
-void pthread_testcancel ( void )  { unimp("pthread_testcancel"); }
+//void pthread_testcancel ( void )  { unimp("pthread_testcancel"); }
 void raise ( void )  { unimp("raise"); }
 void sem_close ( void )  { unimp("sem_close"); }
 void sem_open ( void )  { unimp("sem_open"); }
diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c
index 10ea058..9786e5b 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -881,8 +881,8 @@
 
    /* Awaken any sleeping threads whose sleep has expired. */
    for (tid = 1; tid < VG_N_THREADS; tid++)
-     if (vg_threads[tid].status == VgTs_Sleeping)
-        break;
+      if (vg_threads[tid].status == VgTs_Sleeping)
+         break;
 
    /* Avoid pointless calls to VG_(read_millisecond_timer). */
    if (tid < VG_N_THREADS) {
@@ -1442,21 +1442,34 @@
    -------------------------------------------------------- */
 
 static
-void do_pthread_cancel ( ThreadId  tid_canceller,
+void do_pthread_cancel ( ThreadId  tid,
                          pthread_t tid_cancellee )
 {
    Char msg_buf[100];
+
+   vg_assert(is_valid_tid(tid));
+   vg_assert(vg_threads[tid].status != VgTs_Empty);
+
+   if (!is_valid_tid(tid_cancellee)
+       || vg_threads[tid_cancellee].status == VgTs_Empty) {
+      vg_threads[tid].m_edx = ESRCH;
+      return;
+   }
+
    /* We want make is appear that this thread has returned to
       do_pthread_create_bogusRA with PTHREAD_CANCELED as the
       return value.  So: simple: put PTHREAD_CANCELED into %EAX
       and &do_pthread_create_bogusRA into %EIP and keep going! */
    if (VG_(clo_trace_sched)) {
-      VG_(sprintf)(msg_buf, "cancelled by %d", tid_canceller);
+      VG_(sprintf)(msg_buf, "cancelled by %d", tid);
       print_sched_event(tid_cancellee, msg_buf);
    }
    vg_threads[tid_cancellee].m_eax  = (UInt)PTHREAD_CANCELED;
    vg_threads[tid_cancellee].m_eip  = (UInt)&VG_(pthreadreturn_bogusRA);
    vg_threads[tid_cancellee].status = VgTs_Runnable;
+
+   /* We return with success (0). */
+   vg_threads[tid].m_edx = 0;
 }
 
 
@@ -1852,8 +1865,9 @@
             /* return 0 (success). */
             mutex->__m_count++;
             vg_threads[tid].m_edx = 0;
-	    VG_(printf)("!!!!!! tid %d, mx %p -> locked %d\n", 
-                        tid, mutex, mutex->__m_count);
+            if (0)
+               VG_(printf)("!!!!!! tid %d, mx %p -> locked %d\n", 
+                           tid, mutex, mutex->__m_count);
             return;
          } else {
             if (is_trylock)
diff --git a/vg_libpthread.c b/vg_libpthread.c
index 370acec..2715953 100644
--- a/vg_libpthread.c
+++ b/vg_libpthread.c
@@ -259,6 +259,13 @@
 }
 
 
+int pthread_detach(pthread_t th)
+{
+   ignored("pthread_detach");
+   return 0;
+}
+
+
 /* ---------------------------------------------------
    MUTEX ATTRIBUTES
    ------------------------------------------------ */
@@ -493,13 +500,18 @@
    CANCELLATION
    ------------------------------------------------ */
 
+int pthread_setcancelstate(int state, int *oldstate)
+{
+   ignored("pthread_setcancelstate");
+   return 0;
+}
+
 int pthread_setcanceltype(int type, int *oldtype)
 {
    ignored("pthread_setcanceltype");
    return 0;
 }
 
-
 int pthread_cancel(pthread_t thread)
 {
    int res;
@@ -510,6 +522,27 @@
    return res;
 }
 
+void pthread_testcancel(void)
+{
+}
+
+/*-------------------*/
+static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER;
+
+void __pthread_kill_other_threads_np ( void )
+{
+   int i, res, me;
+   pthread_mutex_lock(&massacre_mx);
+   me = pthread_self();
+   for (i = 1; i < VG_N_THREADS; i++) {
+      if (i == me) continue;
+      res = pthread_cancel(i);
+      if (res == 0)
+         printf("----------- NUKED %d\n", i);
+   }
+   pthread_mutex_unlock(&massacre_mx);
+}
+
 
 /* ---------------------------------------------------
    THREAD-SPECIFICs
@@ -584,6 +617,19 @@
 
 
 /* ---------------------------------------------------
+   MISC
+   ------------------------------------------------ */
+
+int pthread_atfork ( void (*prepare)(void),
+                     void (*parent)(void),
+                     void (*child)(void) )
+{
+   ignored("pthread_atfork");
+   return 0;
+}
+
+
+/* ---------------------------------------------------
    LIBRARY-PRIVATE THREAD SPECIFIC STATE
    ------------------------------------------------ */
 
@@ -698,18 +744,18 @@
 
  
 extern
-int __libc_open64(const char *pathname, int flags, ...);
-int open64(const char *pathname, int flags, ...)
+int __libc_open64(const char *pathname, int flags, mode_t mode);
+int open64(const char *pathname, int flags, mode_t mode)
 {
-   return __libc_open64(pathname, flags);
+   return __libc_open64(pathname, flags, mode);
 }
 
 
 extern
-int __libc_open(const char *pathname, int flags);
-int open(const char *pathname, int flags)
+int __libc_open(const char *pathname, int flags, mode_t mode);
+int open(const char *pathname, int flags, mode_t mode)
 {
-   return __libc_open(pathname, flags);
+   return __libc_open(pathname, flags, mode);
 }
 
 
@@ -1142,6 +1188,7 @@
   extern __typeof (name) aliasname __attribute__ ((alias (#name)));
 
 strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
+strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
 strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
 strong_alias(pthread_mutexattr_init, __pthread_mutexattr_init)
 strong_alias(pthread_mutexattr_settype, __pthread_mutexattr_settype)
@@ -1149,7 +1196,9 @@
 strong_alias(pthread_mutexattr_destroy, __pthread_mutexattr_destroy)
 strong_alias(pthread_mutex_destroy, __pthread_mutex_destroy)
 strong_alias(pthread_once, __pthread_once)
+strong_alias(pthread_atfork, __pthread_atfork)
 
+strong_alias(fork, __fork)
 strong_alias(close, __close)
 strong_alias(write, __write)
 strong_alias(read, __read)
@@ -1171,16 +1220,18 @@
 #undef _IO_flockfile
 void _IO_flockfile ( _IO_FILE * file )
 {
-   //   char* str = "_IO_flockfile\n";
-   //   write(2, str, strlen(str));
+   //char* str = "_IO_flockfile\n";
+   //write(2, str, strlen(str));
+   pthread_mutex_lock(file->_lock);
    //  barf("_IO_flockfile");
 }
 
 #undef _IO_funlockfile
 void _IO_funlockfile ( _IO_FILE * file )
 {
-   //   char* str = "_IO_funlockfile\n";
-   //   write(2, str, strlen(str));
+   //char* str = "_IO_funlockfile\n";
+   //write(2, str, strlen(str));
+   pthread_mutex_unlock(file->_lock);
    //  barf("_IO_funlockfile");
 }
 
diff --git a/vg_libpthread_unimp.c b/vg_libpthread_unimp.c
index 24c154c..d01dc5b 100644
--- a/vg_libpthread_unimp.c
+++ b/vg_libpthread_unimp.c
@@ -13,7 +13,7 @@
 //void __connect ( void )  { unimp("__connect"); }
 //void __errno_location ( void )  { unimp("__errno_location"); }
 //void __fcntl ( void )  { unimp("__fcntl"); }
-void __fork ( void )  { unimp("__fork"); }
+//void __fork ( void )  { unimp("__fork"); }
 //void __h_errno_location ( void )  { unimp("__h_errno_location"); }
 void __libc_allocate_rtsig ( void )  { unimp("__libc_allocate_rtsig"); }
 void __libc_current_sigrtmax ( void )  { unimp("__libc_current_sigrtmax"); }
@@ -22,14 +22,14 @@
 //void __open ( void )  { unimp("__open"); }
 //void __open64 ( void )  { unimp("__open64"); }
 void __pread64 ( void )  { unimp("__pread64"); }
-void __pthread_atfork ( void )  { unimp("__pthread_atfork"); }
+//void __pthread_atfork ( void )  { unimp("__pthread_atfork"); }
 //void __pthread_getspecific ( void )  { unimp("__pthread_getspecific"); }
 //void __pthread_key_create ( void )  { unimp("__pthread_key_create"); }
-void __pthread_kill_other_threads_np ( void )  { unimp("__pthread_kill_other_threads_np"); }
+//void __pthread_kill_other_threads_np ( void )  { unimp("__pthread_kill_other_threads_np"); }
 //void __pthread_mutex_destroy ( void )  { unimp("__pthread_mutex_destroy"); }
 //void __pthread_mutex_init ( void )  { unimp("__pthread_mutex_init"); }
 //void __pthread_mutex_lock ( void )  { unimp("__pthread_mutex_lock"); }
-void __pthread_mutex_trylock ( void )  { unimp("__pthread_mutex_trylock"); }
+//void __pthread_mutex_trylock ( void )  { unimp("__pthread_mutex_trylock"); }
 //void __pthread_mutex_unlock ( void )  { unimp("__pthread_mutex_unlock"); }
 //void __pthread_mutexattr_destroy ( void )  { unimp("__pthread_mutexattr_destroy"); }
 //void __pthread_mutexattr_init ( void )  { unimp("__pthread_mutexattr_init"); }
@@ -49,7 +49,7 @@
 void _pthread_cleanup_push ( void )  { unimp("_pthread_cleanup_push"); }
 //void _pthread_cleanup_push_defer ( void )  { unimp("_pthread_cleanup_push_defer"); }
 //void longjmp ( void )  { unimp("longjmp"); }
-void pthread_atfork ( void )  { unimp("pthread_atfork"); }
+//void pthread_atfork ( void )  { unimp("pthread_atfork"); }
 //void pthread_attr_destroy ( void )  { unimp("pthread_attr_destroy"); }
 void pthread_attr_getdetachstate ( void )  { unimp("pthread_attr_getdetachstate"); }
 void pthread_attr_getinheritsched ( void )  { unimp("pthread_attr_getinheritsched"); }
@@ -79,7 +79,7 @@
 void pthread_condattr_getpshared ( void )  { unimp("pthread_condattr_getpshared"); }
 //void pthread_condattr_init ( void )  { unimp("pthread_condattr_init"); }
 void pthread_condattr_setpshared ( void )  { unimp("pthread_condattr_setpshared"); }
-void pthread_detach ( void )  { unimp("pthread_detach"); }
+//void pthread_detach ( void )  { unimp("pthread_detach"); }
 //void pthread_equal ( void )  { unimp("pthread_equal"); }
 //void pthread_exit ( void )  { unimp("pthread_exit"); }
 void pthread_getattr_np ( void )  { unimp("pthread_getattr_np"); }
@@ -115,12 +115,12 @@
 void pthread_rwlockattr_setkind_np ( void )  { unimp("pthread_rwlockattr_setkind_np"); }
 void pthread_rwlockattr_setpshared ( void )  { unimp("pthread_rwlockattr_setpshared"); }
 //void pthread_self ( void )  { unimp("pthread_self"); }
-void pthread_setcancelstate ( void )  { unimp("pthread_setcancelstate"); }
+//void pthread_setcancelstate ( void )  { unimp("pthread_setcancelstate"); }
 //void pthread_setcanceltype ( void )  { unimp("pthread_setcanceltype"); }
 //void pthread_setschedparam ( void )  { unimp("pthread_setschedparam"); }
 //void pthread_setspecific ( void )  { unimp("pthread_setspecific"); }
 void pthread_sigmask ( void )  { unimp("pthread_sigmask"); }
-void pthread_testcancel ( void )  { unimp("pthread_testcancel"); }
+//void pthread_testcancel ( void )  { unimp("pthread_testcancel"); }
 void raise ( void )  { unimp("raise"); }
 void sem_close ( void )  { unimp("sem_close"); }
 void sem_open ( void )  { unimp("sem_open"); }
diff --git a/vg_scheduler.c b/vg_scheduler.c
index 10ea058..9786e5b 100644
--- a/vg_scheduler.c
+++ b/vg_scheduler.c
@@ -881,8 +881,8 @@
 
    /* Awaken any sleeping threads whose sleep has expired. */
    for (tid = 1; tid < VG_N_THREADS; tid++)
-     if (vg_threads[tid].status == VgTs_Sleeping)
-        break;
+      if (vg_threads[tid].status == VgTs_Sleeping)
+         break;
 
    /* Avoid pointless calls to VG_(read_millisecond_timer). */
    if (tid < VG_N_THREADS) {
@@ -1442,21 +1442,34 @@
    -------------------------------------------------------- */
 
 static
-void do_pthread_cancel ( ThreadId  tid_canceller,
+void do_pthread_cancel ( ThreadId  tid,
                          pthread_t tid_cancellee )
 {
    Char msg_buf[100];
+
+   vg_assert(is_valid_tid(tid));
+   vg_assert(vg_threads[tid].status != VgTs_Empty);
+
+   if (!is_valid_tid(tid_cancellee)
+       || vg_threads[tid_cancellee].status == VgTs_Empty) {
+      vg_threads[tid].m_edx = ESRCH;
+      return;
+   }
+
    /* We want make is appear that this thread has returned to
       do_pthread_create_bogusRA with PTHREAD_CANCELED as the
       return value.  So: simple: put PTHREAD_CANCELED into %EAX
       and &do_pthread_create_bogusRA into %EIP and keep going! */
    if (VG_(clo_trace_sched)) {
-      VG_(sprintf)(msg_buf, "cancelled by %d", tid_canceller);
+      VG_(sprintf)(msg_buf, "cancelled by %d", tid);
       print_sched_event(tid_cancellee, msg_buf);
    }
    vg_threads[tid_cancellee].m_eax  = (UInt)PTHREAD_CANCELED;
    vg_threads[tid_cancellee].m_eip  = (UInt)&VG_(pthreadreturn_bogusRA);
    vg_threads[tid_cancellee].status = VgTs_Runnable;
+
+   /* We return with success (0). */
+   vg_threads[tid].m_edx = 0;
 }
 
 
@@ -1852,8 +1865,9 @@
             /* return 0 (success). */
             mutex->__m_count++;
             vg_threads[tid].m_edx = 0;
-	    VG_(printf)("!!!!!! tid %d, mx %p -> locked %d\n", 
-                        tid, mutex, mutex->__m_count);
+            if (0)
+               VG_(printf)("!!!!!! tid %d, mx %p -> locked %d\n", 
+                           tid, mutex, mutex->__m_count);
             return;
          } else {
             if (is_trylock)