// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/edk/system/core.h"

#include <memory>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "mojo/edk/embedder/platform_support.h"
#include "mojo/edk/platform/platform_shared_buffer.h"
#include "mojo/edk/platform/time_ticks.h"
#include "mojo/edk/system/async_waiter.h"
#include "mojo/edk/system/configuration.h"
#include "mojo/edk/system/data_pipe.h"
#include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
#include "mojo/edk/system/data_pipe_producer_dispatcher.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/handle_signals_state.h"
#include "mojo/edk/system/handle_transport.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "mojo/edk/system/shared_buffer_dispatcher.h"
#include "mojo/edk/system/waiter.h"
#include "mojo/public/c/system/macros.h"
#include "mojo/public/cpp/system/macros.h"

using mojo::platform::GetTimeTicks;
using mojo::platform::PlatformSharedBufferMapping;
using mojo::util::MutexLocker;
using mojo::util::RefPtr;

namespace mojo {
namespace system {

// Implementation notes
//
// Mojo primitives are implemented by the singleton |Core| object. Most calls
// are for a "primary" handle (the first argument). |Core::GetHandle()| is used
// to look up a |Handle| (in particular, a |Dispatcher| object) for a given
// handle value. The |Dispatcher| object implements most primitives for that
// (conceptual/logical) object. The wait primitives are not attached to objects
// and are implemented by |Core| itself.
//
// Some objects have multiple handles associated to them, e.g., message pipes
// (which have two). In such a case, there is still a |Dispatcher| (e.g.,
// |MessagePipeDispatcher|) for each handle, with each handle having a strong
// reference to the common "secondary" object (e.g., |MessagePipe|). This
// secondary object does NOT have any references to the |Dispatcher|s (even if
// it did, it wouldn't be able to do anything with them due to lock order
// requirements -- see below).
//
// Waiting is implemented by having the thread that wants to wait call the
// |Dispatcher|s for the handles that it wants to wait on with a |Waiter|
// object; this |Waiter| object may be created on the stack of that thread or be
// kept in thread local storage for that thread (TODO(vtl): future improvement).
// The |Dispatcher| then adds the |Waiter| to an |AwakableList| that's either
// owned by that |Dispatcher| (see |SimpleDispatcher|) or by a secondary object
// (e.g., |MessagePipe|). To signal/wake a |Waiter|, the object in question --
// either a |SimpleDispatcher| or a secondary object -- talks to its
// |AwakableList|.

// Thread-safety notes
//
// Mojo primitives calls are thread-safe. We achieve this with relatively
// fine-grained locking. There is a global handle table lock. This lock should
// be held as briefly as possible (TODO(vtl): a future improvement would be to
// switch it to a reader-writer lock). Each |Dispatcher| object then has a lock
// (which subclasses can use to protect their data).
//
// The lock ordering is as follows:
//   1. global handle table lock, global mapping table lock
//   2. |Dispatcher| locks
//   3. secondary object locks
//   ...
//   INF. |Waiter| locks
//
// Notes:
//    - While holding a |Dispatcher| lock, you may not unconditionally attempt
//      to take another |Dispatcher| lock. (This has consequences on the
//      concurrency semantics of |MojoWriteMessage()| when passing handles.)
//      Doing so would lead to deadlock.
//    - Locks at the "INF" level may not have any locks taken while they are
//      held.

Core::Core(embedder::PlatformSupport* platform_support)
    : platform_support_(platform_support),
      handle_table_(GetConfiguration().max_handle_table_size) {}

Core::~Core() {}

MojoHandle Core::AddHandle(Handle&& handle) {
  MutexLocker locker(&handle_table_mutex_);
  return handle_table_.AddHandle(std::move(handle));
}

MojoResult Core::GetHandle(MojoHandle handle, Handle* h) {
  if (handle == MOJO_HANDLE_INVALID)
    return MOJO_RESULT_INVALID_ARGUMENT;

  MutexLocker locker(&handle_table_mutex_);
  return handle_table_.GetHandle(handle, h);
}

MojoResult Core::GetAndRemoveHandle(MojoHandle handle, Handle* h) {
  if (handle == MOJO_HANDLE_INVALID)
    return MOJO_RESULT_INVALID_ARGUMENT;

  MutexLocker locker(&handle_table_mutex_);
  return handle_table_.GetAndRemoveHandle(handle, h);
}

MojoResult Core::GetDispatcherAndCheckRights(
    MojoHandle handle,
    MojoHandleRights required_handle_rights,
    EntrypointClass entrypoint_class,
    util::RefPtr<Dispatcher>* dispatcher) {
  if (handle == MOJO_HANDLE_INVALID)
    return MOJO_RESULT_INVALID_ARGUMENT;

  Handle h;
  MojoResult result = GetHandle(handle, &h);
  if (result != MOJO_RESULT_OK)
    return result;

  if (!h.has_all_rights(required_handle_rights)) {
    return h.dispatcher->SupportsEntrypointClass(entrypoint_class)
               ? MOJO_RESULT_PERMISSION_DENIED
               : MOJO_RESULT_INVALID_ARGUMENT;
  }

  *dispatcher = std::move(h.dispatcher);
  return MOJO_RESULT_OK;
}

MojoResult Core::AsyncWait(MojoHandle handle,
                           MojoHandleSignals signals,
                           const std::function<void(MojoResult)>& callback) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      handle, MOJO_HANDLE_RIGHT_NONE, EntrypointClass::NONE, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  std::unique_ptr<AsyncWaiter> waiter(new AsyncWaiter(callback));
  result = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr);
  if (result == MOJO_RESULT_OK)
    ignore_result(waiter.release());
  return result;
}

