request_context.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef MOJO_CORE_REQUEST_CONTEXT_H_
  5. #define MOJO_CORE_REQUEST_CONTEXT_H_
  6. #include "base/containers/stack_container.h"
  7. #include "base/memory/raw_ptr_exclusion.h"
  8. #include "mojo/core/handle_signals_state.h"
  9. #include "mojo/core/system_impl_export.h"
  10. #include "mojo/core/watch.h"
  11. namespace base {
  12. template <typename T>
  13. class ThreadLocalPointer;
  14. }
  15. namespace mojo {
  16. namespace core {
  17. // A RequestContext is a thread-local object which exists for the duration of
  18. // a single system API call. It is constructed immediately upon EDK entry and
  19. // destructed immediately before returning to the caller, after any internal
  20. // locks have been released.
  21. //
  22. // NOTE: It is legal to construct a RequestContext while another one already
  23. // exists on the current thread, but it is not safe to use the nested context
  24. // for any reason. Therefore it is important to always use
  25. // |RequestContext::current()| rather than referring to any local instance
  26. // directly.
  27. class MOJO_SYSTEM_IMPL_EXPORT RequestContext {
  28. public:
  29. // Identifies the source of the current stack frame's RequestContext.
  30. enum class Source {
  31. LOCAL_API_CALL,
  32. SYSTEM,
  33. };
  34. // Constructs a RequestContext with a LOCAL_API_CALL Source.
  35. RequestContext();
  36. explicit RequestContext(Source source);
  37. RequestContext(const RequestContext&) = delete;
  38. RequestContext& operator=(const RequestContext&) = delete;
  39. ~RequestContext();
  40. // Returns the current thread-local RequestContext.
  41. static RequestContext* current();
  42. Source source() const { return source_; }
  43. // Adds a finalizer to this RequestContext corresponding to a watch callback
  44. // which should be triggered in response to some handle state change. If
  45. // the WatcherDispatcher hasn't been closed by the time this RequestContext is
  46. // destroyed, its WatchCallback will be invoked with |result| and |state|
  47. // arguments.
  48. void AddWatchNotifyFinalizer(scoped_refptr<Watch> watch,
  49. MojoResult result,
  50. const HandleSignalsState& state);
  51. // Adds a finalizer to this RequestContext corresponding to a watch callback
  52. // which should be triggered to notify of watch cancellation. This appends to
  53. // a separate finalizer list from AddWatchNotifyFinalizer, as pending
  54. // cancellations must always preempt other pending notifications.
  55. void AddWatchCancelFinalizer(scoped_refptr<Watch> watch);
  56. private:
  57. // Is this request context the current one?
  58. bool IsCurrent() const;
  59. struct WatchNotifyFinalizer {
  60. WatchNotifyFinalizer(scoped_refptr<Watch> watch,
  61. MojoResult result,
  62. const HandleSignalsState& state);
  63. WatchNotifyFinalizer(const WatchNotifyFinalizer& other);
  64. ~WatchNotifyFinalizer();
  65. scoped_refptr<Watch> watch;
  66. MojoResult result;
  67. HandleSignalsState state;
  68. };
  69. // NOTE: This upper bound was chosen somewhat arbitrarily after observing some
  70. // rare worst-case behavior in Chrome. A vast majority of RequestContexts only
  71. // ever accumulate 0 or 1 finalizers.
  72. static const size_t kStaticWatchFinalizersCapacity = 8;
  73. using WatchNotifyFinalizerList =
  74. base::StackVector<WatchNotifyFinalizer, kStaticWatchFinalizersCapacity>;
  75. using WatchCancelFinalizerList =
  76. base::StackVector<scoped_refptr<Watch>, kStaticWatchFinalizersCapacity>;
  77. const Source source_;
  78. WatchNotifyFinalizerList watch_notify_finalizers_;
  79. WatchCancelFinalizerList watch_cancel_finalizers_;
  80. // Pointer to the TLS context. Although this can easily be accessed via the
  81. // global LazyInstance, accessing a LazyInstance has a large cost relative to
  82. // the rest of this class and its usages.
  83. //
  84. // `tls_context` is not a raw_ptr<...> as a performance optimization: The
  85. // pointee doesn't need UaF protection (it has a global/static lifetime).
  86. RAW_PTR_EXCLUSION base::ThreadLocalPointer<RequestContext>* tls_context_;
  87. };
  88. } // namespace core
  89. } // namespace mojo
  90. #endif // MOJO_CORE_REQUEST_CONTEXT_H_