Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/ShmemPool.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set sw=2 ts=8 et ft=cpp : */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_ShmemPool_h
8
#define mozilla_ShmemPool_h
9
10
#include "mozilla/ipc/Shmem.h"
11
#include "mozilla/Mutex.h"
12
13
#undef LOG
14
#undef LOG_ENABLED
15
extern mozilla::LazyLogModule gCamerasParentLog;
16
0
#define LOG(args) MOZ_LOG(gCamerasParentLog, mozilla::LogLevel::Debug, args)
17
#define LOG_ENABLED() MOZ_LOG_TEST(gCamerasParentLog, mozilla::LogLevel::Debug)
18
19
namespace mozilla {
20
21
class ShmemPool;
22
23
class ShmemBuffer {
24
public:
25
0
  ShmemBuffer() : mInitialized(false) {}
26
0
  explicit ShmemBuffer(mozilla::ipc::Shmem aShmem) {
27
0
    mInitialized = true;
28
0
    mShmem = aShmem;
29
0
  }
30
31
0
  ShmemBuffer(ShmemBuffer&& rhs) {
32
0
    mInitialized = rhs.mInitialized;
33
0
    mShmem = std::move(rhs.mShmem);
34
0
  }
35
36
0
  ShmemBuffer& operator=(ShmemBuffer&& rhs) {
37
0
    MOZ_ASSERT(&rhs != this, "self-moves are prohibited");
38
0
    mInitialized = rhs.mInitialized;
39
0
    mShmem = std::move(rhs.mShmem);
40
0
    return *this;
41
0
  }
42
43
  // No copies allowed
44
  ShmemBuffer(const ShmemBuffer&) = delete;
45
  ShmemBuffer& operator=(const ShmemBuffer&) = delete;
46
47
0
  bool Valid() {
48
0
    return mInitialized;
49
0
  }
50
51
0
  uint8_t * GetBytes() {
52
0
    return mShmem.get<uint8_t>();
53
0
  }
54
55
0
  mozilla::ipc::Shmem& Get() {
56
0
    return mShmem;
57
0
  }
58
59
private:
60
  friend class ShmemPool;
61
62
  bool mInitialized;
63
  mozilla::ipc::Shmem mShmem;
64
};
65
66
class ShmemPool {
67
public:
68
  explicit ShmemPool(size_t aPoolSize);
69
  ~ShmemPool();
70
  // Get/GetIfAvailable differ in what thread they can run on. GetIfAvailable
71
  // can run anywhere but won't allocate if the right size isn't available.
72
  ShmemBuffer GetIfAvailable(size_t aSize);
73
  void Put(ShmemBuffer&& aShmem);
74
75
  // We need to use the allocation/deallocation functions
76
  // of a specific IPC child/parent instance.
77
  template <class T>
78
  void Cleanup(T* aInstance)
79
0
  {
80
0
    MutexAutoLock lock(mMutex);
81
0
    for (size_t i = 0; i < mShmemPool.Length(); i++) {
82
0
      if (mShmemPool[i].mInitialized) {
83
0
        aInstance->DeallocShmem(mShmemPool[i].Get());
84
0
        mShmemPool[i].mInitialized = false;
85
0
      }
86
0
    }
87
0
  }
88
89
  template <class T>
90
  ShmemBuffer Get(T* aInstance, size_t aSize)
91
0
  {
92
0
    MutexAutoLock lock(mMutex);
93
0
94
0
    // Pool is empty, don't block caller.
95
0
    if (mPoolFree == 0) {
96
0
      // This isn't initialized, so will be understood as an error.
97
0
      return ShmemBuffer();
98
0
    }
99
0
100
0
    ShmemBuffer& res = mShmemPool[mPoolFree - 1];
101
0
102
0
    if (!res.mInitialized) {
103
0
      LOG(("Initializing new Shmem in pool"));
104
0
      if (!aInstance->AllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC, &res.mShmem)) {
105
0
        LOG(("Failure allocating new Shmem buffer"));
106
0
        return ShmemBuffer();
107
0
      }
108
0
      res.mInitialized = true;
109
0
    }
110
0
111
0
    MOZ_ASSERT(res.mShmem.IsWritable(), "Shmem in Pool is not writable?");
112
0
113
0
    // Prepare buffer, increase size if needed (we never shrink as we don't
114
0
    // maintain seperate sized pools and we don't want to keep reallocating)
115
0
    if (res.mShmem.Size<char>() < aSize) {
116
0
      LOG(("Size change/increase in Shmem Pool"));
117
0
      aInstance->DeallocShmem(res.mShmem);
118
0
      res.mInitialized = false;
119
0
      // this may fail; always check return value
120
0
      if (!aInstance->AllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC, &res.mShmem)) {
121
0
        LOG(("Failure allocating resized Shmem buffer"));
122
0
        return ShmemBuffer();
123
0
      } else {
124
0
        res.mInitialized = true;
125
0
      }
126
0
    }
127
0
128
0
    MOZ_ASSERT(res.mShmem.IsWritable(), "Shmem in Pool is not writable post resize?");
129
0
130
0
    mPoolFree--;
131
#ifdef DEBUG
132
    size_t poolUse = mShmemPool.Length() - mPoolFree;
133
    if (poolUse > mMaxPoolUse) {
134
      mMaxPoolUse = poolUse;
135
      LOG(("Maximum ShmemPool use increased: %zu buffers", mMaxPoolUse));
136
    }
137
#endif
138
    return std::move(res);
139
0
  }
140
141
private:
142
  Mutex mMutex;
143
  size_t mPoolFree;
144
#ifdef DEBUG
145
  size_t mMaxPoolUse;
146
#endif
147
  nsTArray<ShmemBuffer> mShmemPool;
148
};
149
150
151
} // namespace mozilla
152
153
#endif  // mozilla_ShmemPool_h