MojoTimeTicks Core::GetTimeTicksNow() {
  return GetTimeTicks();
}

MojoResult Core::Close(MojoHandle handle) {
  if (handle == MOJO_HANDLE_INVALID)
    return MOJO_RESULT_INVALID_ARGUMENT;

  Handle h;
  {
    MutexLocker locker(&handle_table_mutex_);
    MojoResult result = handle_table_.GetAndRemoveHandle(handle, &h);
    if (result != MOJO_RESULT_OK)
      return result;
  }

  // The dispatcher doesn't have a say in being closed, but gets notified of it.
  // Note: This is done outside of |handle_table_mutex_|. As a result, there's a
  // race condition that the dispatcher must handle; see the comment in
  // |Dispatcher| in dispatcher.h.
  return h.dispatcher->Close();
}

MojoResult Core::GetRights(MojoHandle handle,
                           UserPointer<MojoHandleRights> rights) {
  Handle h;
  MojoResult result = GetHandle(handle, &h);
  if (result != MOJO_RESULT_OK)
    return result;

  rights.Put(h.rights);
  return MOJO_RESULT_OK;
}

MojoResult Core::Wait(MojoHandle handle,
                      MojoHandleSignals signals,
                      MojoDeadline deadline,
                      UserPointer<MojoHandleSignalsState> signals_state) {
  uint32_t unused = static_cast<uint32_t>(-1);
  HandleSignalsState hss;
  MojoResult result = WaitManyInternal(&handle, &signals, 1, deadline, &unused,
                                       signals_state.IsNull() ? nullptr : &hss);
  if (result != MOJO_RESULT_INVALID_ARGUMENT && !signals_state.IsNull())
    signals_state.Put(hss);
  return result;
}

MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles,
                          UserPointer<const MojoHandleSignals> signals,
                          uint32_t num_handles,
                          MojoDeadline deadline,
                          UserPointer<uint32_t> result_index,
                          UserPointer<MojoHandleSignalsState> signals_states) {
  if (num_handles < 1)
    return MOJO_RESULT_INVALID_ARGUMENT;
  if (num_handles > GetConfiguration().max_wait_many_num_handles)
    return MOJO_RESULT_RESOURCE_EXHAUSTED;

  UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles);
  UserPointer<const MojoHandleSignals>::Reader signals_reader(signals,
                                                              num_handles);
  uint32_t index = static_cast<uint32_t>(-1);
  MojoResult result;
  if (signals_states.IsNull()) {
    result = WaitManyInternal(handles_reader.GetPointer(),
                              signals_reader.GetPointer(), num_handles,
                              deadline, &index, nullptr);
  } else {
    UserPointer<MojoHandleSignalsState>::Writer signals_states_writer(
        signals_states, num_handles);
    // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a
    // subclass of |MojoHandleSignalsState| that doesn't add any data members.
    result = WaitManyInternal(
        handles_reader.GetPointer(), signals_reader.GetPointer(), num_handles,
        deadline, &index, reinterpret_cast<HandleSignalsState*>(
                              signals_states_writer.GetPointer()));
    if (result != MOJO_RESULT_INVALID_ARGUMENT)
      signals_states_writer.Commit();
  }
  if (index != static_cast<uint32_t>(-1) && !result_index.IsNull())
    result_index.Put(index);
  return result;
}

