WIP(dispatcher-isolate): Dispatchers in userspace

Would really help with unit testing

Can currently instatiate (with stubs)
  - ChannelDispatcher
  - EventDispatcher
  - Handle
  - StateTracker

Change-Id: I478374e16682aaecc7b7750c710b83a686fd067c
diff --git a/kernel/object/channel_dispatcher.cpp b/kernel/object/channel_dispatcher.cpp
index 5d4ec58..61a6836 100644
--- a/kernel/object/channel_dispatcher.cpp
+++ b/kernel/object/channel_dispatcher.cpp
@@ -10,14 +10,16 @@
 
 #include <assert.h>
 #include <err.h>
-#include <trace.h>
+//#include <trace.h>
 
 #include <kernel/event.h>
-#include <platform.h>
+//#include <platform.h>
 #include <object/handle.h>
 #include <object/message_packet.h>
+#ifdef _KERNEL
 #include <object/process_dispatcher.h>
 #include <object/thread_dispatcher.h>
+#endif
 
 #include <zircon/rights.h>
 #include <fbl/alloc_checker.h>
@@ -28,6 +30,12 @@
 
 #define LOCAL_TRACE 0
 
+#ifndef _KERNEL
+#define thread_reschedule(args...) ((void)0)
+#undef TA_NO_THREAD_SAFETY_ANALYSIS
+#define TA_NO_THREAD_SAFETY_ANALYSIS /**/
+#endif
+
 // static
 zx_status_t ChannelDispatcher::Create(fbl::RefPtr<Dispatcher>* dispatcher0,
                                       fbl::RefPtr<Dispatcher>* dispatcher1,
@@ -187,11 +195,17 @@
 
     canary_.Assert();
 
+#ifdef _KERNEL
     auto waiter = ThreadDispatcher::GetCurrent()->GetMessageWaiter();
+#else
+    MessageWaiter *waiter = nullptr;
+#endif
     if (unlikely(waiter->BeginWait(fbl::WrapRefPtr(this), msg->get_txid()) != ZX_OK)) {
+#ifdef _KERNEL
         // If a thread tries BeginWait'ing twice, the VDSO contract around retrying
         // channel calls has been violated.  Shoot the misbehaving process.
         ProcessDispatcher::GetCurrent()->Kill();
+#endif
         return ZX_ERR_BAD_STATE;
     }
 
@@ -314,7 +328,7 @@
     if (unlikely(channel_)) {
         channel_->RemoveWaiter(this);
     }
-    DEBUG_ASSERT(!InContainer());
+    ZX_DEBUG_ASSERT(!InContainer());
 }
 
 zx_status_t ChannelDispatcher::MessageWaiter::BeginWait(fbl::RefPtr<ChannelDispatcher> channel,
@@ -322,7 +336,7 @@
     if (unlikely(channel_)) {
         return ZX_ERR_BAD_STATE;
     }
-    DEBUG_ASSERT(!InContainer());
+    ZX_DEBUG_ASSERT(!InContainer());
 
     txid_ = txid;
     status_ = ZX_ERR_TIMED_OUT;
@@ -332,7 +346,7 @@
 }
 
 int ChannelDispatcher::MessageWaiter::Deliver(fbl::unique_ptr<MessagePacket> msg) {
-    DEBUG_ASSERT(channel_);
+    ZX_DEBUG_ASSERT(channel_);
 
     msg_ = fbl::move(msg);
     status_ = ZX_OK;
@@ -340,8 +354,8 @@
 }
 
 int ChannelDispatcher::MessageWaiter::Cancel(zx_status_t status) {
-    DEBUG_ASSERT(!InContainer());
-    DEBUG_ASSERT(channel_);
+    ZX_DEBUG_ASSERT(!InContainer());
+    ZX_DEBUG_ASSERT(channel_);
     status_ = status;
     return event_.Signal(status);
 }
diff --git a/kernel/object/dispatcher.cpp b/kernel/object/dispatcher.cpp
index 58d5f70..172ab3a 100644
--- a/kernel/object/dispatcher.cpp
+++ b/kernel/object/dispatcher.cpp
@@ -6,8 +6,10 @@
 
 #include <object/dispatcher.h>
 
