Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "GMPSharedMemManager.h"
7 : #include "GMPMessageUtils.h"
8 : #include "mozilla/ipc/SharedMemory.h"
9 : #include "mozilla/StaticPtr.h"
10 : #include "mozilla/ClearOnShutdown.h"
11 :
12 : namespace mozilla {
13 : namespace gmp {
14 :
15 : // Really one set of pools on each side of the plugin API.
16 :
17 : // YUV buffers go from Encoder parent to child; pool there, and then return
18 : // with Decoded() frames to the Decoder parent and goes into the parent pool.
19 : // Compressed (encoded) data goes from the Decoder parent to the child;
20 : // pool there, and then return with Encoded() frames and goes into the parent
21 : // pool.
22 : bool
23 0 : GMPSharedMemManager::MgrAllocShmem(GMPSharedMem::GMPMemoryClasses aClass, size_t aSize,
24 : ipc::Shmem::SharedMemory::SharedMemoryType aType,
25 : ipc::Shmem* aMem)
26 : {
27 0 : mData->CheckThread();
28 :
29 : // first look to see if we have a free buffer large enough
30 0 : for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) {
31 0 : MOZ_ASSERT(GetGmpFreelist(aClass)[i].IsWritable());
32 0 : if (aSize <= GetGmpFreelist(aClass)[i].Size<uint8_t>()) {
33 0 : *aMem = GetGmpFreelist(aClass)[i];
34 0 : GetGmpFreelist(aClass).RemoveElementAt(i);
35 0 : return true;
36 : }
37 : }
38 :
39 : // Didn't find a buffer free with enough space; allocate one
40 0 : size_t pagesize = ipc::SharedMemory::SystemPageSize();
41 0 : aSize = (aSize + (pagesize-1)) & ~(pagesize-1); // round up to page size
42 0 : bool retval = Alloc(aSize, aType, aMem);
43 0 : if (retval) {
44 : // The allocator (or NeedsShmem call) should never return less than we ask for...
45 0 : MOZ_ASSERT(aMem->Size<uint8_t>() >= aSize);
46 0 : mData->mGmpAllocated[aClass]++;
47 : }
48 0 : return retval;
49 : }
50 :
51 : bool
52 0 : GMPSharedMemManager::MgrDeallocShmem(GMPSharedMem::GMPMemoryClasses aClass, ipc::Shmem& aMem)
53 : {
54 0 : mData->CheckThread();
55 :
56 0 : size_t size = aMem.Size<uint8_t>();
57 0 : size_t total = 0;
58 :
59 : // XXX Bug NNNNNNN Until we put better guards on ipc::shmem, verify we
60 : // weren't fed an shmem we already had.
61 0 : for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) {
62 0 : if (NS_WARN_IF(aMem == GetGmpFreelist(aClass)[i])) {
63 : // Safest to crash in this case; should never happen in normal
64 : // operation.
65 0 : MOZ_CRASH("Deallocating Shmem we already have in our cache!");
66 : //return true;
67 : }
68 : }
69 :
70 : // XXX This works; there are better pool algorithms. We need to avoid
71 : // "falling off a cliff" with too low a number
72 0 : if (GetGmpFreelist(aClass).Length() > 10) {
73 0 : Dealloc(GetGmpFreelist(aClass)[0]);
74 0 : GetGmpFreelist(aClass).RemoveElementAt(0);
75 : // The allocation numbers will be fubar on the Child!
76 0 : mData->mGmpAllocated[aClass]--;
77 : }
78 0 : for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) {
79 0 : MOZ_ASSERT(GetGmpFreelist(aClass)[i].IsWritable());
80 0 : total += GetGmpFreelist(aClass)[i].Size<uint8_t>();
81 0 : if (size < GetGmpFreelist(aClass)[i].Size<uint8_t>()) {
82 0 : GetGmpFreelist(aClass).InsertElementAt(i, aMem);
83 0 : return true;
84 : }
85 : }
86 0 : GetGmpFreelist(aClass).AppendElement(aMem);
87 :
88 0 : return true;
89 : }
90 :
91 : uint32_t
92 0 : GMPSharedMemManager::NumInUse(GMPSharedMem::GMPMemoryClasses aClass)
93 : {
94 0 : return mData->mGmpAllocated[aClass] - GetGmpFreelist(aClass).Length();
95 : }
96 :
97 : } // namespace gmp
98 : } // namespace mozilla
|