MojoResult Core::CreateMessagePipe(
    UserPointer<const MojoCreateMessagePipeOptions> options,
    UserPointer<MojoHandle> message_pipe_handle0,
    UserPointer<MojoHandle> message_pipe_handle1) {
  MojoCreateMessagePipeOptions validated_options = {};
  MojoResult result =
      MessagePipeDispatcher::ValidateCreateOptions(options, &validated_options);
  if (result != MOJO_RESULT_OK)
    return result;

  auto dispatcher0 = MessagePipeDispatcher::Create(validated_options);
  auto dispatcher1 = MessagePipeDispatcher::Create(validated_options);

  std::pair<MojoHandle, MojoHandle> handle_pair;
  {
    MutexLocker locker(&handle_table_mutex_);
    handle_pair = handle_table_.AddHandlePair(
        Handle(dispatcher0.Clone(),
               MessagePipeDispatcher::kDefaultHandleRights),
        Handle(dispatcher1.Clone(),
               MessagePipeDispatcher::kDefaultHandleRights));
  }
  if (handle_pair.first == MOJO_HANDLE_INVALID) {
    DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID);
    LOG(ERROR) << "Handle table full";
    dispatcher0->Close();
    dispatcher1->Close();
    return MOJO_RESULT_RESOURCE_EXHAUSTED;
  }

  auto message_pipe = MessagePipe::CreateLocalLocal();
  dispatcher0->Init(message_pipe.Clone(), 0);
  dispatcher1->Init(std::move(message_pipe), 1);

  message_pipe_handle0.Put(handle_pair.first);
  message_pipe_handle1.Put(handle_pair.second);
  return MOJO_RESULT_OK;
}

// Implementation note: To properly cancel waiters and avoid other races, this
// does not transfer dispatchers from one handle to another, even when sending a
// message in-process. Instead, it must transfer the "contents" of the
// dispatcher to a new dispatcher, and then close the old dispatcher. If this
// isn't done, in the in-process case, calls on the old handle may complete
// after the the message has been received and a new handle created (and
// possibly even after calls have been made on the new handle).
MojoResult Core::WriteMessage(MojoHandle message_pipe_handle,
                              UserPointer<const void> bytes,
                              uint32_t num_bytes,
                              UserPointer<const MojoHandle> handles,
                              uint32_t num_handles,
                              MojoWriteMessageFlags flags) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result =
      GetDispatcherAndCheckRights(message_pipe_handle, MOJO_HANDLE_RIGHT_WRITE,
                                  EntrypointClass::MESSAGE_PIPE, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  // Easy case: not sending any handles.
  if (num_handles == 0)
    return dispatcher->WriteMessage(bytes, num_bytes, nullptr, flags);

  // We have to handle |handles| here, since we have to mark them busy in the
  // global handle table. We can't delegate this to the dispatcher, since the
  // handle table lock must be acquired before the dispatcher lock.
  //
  // (This leads to an oddity: |handles|/|num_handles| are always verified for
  // validity, even for dispatchers that don't support |WriteMessage()| and will
  // simply return failure unconditionally. It also breaks the usual
  // left-to-right verification order of arguments.)
  if (num_handles > GetConfiguration().max_message_num_handles)
    return MOJO_RESULT_RESOURCE_EXHAUSTED;

  UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles);

  // We'll need to hold on to the dispatchers so that we can pass them on to
  // |WriteMessage()| and also so that we can unlock their locks afterwards
  // without accessing the handle table. These can be dumb pointers, since their
  // entries in the handle table won't get removed (since they'll be marked as
  // busy).
  std::vector<HandleTransport> transports(num_handles);

  // When we pass handles, we have to try to take all their dispatchers' locks
  // and mark the handles as busy. If the call succeeds, we then remove the
  // handles from the handle table.
  {
    MutexLocker locker(&handle_table_mutex_);
    MojoResult result = handle_table_.MarkBusyAndStartTransport(
        message_pipe_handle, handles_reader.GetPointer(), num_handles,
        &transports);
    if (result != MOJO_RESULT_OK)
      return result;
  }

  result = dispatcher->WriteMessage(bytes, num_bytes, &transports, flags);

  // We need to release the dispatcher locks before we take the handle table
  // lock.
  for (uint32_t i = 0; i < num_handles; i++)
    transports[i].End();

  {
    MutexLocker locker(&handle_table_mutex_);
    if (result == MOJO_RESULT_OK) {
      handle_table_.RemoveBusyHandles(handles_reader.GetPointer(), num_handles);
    } else {
      handle_table_.RestoreBusyHandles(handles_reader.GetPointer(),
                                       num_handles);
    }
  }

  return result;
}

