tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Flow.h (3258B)


      1 /*
      2 * Copyright (C) 2021 The Android Open Source Project
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 *      http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 #ifndef Flow_h
     18 #define Flow_h
     19 
     20 // We use a Flow for connecting markers over time. It's a
     21 // global (cross-process) 64bit id that will connect any markers that have the
     22 // same id until we see a terminating-flow with that id.
     23 //
     24 // With these semanatics we can derive a flow from a pointer by xoring it with
     25 // gProcessUUID and using a terminating-flow when we're done with
     26 // that pointer e.g. destructor. This doesn't ensure that the flow is globally
     27 // unique but makes collisions unlikely enough that it mostly works.
     28 
     29 // The following code for Flow is derived from Perfetto
     30 
     31 #include <stdint.h>
     32 #include "mozilla/ProfileBufferEntrySerialization.h"
     33 
     34 extern uint64_t MFBT_DATA gProcessUUID;
     35 
     36 // This class is used as a marker field type and is used in the marker schema.
     37 // To create a Flow, use Flow::FromPointer, Flow::ProcessScoped or Flow::Global.
     38 class Flow {
     39 public:
     40  // |aFlow| which is local within a given process (e.g. atomic counter xor'ed
     41  // with feature-specific value). This value is xor'ed with processUUID
     42  // to attempt to ensure that it's globally-unique.
     43  static inline Flow ProcessScoped(uint64_t aFlowId) {
     44    return Global(aFlowId ^ gProcessUUID);
     45  }
     46 
     47  // Same as above, but construct an id from a pointer.
     48  // NOTE: After the object is destroyed, the value of |aPtr| can be reused for
     49  // a different object (in particular if the object is allocated on a stack)
     50  // but it needs to be emitted as terminating flow first.
     51  static inline Flow FromPointer(void* aPtr) {
     52    return ProcessScoped(reinterpret_cast<uintptr_t>(aPtr));
     53  }
     54 
     55  // The caller is responsible for ensuring that it's
     56  // globally-unique (e.g. by generating a random value). This should be used
     57  // only for flow events which cross the process boundary (e.g. IPCs).
     58  static inline Flow Global(uint64_t aFlowId) { return Flow(aFlowId); }
     59 
     60  uint64_t Id() const { return mFlowId; }
     61 
     62  static MFBT_API void Init();
     63 
     64 private:
     65  explicit Flow(uint64_t aFlowId) : mFlowId(aFlowId) {}
     66  const uint64_t mFlowId;
     67 };
     68 
     69 template <>
     70 struct mozilla::ProfileBufferEntryWriter::Serializer<Flow> {
     71  static constexpr Length Bytes(const Flow& aFlow) { return sizeof(Flow); }
     72 
     73  static void Write(ProfileBufferEntryWriter& aEW, const Flow& aFlow) {
     74    aEW.WriteBytes(&aFlow, sizeof(Flow));
     75  }
     76 };
     77 
     78 template <>
     79 struct mozilla::ProfileBufferEntryReader::Deserializer<Flow> {
     80  static void ReadInto(ProfileBufferEntryReader& aER, uint64_t& aFlow) {
     81    aER.ReadBytes(&aFlow, sizeof(Flow));
     82  }
     83 
     84  static Flow Read(ProfileBufferEntryReader& aER) {
     85    uint64_t flow;
     86    ReadInto(aER, flow);
     87    return Flow::Global(flow);
     88  }
     89 };
     90 
     91 #endif  // Flow_h