1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "RefCountedShmem.h"
8
9 #include "mozilla/Atomics.h"
10 #include "mozilla/ipc/ProtocolUtils.h"
11 #include "mozilla/layers/WebRenderMessages.h"
12
13 #define SHM_REFCOUNT_HEADER_SIZE 16
14
15 namespace mozilla {
16 namespace layers {
17
GetBytes(const RefCountedShmem & aShm)18 uint8_t* RefCountedShm::GetBytes(const RefCountedShmem& aShm) {
19 uint8_t* data = aShm.buffer().get<uint8_t>();
20 if (!data) {
21 return nullptr;
22 }
23 return data + SHM_REFCOUNT_HEADER_SIZE;
24 }
25
GetSize(const RefCountedShmem & aShm)26 size_t RefCountedShm::GetSize(const RefCountedShmem& aShm) {
27 if (!IsValid(aShm)) {
28 return 0;
29 }
30 size_t totalSize = aShm.buffer().Size<uint8_t>();
31 if (totalSize < SHM_REFCOUNT_HEADER_SIZE) {
32 return 0;
33 }
34
35 return totalSize - SHM_REFCOUNT_HEADER_SIZE;
36 }
37
IsValid(const RefCountedShmem & aShm)38 bool RefCountedShm::IsValid(const RefCountedShmem& aShm) {
39 return aShm.buffer().IsWritable() &&
40 aShm.buffer().Size<uint8_t>() > SHM_REFCOUNT_HEADER_SIZE;
41 }
42
GetReferenceCount(const RefCountedShmem & aShm)43 int32_t RefCountedShm::GetReferenceCount(const RefCountedShmem& aShm) {
44 if (!IsValid(aShm)) {
45 return 0;
46 }
47
48 return *aShm.buffer().get<Atomic<int32_t>>();
49 }
50
AddRef(const RefCountedShmem & aShm)51 int32_t RefCountedShm::AddRef(const RefCountedShmem& aShm) {
52 if (!IsValid(aShm)) {
53 return 0;
54 }
55
56 auto* counter = aShm.buffer().get<Atomic<int32_t>>();
57 if (counter) {
58 return (*counter)++;
59 }
60 return 0;
61 }
62
Release(const RefCountedShmem & aShm)63 int32_t RefCountedShm::Release(const RefCountedShmem& aShm) {
64 if (!IsValid(aShm)) {
65 return 0;
66 }
67
68 auto* counter = aShm.buffer().get<Atomic<int32_t>>();
69 if (counter) {
70 return --(*counter);
71 }
72
73 return 0;
74 }
75
Alloc(mozilla::ipc::IProtocol * aAllocator,size_t aSize,RefCountedShmem & aShm)76 bool RefCountedShm::Alloc(mozilla::ipc::IProtocol* aAllocator, size_t aSize,
77 RefCountedShmem& aShm) {
78 MOZ_ASSERT(!IsValid(aShm));
79 auto shmType = ipc::SharedMemory::SharedMemoryType::TYPE_BASIC;
80 auto size = aSize + SHM_REFCOUNT_HEADER_SIZE;
81 if (!aAllocator->AllocUnsafeShmem(size, shmType, &aShm.buffer())) {
82 return false;
83 }
84 return true;
85 }
86
Dealloc(mozilla::ipc::IProtocol * aAllocator,RefCountedShmem & aShm)87 void RefCountedShm::Dealloc(mozilla::ipc::IProtocol* aAllocator,
88 RefCountedShmem& aShm) {
89 aAllocator->DeallocShmem(aShm.buffer());
90 aShm.buffer() = ipc::Shmem();
91 }
92
93 } // namespace layers
94 } // namespace mozilla
95