MojoResult Core::ReadMessage(MojoHandle message_pipe_handle,
                             UserPointer<void> bytes,
                             UserPointer<uint32_t> num_bytes,
                             UserPointer<MojoHandle> handles,
                             UserPointer<uint32_t> num_handles,
                             MojoReadMessageFlags flags) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result =
      GetDispatcherAndCheckRights(message_pipe_handle, MOJO_HANDLE_RIGHT_READ,
                                  EntrypointClass::MESSAGE_PIPE, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  uint32_t num_handles_value = num_handles.IsNull() ? 0 : num_handles.Get();

  if (num_handles_value == 0) {
    // Easy case: won't receive any handles.
    result = dispatcher->ReadMessage(bytes, num_bytes, nullptr,
                                     &num_handles_value, flags);
  } else {
    HandleVector hs;
    result = dispatcher->ReadMessage(bytes, num_bytes, &hs, &num_handles_value,
                                     flags);
    if (!hs.empty()) {
      DCHECK_EQ(result, MOJO_RESULT_OK);
      DCHECK(!num_handles.IsNull());
      DCHECK_LE(hs.size(), static_cast<size_t>(num_handles_value));

      bool success;
      UserPointer<MojoHandle>::Writer handles_writer(handles, hs.size());
      {
        MutexLocker locker(&handle_table_mutex_);
        success =
            handle_table_.AddHandleVector(&hs, handles_writer.GetPointer());
      }
      if (success) {
        handles_writer.Commit();
      } else {
        LOG(ERROR) << "Received message with " << hs.size()
                   << " handles, but handle table full";
        // Close dispatchers (outside the lock).
        for (size_t i = 0; i < hs.size(); i++) {
          if (hs[i])
            hs[i].dispatcher->Close();
        }
        if (result == MOJO_RESULT_OK)
          result = MOJO_RESULT_RESOURCE_EXHAUSTED;
      }
    }
  }

  if (!num_handles.IsNull())
    num_handles.Put(num_handles_value);
  return result;
}

MojoResult Core::CreateDataPipe(
    UserPointer<const MojoCreateDataPipeOptions> options,
    UserPointer<MojoHandle> data_pipe_producer_handle,
    UserPointer<MojoHandle> data_pipe_consumer_handle) {
  MojoCreateDataPipeOptions validated_options = {};
  MojoResult result =
      DataPipe::ValidateCreateOptions(options, &validated_options);
  if (result != MOJO_RESULT_OK)
    return result;

  auto producer_dispatcher = DataPipeProducerDispatcher::Create();
  auto consumer_dispatcher = DataPipeConsumerDispatcher::Create();

  std::pair<MojoHandle, MojoHandle> handle_pair;
  {
    MutexLocker locker(&handle_table_mutex_);
    handle_pair = handle_table_.AddHandlePair(
        Handle(producer_dispatcher.Clone(),
               DataPipeProducerDispatcher::kDefaultHandleRights),
        Handle(consumer_dispatcher.Clone(),
               DataPipeConsumerDispatcher::kDefaultHandleRights));
  }
  if (handle_pair.first == MOJO_HANDLE_INVALID) {
    DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID);
    LOG(ERROR) << "Handle table full";
    producer_dispatcher->Close();
    consumer_dispatcher->Close();
    return MOJO_RESULT_RESOURCE_EXHAUSTED;
  }
  DCHECK_NE(handle_pair.second, MOJO_HANDLE_INVALID);

  auto data_pipe = DataPipe::CreateLocal(validated_options);
  producer_dispatcher->Init(data_pipe.Clone());
  consumer_dispatcher->Init(std::move(data_pipe));

  data_pipe_producer_handle.Put(handle_pair.first);
  data_pipe_consumer_handle.Put(handle_pair.second);
  return MOJO_RESULT_OK;
}

MojoResult Core::SetDataPipeProducerOptions(
    MojoHandle data_pipe_producer_handle,
    UserPointer<const MojoDataPipeProducerOptions> options) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_producer_handle, MOJO_HANDLE_RIGHT_SET_OPTIONS,
      EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->SetDataPipeProducerOptions(options);
}

