]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Use the pthread implementation of sync mutex in open-vm-tools.
authorVMware, Inc <>
Mon, 28 Sep 2009 20:30:51 +0000 (13:30 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Mon, 28 Sep 2009 20:30:51 +0000 (13:30 -0700)
This avoids having to deal with the eventfd library used by the
syncWaitQ code.

For some background of "issues this change avoids", see
sourceforge.net bug 2865804.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/configure.ac
open-vm-tools/lib/include/eventfd.h [deleted file]
open-vm-tools/lib/misc/Makefile.am
open-vm-tools/lib/misc/eventfd.c [deleted file]
open-vm-tools/lib/sync/Makefile.am
open-vm-tools/lib/sync/syncMutexPthread.c [moved from open-vm-tools/lib/sync/syncMutex.c with 65% similarity]
open-vm-tools/lib/sync/syncWaitQPosix.c [deleted file]

index c9ad095e3a3494caeb7ab5c8d05fb9ab5b0c092a..0b2221346d919f7cafd0d9f16fdd0cc427a83612 100644 (file)
@@ -743,11 +743,6 @@ AC_PATH_PROG(
 ### Headers
 ###
 
-AC_CHECK_DECL([SYS_eventfd],
-              [has_sys_eventfd="yes"],
-              [has_sys_eventfd="no"],
-              [ [#include <syscall.h>] ])
-
 AC_CHECK_HEADERS([crypt.h])
 AC_CHECK_HEADERS([inttypes.h])
 AC_CHECK_HEADERS([stdint.h])
@@ -1056,7 +1051,6 @@ AM_CONDITIONAL(HAVE_FUSE, test "$have_fuse" = "yes")
 AM_CONDITIONAL(HAVE_GNU_LD, test "$with_gnu_ld" = "yes")
 AM_CONDITIONAL(HAVE_GTKMM, test "$have_x" = "yes" -a "$with_gtkmm" = "yes")
 AM_CONDITIONAL(HAVE_PAM, test "$with_pam" = "yes")
-AM_CONDITIONAL(NEED_EVENTFD, test "$has_sys_eventfd" = "no")
 AM_CONDITIONAL(USE_SLASH_PROC, test "os" = "linux" -a "$have_glib_2_14" = "yes")
 
 ### Feature-specific flags / actions
diff --git a/open-vm-tools/lib/include/eventfd.h b/open-vm-tools/lib/include/eventfd.h
deleted file mode 100644 (file)
index 1e0b8e2..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*********************************************************
- * Copyright (C) 2009 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation version 2.1 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
- *
- *********************************************************/
-
-/*
- * eventfd.h --
- *
- *    eventfd interface.  Use only if platform does not have
- *    its own.
- */
-
-#ifndef EVENTFD_H
-#define EVENTFD_H
-
-#define INCLUDE_ALLOW_USERLEVEL
-#include "includeCheck.h"
-
-#include "vm_basic_types.h"
-
-#include <fcntl.h>
-#include <errno.h>
-
-typedef uint64 eventfd_t;
-
-#define EFD_CLOEXEC  O_CLOEXEC
-#define EFD_NONBLOCK O_NONBLOCK
-
-/* Only Linux eventfd implementation is available. */
-#if defined(__linux__) && !defined(N_PLAT_NLM)
-#  define VMWARE_EVENTFD_REAL
-
-int eventfd(int count, int flags);
-int eventfd_read(int fd, eventfd_t *value);
-int eventfd_write(int fd, eventfd_t value);
-
-#else
-
-static INLINE int
-eventfd(int count, int flags)
-{
-   errno = ENOSYS;
-   return -1;
-}
-
-static INLINE int
-eventfd_read(int fd, eventfd_t *value)
-{
-   errno = ENOSYS;
-   return -1;
-}
-
-static INLINE int
-eventfd_write(int fd, eventfd_t value)
-{
-   errno = ENOSYS;
-   return -1;
-}
-
-#endif
-
-#endif /* EVENTFD_H */
index 3f111301e26e256f54e8cc59a2daa0be7500eee2..ff2ef3f946cb1f5c43f10412b10012a8eaa132cc 100644 (file)
@@ -25,9 +25,6 @@ libMisc_la_SOURCES += dbllnklst.c
 libMisc_la_SOURCES += dynarray.c
 libMisc_la_SOURCES += dynbuf.c
 libMisc_la_SOURCES += escape.c
-if NEED_EVENTFD
-libMisc_la_SOURCES += eventfd.c
-endif
 libMisc_la_SOURCES += hashTable.c
 libMisc_la_SOURCES += hostinfoPosix.c
 libMisc_la_SOURCES += hostname.c
diff --git a/open-vm-tools/lib/misc/eventfd.c b/open-vm-tools/lib/misc/eventfd.c
deleted file mode 100644 (file)
index 05c2608..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*********************************************************
- * Copyright (C) 2009 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation version 2.1 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
- *
- *********************************************************/
-
-/*
- * eventfd.c --
- *
- *    Implements eventfd syscall interface.
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include "eventfd.h"
-
-#ifdef VMWARE_EVENTFD_REAL
-#include <unistd.h>
-#include <sys/syscall.h>
-
-
-#ifdef SYS_eventfd2
-/*
- * If this error fires, either start using <sys/eventfd.h> instead of
- * "eventfd.h", or rename our eventfd/eventfd_read/eventfd_write to some
- * private names and modify all users to use them. As you can guess,
- * switching to glibc's eventfd.h is preferred choice.
- */
-
-#   error "You have real SYS_eventfd2.  You should stop using this one."
-#endif
-#ifdef VM_X86_64
-#   define SYS_eventfd  284
-#   define SYS_eventfd2 290
-#else
-#   define SYS_eventfd  323
-#   define SYS_eventfd2 328
-#endif
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * eventfd --
- *
- *      Create eventfd descriptor.
- *
- * Results:
- *      -1 on failure, errno set
- *      >= 0 on success, file descriptor to use
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-int
-eventfd(int count,               // IN: Initial count
-        int flags)               // IN: Initial flags
-{
-   static enum {
-      EVENTFD_UNKNOWN = 0,
-      EVENTFD_UNKNOWN_NOT2,
-      EVENTFD_EVENTFD2,
-      EVENTFD_EVENTFD,
-      EVENTFD_NONE,
-   } eventfdStyle;
-   int ret;
-
-   switch (eventfdStyle) {
-   case EVENTFD_EVENTFD2: /* ESX and linux 2.6.27+ */
-      return syscall(SYS_eventfd2, count, flags);
-   case EVENTFD_EVENTFD:  /* linux 2.6.22 - 2.6.27 */
-      if (flags) {
-         errno = EINVAL;
-         return -1;
-      }
-      return syscall(SYS_eventfd, count);
-   case EVENTFD_UNKNOWN:  /* here we start */
-      ret = syscall(SYS_eventfd2, count, flags);
-      if (ret != -1 || errno != ENOSYS) {
-         /*
-          * We can get back SYS_eventfd2 instead of -1/ENOSYS on some
-          * broken systems - see bug 460859.  This tries to figure out
-          * whether returned value is legitimate fd 328, or just
-          * masqueraded ENOSYS.
-          */
-         if (ret != SYS_eventfd2) {
-            eventfdStyle = EVENTFD_EVENTFD2;
-            return ret;
-         }
-
-         /*
-          * Allocate another eventfd.  If that one is 328 too, it is
-          * clear that kernel is broken, as we already got such fd
-          * above.
-          *
-          * Otherwise if it is not -1, or if errno is not ENOSYS,
-          * then eventfd2 works.  Close newly allocated fd, and
-          * return 328 (we return 328 and not new one so code path
-          * is same for both success & failure).
-          *
-          * If new call failed with ENOSYS, then it means that someone
-          * attached strace between first and second eventfd2 syscalls -
-          * it means that 328 we got was bogus, and system does not
-          * support eventfd2.
-          */
-         ret = syscall(SYS_eventfd2, count, flags);
-         if (ret != SYS_eventfd2) {
-            if (ret != -1 || errno != ENOSYS) {
-               eventfdStyle = EVENTFD_EVENTFD2;
-               if (ret >= 0) {
-                  close(ret);
-               }
-               return SYS_eventfd2;
-            }
-         }
-      }
-      eventfdStyle = EVENTFD_UNKNOWN_NOT2;
-      /* FALLTHRU */
-   case EVENTFD_UNKNOWN_NOT2: /* not eventfd2, but caller needed flags */
-      if (flags) {
-         errno = EINVAL;
-         return -1;
-      }
-      ret = syscall(SYS_eventfd, count);
-      if (ret != -1 || errno != ENOSYS) {
-         eventfdStyle = EVENTFD_EVENTFD;
-         return ret;
-      }
-      eventfdStyle = EVENTFD_NONE;
-      /* FALLTHRU */
-   default:             /* none - 2.6.21 and older */
-      break;
-   }
-   errno = ENOSYS;
-   return -1;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * eventfd_read --
- *
- *      Read count from the descriptor.
- *
- * Results:
- *      -1 on failure, errno set
- *      0 on success, number of pending events retrieved
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-int
-eventfd_read(int fd,             // IN: event fd
-             eventfd_t *value)   // OUT: value
-{
-   ssize_t ret;
-
-   ret = read(fd, value, sizeof *value);
-   if (ret == sizeof *value) {
-      return 0;
-   }
-   if (ret != -1) {
-      errno = EINVAL;
-   }
-   return -1;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * eventfd_write --
- *
- *      Write (increase) count on the descriptor.
- *
- * Results:
- *      -1 on failure, errno set
- *      0 on success, number of pending events increased
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-int
-eventfd_write(int fd,            // IN: event fd
-              eventfd_t value)   // OUT: value
-{
-   ssize_t ret;
-
-   ret = write(fd, &value, sizeof value);
-   if (ret == sizeof value) {
-      return 0;
-   }
-   if (ret != -1) {
-      errno = EINVAL;
-   }
-   return -1;
-}
-
-#endif /* VMWARE_EVENTFD_REAL */
index ccb7495ea1ac86546b2dbcbba5ca0f3d4bda7a70..cc0cb11c20f959bdb3f4ae4c7f277512553812fc 100644 (file)
@@ -18,6 +18,5 @@
 noinst_LTLIBRARIES = libSync.la
 
 libSync_la_SOURCES =
-libSync_la_SOURCES += syncMutex.c
-libSync_la_SOURCES += syncWaitQPosix.c
+libSync_la_SOURCES += syncMutexPthread.c
 
similarity index 65%
rename from open-vm-tools/lib/sync/syncMutex.c
rename to open-vm-tools/lib/sync/syncMutexPthread.c
index e0a84ffd5ed6c04bb9cc60a79841aacb5f531d98..c212fd3d62192d411e248a5a9ad39609d32e0ba4 100644 (file)
  *********************************************************/
 
 /*
- * syncMutex.c --
+ * syncMutexPthread.c --
  *
- *      Implements a non-recursive mutex in a platform independent way.
+ *      Implements a non-recursive mutex using pthreads
  */
 
-#if defined(_WIN32)
-#include <windows.h>
-#elif defined(N_PLAT_NLM)
-#include <nwerrno.h>
-#include <nwadv.h>
-#include <nwthread.h>
-#include <nwsemaph.h>
-#else
-#include <sys/poll.h>
+#include <pthread.h>
 #include <errno.h>
-#endif
+#include <stdlib.h>
 
 #include "vm_assert.h"
 #include "syncMutex.h"
@@ -57,22 +49,14 @@ Bool
 SyncMutex_Init(SyncMutex *that,      // OUT
               char const *path) // IN
 {
-   ASSERT(that);
-
-#if defined(N_PLAT_NLM)
-   that->semaphoreHandle = OpenLocalSemaphore(0);
-#else
-   if (!SyncWaitQ_Init(&that->wq, path)) {
+   int error;
+   error = pthread_mutex_init(&that->_mutex, NULL);
+   if (error != 0) {
       return FALSE;
    }
-
-   Atomic_Write(&that->unlocked, TRUE);
-#endif
-
    return TRUE;
 }
 
-
 /*
  *----------------------------------------------------------------------
  *
@@ -87,17 +71,15 @@ SyncMutex_Init(SyncMutex *that,      // OUT
 void
 SyncMutex_Destroy(SyncMutex *that) // IN
 {
-   ASSERT(that);
-
-#if defined(N_PLAT_NLM)
-   WaitOnLocalSemaphore(that->semaphoreHandle);
-   CloseLocalSemaphore(that->semaphoreHandle);
-#else
-   SyncWaitQ_Destroy(&that->wq);
+#ifdef VMX86_DEBUG
+   int error = 
+#endif
+      pthread_mutex_destroy(&that->_mutex);
+#ifdef VMX86_DEBUG
+   ASSERT(error != EBUSY);
 #endif
 }
 
-
 /*
  *----------------------------------------------------------------------
  *
@@ -114,77 +96,14 @@ SyncMutex_Destroy(SyncMutex *that) // IN
 Bool
 SyncMutex_Lock(SyncMutex *that) // IN
 {
-#if defined(N_PLAT_NLM)
-   ASSERT(that);
-
-   WaitOnLocalSemaphore(that->semaphoreHandle);
-#else
-#if defined(VMX86_DEVEL)
-#define RETRY_TIMEOUT_MS (-1) // Infinite time out to catch bug #23716 (devel)
-#else
-#define RETRY_TIMEOUT_MS 5000 // Workaround for bug #23716
-#endif
-   
-   PollDevHandle handle;
-
-   ASSERT(that);
-
-   if (Atomic_ReadIfEqualWrite(&that->unlocked, TRUE, FALSE)) {
-      return TRUE;
-   }
-
-   for (;;) {
-      int status;
-
-      handle = SyncWaitQ_Add(&that->wq);
-      if (handle < 0) {
-         return FALSE;
-      }
-
-      if (Atomic_ReadIfEqualWrite(&that->unlocked, TRUE, FALSE)) {
-         if (!SyncWaitQ_Remove(&that->wq, handle)) {
-            return FALSE;
-         }
-
-         break;
-      }
-
-#if defined(_WIN32)
-      status = WaitForSingleObject((HANDLE) handle, RETRY_TIMEOUT_MS);
-      ASSERT(status != WAIT_FAILED);
-#else // #ifdef _WIN32
-      {
-        struct pollfd p;
-        p.events = POLLIN;
-        p.fd     = handle;
-
-        for (;;) {
-           status = poll(&p, 1, RETRY_TIMEOUT_MS);
-           if (status == 1 || status == 0) {
-              break;
-           }
-
-           ASSERT(status < 0);
-           if (errno != EINTR) {
-              SyncWaitQ_Remove(&that->wq, handle);
-              return FALSE;
-           }
-
-           /* We were interrupted by a signal, retry --hpreg */
-        }
-      }
-#endif // #ifdef _WIN32
-
-      if (!SyncWaitQ_Remove(&that->wq, handle)) {
-         return FALSE;
-      }
+   int error = pthread_mutex_lock(&that->_mutex);
+   ASSERT(error != EINVAL);
+   if (error != 0) {
+      return FALSE;
    }
-#endif
-
    return TRUE;
 }
 
-
 /*
  *----------------------------------------------------------------------
  *
@@ -201,17 +120,12 @@ SyncMutex_Lock(SyncMutex *that) // IN
 Bool
 SyncMutex_Unlock(SyncMutex *that) // IN
 {
-   ASSERT(that);
-
-#if defined(N_PLAT_NLM)
-   SignalLocalSemaphore(that->semaphoreHandle);
-
+   int error = pthread_mutex_unlock(&that->_mutex);
+   ASSERT(error != EINVAL);
+   if (error != 0) {
+      return FALSE;
+   }
    return TRUE;
-#else
-   Atomic_Write(&that->unlocked, TRUE);
-
-   return SyncWaitQ_WakeUp(&that->wq);
-#endif
 }
 
 
@@ -265,7 +179,6 @@ SyncMutex_CreateSingleton(Atomic_Ptr *lckStorage) // IN
 }
 
 
-#if !defined(N_PLAT_NLM)
 /*
  *-----------------------------------------------------------------------------
  *
@@ -286,8 +199,10 @@ Bool
 SyncMutex_Trylock(SyncMutex *that)
 {
    ASSERT(that);
-   
-   return Atomic_ReadIfEqualWrite(&that->unlocked, TRUE, FALSE);
-}
+#ifdef VMX86_SERVER
+   NOT_IMPLEMENTED();
+   return FALSE;
+#else
+   return (0 == pthread_mutex_trylock(&that->_mutex));
 #endif
-
+}
diff --git a/open-vm-tools/lib/sync/syncWaitQPosix.c b/open-vm-tools/lib/sync/syncWaitQPosix.c
deleted file mode 100644 (file)
index 755f15c..0000000
+++ /dev/null
@@ -1,1069 +0,0 @@
-/*********************************************************
- * Copyright (C) 1998 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation version 2.1 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
- *
- *********************************************************/
-
-#ifdef _WIN32
-#error "This file should not be compiled under Win32"
-#endif
-
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef __APPLE__
-#include <sys/utsname.h>
-#endif
-
-#include "vm_assert.h"
-#include "str.h"
-#include "util.h"
-#include "syncWaitQ.h"
-#include "posix.h"
-#include "eventfd.h"
-
-#define LOGLEVEL_MODULE syncWaitQ
-#include "loglevel_user.h"
-
-#define LGPFX "SyncWaitQ: "
-
-
-/*
- * syncWaitQPosix.c --
- *
- *      Kernel (2.4, it changed a bit in 2.5) wait-queue semantics in
- *      userland, yeah baby! -- hpreg
- *
- *      The semantics of this implementation are as follows:
- *
- *      o Client threads can add themselves to a waitqueue object and
- *      receive a pollable handle via a call to SyncWaitQ_Add
- *
- *      o When the waitqueue is woken up, each handle that was
- *      previously obtained via a call to SyncWaitQ_Add becomes
- *      signalled and remains so until it is removed via a call to
- *      SyncWaitQ_Remove. Any calls to SyncWaitQ_Add, after the queue
- *      has been woken up, will return fresh, unsignalled handles.
- * 
- */
-
-/*
- * TODO:
- * Run this test code on 2.0 and 2.2 kernels
- * 
- * kernel                        user
- * ------                        ----
- * wait queue                    FIFO
- * 
- * state=INT, add to wait queue  open FIFO in read mode
- * check sleep condition         check sleep condition
- * schedule                      poll
- * remove from wait queue        close
- * 
- * wake_up wait queue            open FIFO in write mode + close
- * 
- *  I put a lot of thought into this, we may want to patent it just
- *  for fun. I don't know of any prior art --hpreg 
- */
-
-/*
- * How to use this to avoid races:
- * 
- * Some process initializes the wait queue in shared mem with
- * SyncWaitQ_Init(&wq)
- * 
- * P0 does:
- *
- * for (;;) {
- *    fd = SyncWaitQ_Add(&wq);
- *    if (some condition) {
- *       SyncWaitQ_Remove(&wq, fd);
- *       break;
- *    }
- *    poll(fd, ...);
- *    SyncWaitQ_Remove(&wq, fd);
- * }
- * 
- * P1 does:
- *
- * some condition = TRUE;
- * SyncWaitQ_WakeUp(&wq);
- * 
- * Note2: if there is activity on a wait-queue fd, it basically means
- * that the fd becomes unusable after that (it keeps returning
- * POLLHUP), and you need a new one. Actually I take this back, we can
- * reopen and then dup2, so we keep the same fd number and there is no
- * need for the client code to re-register the new fd with its poll
- * loop. I knew this trick would be useful one day :)
- *
- */
-
-typedef union {
-   uint32 fd[2];
-   uint64 i64;
-} HandlesAsI64;
-
-
-static INLINE Bool SyncWaitQWakeUpNamed(SyncWaitQ *that);
-static INLINE Bool SyncWaitQWakeUpAnon(SyncWaitQ *that);
-
-
-#if __APPLE__
-/*
- * See VMware bug 116441: we workaround Apple bug 4751096 (calling close and
- * dup simultaneously on the same fd makes the Mac OS kernel panic when the
- * application exits) by serializing these calls.
- *
- * The bug is fixed in Leopard GA (build 9A581).
- */
-
-enum {
-   WORKAROUND_UNKNOWN,
-   WORKAROUND_NO,
-   WORKAROUND_YES,
-};
-static Atomic_Int workaround = { WORKAROUND_UNKNOWN, };
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQInit --
- *
- *      If the workaround is needed, initialize the wait queue's mutex.
- *
- * Results:
- *      On success: 0.
- *      On failure: errno.
- *
- * Side effects:
- *      None
- *
- *---------------------------------------------------------------------------- 
- */
-
-static int
-SyncWaitQInit(SyncWaitQ *that)  // IN:
-{
-   if (UNLIKELY(Atomic_ReadInt(&workaround) == WORKAROUND_UNKNOWN)) {
-      struct utsname u;
-      unsigned int major;
-
-      /*
-       * We purposedly do not use Hostinfo_OSVersion() to avoid introducing a
-       * library dependency just for a workaround.
-       */
-
-      Atomic_ReadIfEqualWriteInt(&workaround, WORKAROUND_UNKNOWN,
-         (   uname(&u) == -1
-          || sscanf(u.release, "%u.", &major) != 1
-          || major < 9) ? WORKAROUND_YES : WORKAROUND_NO);
-      LOG(1, (LGPFX "dup() crash workaround %s\n",
-              Atomic_ReadInt(&workaround) == WORKAROUND_YES ? "activated"
-                                                            : "not necessary"));
-   }
-
-   ASSERT(Atomic_ReadInt(&workaround) != WORKAROUND_UNKNOWN);
-
-   return Atomic_ReadInt(&workaround) == WORKAROUND_YES ?
-                                  pthread_mutex_init(&that->mutex, NULL) : 0;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQDestroy --
- *
- *      If the workaround is needed, destroy the wait queue's mutex.
- *
- * Results:
- *      None
- *
- * Side effects:
- *      None
- *
- *----------------------------------------------------------------------------
- */
-
-static void
-SyncWaitQDestroy(SyncWaitQ *that) // IN
-{
-   ASSERT(Atomic_ReadInt(&workaround) != WORKAROUND_UNKNOWN);
-   if (Atomic_ReadInt(&workaround) == WORKAROUND_YES) {
-      int result;
-
-      result = pthread_mutex_destroy(&that->mutex);
-      ASSERT(!result);
-   }
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQLock --
- *
- *      If the workaround is needed, grab the wait queue's mutex.
- *
- * Results:
- *      None
- *
- * Side effects:
- *      None
- *
- *---------------------------------------------------------------------------- 
- */
-
-static void
-SyncWaitQLock(SyncWaitQ *that) // IN
-{
-   ASSERT(Atomic_ReadInt(&workaround) != WORKAROUND_UNKNOWN);
-   if (Atomic_ReadInt(&workaround) == WORKAROUND_YES) {
-      int result;
-
-      result = pthread_mutex_lock(&that->mutex);
-      ASSERT(!result);
-   }
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQUnlock --
- *
- *      If the workaround is needed, release the wait queue's mutex.
- *
- * Results:
- *      None
- *
- * Side effects:
- *      None
- *
- *---------------------------------------------------------------------------- 
- */
-
-static void
-SyncWaitQUnlock(SyncWaitQ *that)  // IN:
-{
-   ASSERT(Atomic_ReadInt(&workaround) != WORKAROUND_UNKNOWN);
-
-   if (Atomic_ReadInt(&workaround) == WORKAROUND_YES) {
-      int result;
-
-      result = pthread_mutex_unlock(&that->mutex);
-      ASSERT(!result);
-   }
-}
-
-#else
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQ{Init,Destroy,Lock,Unlock} --
- *
- *      Non-OS X version of dup() crash workaround.
- *
- * Results:
- *      Init:         0, success
- *      Lock,Unlock:  None.
- *
- * Side effects:
- *      None
- *
- *----------------------------------------------------------------------------
- */
-
-static INLINE int SyncWaitQInit(SyncWaitQ *dummy) { return 0; }
-static INLINE void SyncWaitQDestroy(SyncWaitQ *dummy) { }
-static INLINE void SyncWaitQLock(SyncWaitQ *dummy) { }
-static INLINE void SyncWaitQUnlock(SyncWaitQ *dummy) { }
-
-#endif
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQPanicOnFdLimit --
- *
- *      Panic if 'error' corresponds to an fd limit being reached. See bug
- *      72108. Just like an out-of-memory condition, an out-of-fd condition is
- *      pretty much unrecoverable. The only thing we can do is help our users
- *      diagnose the problem.
- *
- * Results:
- *      None
- *
- * Side effects:
- *      None
- *
- *---------------------------------------------------------------------------- 
- */
-
-static void
-SyncWaitQPanicOnFdLimit(int error)  // IN:
-{
-   switch (error) {
-   case EMFILE:
-      Panic("%s: Too many file descriptors are in use by the process.\n",
-            __FUNCTION__);
-      break;
-
-   case ENFILE:
-      Panic("%s: The system limit on the total number of open files has "
-            "been reached.\n", __FUNCTION__);
-      break;
-
-   default:
-      break;
-   }
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQCreateNonBlockingPipe --
- *
- *      Creates non-blocking pipe.
- *
- * Results:
- *      FALSE on sucess.
- *      TRUE on failure.
- *
- * Side effects:
- *      Panics if EMFILE or ENFILE are hit.
- *
- *----------------------------------------------------------------------------
- */
-
-static Bool
-SyncWaitQCreateNonBlockingPipe(int fd[2])  // OUT
-{
-   if (pipe(fd) < 0) {
-      int error = errno;
-
-      LOG(0, (LGPFX "Could not create pipe pair: %s (%d)\n",
-              strerror(error), error));
-      SyncWaitQPanicOnFdLimit(error);
-      return TRUE;
-   }
-
-   if (fcntl(fd[0], F_SETFL, O_RDONLY | O_NONBLOCK) < 0 ||
-       fcntl(fd[1], F_SETFL, O_WRONLY | O_NONBLOCK) < 0) {
-      int error = errno;
-
-      Warning("%s: fcntl failed, %s (%d)\n", __FUNCTION__, strerror(error), error);
-      close(fd[1]);
-      close(fd[0]);
-      return TRUE;
-   }
-   return FALSE;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SyncWaitQ_Init --
- *
- *      Initializes a waitqueue structure.
- *
- *      On Win32 the 'path' is the name of the waitqueue in the kernel
- *      namespace (actually a Win32 event).
- *
- *      On Posix the 'path' is the file path to a fifo. The fifo
- *      object itself does not have to exist, but its parent directory
- *      must exist.
- *
- *      If 'path' is NULL, then the waitqueue object is anonymous
- *
- *      It is illegal for the 'path' argument to be empty string.
- *
- * Results:
- *      TRUE on success and FALSE otherwise.
- *
- * Side effects:
- *      On Posix, when named creates a fifo.
- *
- *---------------------------------------------------------------------- 
- */
-
-Bool
-SyncWaitQ_Init(SyncWaitQ *that,   // OUT:
-              char const *path)  // IN/OPT:
-{
-   ASSERT(that);
-   ASSERT(!path || path[0]);
-
-   memset(that, 0, sizeof(SyncWaitQ));
-
-   if (!path) {
-      /*
-       * Anonymous
-       */
-
-      int fd = eventfd(0, EFD_NONBLOCK);
-
-      if (fd >= 0) {
-         LOG(3, (LGPFX "Queue %p uses event fd %d\n", that, fd));
-         that->usesEventFd = TRUE;
-         if (SyncWaitQInit(that)) {
-            close(fd);
-            return FALSE;
-         }
-         Atomic_Write32(&that->u.eventHandle, fd);
-      } else if (errno != ENOSYS && errno != EINVAL) {
-         int error = errno;
-
-         LOG(2, (LGPFX "Could not allocate event fd for %p: %s (%d)\n",
-                 that, strerror(error), error));
-         SyncWaitQPanicOnFdLimit(error);
-         return FALSE;
-      } else {
-         HandlesAsI64 rwHandles;
-
-         if (SyncWaitQCreateNonBlockingPipe(rwHandles.fd)) {
-            return FALSE;
-         }
-
-         LOG(3, (LGPFX "Queue %p uses pair of pipes, %d & %d\n", that,
-                 rwHandles.fd[0], rwHandles.fd[1]));
-
-         if (SyncWaitQInit(that)) {
-            close(rwHandles.fd[0]);
-            close(rwHandles.fd[1]);
-            return FALSE;
-         }
-
-         Atomic_Write64(&that->u.pipeHandles64, rwHandles.i64);
-      }
-   } else {
-      /*
-       * Named
-       */
-
-      LOG(3, (LGPFX "Queue %p uses base name %s\n", that, path));
-      that->pathName = Util_SafeStrdup(path);
-   }
-
-   that->initialized = TRUE;
-   return TRUE;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SyncWaitQMakeName --
- *
- *       Computes the name of the named system object based on the
- *       path of the wait queue and a sequence number
- *
- *----------------------------------------------------------------------
- */
-
-static char *
-SyncWaitQMakeName(const char *path,  // IN:
-                  uint64 seq)        // IN:
-{
-   return Str_SafeAsprintf(NULL, "%s.%"FMT64"x", path, seq);
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SyncWaitQ_Destroy --
- *
- *      Destroys the system resources associated with the specified
- *      waitqueue. The waitqueue structure itself is not freed.
- *
- * Side effects:
- *      Closes handles. On Posix, also unlinks the fifo associated
- *      with this waitqueue.
- *
- *---------------------------------------------------------------------- 
- */
-
-void
-SyncWaitQ_Destroy(SyncWaitQ *that)  // IN:
-{
-   if (!that->initialized) {
-      LOG(0, (LGPFX "Uninitialized queue %p is being destroyed!\n", that));
-      return;
-   }
-
-   if (that->pathName == NULL) {
-      /*
-       * Anonymous
-       */
-
-      if (that->usesEventFd) {
-         int fd;
-         int err;
-
-         fd = Atomic_Read32(&that->u.eventHandle);
-         LOG(3, (LGPFX "Destroying queue %p with event fd %d\n", that, fd));
-         err = close(fd);
-         ASSERT(err == 0);
-      } else {
-         HandlesAsI64 rwHandles;
-
-         rwHandles.i64 = Atomic_Read64(&that->u.pipeHandles64);
-         LOG(3, (LGPFX "Destroying queue %p with pipe pair %d, %d\n",
-                 that, rwHandles.fd[0], rwHandles.fd[1]));
-         close(rwHandles.fd[0]);
-         close(rwHandles.fd[1]);
-      }
-      SyncWaitQDestroy(that);
-   } else {
-      /*
-       * Named
-       */
-
-      uint64 seq;
-      char *name;
-
-      seq = Atomic_Read64(&that->seq);
-      name = SyncWaitQMakeName(that->pathName, seq);
-      LOG(3, (LGPFX "Destroying queue %p with name %s\n", that, name));
-      Posix_Unlink(name);
-      free(name);
-      free(that->pathName);
-      that->pathName = NULL;
-   }
-
-   that->initialized = FALSE;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQ_Add --
- *
- *      Add a waiter to the waitqueue.
- *
- * Results:
- *      On success, a pollable handle (fd on Posix and a HANDLE on Win32)
- *      that can be used by the caller to determine when the queue has been
- *      woken up. On failure, -1.
- *
- *-----------------------------------------------------------------------------
- */
-
-PollDevHandle
-SyncWaitQ_Add(SyncWaitQ *that)  // IN:
-{
-   uint64 seq;
-   int ret = -1;
-   char *name = NULL;
-
-   ASSERT(that);
-   ASSERT(that->initialized);
-
-   /* Hint that we are about to wait */
-   Atomic_Write(&that->waiters, TRUE);
-   
-   /*
-    * The following statement is the demarcation line for Add.  Any
-    * wakeup that happens after this line should wake up this waiter
-    * -- Ticho
-    */
-
-   seq = Atomic_Read64(&that->seq);
-
-   /*
-    * It is OK to fail in the following 2 paths, because if the sequence
-    * number has changed, we manufacture our own fd, so any error is harmless.
-    */
-
-   if (that->pathName == NULL) {
-      /*
-       * Anonymous
-       */
-
-      int fd;
-
-      /*
-       * XXX?
-       *
-       * There is an extremely small chance for a side effect to
-       * unrelated code caused by a race condition here. Please refer
-       * to the corresponding comment in syncWaitQWin32.c for more
-       * information
-       *
-       * -- Ticho 
-       */
-
-      if (that->usesEventFd) {
-         fd = Atomic_Read32(&that->u.eventHandle);
-         LOG(5, (LGPFX "Adding waiter for queue %p.  "
-                 "Current event fd is %d, sequence %"FMT64"u\n",
-                 that, fd, seq));
-      } else {
-         fd = Atomic_Read32(&that->u.pipeHandles[0]);
-         LOG(5, (LGPFX "Adding waiter for queue %p.  "
-                 "Current read pipe fd is %d, sequence %"FMT64"u\n",
-                 that, fd, seq));
-      }
-      SyncWaitQLock(that);
-      ret = dup(fd);
-      SyncWaitQUnlock(that);
-      if (ret < 0) {
-         int error = errno;
-
-         LOG(5, (LGPFX "Could not duplicate file descriptor %d: %s (%d)\n",
-                 fd, strerror(error), error));
-         SyncWaitQPanicOnFdLimit(error);
-      } else {
-         LOG(5, (LGPFX "Created private read descriptor %d\n", ret));
-      }
-   } else {
-      /*
-       * Named
-       */
-
-      name = SyncWaitQMakeName(that->pathName, seq);
-
-      /*
-       * Create fifo object with the generated name
-       *
-       * XXX? Note that if the object already exists on the file
-       * system, we will assume that this is a fifo created by another
-       * waiter for this wait queue. Of course, this cannot be
-       * guaranteed 100%, but in practice this will be the case since
-       * the names of the waitqueues are fairly unique and since in
-       * practice they will be created in a specially designated
-       * directory. -- Ticho.
-       */
-
-      LOG(5, (LGPFX "Adding waiter for queue %p.  "
-              "Current event name is %s, sequence %"FMT64"u\n",
-              that, name, seq));
-
-      ret = Posix_Mkfifo(name, S_IRUSR | S_IWUSR);
-      if (ret >= 0 || errno == EEXIST) {
-         /*
-          * We open in non-blocking mode so that we won't block if nobody
-          * has opened in write mode. We prefer to block in poll, because
-          * we can block on several wait queues, and we can have a
-          * timeout without using signals --hpreg 
-          */
-
-         /*
-          * It is possible that from the time we create the fifo to the
-          * time it is opened, the wait queue was woken up and the fifo
-          * was unlinked from the file system. That is OK because we
-          * detect this case and will not use the fd returned from open() 
-          * -- Ticho.
-          */
-
-         ret = Posix_Open(name, O_RDONLY | O_NONBLOCK);
-         if (ret < 0) {
-            int error = errno;
-
-            LOG(5, (LGPFX "Could not open named pipe: %s (%d)\n",
-                    strerror(error), error));
-            SyncWaitQPanicOnFdLimit(error);
-         } else {
-            LOG(5, (LGPFX "Created private fd %d for named pipe\n",
-                    ret));
-         }
-      } else {
-         LOG_ONLY(int error = errno;)
-
-         LOG(5, (LGPFX "Problem when creating named pipe: %s (%d)\n",
-                 strerror(error), error));
-      }
-   }
-
-   /*
-    * Check to see whether someone didn't wake us up while we were
-    * adding ourselves to the queue
-    */
-
-   if (seq != Atomic_Read64(&that->seq)) {
-      /*
-       * Someone woke up the queue while we were adding ourselves to it, so
-       * just pretend that we were woken up too by returning a conjured up,
-       * woken up handle
-       */
-
-      LOG(5, (LGPFX "Sequence number changed on queue %p\n", that));
-
-      if (ret >= 0) {
-        close(ret);
-         if (that->pathName != NULL) {
-            Posix_Unlink(name);
-         }
-      }
-
-      /* Create event with initial value of 1.  Any non-zero value is good. */
-      ret = eventfd(1, EFD_NONBLOCK);
-      if (ret >= 0) {
-         /* We are done... */
-         LOG(5, (LGPFX "Created dummy event fd %d\n", ret));
-      } else if (errno != ENOSYS && errno != EINVAL) {
-         int error = errno;
-
-         LOG(0, (LGPFX "Could not create dummy event fd: %s (%d)\n",
-                 strerror(error), error));
-         SyncWaitQPanicOnFdLimit(error);
-         ASSERT(ret == -1);
-      } else {
-         int fd[2];
-
-         if (SyncWaitQCreateNonBlockingPipe(fd)) {
-            free(name);
-            return -1;
-         }
-
-         LOG(5, (LGPFX "Created dummy pipe pair %d, %d\n", fd[0], fd[1]));
-
-         if (write(fd[1], "X", 1) == 1) {
-            /*
-             * fd[0] now should be in a perpetual woken up state. It will be
-             * closed when the client code calls SyncWaitQ_Remove() on it.
-             */
-
-            ret = fd[0];
-         } else {
-            close(fd[0]);
-            ret = -1;
-         }
-
-         close(fd[1]);
-      }
-   } else {
-      if (ret < 0) {
-         free(name);
-         return -1;
-      }
-
-      /*
-       * It is possible that another thread woke up the queue and set
-       * waiters=FALSE, even if we didn't detect that the sequence
-       * number has changed. This can happen like so 
-       *
-       * (T1=this thread, T2=wakeup thread):
-       * 
-       * T1: Set waiters=TRUE
-       * T2: Set waiters=FALSE
-       * T2: Create and save new wakeup handle
-       * T1: Read seq
-       * T1: Dup new wakeup handle
-       * T1: compare seq (they match, so the thread won't wake itself up)
-       *
-       * At this point T1 has a new event handle that hasn't been
-       * woken up, but 'waiters' is FALSE. To prevent that case, we
-       * set waiters=TRUE once again here. 
-       *
-       * Note that there is no harm, as far as correctness is
-       * concerned in setting waiters=TRUE anywhere
-       *
-       *      -- Ticho 09/11/2003
-       *
-       */
-
-      Atomic_Write(&that->waiters, TRUE);
-   }
-
-   free(name);
-
-   LOG(4, (LGPFX "New waiter on queue %p: %d\n", that, ret));
-
-   return ret;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * SyncWaitQ_Remove --
- *
- *      Removes the caller from the waitqueue. The caller must provide
- *      the handle which it originally obtained via a call to
- *      SyncWaitQ_Add
- *
- * Results:
- *      TRUE on success and FALSE otherwise
- *
- * Side effects:
- *      The caller supplied handle is closed
- *
- *---------------------------------------------------------------------- 
- */
-
-Bool
-SyncWaitQ_Remove(SyncWaitQ *that,       // Unused
-                PollDevHandle handle)  // IN:
-{
-   ASSERT(that);
-   if (!that->initialized) {
-      LOG(0, (LGPFX "Poll handle %d on queue %p is released after queue is destroyed\n",
-              handle, that));
-      return FALSE;
-   }
-
-   /*
-    * The anonymous and named case are the same. -- Ticho
-    */
-
-   LOG(4, (LGPFX "Destroying waiter %d on queue %p\n", handle, that));
-
-   return close(handle) >= 0;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQ_WakeUp --
- *
- *      Wakes up all waiters (if any) by making their pollable handles
- *      signalled.
- *
- *      Note that there are no provisions for the handles previously
- *      given to the waiters to be made unsignalled and used again for
- *      waiting. If an ex-waiter wants to wait again, it will have to
- *      first call SyncWaitQ_Remove and then SyncWaitQ_Add again. The
- *      latter will give it a fresh pollable handle to wait on.
- *
- * Results:
- *      TRUE on success
- *      FALSE on failure
- *
- * Side effects:
- *      None
- *
- *---------------------------------------------------------------------------- 
- */
-
-Bool
-SyncWaitQ_WakeUp(SyncWaitQ *that)  // IN:
-{
-   ASSERT(that);
-   ASSERT(that->initialized);
-
-   if (!Atomic_Read(&that->waiters)) {
-      /* Fast path --hpreg */
-      LOG(4, (LGPFX "Waking up queue %p: no waiters\n", that));
-      return TRUE;
-   }
-
-   Atomic_Write(&that->waiters, FALSE);
-
-   /* 
-    * Slow path --hpreg 
-    */
-   
-   return (that->pathName == NULL) ? SyncWaitQWakeUpAnon(that) :
-                                     SyncWaitQWakeUpNamed(that);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQWakeUpAnon --
- *
- *      Anonymous version of SyncWaitQ_WakeUp
- *
- * Results:
- *      TRUE on success
- *      FALSE on failure
- *
- * Side effects:
- *      None
- *
- *---------------------------------------------------------------------------- 
- */
-
-static Bool
-SyncWaitQWakeUpAnon(SyncWaitQ *that)  // IN:
-{
-   if (that->usesEventFd) {
-      int fd;
-      int ret;
-      int error;
-
-      fd = eventfd(0, EFD_NONBLOCK);
-      if (fd < 0) {
-         int error = errno;
-
-         LOG(1, (LGPFX "Could not create event fd while waking up queue %p: %s (%d)\n",
-                 that, strerror(error), error));
-         ASSERT(error != ENOSYS && errno != EINVAL);
-         SyncWaitQPanicOnFdLimit(error);
-         return FALSE;
-      }
-      LOG(4, (LGPFX "Queue %p woken up.  New event fd is %d\n", that, fd));
-      fd = Atomic_ReadWrite32(&that->u.eventHandle, fd);
-      Atomic_Inc64(&that->seq);
-      ret = eventfd_write(fd, 1);
-      error = errno;
-      SyncWaitQLock(that);
-      close(fd);
-      SyncWaitQUnlock(that);
-      if (ret != 0) {
-         Warning("%s: eventfd_write failed, %s (%d)\n",
-                 __FUNCTION__, strerror(ret), error);
-         return FALSE;
-      }
-   } else {
-      HandlesAsI64 rwHandles, wakeupHandles;
-      ssize_t ret;
-      int error;
-
-      /* Create the new anonymous handle. */
-      if (SyncWaitQCreateNonBlockingPipe(rwHandles.fd)) {
-         return FALSE;
-      }
-
-      /*
-       * The following statement is the demarcation line for wakeup
-       *
-       * There is a possibility for suprious wakeups if the WaitQ_Add
-       * began executing after this line but before the inc of the sequence.
-       *
-       * We assume that spurious wakups are OK.
-       */
-
-      LOG(4, (LGPFX "Queue %p woken up.  New pipe pair is %d, %d\n",
-              that, rwHandles.fd[0], rwHandles.fd[1]));
-      wakeupHandles.i64 = Atomic_ReadWrite64(&that->u.pipeHandles64, rwHandles.i64);
-      Atomic_Inc64(&that->seq);
-
-      ret = write(wakeupHandles.fd[1], "X", 1);
-      error = errno;
-      close(wakeupHandles.fd[1]);
-      SyncWaitQLock(that);
-      close(wakeupHandles.fd[0]);
-      SyncWaitQUnlock(that);
-      if (ret != 1) {
-         if (ret < 0) {
-            Warning("%s: write to pipe failed, %s (%d)\n",
-                    __FUNCTION__, strerror(error), error);
-         } else {
-            Warning("%s: write to pipe failed, %"FMTSZ"d bytes written\n",
-                    __FUNCTION__, ret);
-         }
-         return FALSE;
-      }
-   }
-   return TRUE;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * SyncWaitQWakeUpNamed --
- *
- *      Named version of SyncWaitQ_WakeUp
- *
- * Results:
- *      TRUE on success
- *      FALSE on failure
- *
- * Side effects:
- *      None
- *
- *---------------------------------------------------------------------------- 
- */
-
-static Bool
-SyncWaitQWakeUpNamed(SyncWaitQ *that)  // IN:
-{
-   uint64 seq;
-   char *name;
-   int wakeupHandle = -1;
-   ssize_t ret;
-   int error;
-
-   /* The following statement is the demarcation line for wakeup */
-   seq = Atomic_FetchAndInc64(&that->seq);
-   name = SyncWaitQMakeName(that->pathName, seq);
-
-   /*
-    * We open in non-blocking mode so that we won't block if there is
-    * no reader, instead we will get ENXIO. Another way would be to
-    * open in non-blocking read-write mode, but it adds an extra close
-    * system call.
-    */
-
-   wakeupHandle = Posix_Open(name, O_WRONLY | O_NONBLOCK);
-   error = errno;
-   Posix_Unlink(name);
-   free(name);
-
-   if (wakeupHandle < 0) {
-      SyncWaitQPanicOnFdLimit(error);
-
-      /*
-       * If error == ENXIO or ENOENT, then there are no waiters, so
-       * the wakeup is considered successful.
-       */
-
-      if (error == ENXIO || error == ENOENT) {
-         LOG(4, (LGPFX "No waiters while waking up queue %p "
-                 "using name %s and sequence %"FMT64"u\n",
-                 that, that->pathName, seq));
-         return TRUE;
-      }
-
-      Warning("%s: open failed, %s (%d)\n", __FUNCTION__, strerror(error), error);
-      return FALSE;
-   }
-
-   ret = write(wakeupHandle, "X", 1);
-   error = errno;
-   close(wakeupHandle);
-   if (ret != 1) {
-      if (ret < 0) {
-         if (error == EPIPE) {
-            /*
-             * If a waiter was signalled by another thread and the waiter
-             * just closed the read end of the pipe, we may get an EPIPE
-             * error. That's OK, because the waiter was already woken up.
-             */
-
-            LOG(4, (LGPFX "Waiter disappeared while waking up queue %p "
-                    "using name %s and sequence %"FMT64"u\n",
-                    that, that->pathName, seq));
-            return TRUE;
-         }
-         Warning("%s: write failed, %s (%d)\n", __FUNCTION__,
-                 strerror(error), error);
-      } else {
-         Warning("%s: write failed, %"FMTSZ"d bytes written\n", __FUNCTION__, ret);
-      }
-      return FALSE;
-   }
-   LOG(4, (LGPFX "Waiters woken up on queue %p for name %s and sequence %"FMT64"u\n",
-           that, that->pathName, seq));
-   return TRUE;
-}