Added a kqueue class which isn't being used yet, but was part of trying to work around the limitations with the unix select() call and how it is limited to FD_SETSIZE file descriptors.

Also added a TimeSpecTimeout class which can be used with any calls that take a "struct timespec *" as an argument. It is used by the KQueue class.

Also updated some project settings.



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@175377 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Utility/KQueue.cpp b/source/Utility/KQueue.cpp
new file mode 100644
index 0000000..c0aace4
--- /dev/null
+++ b/source/Utility/KQueue.cpp
@@ -0,0 +1,87 @@
+//===--------------------- KQueue.cpp ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "KQueue.h"
+
+#ifdef LLDB_USE_KQUEUES
+
+#include "lldb/Core/Error.h"
+
+#include "Utility/TimeSpecTimeout.h"
+
+using namespace lldb_private;
+
+int
+KQueue::GetFD (bool can_create)
+{
+    if (!IsValid () && can_create)
+        m_fd = kqueue();
+    return m_fd;
+}
+
+int
+KQueue::Close ()
+{
+    const int fd = m_fd;
+    if (fd >= 0)
+    {
+        m_fd = -1;
+        return close(fd);
+    }
+    return 0;
+}
+
+int
+KQueue::WaitForEvents (struct kevent *events, int num_events, Error &error, uint32_t timeout_usec)
+{
+    const int fd_kqueue = GetFD(false);
+    if (fd_kqueue >= 0)
+    {
+        TimeSpecTimeout timeout;
+        const struct timespec *timeout_ptr = timeout.SetRelativeTimeoutMircoSeconds32 (timeout_usec);
+        int result = ::kevent(fd_kqueue, NULL, 0, events, num_events, timeout_ptr);
+        if (result == -1)
+            error.SetErrorToErrno();
+        else
+            error.Clear();
+        return result;
+    }
+    else
+    {
+        error.SetErrorString("invalid kqueue fd");
+    }
+    return 0;
+}
+
+bool
+KQueue::AddFDEvent (int fd, bool read, bool write, bool vnode)
+{
+    const int fd_kqueue = GetFD(true);
+    if (fd_kqueue >= 0)
+    {
+        struct kevent event;
+        event.ident  = fd;
+        event.filter = 0;
+        if (read)
+            event.filter |= EVFILT_READ;
+        if (write)
+            event.filter |= EVFILT_WRITE;
+        if (vnode)
+            event.filter |= EVFILT_VNODE;
+        event.flags  = EV_ADD | EV_CLEAR;
+        event.fflags = 0;
+        event.data   = 0;
+        event.udata  = NULL;
+        int err = ::kevent(fd_kqueue, &event, 1, NULL, 0, NULL);
+        return err == 0;
+    }
+    return false;
+}
+
+#endif
diff --git a/source/Utility/KQueue.h b/source/Utility/KQueue.h
new file mode 100644
index 0000000..8a23256
--- /dev/null
+++ b/source/Utility/KQueue.h
@@ -0,0 +1,72 @@
+//===--------------------- KQueue.h -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_KQueue_h_
+#define utility_KQueue_h_
+
+#if defined(__APPLE__)
+#define LLDB_USE_KQUEUES
+#endif
+
+#ifdef LLDB_USE_KQUEUES
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+
+#include "lldb-defines.h"
+
+namespace lldb_private {
+
+class KQueue
+{
+public:
+    KQueue() :
+        m_fd(-1)
+    {
+    }
+
+    ~KQueue()
+    {
+        Close();
+    }
+    
+    bool
+    IsValid () const
+    {
+        return m_fd >= 0;
+    }
+
+    int
+    GetFD (bool can_create);
+
+    int
+    Close ();
+
+    bool
+    AddFDEvent (int fd,
+                bool read,
+                bool write,
+                bool vnode);
+
+    int
+    WaitForEvents (struct kevent *events,
+                   int num_events,
+                   Error &error,
+                   uint32_t timeout_usec = UINT32_MAX); // UINT32_MAX means infinite timeout
+
+protected:
+    int m_fd; // The kqueue fd
+};
+
+} // namespace lldb_private
+
+#endif // #ifdef LLDB_USE_KQUEUES
+
+#endif // #ifndef utility_KQueue_h_
diff --git a/source/Utility/TimeSpecTimeout.cpp b/source/Utility/TimeSpecTimeout.cpp
new file mode 100644
index 0000000..33b3b4e
--- /dev/null
+++ b/source/Utility/TimeSpecTimeout.cpp
@@ -0,0 +1,48 @@
+//===--------------------- TimeSpecTimeout.cpp ------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TimeSpecTimeout.h"
+
+using namespace lldb_private;
+
+const struct timespec *
+TimeSpecTimeout::SetAbsoluteTimeoutMircoSeconds32 (uint32_t timeout_usec)
+{
+    if (timeout_usec == UINT32_MAX)
+    {
+        m_infinite = true;
+    }
+    else
+    {
+        m_infinite = false;
+        TimeValue time_value(TimeValue::Now());
+        time_value.OffsetWithMicroSeconds(timeout_usec);
+        m_timespec = time_value.GetAsTimeSpec();
+    }
+    return GetTimeSpecPtr ();
+}
+
+const struct timespec *
+TimeSpecTimeout::SetRelativeTimeoutMircoSeconds32 (uint32_t timeout_usec)
+{
+    if (timeout_usec == UINT32_MAX)
+    {
+        m_infinite = true;
+    }
+    else
+    {
+        m_infinite = false;
+        TimeValue time_value;
+        time_value.OffsetWithMicroSeconds(timeout_usec);
+        m_timespec = time_value.GetAsTimeSpec();
+    }
+    return GetTimeSpecPtr ();
+}
+
+
diff --git a/source/Utility/TimeSpecTimeout.h b/source/Utility/TimeSpecTimeout.h
new file mode 100644
index 0000000..32cdd06
--- /dev/null
+++ b/source/Utility/TimeSpecTimeout.h
@@ -0,0 +1,90 @@
+//===--------------------- TimeSpecTimeout.h --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_TimeSpecTimeout_h_
+#define utility_TimeSpecTimeout_h_
+
+#include "lldb/Host/TimeValue.h"
+
+namespace lldb_private {
+
+class TimeSpecTimeout
+{
+public:
+    TimeSpecTimeout() :
+        m_infinite (false)
+    {
+        m_timespec.tv_sec = 0;
+        m_timespec.tv_nsec = 0;
+    }
+    ~TimeSpecTimeout()
+    {
+    }
+
+    //----------------------------------------------------------------------
+    /// Sets the timespec pointer correctly given a timeout relative to the
+    /// current time. This function should be called immediately prior to
+    /// calling the function you will use this timeout with since time can
+    /// elapse between when this function is called and when the timeout is
+    /// used.
+    ///
+    /// @param[in] timeout_usec
+    ///     The timeout in micro seconds. If timeout_usec is UINT32_MAX, the
+    ///     timeout should be set to INFINITE. Otherwise the current time is
+    ///     filled into the timespec and \a timeout_usec is added to the
+    ///     current time.
+    ///
+    /// @return
+    ///     If the timeout is INFINITE, then return NULL, otherwise return
+    ///     a pointer to the timespec with the appropriate timeout value.
+    //----------------------------------------------------------------------
+    const struct timespec *
+    SetAbsoluteTimeoutMircoSeconds32 (uint32_t timeout_usec);
+
+    //----------------------------------------------------------------------
+    /// Sets the timespec pointer correctly given a relative time in micro
+    /// seconds. 
+    ///
+    /// @param[in] timeout_usec
+    ///     The timeout in micro seconds. If timeout_usec is UINT32_MAX, the
+    ///     timeout should be set to INFINITE. Otherwise \a timeout_usec
+    ///     is correctly placed into the timespec.
+    ///
+    /// @return
+    ///     If the timeout is INFINITE, then return NULL, otherwise return
+    ///     a pointer to the timespec with the appropriate timeout value.
+    //----------------------------------------------------------------------
+    const struct timespec *
+    SetRelativeTimeoutMircoSeconds32 (uint32_t timeout_usec);
+
+    //----------------------------------------------------------------------
+    /// Gets the timespec pointer that is appropriate for the timeout
+    /// specified. This function should only be used after a call to
+    /// SetRelativeTimeoutXXX() functions.
+    ///
+    /// @return
+    ///     If the timeout is INFINITE, then return NULL, otherwise return
+    ///     a pointer to the timespec with the appropriate timeout value.
+    //----------------------------------------------------------------------
+    const struct timespec *
+    GetTimeSpecPtr () const
+    {
+        if (m_infinite)
+            return NULL;
+        return &m_timespec;
+    }
+    
+protected:
+    struct timespec m_timespec;
+    bool m_infinite;
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef utility_TimeSpecTimeout_h_