MojoResult Core::GetDataPipeProducerOptions(
    MojoHandle data_pipe_producer_handle,
    UserPointer<MojoDataPipeProducerOptions> options,
    uint32_t options_num_bytes) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_producer_handle, MOJO_HANDLE_RIGHT_GET_OPTIONS,
      EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->GetDataPipeProducerOptions(options, options_num_bytes);
}

MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle,
                           UserPointer<const void> elements,
                           UserPointer<uint32_t> num_bytes,
                           MojoWriteDataFlags flags) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE,
      EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->WriteData(elements, num_bytes, flags);
}

MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle,
                                UserPointer<void*> buffer,
                                UserPointer<uint32_t> buffer_num_bytes,
                                MojoWriteDataFlags flags) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE,
      EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags);
}

MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle,
                              uint32_t num_bytes_written) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE,
      EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->EndWriteData(num_bytes_written);
}

MojoResult Core::SetDataPipeConsumerOptions(
    MojoHandle data_pipe_consumer_handle,
    UserPointer<const MojoDataPipeConsumerOptions> options) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_SET_OPTIONS,
      EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->SetDataPipeConsumerOptions(options);
}

MojoResult Core::GetDataPipeConsumerOptions(
    MojoHandle data_pipe_consumer_handle,
    UserPointer<MojoDataPipeConsumerOptions> options,
    uint32_t options_num_bytes) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_GET_OPTIONS,
      EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->GetDataPipeConsumerOptions(options, options_num_bytes);
}

MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle,
                          UserPointer<void> elements,
                          UserPointer<uint32_t> num_bytes,
                          MojoReadDataFlags flags) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ,
      EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->ReadData(elements, num_bytes, flags);
}

MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle,
                               UserPointer<const void*> buffer,
                               UserPointer<uint32_t> buffer_num_bytes,
                               MojoReadDataFlags flags) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ,
      EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags);
}

MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle,
                             uint32_t num_bytes_read) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result = GetDispatcherAndCheckRights(
      data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ,
      EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->EndReadData(num_bytes_read);
}

MojoResult Core::CreateSharedBuffer(
    UserPointer<const MojoCreateSharedBufferOptions> options,
    uint64_t num_bytes,
    UserPointer<MojoHandle> shared_buffer_handle) {
  MojoCreateSharedBufferOptions validated_options = {};
  MojoResult result = SharedBufferDispatcher::ValidateCreateOptions(
      options, &validated_options);
  if (result != MOJO_RESULT_OK)
    return result;

  auto dispatcher = SharedBufferDispatcher::Create(
      platform_support_, validated_options, num_bytes, &result);
  if (result != MOJO_RESULT_OK) {
    DCHECK(!dispatcher);
    return result;
  }

  MojoHandle h = AddHandle(
      Handle(dispatcher.Clone(), SharedBufferDispatcher::kDefaultHandleRights));
  if (h == MOJO_HANDLE_INVALID) {
    LOG(ERROR) << "Handle table full";
    dispatcher->Close();
    return MOJO_RESULT_RESOURCE_EXHAUSTED;
  }

  shared_buffer_handle.Put(h);
  return MOJO_RESULT_OK;
}

