blob: 54a4744c78acae51fffffd428edb99bcc4f5ba3f [file] [log] [blame]
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef IREE_RT_DEBUG_DEBUG_SERVICE_H_
#define IREE_RT_DEBUG_DEBUG_SERVICE_H_
#include <vector>
#include "absl/base/thread_annotations.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "base/status.h"
#include "flatbuffers/flatbuffers.h"
#include "rt/context.h"
#include "rt/debug/debug_session.h"
#include "schemas/debug_service_generated.h"
namespace iree {
namespace rt {
namespace debug {
// Debugging service used to implement the DebugService RPC methods in a
// transport-independent way. Specific DebugServer implementations can compose
// with a DebugService to avoid needing to maintain state themselves. Multiple
// DebugServer instances could share the same DebugService instance to ensure
// all clients - regardless of transport - share the same state.
//
// Thread-safe.
class DebugService {
public:
// Registers a context with the debug service.
// Ownership remains with the caller and UnregisterContext must be called
// prior to the context being destroyed.
Status RegisterContext(Context* context);
Status UnregisterContext(Context* context);
// Registers a new module linked into an existing Context.
Status RegisterContextModule(Context* context, Module* module);
// Registers a invocation state with the debug service.
// Ownership remains with the caller and UnregisterInvocation must be called
// prior to the invocation state being destroyed.
Status RegisterInvocation(Invocation* invocation);
Status UnregisterInvocation(Invocation* invocation);
// Registers a debug session with the service.
Status RegisterDebugSession(DebugSession* session);
Status UnregisterDebugSession(DebugSession* session);
// Blocks the caller until all sessions are ready.
// Returns AbortedError if a session connects/is already connected but
// disconnects during the wait.
Status WaitUntilAllSessionsReady();
StatusOr<::flatbuffers::Offset<rpc::MakeReadyResponse>> MakeReady(
const rpc::MakeReadyRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::GetStatusResponse>> GetStatus(
const rpc::GetStatusRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::ListContextsResponse>> ListContexts(
const rpc::ListContextsRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::GetModuleResponse>> GetModule(
const rpc::GetModuleRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::GetFunctionResponse>> GetFunction(
const rpc::GetFunctionRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::ResolveFunctionResponse>> ResolveFunction(
const rpc::ResolveFunctionRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::ListInvocationsResponse>> ListInvocations(
const rpc::ListInvocationsRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::SuspendInvocationsResponse>>
SuspendInvocations(const rpc::SuspendInvocationsRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::ResumeInvocationsResponse>>
ResumeInvocations(const rpc::ResumeInvocationsRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::StepInvocationResponse>> StepInvocation(
const rpc::StepInvocationRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::GetInvocationLocalResponse>>
GetInvocationLocal(const rpc::GetInvocationLocalRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::SetInvocationLocalResponse>>
SetInvocationLocal(const rpc::SetInvocationLocalRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::ListBreakpointsResponse>> ListBreakpoints(
const rpc::ListBreakpointsRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::AddBreakpointResponse>> AddBreakpoint(
const rpc::AddBreakpointRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::RemoveBreakpointResponse>>
RemoveBreakpoint(const rpc::RemoveBreakpointRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::StartProfilingResponse>> StartProfiling(
const rpc::StartProfilingRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
StatusOr<::flatbuffers::Offset<rpc::StopProfilingResponse>> StopProfiling(
const rpc::StopProfilingRequest& request,
::flatbuffers::FlatBufferBuilder* fbb);
// Serializes an invocation and its stack frames.
StatusOr<::flatbuffers::Offset<rpc::InvocationDef>> SerializeInvocation(
const Invocation& invocation, ::flatbuffers::FlatBufferBuilder* fbb);
private:
StatusOr<Context*> GetContext(int context_id) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
StatusOr<Module*> GetModule(int context_id,
absl::string_view module_name) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
StatusOr<Invocation*> GetInvocation(int invocation_id) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Suspends all invocations on all contexts. Returns only once all invocations
// have been suspended successfully. Fails if any invocation fails to suspend.
Status SuspendAllInvocations() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Resumes all invocations on all contexts (the inverse of
// SuspendAllInvocations). Returns immediately.
Status ResumeAllInvocations() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Marks all sessions as unready.
Status UnreadyAllSessions() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Attempts to re-register all breakpoints for a module.
Status RegisterModuleBreakpoints(Context* context, Module* module)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Status RegisterFunctionBreakpoint(Context* context, Module* module,
rpc::BreakpointDefT* breakpoint)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Status UnregisterFunctionBreakpoint(const rpc::BreakpointDefT& breakpoint)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Signals that the given breakpoint was hit by the specified invocation.
// Called without the debug lock held.
Status OnFunctionBreakpointHit(int breakpoint_id,
const Invocation& invocation);
absl::Mutex mutex_;
std::vector<Context*> contexts_ ABSL_GUARDED_BY(mutex_);
std::vector<Invocation*> invocations_ ABSL_GUARDED_BY(mutex_);
std::vector<DebugSession*> sessions_ ABSL_GUARDED_BY(mutex_);
int sessions_unready_ ABSL_GUARDED_BY(mutex_) = 0;
int sessions_ready_ ABSL_GUARDED_BY(mutex_) = 0;
std::vector<rpc::BreakpointDefT> breakpoints_ ABSL_GUARDED_BY(mutex_);
};
} // namespace debug
} // namespace rt
} // namespace iree
#endif // IREE_RT_DEBUG_DEBUG_SERVICE_H_