Comparar commits
2 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 0f4eeea3cb | |||
| d8a86a5a0e |
@@ -10,16 +10,18 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <trace.h>
|
||||
//#include <trace.h>
|
||||
|
||||
#include <kernel/event.h>
|
||||
#include <platform.h>
|
||||
//#include <platform.h>
|
||||
|
||||
#include <magenta/handle.h>
|
||||
#include <magenta/message_packet.h>
|
||||
#ifdef _KERNEL
|
||||
#include <magenta/process_dispatcher.h>
|
||||
#include <magenta/rights.h>
|
||||
#include <magenta/thread_dispatcher.h>
|
||||
#endif
|
||||
#include <magenta/rights.h>
|
||||
|
||||
#include <mxtl/alloc_checker.h>
|
||||
#include <mxtl/auto_lock.h>
|
||||
@@ -29,8 +31,14 @@ using mxtl::AutoLock;
|
||||
|
||||
#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
|
||||
status_t ChannelDispatcher::Create(uint32_t flags,
|
||||
mx_status_t ChannelDispatcher::Create(uint32_t flags,
|
||||
mxtl::RefPtr<Dispatcher>* dispatcher0,
|
||||
mxtl::RefPtr<Dispatcher>* dispatcher1,
|
||||
mx_rights_t* rights) {
|
||||
@@ -54,7 +62,7 @@ status_t ChannelDispatcher::Create(uint32_t flags,
|
||||
|
||||
ChannelDispatcher::ChannelDispatcher(uint32_t flags)
|
||||
: state_tracker_(MX_CHANNEL_WRITABLE) {
|
||||
DEBUG_ASSERT(flags == 0);
|
||||
MX_DEBUG_ASSERT(flags == 0);
|
||||
}
|
||||
|
||||
// This is called before either ChannelDispatcher is accessible from threads other than the one
|
||||
@@ -132,7 +140,7 @@ void ChannelDispatcher::OnPeerZeroHandles() {
|
||||
}
|
||||
}
|
||||
|
||||
status_t ChannelDispatcher::Read(uint32_t* msg_size,
|
||||
mx_status_t ChannelDispatcher::Read(uint32_t* msg_size,
|
||||
uint32_t* msg_handle_count,
|
||||
mxtl::unique_ptr<MessagePacket>* msg,
|
||||
bool may_discard) {
|
||||
@@ -148,7 +156,7 @@ status_t ChannelDispatcher::Read(uint32_t* msg_size,
|
||||
|
||||
*msg_size = messages_.front().data_size();
|
||||
*msg_handle_count = messages_.front().num_handles();
|
||||
status_t rv = MX_OK;
|
||||
mx_status_t rv = MX_OK;
|
||||
if (*msg_size > max_size || *msg_handle_count > max_handle_count) {
|
||||
if (!may_discard)
|
||||
return MX_ERR_BUFFER_TOO_SMALL;
|
||||
@@ -163,7 +171,7 @@ status_t ChannelDispatcher::Read(uint32_t* msg_size,
|
||||
return rv;
|
||||
}
|
||||
|
||||
status_t ChannelDispatcher::Write(mxtl::unique_ptr<MessagePacket> msg) {
|
||||
mx_status_t ChannelDispatcher::Write(mxtl::unique_ptr<MessagePacket> msg) {
|
||||
canary_.Assert();
|
||||
|
||||
mxtl::RefPtr<ChannelDispatcher> other;
|
||||
@@ -184,17 +192,23 @@ status_t ChannelDispatcher::Write(mxtl::unique_ptr<MessagePacket> msg) {
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
status_t ChannelDispatcher::Call(mxtl::unique_ptr<MessagePacket> msg,
|
||||
mx_status_t ChannelDispatcher::Call(mxtl::unique_ptr<MessagePacket> msg,
|
||||
mx_time_t deadline, bool* return_handles,
|
||||
mxtl::unique_ptr<MessagePacket>* reply) {
|
||||
|
||||
canary_.Assert();
|
||||
|
||||
#ifdef _KERNEL
|
||||
auto waiter = ThreadDispatcher::GetCurrent()->GetMessageWaiter();
|
||||
#else
|
||||
MessageWaiter *waiter = nullptr;
|
||||
#endif
|
||||
if (unlikely(waiter->BeginWait(mxtl::WrapRefPtr(this), msg->get_txid()) != MX_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 MX_ERR_BAD_STATE;
|
||||
}
|
||||
|
||||
@@ -224,7 +238,7 @@ status_t ChannelDispatcher::Call(mxtl::unique_ptr<MessagePacket> msg,
|
||||
return ResumeInterruptedCall(waiter, deadline, reply);
|
||||
}
|
||||
|
||||
status_t ChannelDispatcher::ResumeInterruptedCall(MessageWaiter* waiter,
|
||||
mx_status_t ChannelDispatcher::ResumeInterruptedCall(MessageWaiter* waiter,
|
||||
mx_time_t deadline,
|
||||
mxtl::unique_ptr<MessagePacket>* reply) {
|
||||
canary_.Assert();
|
||||
@@ -285,7 +299,7 @@ int ChannelDispatcher::WriteSelf(mxtl::unique_ptr<MessagePacket> msg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t ChannelDispatcher::user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) {
|
||||
mx_status_t ChannelDispatcher::user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) {
|
||||
canary_.Assert();
|
||||
|
||||
if ((set_mask & ~MX_USER_SIGNAL_ALL) || (clear_mask & ~MX_USER_SIGNAL_ALL))
|
||||
@@ -307,7 +321,7 @@ status_t ChannelDispatcher::user_signal(uint32_t clear_mask, uint32_t set_mask,
|
||||
return other->UserSignalSelf(clear_mask, set_mask);
|
||||
}
|
||||
|
||||
status_t ChannelDispatcher::UserSignalSelf(uint32_t clear_mask, uint32_t set_mask) {
|
||||
mx_status_t ChannelDispatcher::UserSignalSelf(uint32_t clear_mask, uint32_t set_mask) {
|
||||
canary_.Assert();
|
||||
state_tracker_.UpdateState(clear_mask, set_mask);
|
||||
return MX_OK;
|
||||
@@ -317,7 +331,7 @@ ChannelDispatcher::MessageWaiter::~MessageWaiter() {
|
||||
if (unlikely(channel_)) {
|
||||
channel_->RemoveWaiter(this);
|
||||
}
|
||||
DEBUG_ASSERT(!InContainer());
|
||||
MX_DEBUG_ASSERT(!InContainer());
|
||||
}
|
||||
|
||||
mx_status_t ChannelDispatcher::MessageWaiter::BeginWait(mxtl::RefPtr<ChannelDispatcher> channel,
|
||||
@@ -325,7 +339,7 @@ mx_status_t ChannelDispatcher::MessageWaiter::BeginWait(mxtl::RefPtr<ChannelDisp
|
||||
if (unlikely(channel_)) {
|
||||
return MX_ERR_BAD_STATE;
|
||||
}
|
||||
DEBUG_ASSERT(!InContainer());
|
||||
MX_DEBUG_ASSERT(!InContainer());
|
||||
|
||||
txid_ = txid;
|
||||
status_ = MX_ERR_TIMED_OUT;
|
||||
@@ -335,16 +349,16 @@ mx_status_t ChannelDispatcher::MessageWaiter::BeginWait(mxtl::RefPtr<ChannelDisp
|
||||
}
|
||||
|
||||
int ChannelDispatcher::MessageWaiter::Deliver(mxtl::unique_ptr<MessagePacket> msg) {
|
||||
DEBUG_ASSERT(channel_);
|
||||
MX_DEBUG_ASSERT(channel_);
|
||||
|
||||
msg_ = mxtl::move(msg);
|
||||
status_ = MX_OK;
|
||||
return event_.Signal(MX_OK);
|
||||
}
|
||||
|
||||
int ChannelDispatcher::MessageWaiter::Cancel(status_t status) {
|
||||
DEBUG_ASSERT(!InContainer());
|
||||
DEBUG_ASSERT(channel_);
|
||||
int ChannelDispatcher::MessageWaiter::Cancel(mx_status_t status) {
|
||||
MX_DEBUG_ASSERT(!InContainer());
|
||||
MX_DEBUG_ASSERT(channel_);
|
||||
status_ = status;
|
||||
return event_.Signal(status);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
#include <magenta/dispatcher.h>
|
||||
#include <magenta/state_tracker.h>
|
||||
|
||||
#include <arch/ops.h>
|
||||
//#include <arch/ops.h>
|
||||
#if WITH_LIB_KTRACE
|
||||
#include <lib/ktrace.h>
|
||||
#endif
|
||||
#include <mxtl/atomic.h>
|
||||
|
||||
// The first 1K koids are reserved.
|
||||
@@ -29,7 +31,7 @@ Dispatcher::~Dispatcher() {
|
||||
#endif
|
||||
}
|
||||
|
||||
status_t Dispatcher::add_observer(StateObserver* observer) {
|
||||
mx_status_t Dispatcher::add_observer(StateObserver* observer) {
|
||||
auto state_tracker = get_state_tracker();
|
||||
if (!state_tracker)
|
||||
return MX_ERR_NOT_SUPPORTED;
|
||||
@@ -37,7 +39,7 @@ status_t Dispatcher::add_observer(StateObserver* observer) {
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
status_t Dispatcher::user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) {
|
||||
mx_status_t Dispatcher::user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) {
|
||||
if (peer)
|
||||
return MX_ERR_NOT_SUPPORTED;
|
||||
|
||||
@@ -53,4 +55,3 @@ status_t Dispatcher::user_signal(uint32_t clear_mask, uint32_t set_mask, bool pe
|
||||
state_tracker->UpdateState(clear_mask, set_mask);
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
constexpr uint32_t kUserSignalMask = MX_EVENT_SIGNALED | MX_USER_SIGNAL_ALL;
|
||||
|
||||
status_t EventDispatcher::Create(uint32_t options, mxtl::RefPtr<Dispatcher>* dispatcher,
|
||||
mx_status_t EventDispatcher::Create(uint32_t options, mxtl::RefPtr<Dispatcher>* dispatcher,
|
||||
mx_rights_t* rights) {
|
||||
mxtl::AllocChecker ac;
|
||||
auto disp = new (&ac) EventDispatcher(options);
|
||||
@@ -31,7 +31,7 @@ EventDispatcher::EventDispatcher(uint32_t options)
|
||||
|
||||
EventDispatcher::~EventDispatcher() {}
|
||||
|
||||
status_t EventDispatcher::user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) {
|
||||
mx_status_t EventDispatcher::user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) {
|
||||
canary_.Assert();
|
||||
|
||||
if (peer)
|
||||
|
||||
@@ -25,15 +25,15 @@ class ChannelDispatcher final : public Dispatcher {
|
||||
public:
|
||||
class MessageWaiter;
|
||||
|
||||
static status_t Create(uint32_t flags, mxtl::RefPtr<Dispatcher>* dispatcher0,
|
||||
mxtl::RefPtr<Dispatcher>* dispatcher1, mx_rights_t* rights);
|
||||
static mx_status_t Create(uint32_t flags, mxtl::RefPtr<Dispatcher>* dispatcher0,
|
||||
mxtl::RefPtr<Dispatcher>* dispatcher1, mx_rights_t* rights);
|
||||
|
||||
~ChannelDispatcher() final;
|
||||
mx_obj_type_t get_type() const final { return MX_OBJ_TYPE_CHANNEL; }
|
||||
StateTracker* get_state_tracker() final { return &state_tracker_; }
|
||||
mx_status_t add_observer(StateObserver* observer) final;
|
||||
mx_koid_t get_related_koid() const final TA_REQ(lock_) { return other_koid_; }
|
||||
status_t user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) final;
|
||||
mx_status_t user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) final;
|
||||
|
||||
void on_zero_handles() final;
|
||||
|
||||
@@ -42,21 +42,21 @@ public:
|
||||
// size and handle count, respectively. On MX_OK or MX_ERR_BUFFER_TOO_SMALL, they specify the
|
||||
// actual size and handle count of the next message. The next message is returned in |*msg| on
|
||||
// MX_OK and also on MX_ERR_BUFFER_TOO_SMALL when |may_discard| is set.
|
||||
status_t Read(uint32_t* msg_size,
|
||||
uint32_t* msg_handle_count,
|
||||
mxtl::unique_ptr<MessagePacket>* msg,
|
||||
bool may_disard);
|
||||
mx_status_t Read(uint32_t* msg_size,
|
||||
uint32_t* msg_handle_count,
|
||||
mxtl::unique_ptr<MessagePacket>* msg,
|
||||
bool may_disard);
|
||||
|
||||
// Write to the opposing endpoint's message queue.
|
||||
status_t Write(mxtl::unique_ptr<MessagePacket> msg);
|
||||
status_t Call(mxtl::unique_ptr<MessagePacket> msg,
|
||||
mx_time_t deadline, bool* return_handles,
|
||||
mxtl::unique_ptr<MessagePacket>* reply);
|
||||
mx_status_t Write(mxtl::unique_ptr<MessagePacket> msg);
|
||||
mx_status_t Call(mxtl::unique_ptr<MessagePacket> msg,
|
||||
mx_time_t deadline, bool* return_handles,
|
||||
mxtl::unique_ptr<MessagePacket>* reply);
|
||||
|
||||
// Performs the wait-then-read half of Call. This is meant for retrying
|
||||
// after an interruption caused by suspending.
|
||||
status_t ResumeInterruptedCall(MessageWaiter* waiter, mx_time_t deadline,
|
||||
mxtl::unique_ptr<MessagePacket>* reply);
|
||||
mx_status_t ResumeInterruptedCall(MessageWaiter* waiter, mx_time_t deadline,
|
||||
mxtl::unique_ptr<MessagePacket>* reply);
|
||||
|
||||
// MessageWaiter's state is guarded by the lock of the
|
||||
// owning ChannelDispatcher, and Deliver(), Signal(), Cancel(),
|
||||
@@ -70,14 +70,15 @@ public:
|
||||
// See also: comments in ChannelDispatcher::Call()
|
||||
class MessageWaiter : public mxtl::DoublyLinkedListable<MessageWaiter*> {
|
||||
public:
|
||||
MessageWaiter() : txid_(0), status_(MX_ERR_BAD_STATE) {
|
||||
MessageWaiter()
|
||||
: txid_(0), status_(MX_ERR_BAD_STATE) {
|
||||
}
|
||||
|
||||
~MessageWaiter();
|
||||
|
||||
mx_status_t BeginWait(mxtl::RefPtr<ChannelDispatcher> channel, mx_txid_t txid);
|
||||
int Deliver(mxtl::unique_ptr<MessagePacket> msg);
|
||||
int Cancel(status_t status);
|
||||
int Cancel(mx_status_t status);
|
||||
mxtl::RefPtr<ChannelDispatcher> get_channel() { return channel_; }
|
||||
mx_txid_t get_txid() const { return txid_; }
|
||||
mx_status_t Wait(lk_time_t deadline);
|
||||
@@ -103,7 +104,7 @@ private:
|
||||
ChannelDispatcher(uint32_t flags);
|
||||
void Init(mxtl::RefPtr<ChannelDispatcher> other);
|
||||
int WriteSelf(mxtl::unique_ptr<MessagePacket> msg);
|
||||
status_t UserSignalSelf(uint32_t clear_mask, uint32_t set_mask);
|
||||
mx_status_t UserSignalSelf(uint32_t clear_mask, uint32_t set_mask);
|
||||
void OnPeerZeroHandles();
|
||||
|
||||
mxtl::Canary<mxtl::magic("CHAN")> canary_;
|
||||
|
||||
@@ -67,9 +67,9 @@ public:
|
||||
|
||||
virtual StateTracker* get_state_tracker() { return nullptr; }
|
||||
|
||||
virtual status_t add_observer(StateObserver* observer);
|
||||
virtual mx_status_t add_observer(StateObserver* observer);
|
||||
|
||||
virtual status_t user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer);
|
||||
virtual mx_status_t user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer);
|
||||
|
||||
virtual void on_zero_handles() { }
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
|
||||
// set_name() will truncate to MX_MAX_NAME_LEN - 1 and ensure there is a
|
||||
// terminating null
|
||||
virtual status_t set_name(const char* name, size_t len) { return MX_ERR_NOT_SUPPORTED; }
|
||||
virtual mx_status_t set_name(const char* name, size_t len) { return MX_ERR_NOT_SUPPORTED; }
|
||||
|
||||
// Dispatchers that support get/set cookie must provide
|
||||
// a CookieJar for those cookies to be stored in.
|
||||
|
||||
@@ -6,22 +6,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <magenta/types.h>
|
||||
#include <magenta/dispatcher.h>
|
||||
#include <magenta/state_tracker.h>
|
||||
#include <mxtl/canary.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
class EventDispatcher final : public Dispatcher {
|
||||
public:
|
||||
static status_t Create(uint32_t options, mxtl::RefPtr<Dispatcher>* dispatcher,
|
||||
static mx_status_t Create(uint32_t options, mxtl::RefPtr<Dispatcher>* dispatcher,
|
||||
mx_rights_t* rights);
|
||||
|
||||
~EventDispatcher() final;
|
||||
mx_obj_type_t get_type() const final { return MX_OBJ_TYPE_EVENT; }
|
||||
StateTracker* get_state_tracker() final { return &state_tracker_; }
|
||||
CookieJar* get_cookie_jar() final { return &cookie_jar_; }
|
||||
status_t user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) final;
|
||||
mx_status_t user_signal(uint32_t clear_mask, uint32_t set_mask, bool peer) final;
|
||||
|
||||
private:
|
||||
explicit EventDispatcher(uint32_t options);
|
||||
|
||||
@@ -8,13 +8,17 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <kernel/spinlock.h>
|
||||
#include <magenta/state_observer.h>
|
||||
#include <magenta/types.h>
|
||||
#include <mxtl/canary.h>
|
||||
#include <mxtl/intrusive_double_list.h>
|
||||
#include <mxtl/mutex.h>
|
||||
|
||||
#undef TA_GUARDED
|
||||
#undef TA_REQ
|
||||
#define TA_GUARDED(args...) /**/
|
||||
#define TA_REQ(args...) /**/
|
||||
|
||||
class Handle;
|
||||
|
||||
class CookieJar {
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
#include <mxtl/auto_lock.h>
|
||||
#include <mxtl/mutex.h>
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <magenta/assert.h>
|
||||
#define DEBUG_ASSERT(args...) MX_DEBUG_ASSERT(args)
|
||||
#define thread_reschedule() ((void)0)
|
||||
#endif
|
||||
|
||||
using mxtl::AutoLock;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <mxcpp/new.h>
|
||||
|
||||
// kernel/lib/magenta
|
||||
#include <magenta/channel_dispatcher.h>
|
||||
#include <magenta/dispatcher.h>
|
||||
#include <magenta/event_dispatcher.h>
|
||||
#include <magenta/handle.h>
|
||||
#include <magenta/handle_reaper.h>
|
||||
#include <magenta/state_tracker.h>
|
||||
|
||||
// system/public/magenta
|
||||
#include <magenta/types.h>
|
||||
|
||||
Handle* MakeHandle(mxtl::RefPtr<Dispatcher> dispatcher, mx_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) {
|
||||
mxtl::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, MX_RIGHT_READ);
|
||||
StateTracker st(0x5);
|
||||
printf("signals 0x%x\n", st.GetSignalsState());
|
||||
printf("rights 0x%x\n", h->rights());
|
||||
|
||||
mxtl::RefPtr<Dispatcher> ev;
|
||||
mx_rights_t evr;
|
||||
EventDispatcher::Create(0u, &ev, &evr);
|
||||
printf("ev koid %" PRIu64 "\n", ev->get_koid());
|
||||
|
||||
mxtl::RefPtr<Dispatcher> ch0;
|
||||
mxtl::RefPtr<Dispatcher> ch1;
|
||||
mx_rights_t chr;
|
||||
ChannelDispatcher::Create(0u, &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;
|
||||
}
|
||||
@@ -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 := magenta-isolate-test
|
||||
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/main.cpp \
|
||||
kernel/lib/magenta/dispatcher.cpp \
|
||||
kernel/lib/magenta/channel_dispatcher.cpp \
|
||||
kernel/lib/magenta/event_dispatcher.cpp \
|
||||
kernel/lib/magenta/message_packet.cpp \
|
||||
kernel/lib/magenta/handle.cpp \
|
||||
kernel/lib/magenta/state_tracker.cpp
|
||||
|
||||
MODULE_LIBS := \
|
||||
system/ulib/unittest \
|
||||
system/ulib/mxio \
|
||||
system/ulib/magenta \
|
||||
system/ulib/c
|
||||
|
||||
MODULE_STATIC_LIBS := \
|
||||
system/ulib/mxcpp \
|
||||
system/ulib/mxtl
|
||||
|
||||
MODULE_COMPILEFLAGS := \
|
||||
-Ikernel/lib/magenta/include \
|
||||
-Isystem/ulib/mxtl/include \
|
||||
-I$(LOCAL_DIR)/stub-include
|
||||
|
||||
include make/module.mk
|
||||
@@ -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 <magenta/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:
|
||||
// MX_OK - signaled
|
||||
// MX_ERR_TIMED_OUT - time out expired
|
||||
// MX_ERR_INTERNAL_INTR_KILLED - thread killed
|
||||
// Or the |status| which the caller specified in Event::Signal(status)
|
||||
mx_status_t Wait(lk_time_t deadline) {
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
// returns number of ready threads
|
||||
int Signal(mx_status_t status = MX_OK) {
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
mx_status_t Unsignal() {
|
||||
return MX_OK;
|
||||
}
|
||||
};
|
||||
@@ -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 <mxtl/type_support.h>
|
||||
#include <magenta/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 mx_status_t copy_to_user_unsafe(void *dst, const void* src, size_t size) {
|
||||
memcpy(dst, src, size);
|
||||
return MX_OK;
|
||||
}
|
||||
static mx_status_t copy_from_user_unsafe(void *dst, const void* src, size_t size) {
|
||||
memcpy(dst, src, size);
|
||||
return MX_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>
|
||||
mx_status_t copy_to_user(const S& src) const {
|
||||
static_assert(mxtl::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).
|
||||
mx_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).
|
||||
mx_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|.)
|
||||
mx_status_t copy_from_user(typename mxtl::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).
|
||||
mx_status_t copy_array_from_user(typename mxtl::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).
|
||||
mx_status_t copy_array_from_user(typename mxtl::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); }
|
||||
Referência em uma Nova Issue
Bloquear um usuário