blob: 3c94c8aca5a067772f2866e170a04a00a030656f [file] [log] [blame]
// Copyright 2014 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/system/shared_buffer_dispatcher.h"
#include <limits>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "mojo/system/constants.h"
#include "mojo/system/memory.h"
#include "mojo/system/raw_shared_buffer.h"
namespace mojo {
namespace system {
// static
MojoResult SharedBufferDispatcher::ValidateOptions(
const MojoCreateSharedBufferOptions* in_options,
MojoCreateSharedBufferOptions* out_options) {
static const MojoCreateSharedBufferOptions kDefaultOptions = {
static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)),
MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE
};
if (!in_options) {
*out_options = kDefaultOptions;
return MOJO_RESULT_OK;
}
if (in_options->struct_size < sizeof(*in_options))
return MOJO_RESULT_INVALID_ARGUMENT;
out_options->struct_size = static_cast<uint32_t>(sizeof(*out_options));
// All flags are okay (unrecognized flags will be ignored).
out_options->flags = in_options->flags;
return MOJO_RESULT_OK;
}
// static
MojoResult SharedBufferDispatcher::Create(
const MojoCreateSharedBufferOptions& /*validated_options*/,
uint64_t num_bytes,
scoped_refptr<SharedBufferDispatcher>* result) {
if (!num_bytes)
return MOJO_RESULT_INVALID_ARGUMENT;
if (num_bytes > kMaxSharedMemoryNumBytes)
return MOJO_RESULT_RESOURCE_EXHAUSTED;
scoped_refptr<RawSharedBuffer> shared_buffer(
RawSharedBuffer::Create(static_cast<size_t>(num_bytes)));
if (!shared_buffer)
return MOJO_RESULT_RESOURCE_EXHAUSTED;
*result = new SharedBufferDispatcher(shared_buffer);
return MOJO_RESULT_OK;
}
Dispatcher::Type SharedBufferDispatcher::GetType() const {
return kTypeSharedBuffer;
}
SharedBufferDispatcher::SharedBufferDispatcher(
scoped_refptr<RawSharedBuffer> shared_buffer)
: shared_buffer_(shared_buffer) {
DCHECK(shared_buffer_);
}
SharedBufferDispatcher::~SharedBufferDispatcher() {
}
void SharedBufferDispatcher::CloseImplNoLock() {
lock().AssertAcquired();
DCHECK(shared_buffer_);
shared_buffer_ = NULL;
}
scoped_refptr<Dispatcher>
SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
lock().AssertAcquired();
DCHECK(shared_buffer_);
scoped_refptr<RawSharedBuffer> shared_buffer;
shared_buffer.swap(shared_buffer_);
return scoped_refptr<Dispatcher>(new SharedBufferDispatcher(shared_buffer));
}
MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock(
const MojoDuplicateBufferHandleOptions* options,
scoped_refptr<Dispatcher>* new_dispatcher) {
lock().AssertAcquired();
if (options) {
// The |struct_size| field must be valid to read.
if (!VerifyUserPointer<uint32_t>(&options->struct_size, 1))
return MOJO_RESULT_INVALID_ARGUMENT;
// And then |options| must point to at least |options->struct_size| bytes.
if (!VerifyUserPointer<void>(options, options->struct_size))
return MOJO_RESULT_INVALID_ARGUMENT;
if (options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
// We don't actually do anything with |options|.
}
*new_dispatcher = new SharedBufferDispatcher(shared_buffer_);
return MOJO_RESULT_OK;
}
MojoResult SharedBufferDispatcher::MapBufferImplNoLock(
uint64_t offset,
uint64_t num_bytes,
MojoMapBufferFlags flags,
scoped_ptr<RawSharedBufferMapping>* mapping) {
lock().AssertAcquired();
DCHECK(shared_buffer_);
if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
return MOJO_RESULT_INVALID_ARGUMENT;
if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
return MOJO_RESULT_INVALID_ARGUMENT;
if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset),
static_cast<size_t>(num_bytes)))
return MOJO_RESULT_INVALID_ARGUMENT;
DCHECK(mapping);
*mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset),
static_cast<size_t>(num_bytes));
if (!*mapping)
return MOJO_RESULT_RESOURCE_EXHAUSTED;
return MOJO_RESULT_OK;
}
MojoWaitFlags SharedBufferDispatcher::SatisfiedFlagsNoLock() const {
// TODO(vtl): Add transferrable flag.
return MOJO_WAIT_FLAG_NONE;
}
MojoWaitFlags SharedBufferDispatcher::SatisfiableFlagsNoLock() const {
// TODO(vtl): Add transferrable flag.
return MOJO_WAIT_FLAG_NONE;
}
} // namespace system
} // namespace mojo