1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /**
19 * @file pvmf_pool_buffer_allocator.h
20 * @brief This file defines the PV Multimedia Framework (PVMF) media message
21 * header class which is used to hold the basic information such as timestamp,
22 * sequence number, etc for every media message.
23 *
24 */
25 #include "pvlogger.h"
26 #include "pvmf_pool_buffer_allocator.h"
27 #include "oscl_mem.h"
28 #include "oscl_time.h"
29
PVMFBufferPoolAllocator(bool aLeaveOnAllocFailure)30 OSCL_EXPORT_REF PVMFBufferPoolAllocator::PVMFBufferPoolAllocator(bool aLeaveOnAllocFailure) :
31 iFragSize(0),
32 iDestroyPool(false),
33 iLeaveOnAllocFailure(aLeaveOnAllocFailure)
34 {
35 iLogger = PVLogger::GetLoggerObject("pvmf.bufferpoolallocator");
36 iAllocNum = 0;
37 iFailFrequency = 0;
38 }
39
~PVMFBufferPoolAllocator()40 OSCL_EXPORT_REF PVMFBufferPoolAllocator::~PVMFBufferPoolAllocator()
41 {
42 iDestroyPool = true;
43 iAvailFragments.clear();
44 }
45
SetLeaveOnAllocFailure(bool aLeaveOnAllocFailure)46 OSCL_EXPORT_REF void PVMFBufferPoolAllocator::SetLeaveOnAllocFailure(bool aLeaveOnAllocFailure)
47 {
48 iLeaveOnAllocFailure = aLeaveOnAllocFailure;
49 }
50
size(uint16 num_frags,uint16 frag_size)51 OSCL_EXPORT_REF void PVMFBufferPoolAllocator::size(uint16 num_frags, uint16 frag_size)
52 {
53 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFBufferPoolAllocator::size num_frags(%d), frag_size(%d)", num_frags, frag_size));
54 iFragSize = frag_size;
55 iAvailFragments.reserve(num_frags);
56
57 for (uint16 frag_num = 0; frag_num < num_frags; frag_num++)
58 {
59 unsigned aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
60 uint8* buf = (uint8*)OSCL_MALLOC(aligned_refcnt_size + frag_size);
61
62 // check for out-of-memory
63 if (!buf)
64 {
65 iAvailFragments.clear();
66 OSCL_LEAVE(OSCL_BAD_ALLOC_EXCEPTION_CODE);
67 }
68
69 // ref counter will delete itself when refcount goes to 0
70 OsclRefCounterDA* ref_counter = OSCL_PLACEMENT_NEW(buf, OsclRefCounterDA(buf, this));
71 OsclMemoryFragment m;
72 m.ptr = buf + aligned_refcnt_size;
73 m.len = iFragSize;
74 OsclRefCounterMemFrag frag(m, ref_counter, iFragSize);
75 iAvailFragments.push_back(frag);
76 }
77 }
78
clear()79 OSCL_EXPORT_REF void PVMFBufferPoolAllocator::clear()
80 {
81 iDestroyPool = true;
82 iAvailFragments.clear();
83 }
84
destruct_and_dealloc(OsclAny * ptr)85 OSCL_EXPORT_REF void PVMFBufferPoolAllocator::destruct_and_dealloc(OsclAny* ptr)
86 {
87 if (!iDestroyPool)
88 {
89 // Create another ref counter for the buffer and add it back to the available list
90 OsclRefCounterDA* ref_counter = OSCL_PLACEMENT_NEW(ptr, OsclRefCounterDA(ptr, this));
91 unsigned aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
92 OsclMemoryFragment m;
93 m.ptr = (uint8*)ptr + aligned_refcnt_size;
94 m.len = iFragSize;
95 OsclRefCounterMemFrag frag(m, ref_counter, iFragSize);
96 release(frag);
97 }
98 else
99 {
100 OSCL_FREE(ptr);
101 }
102 }
103
get()104 OSCL_EXPORT_REF OsclRefCounterMemFrag PVMFBufferPoolAllocator::get()
105 {
106 OsclRefCounterMemFrag ret;
107 #if _DEBUG
108 ++iAllocNum;
109 if (iFailFrequency)
110 {
111 TimeValue timenow;
112 int ms = timenow.to_msec();
113 if (iAllocNum % ((ms & 0xF) + 1) == 0)
114 {
115 // throw exception
116 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NONFATAL_ERROR, (0, "PVMFBufferPoolAllocator::get - Simulating out of fragment exception !! \n"));
117 if (iLeaveOnAllocFailure)
118 {
119 OSCL_LEAVE(OSCL_BAD_ALLOC_EXCEPTION_CODE);
120 }
121 return ret;
122 }
123 }
124 #endif
125
126 if (!iAvailFragments.empty())
127 {
128 ret = iAvailFragments.back();
129 iAvailFragments.pop_back();
130 ret.getMemFrag().len = iFragSize;
131 return ret;
132 }
133 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NONFATAL_ERROR, (0, "PVMFBufferPoolAllocator::get - Out of fragments !! \n"));
134
135 if (iLeaveOnAllocFailure)
136 {
137 OSCL_LEAVE(OSCL_BAD_ALLOC_EXCEPTION_CODE);
138 }
139 return ret;
140 }
141
release(OsclRefCounterMemFrag & frag)142 OSCL_EXPORT_REF void PVMFBufferPoolAllocator::release(OsclRefCounterMemFrag& frag)
143 {
144 iAvailFragments.push_back(frag);
145 }
146
SetFailFrequency(uint16 aFrequency)147 OSCL_EXPORT_REF void PVMFBufferPoolAllocator::SetFailFrequency(uint16 aFrequency)
148 {
149 iFailFrequency = aFrequency;
150 }
151
152