-#include <arch/ops.h>
+//#include <arch/ops.h>
+#if WITH_LIB_KTRACE
 #include <lib/ktrace.h>
+#endif
 #include <fbl/atomic.h>
 #include <object/state_tracker.h>
 
diff --git a/kernel/object/include/object/event_dispatcher.h b/kernel/object/include/object/event_dispatcher.h
index 7cbb6b9..1d2fabb 100644
--- a/kernel/object/include/object/event_dispatcher.h
+++ b/kernel/object/include/object/event_dispatcher.h
@@ -11,8 +11,6 @@
 #include <object/dispatcher.h>
 #include <object/state_tracker.h>
 
-#include <sys/types.h>
-
 class EventDispatcher final : public Dispatcher {
 public:
     static zx_status_t Create(uint32_t options, fbl::RefPtr<Dispatcher>* dispatcher,
diff --git a/kernel/object/include/object/state_tracker.h b/kernel/object/include/object/state_tracker.h
index a9f1d02..b4ce3e8 100644
--- a/kernel/object/include/object/state_tracker.h
+++ b/kernel/object/include/object/state_tracker.h
@@ -8,13 +8,17 @@
 
 #include <stdint.h>
 
-#include <kernel/spinlock.h>
 #include <zircon/types.h>
 #include <fbl/canary.h>
 #include <fbl/intrusive_double_list.h>
 #include <fbl/mutex.h>
 #include <object/state_observer.h>
 
+#undef TA_GUARDED
+#undef TA_REQ
+#define TA_GUARDED(args...) /**/
+#define TA_REQ(args...) /**/
+
 class Handle;
 
 class CookieJar {
diff --git a/kernel/object/state_tracker.cpp b/kernel/object/state_tracker.cpp
index 327bb660..b08a2cc 100644
--- a/kernel/object/state_tracker.cpp
+++ b/kernel/object/state_tracker.cpp
@@ -9,6 +9,12 @@
 #include <fbl/auto_lock.h>
 #include <fbl/mutex.h>
 
+#ifndef _KERNEL
+#include <zircon/assert.h>
+#define DEBUG_ASSERT(args...) ZX_DEBUG_ASSERT(args)
+#define thread_reschedule() ((void)0)
+#endif
+
 using fbl::AutoLock;
 
 namespace {
diff --git a/system/utest/dispatcher-isolate/main.cpp b/system/utest/dispatcher-isolate/main.cpp
new file mode 100644
index 0000000..90f3f74
--- /dev/null
+++ b/system/utest/dispatcher-isolate/main.cpp
@@ -0,0 +1,61 @@
+#include <inttypes.h>
+
+#include <zxcpp/new.h>
+
+#include <object/channel_dispatcher.h>
+#include <object/dispatcher.h>
+#include <object/event_dispatcher.h>
+#include <object/handle.h>
+#include <object/handle_reaper.h>
+#include <object/state_tracker.h>
+
+#include <zircon/types.h>
+
+Handle* MakeHandle(fbl::RefPtr<Dispatcher> dispatcher, zx_rights_t rights) {
+    return new Handle(dispatcher, rights, /*base_value=*/0x55555555);
+}
+
+namespace internal {
+void TearDownHandle(Handle* handle) {
+    delete handle;
+}
+} // namespace internal
+
+void DeleteHandle(Handle* handle) {
+    fbl::RefPtr<Dispatcher> dispatcher(handle->dispatcher());
+    auto state_tracker = dispatcher->get_state_tracker();
+
+    if (state_tracker) {
+        state_tracker->Cancel(handle);
+    }
+
+    internal::TearDownHandle(handle);
+}
+
+void ReapHandles(Handle** handles, uint32_t num_handles) {
+    while (num_handles > 0) {
+        DeleteHandle(*handles++);
+    }
+}
+
+int main(int argc, char** argv) {
+    Handle* h = MakeHandle(nullptr, ZX_RIGHT_READ);
+    StateTracker st(0x5);
+    printf("signals 0x%x\n", st.GetSignalsState());
+    printf("rights 0x%x\n", h->rights());
+
+    fbl::RefPtr<Dispatcher> ev;
+    zx_rights_t evr;
+    EventDispatcher::Create(0u, &ev, &evr);
+    printf("ev koid %" PRIu64 "\n", ev->get_koid());
+
+    fbl::RefPtr<Dispatcher> ch0;
+    fbl::RefPtr<Dispatcher> ch1;
+    zx_rights_t chr;
+    ChannelDispatcher::Create(&ch0, &ch1, &chr);
+    printf("ch0 koid %" PRIu64 ", related %" PRIu64 "\n",
+           ch0->get_koid(), ch0->get_related_koid());
+    printf("ch1 koid %" PRIu64 ", related %" PRIu64 "\n",
+           ch1->get_koid(), ch1->get_related_koid());
+    return 0;
+}
diff --git a/system/utest/dispatcher-isolate/rules.mk b/system/utest/dispatcher-isolate/rules.mk
new file mode 100644
index 0000000..bc8030a
--- /dev/null
+++ b/system/utest/dispatcher-isolate/rules.mk
@@ -0,0 +1,37 @@
+# Copyright 2016 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_TYPE := usertest
+
+MODULE_NAME := dispatcher-isolate-test
+
+MODULE_SRCS += \
+	$(LOCAL_DIR)/main.cpp \
+	kernel/object/dispatcher.cpp \
+	kernel/object/channel_dispatcher.cpp \
+	kernel/object/event_dispatcher.cpp \
+	kernel/object/message_packet.cpp \
+	kernel/object/handle.cpp \
+	kernel/object/state_tracker.cpp
+
+MODULE_LIBS := \
+    system/ulib/unittest \
+    system/ulib/fdio \
+    system/ulib/zircon \
+    system/ulib/c
+
+MODULE_STATIC_LIBS := \
+    system/ulib/zxcpp \
+    system/ulib/fbl
+
+MODULE_COMPILEFLAGS := \
+  -Ikernel/object/include \
+  -Isystem/ulib/fbl/include \
+  -I$(LOCAL_DIR)/stub-include
+
+include make/module.mk
diff --git a/system/utest/dispatcher-isolate/stub-include/kernel/event.h b/system/utest/dispatcher-isolate/stub-include/kernel/event.h
new file mode 100644
index 0000000..162e37c
--- /dev/null
+++ b/system/utest/dispatcher-isolate/stub-include/kernel/event.h
@@ -0,0 +1,39 @@
+// Copyright 2017 The Fuchsia Authors
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#pragma once
+
+#include <zircon/types.h>
+typedef uint64_t lk_time_t;
+
+class Event {
+public:
+    Event(uint32_t opts = 0) {
+    }
+    ~Event() {
+    }
+
+    Event(const Event&) = delete;
+    Event& operator=(const Event&) = delete;
+
+    // Returns:
+    // ZX_OK - signaled
+    // ZX_ERR_TIMED_OUT - time out expired
+    // ZX_ERR_INTERNAL_INTR_KILLED - thread killed
+    // Or the |status| which the caller specified in Event::Signal(status)
+    zx_status_t Wait(lk_time_t deadline) {
+        return ZX_OK;
+    }
+
+    // returns number of ready threads
+    int Signal(zx_status_t status = ZX_OK) {
+        return ZX_OK;
+    }
+
+    zx_status_t Unsignal() {
+        return ZX_OK;
+    }
+};
diff --git a/system/utest/dispatcher-isolate/stub-include/lib/user_copy/user_ptr.h b/system/utest/dispatcher-isolate/stub-include/lib/user_copy/user_ptr.h
new file mode 100644
index 0000000..52716c0
--- /dev/null
+++ b/system/utest/dispatcher-isolate/stub-include/lib/user_copy/user_ptr.h
@@ -0,0 +1,108 @@
+// Copyright 2017 The Fuchsia Authors
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT
+
+#pragma once
+
+#include <string.h>
+#include <fbl/type_support.h>
+#include <zircon/types.h>
+
+namespace internal {
+template <typename T> inline constexpr size_t type_size() { return sizeof(T); }
+template <> inline constexpr size_t type_size<void>() { return 1u; }
+template <> inline constexpr size_t type_size<const void>() { return 1u; }
+template <> inline constexpr size_t type_size<volatile void>() { return 1u; }
+template <> inline constexpr size_t type_size<const volatile void>() { return 1u; }
+}
+
+template <typename T>
+class user_ptr {
+private:
+    static zx_status_t copy_to_user_unsafe(void *dst, const void* src, size_t size) {
+        memcpy(dst, src, size);
+        return ZX_OK;
+    }
+    static zx_status_t copy_from_user_unsafe(void *dst, const void* src, size_t size) {
+        memcpy(dst, src, size);
+        return ZX_OK;
+    }
+public:
+    explicit user_ptr(T* p) : ptr_(p) {}
+
+    T* get() const { return ptr_; }
+
+    template <typename C>
+    user_ptr<C> reinterpret() const { return user_ptr<C>(reinterpret_cast<C*>(ptr_)); }
+
+    // special operator to return the nullness of the pointer
+    explicit operator bool() const { return ptr_ != nullptr; }
+
+    // Returns a user_ptr pointing to the |index|-th element from this one, or a null user_ptr if
+    // this pointer is null. Note: This does no other validation, and the behavior is undefined on
+    // overflow. (Using this will fail to compile if T is |void|.)
+    user_ptr element_offset(size_t index) const {
+        return ptr_ ? user_ptr(ptr_ + index) : user_ptr(nullptr);
+    }
+
+    // Returns a user_ptr offset by |offset| bytes from this one.
+    user_ptr byte_offset(size_t offset) const {
+        return ptr_ ? user_ptr(reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(ptr_) + offset))
+                    : user_ptr(nullptr);
+    }
+
+    // Copies a single T to user memory. (Using this will fail to compile if T is |void|.)
+    // Note: The templatization is simply to allow the class to compile if T is |void|.
+    template <typename S = T>
+    zx_status_t copy_to_user(const S& src) const {
+        static_assert(fbl::is_same<S, T>::value, "Do not use the template parameter.");
+        return copy_to_user_unsafe(ptr_, &src, sizeof(S));
+    }
+
+    // Copies an array of T to user memory. Note: This takes a count not a size, unless T is |void|.
+    // WARNING: This does not check that |count| is reasonable (i.e., that multiplication won't
+    // overflow).
+    zx_status_t copy_array_to_user(const T* src, size_t count) const {
+        return copy_to_user_unsafe(ptr_, src, count * internal::type_size<T>());
+    }
+
+    // Copies an array of T to user memory. Note: This takes a count not a size, unless T is |void|.
+    // WARNING: This does not check that |count| is reasonable (i.e., that multiplication won't
+    // overflow).
+    zx_status_t copy_array_to_user(const T* src, size_t count, size_t offset) const {
+        return copy_to_user_unsafe(ptr_ + offset, src, count * internal::type_size<T>());
+    }
+
+    // Copies a single T from user memory. (Using this will fail to compile if T is |void|.)
+    zx_status_t copy_from_user(typename fbl::remove_const<T>::type* dst) const {
+        // Intentionally use sizeof(T) here, so *using* this method won't compile if T is |void|.
+        return copy_from_user_unsafe(dst, ptr_, sizeof(T));
+    }
+
+    // Copies an array of T from user memory. Note: This takes a count not a size, unless T is
+    // |void|.
+    // WARNING: This does not check that |count| is reasonable (i.e., that multiplication won't
+    // overflow).
+    zx_status_t copy_array_from_user(typename fbl::remove_const<T>::type* dst, size_t count) const {
+        return copy_from_user_unsafe(dst, ptr_, count * internal::type_size<T>());
+    }
+
+    // Copies a sub-array of T from user memory. Note: This takes a count not a size, unless T is
+    // |void|.
+    // WARNING: This does not check that |count| is reasonable (i.e., that multiplication won't
+    // overflow).
+    zx_status_t copy_array_from_user(typename fbl::remove_const<T>::type* dst, size_t count, size_t offset) const {
+        return copy_from_user_unsafe(dst, ptr_ + offset, count * internal::type_size<T>());
+    }
+
+private:
+    // It is very important that this class only wrap the pointer type itself
+    // and not include any other members so as not to break the ABI between
+    // the kernel and user space.
+    T* const ptr_;
+};
+
+template <typename T>
+user_ptr<T> make_user_ptr(T* p) { return user_ptr<T>(p); }