MojoResult Core::DuplicateBufferHandle(
    MojoHandle buffer_handle,
    UserPointer<const MojoDuplicateBufferHandleOptions> options,
    UserPointer<MojoHandle> new_buffer_handle) {
  // TODO(vtl): This is a big ugly and duplicates some code, but the plan is to
  // remove this method anyway.
  Handle h;
  MojoResult result = GetHandle(buffer_handle, &h);
  if (result != MOJO_RESULT_OK)
    return result;

  if (!h.has_all_rights(MOJO_HANDLE_RIGHT_DUPLICATE)) {
    return h.dispatcher->SupportsEntrypointClass(EntrypointClass::BUFFER)
               ? MOJO_RESULT_PERMISSION_DENIED
               : MOJO_RESULT_INVALID_ARGUMENT;
  }

  // Don't verify |options| here; that's the dispatcher's job.
  RefPtr<Dispatcher> new_dispatcher;
  result = h.dispatcher->DuplicateBufferHandle(options, &new_dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  MojoHandle new_handle = AddHandle(Handle(new_dispatcher.Clone(), h.rights));
  if (new_handle == MOJO_HANDLE_INVALID) {
    LOG(ERROR) << "Handle table full";
    new_dispatcher->Close();
    return MOJO_RESULT_RESOURCE_EXHAUSTED;
  }

  new_buffer_handle.Put(new_handle);
  return MOJO_RESULT_OK;
}

MojoResult Core::GetBufferInformation(MojoHandle buffer_handle,
                                      UserPointer<MojoBufferInformation> info,
                                      uint32_t info_num_bytes) {
  RefPtr<Dispatcher> dispatcher;
  MojoResult result =
      GetDispatcherAndCheckRights(buffer_handle, MOJO_HANDLE_RIGHT_GET_OPTIONS,
                                  EntrypointClass::BUFFER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  return dispatcher->GetBufferInformation(info, info_num_bytes);
}

MojoResult Core::MapBuffer(MojoHandle buffer_handle,
                           uint64_t offset,
                           uint64_t num_bytes,
                           UserPointer<void*> buffer,
                           MojoMapBufferFlags flags) {
  RefPtr<Dispatcher> dispatcher;
  // TODO(vtl): Currently we can only map read/write. So both
  // |MOJO_HANDLE_RIGHT_MAP_READABLE| and |MOJO_HANDLE_RIGHT_MAP_WRITABLE| are
  // required.
  MojoResult result = GetDispatcherAndCheckRights(
      buffer_handle,
      MOJO_HANDLE_RIGHT_MAP_READABLE | MOJO_HANDLE_RIGHT_MAP_WRITABLE,
      EntrypointClass::BUFFER, &dispatcher);
  if (result != MOJO_RESULT_OK)
    return result;

  std::unique_ptr<PlatformSharedBufferMapping> mapping;
  result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping);
  if (result != MOJO_RESULT_OK)
    return result;

  DCHECK(mapping);
  void* address = mapping->GetBase();
  {
    MutexLocker locker(&mapping_table_mutex_);
    result = mapping_table_.AddMapping(std::move(mapping));
  }
  if (result != MOJO_RESULT_OK)
    return result;

  buffer.Put(address);
  return MOJO_RESULT_OK;
}

MojoResult Core::UnmapBuffer(UserPointer<void> buffer) {
  MutexLocker locker(&mapping_table_mutex_);
  return mapping_table_.RemoveMapping(buffer.GetPointerValue());
}

// Note: We allow |handles| to repeat the same handle multiple times, since
// different flags may be specified.
// TODO(vtl): This incurs a performance cost in |Remove()|. Analyze this
// more carefully and address it if necessary.
MojoResult Core::WaitManyInternal(const MojoHandle* handles,
                                  const MojoHandleSignals* signals,
                                  uint32_t num_handles,
                                  MojoDeadline deadline,
                                  uint32_t* result_index,
                                  HandleSignalsState* signals_states) {
  DCHECK_GT(num_handles, 0u);
  DCHECK_EQ(*result_index, static_cast<uint32_t>(-1));

  DispatcherVector dispatchers;
  dispatchers.reserve(num_handles);

  {
    MutexLocker locker(&handle_table_mutex_);
    for (uint32_t i = 0; i < num_handles; i++) {
      if (handles[i] == MOJO_HANDLE_INVALID) {
        *result_index = i;
        return MOJO_RESULT_INVALID_ARGUMENT;
      }

      Handle handle;
      MojoResult result = handle_table_.GetHandle(handles[i], &handle);
      if (result != MOJO_RESULT_OK) {
        *result_index = i;
        return result;
      }
      dispatchers.push_back(std::move(handle.dispatcher));
    }
  }

  // TODO(vtl): Should make the waiter live (permanently) in TLS.
  Waiter waiter;
  waiter.Init();

  uint32_t i;
  MojoResult result = MOJO_RESULT_OK;
  for (i = 0; i < num_handles; i++) {
    result = dispatchers[i]->AddAwakable(
        &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr);
    if (result != MOJO_RESULT_OK) {
      *result_index = i;
      break;
    }
  }
  uint32_t num_added = i;

  if (result == MOJO_RESULT_ALREADY_EXISTS)
    result = MOJO_RESULT_OK;  // The i-th one is already "triggered".
  else if (result == MOJO_RESULT_OK)
    result = waiter.Wait(deadline, result_index);

  // Make sure no other dispatchers try to wake |waiter| for the current
  // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be
  // destroyed, but this would still be required if the waiter were in TLS.)
  for (i = 0; i < num_added; i++) {
    dispatchers[i]->RemoveAwakable(
        &waiter, signals_states ? &signals_states[i] : nullptr);
  }
  if (signals_states) {
    for (; i < num_handles; i++)
      signals_states[i] = dispatchers[i]->GetHandleSignalsState();
  }

  return result;
}

}  // namespace system
}  // namespace mojo
