• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef PVMF_SOCKET_BUFFER_ALLOCATORS_H_INCLUDED
19 #define PVMF_SOCKET_BUFFER_ALLOCATORS_H_INCLUDED
20 
21 #ifndef PVMF_CLIENTSERVER_SOCKET_TUNEABLES_H_INCLUDED
22 #include "pvmf_clientserver_socket_tuneables.h"
23 #endif
24 #ifndef OSCL_DEFALLOC_H_INCLUDED
25 #include "oscl_defalloc.h"
26 #endif
27 #ifndef PVLOGGER_H_INCLUDED
28 #include "pvlogger.h"
29 #endif
30 
31 #define PVMF_RESIZE_ALLOC_OVERHEAD 8
32 #define PVMF_RESIZE_ALLOC_BLK_SIZE_OFFSET 4
33 
34 // constants
35 const uint PVMF_SOCKET_BUF_DEFAULT_SIZE = 200;
36 
37 #define PVMF_SOCKALLOC_LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
38 #define PVMF_SOCKALLOC_LOGWARNING(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_WARNING,m);
39 #define PVMF_SOCKALLOC_LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m);
40 #define PVMF_SOCKALLOC_LOGINFO(m) PVMF_SOCKALLOC_LOGINFOLOW(m)
41 #define PVMF_SOCKALLOC_LOG_ALLOC_RESIZE_DEALLOC(m) PVMF_SOCKALLOC_LOGINFO(m)
42 #define PVMF_SOCKALLOC_LOG_SEQNUM_ALLOC_DEALLOC(m) PVMF_SOCKALLOC_LOGINFO(m)
43 #define PVMF_SOCKALLOC_LOG_OUT_OF_ORDER_DEALLOC(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iOOOLogger,PVLOGMSG_INFO,m);
44 #define PVMF_SOCKALLOC_LOG_MEMCALLBACK(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iCallBackLogger,PVLOGMSG_INFO,m);
45 #define PVMF_SOCKALLOC_LOG_AVAILABILITY(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iSizeLogger,PVLOGMSG_INFO,m);
46 
47 #define PVMF_SOCKALLOC_FILL_MEMBLK_ON_ALLOC 1
48 
49 static const char PVMF_SOCKALLOC_FEEDBACK_PORT_NAME[] = "PVMFJitterBufferPortFeedBack";
50 
51 class PVMFSMSharedBufferAllocWithReSizeAllocDeallocObserver
52 {
53     public:
54         virtual void chunkdeallocated(OsclAny* aContextData) = 0;
55 };
56 
57 /*
58  * This allocator is used to allocate socket buffers, for the purpose of
59  * doing a receive.
60  */
61 class PVMFSocketBufferAllocator : public Oscl_DefAlloc
62 {
63     public:
PVMFSocketBufferAllocator(uint32 numChunks,uint32 chunkSize)64         PVMFSocketBufferAllocator(uint32 numChunks, uint32 chunkSize)
65                 : alloc(numChunks, chunkSize)
66         {
67             iNumChunks = numChunks;
68             iChunkSize = chunkSize;
69             iNumOutStandingBuffers = 0;
70             IncrementKeepAliveCount();
71         };
72 
~PVMFSocketBufferAllocator()73         virtual ~PVMFSocketBufferAllocator() {};
74 
IncrementKeepAliveCount()75         void IncrementKeepAliveCount()
76         {
77             iNumOutStandingBuffers++;
78         }
79 
DecrementKeepAliveCount()80         void DecrementKeepAliveCount()
81         {
82             iNumOutStandingBuffers--;
83         }
84 
allocate(const uint32 n)85         OsclAny* allocate(const uint32 n)
86         {
87             iNumOutStandingBuffers++;
88             return (alloc.allocate(n));
89         }
90 
deallocate(OsclAny * p)91         void deallocate(OsclAny* p)
92         {
93             iNumOutStandingBuffers--;
94             alloc.deallocate(p);
95         }
96 
getNumOutStandingBuffers()97         uint32 getNumOutStandingBuffers()
98         {
99             return iNumOutStandingBuffers;
100         }
101 
102         uint32 getAvailableBufferSpace(bool aFirstParentChunkOnly = false)
103         {
104             OSCL_UNUSED_ARG(aFirstParentChunkOnly);
105             if (iNumChunks > iNumOutStandingBuffers)
106             {
107                 return ((iNumChunks - iNumOutStandingBuffers)*iChunkSize);
108             }
109             return 0;
110         }
111         void notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver& aObserver,
112                                       uint32 aSize,
113                                       OsclAny* aContextData = NULL)
114         {
115             OSCL_UNUSED_ARG(aSize);
116             alloc.notifyfreechunkavailable(aObserver, aContextData);
117         }
118 
CancelFreeChunkAvailableCallback()119         void CancelFreeChunkAvailableCallback()
120         {
121             alloc.CancelFreeChunkAvailableCallback();
122         }
123 
124     private:
125         uint32 iNumChunks;
126         uint32 iChunkSize;
127         OsclMemPoolFixedChunkAllocator alloc;
128         uint32 iNumOutStandingBuffers;
129 };
130 
131 class PVMFSocketBufferCleanupDA : public OsclDestructDealloc
132 {
133     public:
PVMFSocketBufferCleanupDA(Oscl_DefAlloc * in_gen_alloc)134         PVMFSocketBufferCleanupDA(Oscl_DefAlloc* in_gen_alloc) :
135 
136 
137                 gen_alloc(in_gen_alloc) {};
138 
~PVMFSocketBufferCleanupDA()139         virtual ~PVMFSocketBufferCleanupDA() {};
140 
destruct_and_dealloc(OsclAny * ptr)141         virtual void destruct_and_dealloc(OsclAny* ptr)
142         {
143             gen_alloc->deallocate(ptr);
144             /*
145              * in case there are no outstanding buffers delete the allocator
146              */
147             PVMFSocketBufferAllocator* socketDataAllocator =
148                 reinterpret_cast<PVMFSocketBufferAllocator*>(gen_alloc);
149 
150             uint32 numBuffers = socketDataAllocator->getNumOutStandingBuffers();
151 
152             if (numBuffers == 0)
153             {
154                 OSCL_DELETE((socketDataAllocator));
155             }
156         }
157 
158     private:
159         Oscl_DefAlloc* gen_alloc;
160 };
161 
162 class PVMFSMSharedBufferAllocWithReSize : public Oscl_DefAlloc
163 {
164     public:
PVMFSMSharedBufferAllocWithReSize(uint32 aParentChunkSize,const char name[])165         PVMFSMSharedBufferAllocWithReSize(uint32 aParentChunkSize, const char name[])
166         {
167             iLogger = NULL;
168             iSizeLogger = NULL;
169             iOOOLogger = NULL;
170             iLogger = PVLogger::GetLoggerObject("PVMFSMSharedBufferAllocWithReSize");
171             iSizeLogger = PVLogger::GetLoggerObject("PVMFSMSharedBufferAllocWithReSize.availability");
172             iCallBackLogger = PVLogger::GetLoggerObject("PVMFSMSharedBufferAllocWithReSize.memcallback");
173             iOOOLogger = PVLogger::GetLoggerObject("PVMFSMSharedBufferAllocWithReSize.ooo");
174             iName = name;
175 
176             iNumOutOfOrderDeallocs = 0;
177             iLastDeallocatedSeqNum = 0;
178             iSeqCount = 1;
179             iNumOutStandingBuffers = 0;
180 
181             iCallbackPending = false;
182             iCallbackRequestSize = 0;;
183             iObserver = NULL;
184             iNextAvailableContextData = NULL;
185 
186             iJJDataSize = 0;
187             iJJDataDbgSize = 0;
188 
189             if ((int32)aParentChunkSize <= 0)
190             {
191                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize - Invalid Parent Chunk size"));
192                 OSCL_LEAVE(OsclErrArgument);
193             }
194 
195             // set buffer resizing to default values
196             if (oscl_strcmp(iName.get_cstr(), PVMF_SOCKALLOC_FEEDBACK_PORT_NAME) == 0)
197             {
198                 iiRegrowthSize = DEFAULT_MAX_SOCKETMEMPOOL_RESIZELEN_FEEDBACK_PORT;
199             }
200             else
201             {
202                 iiRegrowthSize = DEFAULT_MAX_SOCKETMEMPOOL_RESIZELEN_INPUT_PORT;
203             }
204             iiMaxNumGrows = DEFAULT_MAX_NUM_SOCKETMEMPOOL_RESIZES;
205             iiNumGrows = 0;
206 
207             iDeallocObserver = NULL;
208             iDeallocNotificationContextData = NULL;
209 
210             CreateParentChunk(aParentChunkSize);
211 
212             IncrementKeepAliveCount();
213         }
214 
PVMFSMSharedBufferAllocWithReSize(uint32 aParentChunkSize,const char name[],int aMaxNumGrows,int aGrowSize)215         PVMFSMSharedBufferAllocWithReSize(uint32 aParentChunkSize, const char name[],
216                                           int aMaxNumGrows, int aGrowSize)
217         {
218             iLogger = NULL;
219             iSizeLogger = NULL;
220             iOOOLogger = NULL;
221             iLogger = PVLogger::GetLoggerObject("PVMFSMSharedBufferAllocWithReSize");
222             iSizeLogger = PVLogger::GetLoggerObject("PVMFSMSharedBufferAllocWithReSize.availability");
223             iCallBackLogger = PVLogger::GetLoggerObject("PVMFSMSharedBufferAllocWithReSize.memcallback");
224             iOOOLogger = PVLogger::GetLoggerObject("PVMFSMSharedBufferAllocWithReSize.ooo");
225             iName = name;
226             iCallbackPending = false;
227             iNumOutOfOrderDeallocs = 0;
228             iLastDeallocatedSeqNum = -1;
229             iSeqCount = 0;
230             iNumOutStandingBuffers = 0;
231 
232             iJJDataSize = 0;
233             iJJDataDbgSize = 0;
234             if ((int32)aParentChunkSize <= 0)
235             {
236                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize - Invalid Parent Chunk size"));
237                 OSCL_LEAVE(OsclErrArgument);
238             }
239 
240             // set buffer resizing to specified values
241             iiRegrowthSize = aGrowSize;
242             iiMaxNumGrows = aMaxNumGrows;
243             iiNumGrows = 0;
244 
245             iDeallocObserver = NULL;
246             iDeallocNotificationContextData = NULL;
247 
248             CreateParentChunk(aParentChunkSize);
249             IncrementKeepAliveCount();
250         }
251 
CreateParentChunk(uint32 aSize)252         void CreateParentChunk(uint32 aSize)
253         {
254             ParentChunkContainer parentChunkContainer;
255 
256             parentChunkContainer.id = iParentChunkContainerVec.size();
257             parentChunkContainer.iParentChunkSize = aSize;
258             parentChunkContainer.iParentChunkStart =
259                 (uint8*)(alloc.ALLOCATE(aSize));
260             parentChunkContainer.iParentChunkEnd =
261                 parentChunkContainer.iParentChunkStart + aSize;
262             parentChunkContainer.iAllocationPtr =
263                 parentChunkContainer.iParentChunkStart;
264 
265             iParentChunkContainerVec.push_back(parentChunkContainer);
266             PVMF_SOCKALLOC_LOGINFO((0, "PVMFSMSharedBufferAllocWithReSize::CreateParentChunk - Name=%s, Size=%d", iName.get_cstr(), aSize));
267         }
268 
~PVMFSMSharedBufferAllocWithReSize()269         virtual ~PVMFSMSharedBufferAllocWithReSize()
270         {
271             Oscl_Vector<ParentChunkContainer, OsclMemAllocator>::iterator it;
272 
273             for (it = iParentChunkContainerVec.begin();
274                     it != iParentChunkContainerVec.end();
275                     it++)
276             {
277                 alloc.deallocate(it->iParentChunkStart);
278             }
279 
280             if (iNumOutOfOrderDeallocs != 0)
281             {
282                 OSCL_ASSERT(false);
283             }
284 
285             iParentChunkContainerVec.clear();
286             iLogger = NULL;
287             iJJDataSize = 0;
288             iJJDataDbgSize = 0;
289             iNumOutStandingBuffers = 0;
290             iSeqCount = 0;
291             iLastDeallocatedSeqNum = -1;
292             iNumOutOfOrderDeallocs = 0;
293             iDeallocObserver = NULL;
294         };
295 
296         /*
297          * This allocator is used to create shared buffer which could have a lifetime
298          * that is longer than the module that actually created the allocator. Hence
299          * it is implemented in such a way that this allocator would de destroyed when
300          * all the outstanding buffers allocated by this alloacator are deallocated. Or
301          * in other words this allocator would be destroyed if and when iNumOutStandingBuffers
302          * becomes zero. This could cause problems when due to transient nature of data flow
303          * iNumOutStandingBuffers could become zero when the data flow drys up temporarily.
304          * Under such a scenario we would end up deleting the allocator prematurely. Inorder
305          * to avoid this, these keep alive mechanisms are provided. This ensures that the
306          * module that created the allocator can make sure that the allocator is alive atleast
307          * till its lifetime. Therefore allocator's life is the maximum of:
308          * (buffer life times, allocator creator's life time)
309          */
IncrementKeepAliveCount()310         void IncrementKeepAliveCount()
311         {
312             iDecKeepAliveCalled = false;
313             iNumOutStandingBuffers++;
314             PVMF_SOCKALLOC_LOGINFO((0, "PVMFSMSharedBufferAllocWithReSize::IncrementKeepAliveCount - Name=%s, iNumOutStandingBuffers=%d", iName.get_cstr(), iNumOutStandingBuffers));
315         }
316 
DecrementKeepAliveCount()317         void DecrementKeepAliveCount()
318         {
319             iDecKeepAliveCalled = true;
320             iNumOutStandingBuffers--;
321             PVMF_SOCKALLOC_LOGINFO((0, "PVMFSMSharedBufferAllocWithReSize::DecrementKeepAliveCount - Name=%s, iNumOutStandingBuffers=%d", iName.get_cstr(), iNumOutStandingBuffers));
322         }
323 
324         struct StatBlock
325         {
StatBlockStatBlock326             StatBlock()
327             {
328                 size = 0;
329                 seqNum = 0;
330             };
331 
332             uint32 size;
333             uint32 seqNum;
334         };
335 
336         struct OutOfOrderBlockContainer
337         {
OutOfOrderBlockContainerOutOfOrderBlockContainer338             OutOfOrderBlockContainer()
339             {
340                 ptr = NULL;
341                 seqNum = 0;
342             };
OutOfOrderBlockContainerOutOfOrderBlockContainer343             OutOfOrderBlockContainer(const OsclAny* p, uint32 s)
344             {
345                 ptr = p;
346                 seqNum = s;
347             };
348 
349             const OsclAny* ptr;
350             uint32 seqNum;
351         };
352 
353         class ReassemblyBlock
354         {
355 
356             public:
pnext(p)357                 ReassemblyBlock(const OsclAny* ptr, uint32 seqNum, ReassemblyBlock* p = NULL) : pnext(p)
358                 {
359                     rangeStart = rangeEnd = seqNum;
360                     blocks.push_back(OutOfOrderBlockContainer(ptr, seqNum));
361                 }
362 
~ReassemblyBlock()363                 ~ReassemblyBlock() { }
364 
IsInRange(uint32 seq)365                 bool IsInRange(uint32 seq)
366                 {
367                     return (seq >= rangeStart - 1) && (seq <= rangeEnd + 1);
368                 }
IsInRange(ReassemblyBlock & block)369                 bool IsInRange(ReassemblyBlock& block)
370                 {
371                     return (block.rangeStart == rangeEnd + 1);
372                 }
IsLess(uint32 seq)373                 bool IsLess(uint32 seq)
374                 {
375                     return seq < rangeStart;
376                 }
Merge(ReassemblyBlock & block)377                 void Merge(ReassemblyBlock& block)
378                 {
379                     for (uint i = 0; i < block.blocks.size(); i++)
380                     {
381                         blocks.push_back(block.blocks[i]);
382                         rangeEnd++;
383                     }
384 
385                     rangeEnd = block.rangeEnd;
386                 }
Insert(const OsclAny * ptr,uint32 seqNum)387                 bool Insert(const OsclAny* ptr, uint32 seqNum)
388                 {
389                     if (seqNum == rangeEnd + 1)
390                     {
391                         blocks.push_back(OutOfOrderBlockContainer(ptr, seqNum));
392                         rangeEnd++;
393                         return true;
394                     }
395                     else if (seqNum == rangeStart - 1)
396                     {
397                         blocks.push_front(OutOfOrderBlockContainer(ptr, seqNum));
398                         rangeStart--;
399                         return true;
400                     }
401                     else
402                     {
403                         //OSCL_ASSERT(false);
404                         return false;
405                     }
406                 }
407 
Blocks()408                 Oscl_Vector<OutOfOrderBlockContainer, OsclMemAllocator>* Blocks()
409                 {
410                     return &blocks;
411                 }
412                 ReassemblyBlock* pnext;
413 
414             private:
415                 uint32 rangeStart;
416                 uint32 rangeEnd;
417                 Oscl_Vector<OutOfOrderBlockContainer, OsclMemAllocator> blocks;
418         };
419 
420         class ReassemblyBlockList
421         {
422             public:
ReassemblyBlockList()423                 ReassemblyBlockList()
424                 {
425                     phead = NULL;
426                 }
~ReassemblyBlockList()427                 ~ReassemblyBlockList() { }
428 
Insert(const OsclAny * ptr,uint32 seq)429                 bool Insert(const OsclAny* ptr, uint32 seq)
430                 {
431                     bool oRet = true;
432                     ReassemblyBlock** pp = &phead;
433                     while (1)
434                     {
435                         if (*pp == NULL)
436                         {
437                             *pp = OSCL_NEW(ReassemblyBlock, (ptr, seq));
438                             break;
439                         }
440                         else if ((*pp)->IsInRange(seq))
441                         {
442                             oRet = (*pp)->Insert(ptr, seq);
443                             break;
444                         }
445                         else if ((*pp)->IsLess(seq))
446                         {
447                             ReassemblyBlock* p = *pp;
448                             *pp = OSCL_NEW(ReassemblyBlock, (ptr, seq, p));
449                             break;
450                         }
451                         else
452                         {
453                             pp = &(*pp)->pnext;
454                         }
455                     }
456                     pp = &phead;
457                     while ((*pp)->pnext != NULL)
458                     {
459                         if ((*pp)->IsInRange(*((*pp)->pnext)))
460                         {
461                             (*pp)->Merge(*((*pp)->pnext));
462                             ReassemblyBlock* p = (*pp)->pnext;
463                             (*pp)->pnext = (*pp)->pnext->pnext;
464                             OSCL_DELETE(p);
465                         }
466                         else
467                         {
468                             pp = &(*pp)->pnext;
469                         }
470                     }
471                     return oRet;
472                 }
473 
GetDeletables(uint32 seqNum)474                 Oscl_Vector<OutOfOrderBlockContainer, OsclMemAllocator>* GetDeletables(uint32 seqNum)
475                 {
476                     if (phead == NULL)
477                     {
478                         return NULL;
479                     }
480                     else if (phead->IsInRange(seqNum))
481                     {
482                         return phead->Blocks();
483                     }
484                     else
485                     {
486                         return NULL;
487                     }
488                 }
Prune()489                 void Prune()
490                 {
491                     OSCL_ASSERT(phead != NULL);
492                     ReassemblyBlock* p = phead;
493                     phead = p->pnext;
494                     OSCL_DELETE(p);
495                 }
496 /////// START: clean the head
GetHeadDeletables(uint32 headSeqNum)497                 Oscl_Vector<OutOfOrderBlockContainer, OsclMemAllocator>* GetHeadDeletables(uint32 headSeqNum)
498                 {
499                     ReassemblyBlock *my_ptr = phead;
500 
501                     while (my_ptr != NULL)
502                     {
503                         if (my_ptr->IsInRange(headSeqNum))
504                         { //ok, we got a consecutive chunk end with headSeqNum-1
505                             return my_ptr->Blocks();
506                         }
507 
508                         my_ptr = my_ptr->pnext;
509                     }
510                     return NULL;
511                 }
PruneHead(Oscl_Vector<OutOfOrderBlockContainer,OsclMemAllocator> * ptrBlk)512                 void PruneHead(Oscl_Vector<OutOfOrderBlockContainer, OsclMemAllocator>* ptrBlk)
513                 {
514                     OSCL_ASSERT(phead != NULL);
515                     if (phead->Blocks() == ptrBlk)
516                     {
517                         OSCL_DELETE(phead);
518                         phead = NULL;
519                         return;
520                     }
521 
522                     ReassemblyBlock *myParent_ptr = phead;
523                     ReassemblyBlock *my_ptr = myParent_ptr->pnext;
524 
525                     while (my_ptr != NULL)
526                     {
527                         if (my_ptr->Blocks() == ptrBlk)
528                         {
529                             OSCL_DELETE(my_ptr);
530                             myParent_ptr->pnext = NULL;
531                             return;
532                         }
533 
534                         myParent_ptr = my_ptr;
535                         my_ptr = my_ptr->pnext;
536                     }
537                     OSCL_ASSERT(false);
538                 }
539 /////// END: clean the head
540             private:
541                 ReassemblyBlock* phead;
542         };
543 
544 
545         struct ParentChunkContainer
546         {
ParentChunkContainerParentChunkContainer547             ParentChunkContainer()
548             {
549                 id = 0xFFFFFFFF;
550                 iParentChunkStart = NULL;
551                 iParentChunkEnd = NULL;
552                 iAllocationPtr = NULL;
553                 iEndOfLastDeallocatedBlock = NULL;
554                 iParentChunkSize = 0;
555             };
556             uint32 id;
557             uint8* iParentChunkStart;
558             uint8* iParentChunkEnd;
559             uint32 iParentChunkSize;
560             uint8* iAllocationPtr;
561             uint8* iEndOfLastDeallocatedBlock;
562         };
563 
564         enum PVMF_RESIZE_ALLOC_ERROR_CODE
565         {
566             PVMF_RESIZE_ALLOC_SUCCESS,
567             PVMF_RESIZE_ALLOC_NO_MEMORY,
568             PVMF_RESIZE_ALLOC_MEMORY_CORRUPT,
569             PVMF_RESIZE_OUT_OF_ORDER_BLOCK
570         };
571 
572         PVMF_RESIZE_ALLOC_ERROR_CODE
AllocateInParentChunk(ParentChunkContainer * aPCContainer,OsclAny * & aRequestPtr,const uint32 aReqBlkSize)573         AllocateInParentChunk(ParentChunkContainer* aPCContainer,
574                               OsclAny*& aRequestPtr,
575                               const uint32 aReqBlkSize)
576         {
577             uint32 n = aReqBlkSize + PVMF_RESIZE_ALLOC_OVERHEAD;
578             uint32 availSize = FindLargestContiguousFreeBlock(aPCContainer);
579             if (n > availSize)
580             {
581                 PVMF_SOCKALLOC_LOGINFO((0, "PVMFSMSharedBufferAllocWithReSize::AllocateInParentChunk - No Memory1 Name=%s, ChunkID=%d, ReqSize=%d, AvailSize=%d", iName.get_cstr(), aPCContainer->id, n, availSize));
582                 return (PVMF_RESIZE_ALLOC_NO_MEMORY);
583             }
584             /*
585              * Check and see if the block being allocated would
586              * cause a wrap around of the "iAllocationPtr"
587              */
588             if ((aPCContainer->iAllocationPtr + n) > aPCContainer->iParentChunkEnd)
589             {
590                 /*
591                  * This implies that the requested block is larger
592                  * than whats left towards the end of the parent chunk.
593                  * Since we cannot provide memory in fragments, we
594                  * have to ignore this chunk, wrap the allocation ptr
595                  * to start of the parent chunk and check for alloc size.
596                  */
597                 aPCContainer->iAllocationPtr = aPCContainer->iParentChunkStart;
598             }
599             /*
600              * Next check if we can accomodate this request in one
601              * contiguous block between the current alloc ptr and
602              * last deallocated ptr. Please note that we make use
603              * of the fact that deallocation happens sequentially.
604              * Or in other words blocks are freed in the order
605              * in which they are allocated
606              *
607              * There are two possibilites:
608              * 1) iAllocationPtr < iEndOfLastDeallocatedBlock - This means
609              * that a wrap around has happenned, and we need to check
610              * if there is a large enough block between the two ptrs.
611              * Please note that we assume that the space between
612              * iAllocationPtr and iEndOfLastDeallocatedBlock is all free.
613              * Reason being that blocks are deallocated in the same
614              * order in which they are allocated.
615              *
616              * 2) iAllocationPtr > iEndOfLastDeallocatedBlock - This means
617              * we are ok. Any discrepancies must have been detected
618              * by earlier checks.
619              */
620             if (aPCContainer->iAllocationPtr < aPCContainer->iEndOfLastDeallocatedBlock)
621             {
622                 uint32 diff = (aPCContainer->iEndOfLastDeallocatedBlock -
623                                aPCContainer->iAllocationPtr);
624                 if (diff >= n)
625                 {
626                     iNumOutStandingBuffers++;
627                 }
628                 else
629                 {
630                     /*
631                      * We do not have a large enough block to
632                      * satisfy this request.
633                      */
634                     PVMF_SOCKALLOC_LOGINFO((0, "PVMFSMSharedBufferAllocWithReSize::AllocateInParentChunk - No Memory2 Name=%s, ChunkID=%d, ReqSize=%d, AvailSize=%d", iName.get_cstr(), aPCContainer->id, n, diff));
635                     return (PVMF_RESIZE_ALLOC_NO_MEMORY);
636                 }
637             }
638             else
639             {
640                 iNumOutStandingBuffers++;
641             }
642             /* Set sequence number */
643             oscl_memcpy(aPCContainer->iAllocationPtr, &iSeqCount, sizeof(uint32));
644             /* Set size */
645             oscl_memcpy((aPCContainer->iAllocationPtr + PVMF_RESIZE_ALLOC_BLK_SIZE_OFFSET),
646                         &aReqBlkSize,
647                         sizeof(uint32));
648             aRequestPtr = (OsclAny*)(aPCContainer->iAllocationPtr +
649                                      PVMF_RESIZE_ALLOC_OVERHEAD);
650 
651 #if PVMF_SOCKALLOC_FILL_MEMBLK_ON_ALLOC
652             uint32 value = 0x00;
653             oscl_memset(aRequestPtr, value, aReqBlkSize);
654 #endif
655             // need to remove begin and end variables because of compiler warnings
656             PVMF_SOCKALLOC_LOG_SEQNUM_ALLOC_DEALLOC((0, "PVMFSMSharedBufferAllocWithReSize::allocate - Alloc SeqNum=%d", iSeqCount));
657 
658             PVMF_SOCKALLOC_LOG_ALLOC_RESIZE_DEALLOC((0, "PVMFSMReSize::allocate - "
659                                                     "SeqNum=%d, PtrS=0x%x, PtrE=0x%x, Begin=%d, End=%d, AllocSize=%d, LastDeallocPtr=0x%x, Avail=%d",
660                                                     iSeqCount,
661                                                     aPCContainer->iAllocationPtr,
662                                                     aPCContainer->iAllocationPtr + n,
663                                                     (aPCContainer->iAllocationPtr - aPCContainer->iParentChunkStart),
664                                                     (aPCContainer->iAllocationPtr - aPCContainer->iParentChunkStart) + n,
665                                                     n,
666                                                     aPCContainer->iEndOfLastDeallocatedBlock,
667                                                     getTotalAvailableBufferSpace()));
668             aPCContainer->iAllocationPtr += n;
669 
670             PVMF_SOCKALLOC_LOG_AVAILABILITY((0, "PVMFSMSBAWithReSize::allocate - Name=%s, SN=%d, Alloc=%d, Avail=%d, BufsOS=%d",
671                                              iName.get_cstr(), iSeqCount, n, getTotalAvailableBufferSpace(), iNumOutStandingBuffers));
672 
673             iSeqCount++;
674 
675             iJJDataSize += aReqBlkSize;
676             iJJDataDbgSize += aReqBlkSize;
677 
678             return (PVMF_RESIZE_ALLOC_SUCCESS);
679         }
680 
allocate(const uint32 n)681         OsclAny* allocate(const uint32 n)
682         {
683             OsclAny* requestPtr = NULL;
684             PVMF_RESIZE_ALLOC_ERROR_CODE errCode;
685 
686             Oscl_Vector<ParentChunkContainer, OsclMemAllocator>::iterator it;
687 
688             for (it = iParentChunkContainerVec.begin();
689                     it != iParentChunkContainerVec.end();
690                     it++)
691             {
692                 errCode = AllocateInParentChunk(it, requestPtr, n);
693 
694                 if (errCode == PVMF_RESIZE_ALLOC_MEMORY_CORRUPT)
695                 {
696                     PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::allocate - MEMORY CHUNKS CORRUPT!!! Name=%s", iName.get_cstr()));
697                     OSCL_LEAVE(OsclErrCorrupt);
698                 }
699                 else if (errCode == PVMF_RESIZE_ALLOC_SUCCESS)
700                 {
701                     return requestPtr;
702                 }
703             }
704             /*
705              * This implies that we cannot accomodate the request in any
706              * of the existing chunks. Allocate a new parent chunk.
707              */
708             if (iiNumGrows == iiMaxNumGrows)
709             {
710                 //PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::allocate - Unable to add an another buffer. Limit exceeded.", iName.get_cstr()));
711                 OSCL_LEAVE(OsclErrNoMemory);  // not graceful - can I return NULL instead? TBD.
712             }
713             iiNumGrows++;
714             CreateParentChunk(iiRegrowthSize);
715 
716             PVMF_SOCKALLOC_LOGINFO((0, "PVMFSMSharedBufferAllocWithReSize::allocate - EXPANDING JITTER BUFFER - Name=%s, Size=%d", iName.get_cstr(), iiRegrowthSize));
717 
718             ParentChunkContainer newPCContainer = iParentChunkContainerVec.back();
719 
720             errCode = AllocateInParentChunk(&newPCContainer, requestPtr, n);
721             iParentChunkContainerVec[iParentChunkContainerVec.size()-1] = newPCContainer;
722 
723             if (errCode == PVMF_RESIZE_ALLOC_MEMORY_CORRUPT)
724             {
725                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::allocate - MEMORY CHUNKS CORRUPT!!! Name=%s", iName.get_cstr()));
726                 OSCL_LEAVE(OsclErrCorrupt);
727             }
728             else if (errCode == PVMF_RESIZE_ALLOC_NO_MEMORY)
729             {
730                 /* Too big of a request */
731                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::allocate - TOO BIG A REQUEST Name=%s, ReqSize=%d", iName.get_cstr(), n));
732                 OSCL_LEAVE(OsclErrNoMemory);
733             }
734             return requestPtr;
735         }
736 
FindParentChunk(const OsclAny * p)737         ParentChunkContainer* FindParentChunk(const OsclAny* p)
738         {
739             const uint8* deallocPtr = reinterpret_cast<const uint8*>(p);
740 
741             Oscl_Vector<ParentChunkContainer, OsclMemAllocator>::iterator it;
742 
743             for (it = iParentChunkContainerVec.begin();
744                     it != iParentChunkContainerVec.end();
745                     it++)
746             {
747                 if ((deallocPtr >= it->iParentChunkStart) &&
748                         (deallocPtr < it->iParentChunkEnd))
749                 {
750                     return (it);
751                 }
752             }
753             return NULL;
754         }
755 
756         PVMF_RESIZE_ALLOC_ERROR_CODE
757         DeallocateFromParentChunk(ParentChunkContainer* aPCContainer,
758                                   const OsclAny* aDeallocPtr,
759                                   bool oEnableOutofOrderCheck = true)
760         {
761             uint32 seqNum = 0;
762             uint32 blkSize = 0;
763             uint8* p = ((uint8*)(aDeallocPtr) - PVMF_RESIZE_ALLOC_OVERHEAD);
764             /* Get the corresponding block size & seqnum from the pointer itself */
765             oscl_memcpy(&seqNum, (OsclAny*)p, sizeof(uint32));
766             oscl_memcpy(&blkSize, (OsclAny*)(p + PVMF_RESIZE_ALLOC_BLK_SIZE_OFFSET), sizeof(uint32));
767             blkSize += PVMF_RESIZE_ALLOC_OVERHEAD;
768             if (oEnableOutofOrderCheck)
769             {
770                 iJJDataSize -= (blkSize - PVMF_RESIZE_ALLOC_OVERHEAD);
771                 if (seqNum != (uint32)(iLastDeallocatedSeqNum + 1))
772                 {
773                     if (seqNum + 1 == iSeqCount)
774                     {//just allocated, now free, so we pretend we didn't allocate this one to increase mem efficiency
775                         if (aPCContainer->iAllocationPtr != p + blkSize)
776                         {
777                             PVMF_SOCKALLOC_LOG_ALLOC_RESIZE_DEALLOC((0, "SM ATTN seqNum %d blkSize %d iAlloc 0x%x p 0x%x Ln %d"
778                                                                     , seqNum, blkSize, aPCContainer->iAllocationPtr, p, __LINE__));
779                             PVMF_SOCKALLOC_LOG_ALLOC_RESIZE_DEALLOC((0, "SM ATTN start 0x%x end 0x%x lastD 0x%x Ln %d"
780                                                                     , aPCContainer->iParentChunkStart, aPCContainer->iParentChunkEnd, aPCContainer->iEndOfLastDeallocatedBlock, __LINE__));
781                         }
782 
783                         iJJDataDbgSize -= (blkSize - PVMF_RESIZE_ALLOC_OVERHEAD);
784 
785                         aPCContainer->iAllocationPtr = p;
786 
787                         iNumOutStandingBuffers--;
788                         iSeqCount--;
789                         return (PVMF_RESIZE_ALLOC_SUCCESS);
790                     }
791 
792                     bool oRet = iOutOfOrderBlocks.Insert(aDeallocPtr, seqNum);
793                     if (oRet == true)
794                     {
795                         iNumOutOfOrderDeallocs++;
796                     }
797                     PVMF_SOCKALLOC_LOG_OUT_OF_ORDER_DEALLOC((0, "PVMFSMSharedBufferAllocWithReSize::DeallocateFromParentChunk - OOO Dealloc SeqNum=%d, Size=%d, Ptr=0x%x, NumOOODeallocs=%d", seqNum, blkSize, p, iNumOutOfOrderDeallocs));
798                     return (PVMF_RESIZE_OUT_OF_ORDER_BLOCK);
799                 }
800 
801             }
802 
803             iJJDataDbgSize -= (blkSize - PVMF_RESIZE_ALLOC_OVERHEAD);
804 
805             iLastDeallocatedSeqNum = (int32)(seqNum);
806             aPCContainer->iEndOfLastDeallocatedBlock = ((uint8*)p + blkSize);
807 
808             if (aPCContainer->iEndOfLastDeallocatedBlock == aPCContainer->iAllocationPtr)
809             {
810                 aPCContainer->iEndOfLastDeallocatedBlock = NULL;
811                 aPCContainer->iAllocationPtr = aPCContainer->iParentChunkStart;
812             }
813             iNumOutStandingBuffers--;
814 
815 #if PVMF_SOCKALLOC_FILL_MEMBLK_ON_ALLOC
816             uint32 value = 0x00;
817             oscl_memset(p, value, blkSize);
818 #endif
819             // need to remove begin and end variables because of compiler warnings
820             PVMF_SOCKALLOC_LOG_SEQNUM_ALLOC_DEALLOC((0, "PVMFSMSharedBufferAllocWithReSize::DeallocateFromParentChunk - Dealloc SeqNum=%d", iLastDeallocatedSeqNum));
821             PVMF_SOCKALLOC_LOG_ALLOC_RESIZE_DEALLOC((0, "PVMFSMReSize::Dealloc - "
822                                                     "SeqNum=%d, PtrS=0x%x, PtrE=0x%x, Begin=%d, End=%d, BlockSize=%d, LastDeallocatedPtr=0x%x, Avail=%d",
823                                                     seqNum,
824                                                     p,
825                                                     p + blkSize,
826                                                     ((uint8*)p - aPCContainer->iParentChunkStart),
827                                                     ((uint8*)p - aPCContainer->iParentChunkStart) + blkSize,
828                                                     blkSize,
829                                                     aPCContainer->iEndOfLastDeallocatedBlock,
830                                                     getTotalAvailableBufferSpace()));
831             PVMF_SOCKALLOC_LOG_AVAILABILITY((0, "PVMFSMSBAWithReSize::DeallocateFromParentChunk - Name=%s, SN=%d, Dealloc=%d, Avail=%d, BufsOS=%d",
832                                              iName.get_cstr(), seqNum, blkSize, getTotalAvailableBufferSpace(), iNumOutStandingBuffers));
833             return (PVMF_RESIZE_ALLOC_SUCCESS);
834         }
835 
836         PVMF_RESIZE_ALLOC_ERROR_CODE
SearchAndDeallocateAnyPrevOutofOrderBlocks(uint32 aSeqNum)837         SearchAndDeallocateAnyPrevOutofOrderBlocks(uint32 aSeqNum)
838         {
839             Oscl_Vector<OutOfOrderBlockContainer, OsclMemAllocator>* deleteList =
840                 iOutOfOrderBlocks.GetDeletables(aSeqNum);
841 
842             if (deleteList == NULL)
843             {
844                 return (PVMF_RESIZE_ALLOC_SUCCESS);
845             }
846 
847             for (uint i = 0; i < (*deleteList).size(); i++)
848             {
849                 DeallocateOutofOrderBlock((*deleteList)[i].ptr);
850                 iNumOutOfOrderDeallocs--;
851             }
852 
853             iOutOfOrderBlocks.Prune();
854             return (PVMF_RESIZE_ALLOC_SUCCESS);
855         }
856 
DeallocateOutofOrderBlock(const OsclAny * p)857         void DeallocateOutofOrderBlock(const OsclAny* p)
858         {
859             ParentChunkContainer* parentChunkContainer = FindParentChunk(p);
860 
861             if (parentChunkContainer == NULL)
862             {
863                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::DeallocateOutofOrderBlock - INVALID PTR!!! Name=%s", iName.get_cstr()));
864                 OSCL_LEAVE(OsclErrArgument);
865             }
866             bool oEnableOutofOrderCheck = false;
867             if (DeallocateFromParentChunk(parentChunkContainer, p, oEnableOutofOrderCheck) == PVMF_RESIZE_ALLOC_MEMORY_CORRUPT)
868             {
869                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::DeallocateOutofOrderBlock - CORRUPT PTR!!! Name=%s", iName.get_cstr()));
870                 OSCL_LEAVE(OsclErrArgument);
871             }
872         }
873 
PurgeOutofOrderBlockVec()874         void PurgeOutofOrderBlockVec()
875         {
876             if (iOutofOrderBlockVec.size() > 0)
877             {
878                 Oscl_Vector<OutOfOrderBlockContainer, OsclMemAllocator>::iterator it;
879                 uint32 count = iOutofOrderBlockVec.size();
880                 if (count != iNumOutOfOrderDeallocs)
881                 {
882                     OSCL_ASSERT(false);
883                 }
884                 while (iOutofOrderBlockVec.size() > 0)
885                 {
886                     it = iOutofOrderBlockVec.begin();
887                     DeallocateOutofOrderBlock(it->ptr);
888                     iOutofOrderBlockVec.erase(it);
889                 }
890             }
891         }
892 
deallocate(OsclAny * p)893         virtual void deallocate(OsclAny* p)
894         {
895             ParentChunkContainer* parentChunkContainer = FindParentChunk(p);
896             if (parentChunkContainer == NULL)
897             {
898                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::deallocate - INVALID PTR!!! Name=%s", iName.get_cstr()));
899                 OSCL_LEAVE(OsclErrArgument);
900             }
901             /* Deallocate the current ptr */
902             PVMF_RESIZE_ALLOC_ERROR_CODE errCode = DeallocateFromParentChunk(parentChunkContainer, p);
903 
904             if (errCode == PVMF_RESIZE_ALLOC_MEMORY_CORRUPT)
905             {
906                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::deallocate - CORRUPT PTR - 2!!! Name=%s", iName.get_cstr()));
907                 OSCL_LEAVE(OsclErrArgument);
908             }
909             else if ((errCode == PVMF_RESIZE_ALLOC_SUCCESS) || (errCode == PVMF_RESIZE_OUT_OF_ORDER_BLOCK))
910             {
911                 if (iDeallocObserver != NULL)
912                 {
913                     iDeallocObserver->chunkdeallocated(iDeallocNotificationContextData);
914                 }
915                 /* Deallocate any out of order blocks */
916                 if (iNumOutOfOrderDeallocs > 0)
917                 {
918                     SearchAndDeallocateAnyPrevOutofOrderBlocks(iLastDeallocatedSeqNum);
919                 }
920 
921                 if (iNumOutOfOrderDeallocs > 0)
922                 {//delete from head, maybe?
923                     Oscl_Vector<OutOfOrderBlockContainer, OsclMemAllocator>* deleteList =
924                         iOutOfOrderBlocks.GetHeadDeletables(iSeqCount);
925 
926                     if (NULL != deleteList)
927                     {
928                         for (int32 i = (*deleteList).size() - 1; i >= 0; i--)
929                         {
930                             uint8* p = (uint8*)((*deleteList)[i].ptr);
931                             ParentChunkContainer* parentChunkContainer = FindParentChunk(p);
932 
933                             if (parentChunkContainer == NULL)
934                             {
935                                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::deallocate - INVALID PTR!!! Name=%s Ln %d", iName.get_cstr(), __LINE__));
936                                 OSCL_LEAVE(OsclErrArgument);
937                             }
938                             uint32 seqNum = 0;
939                             uint32 blkSize = 0;
940                             p -= PVMF_RESIZE_ALLOC_OVERHEAD;
941                             /* Get the corresponding block size & seqnum from the pointer itself */
942                             oscl_memcpy(&seqNum, (OsclAny*)p, sizeof(uint32));
943                             oscl_memcpy(&blkSize, (OsclAny*)(p + PVMF_RESIZE_ALLOC_BLK_SIZE_OFFSET), sizeof(uint32));
944 
945                             if (seqNum + 1 != iSeqCount)
946                             {
947                                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::deallocate - ERROR seqNum %d iSeqCount %d Name=%s", seqNum, iSeqCount, iName.get_cstr()));
948                                 OSCL_LEAVE(OsclErrArgument);
949                             }
950 
951                             if (p + blkSize + PVMF_RESIZE_ALLOC_OVERHEAD != parentChunkContainer->iAllocationPtr)
952                             {//just for logging wrap-around
953                                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::deallocate - p 0x%x iAllocPtr 0x%x seqNum %d iSeqCount %d Name=%s",
954                                                          p, parentChunkContainer->iAllocationPtr, seqNum, iSeqCount, iName.get_cstr()));
955                             }
956                             parentChunkContainer->iAllocationPtr = p;
957 
958                             OSCL_ASSERT(parentChunkContainer->iAllocationPtr != parentChunkContainer->iEndOfLastDeallocatedBlock);
959 
960                             iNumOutOfOrderDeallocs--;
961                             iNumOutStandingBuffers--;
962                             iSeqCount--;
963                             iJJDataDbgSize -= blkSize;
964                         }
965 
966                         iOutOfOrderBlocks.PruneHead(deleteList);
967                     }
968                 }
969             }
970             CheckAndNotifyFreeChunkAvailable();
971         }
972 
973         PVMF_RESIZE_ALLOC_ERROR_CODE
ReSizeFromParentChunk(ParentChunkContainer * aPCContainer,OsclAny * aPtr,uint32 aBytesToReclaim)974         ReSizeFromParentChunk(ParentChunkContainer* aPCContainer,
975                               OsclAny* aPtr,
976                               uint32 aBytesToReclaim)
977         {
978             uint32 seqNum = 0;
979             uint32 blkSize = 0;
980             uint8* p = ((uint8*)(aPtr) - PVMF_RESIZE_ALLOC_OVERHEAD);
981             /* Get the corresponding block size & seqnum from the pointer itself */
982             oscl_memcpy(&seqNum, (OsclAny*)p, sizeof(uint32));
983             oscl_memcpy(&blkSize, (OsclAny*)(p + PVMF_RESIZE_ALLOC_BLK_SIZE_OFFSET), sizeof(uint32));
984             if (aBytesToReclaim > blkSize)
985             {
986                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::ReSizeFromParentChunk - Invalid Reclaim Size - Name=%s, ChunkID=%d, SeqNum=%d, Ptr=0x%x, BlockSize=%d, ReclaimSize=%d", iName.get_cstr(), aPCContainer->id, seqNum, p, blkSize, aBytesToReclaim));
987                 return (PVMF_RESIZE_ALLOC_MEMORY_CORRUPT);
988             }
989             blkSize -= aBytesToReclaim;
990             aPCContainer->iAllocationPtr -= aBytesToReclaim;
991 
992             iJJDataSize -= aBytesToReclaim;
993             iJJDataDbgSize -= aBytesToReclaim;
994             if (iSeqCount > seqNum + 1)
995             {
996                 //Resize can ONLY be applied to the buffer just allocated.
997                 PVMF_SOCKALLOC_LOGERROR((0, "Resize ERROR seq %d iSeqCount %d iJJDataSize %d", seqNum, iSeqCount, iJJDataSize));
998                 return (PVMF_RESIZE_ALLOC_MEMORY_CORRUPT);
999             }
1000             /* reset the block size */
1001             oscl_memcpy((OsclAny*)(p + PVMF_RESIZE_ALLOC_BLK_SIZE_OFFSET),
1002                         &blkSize,
1003                         sizeof(uint32));
1004             // need to remove begin and end variables because of compiler warnings
1005             PVMF_SOCKALLOC_LOG_ALLOC_RESIZE_DEALLOC((0, "PVMFSMReSize::ReSize - "
1006                                                     "SeqNum=%d, PtrS=0x%x, PtrE=0x%x, AllocPtr=0x%x, Begin=%d, End=%d, NewSize=%d, Avail=%d",
1007                                                     seqNum,
1008                                                     p,
1009                                                     p + blkSize + PVMF_RESIZE_ALLOC_OVERHEAD,
1010                                                     aPCContainer->iAllocationPtr,
1011                                                     (p - aPCContainer->iParentChunkStart),
1012                                                     (p - aPCContainer->iParentChunkStart) + blkSize + PVMF_RESIZE_ALLOC_OVERHEAD,
1013                                                     blkSize,
1014                                                     getTotalAvailableBufferSpace()));
1015             PVMF_SOCKALLOC_LOG_AVAILABILITY((0, "PVMFSMSBAWithReSize::ReSizeFromParentChunk - Name=%s, SN=%d, Reclaim=%d, Avail=%d",
1016                                              iName.get_cstr(), seqNum, aBytesToReclaim, getTotalAvailableBufferSpace()));
1017             return (PVMF_RESIZE_ALLOC_SUCCESS);
1018         }
1019 
resize(OsclAny * p,uint32 aBytesToReclaim)1020         void resize(OsclAny* p, uint32 aBytesToReclaim)
1021         {
1022             ParentChunkContainer* parentChunkContainer = FindParentChunk(p);
1023 
1024             if (parentChunkContainer == NULL)
1025             {
1026                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::resize - INVALID PTR!!! Name=%s", iName.get_cstr()));
1027                 OSCL_LEAVE(OsclErrArgument);
1028             }
1029             if (ReSizeFromParentChunk(parentChunkContainer,
1030                                       p,
1031                                       aBytesToReclaim) == PVMF_RESIZE_ALLOC_MEMORY_CORRUPT)
1032             {
1033                 PVMF_SOCKALLOC_LOGERROR((0, "PVMFSMSharedBufferAllocWithReSize::resize - INVALID PTR!!! Name=%s", iName.get_cstr()));
1034                 OSCL_LEAVE(OsclErrArgument);
1035             }
1036             CheckAndNotifyFreeChunkAvailable();
1037         }
1038 
getNumOutStandingBuffers()1039         uint32 getNumOutStandingBuffers()
1040         {
1041             return iNumOutStandingBuffers;
1042         }
1043 
getTotalBufferSize()1044         uint32 getTotalBufferSize()
1045         {
1046             uint32 totalsize = 0;
1047             Oscl_Vector<ParentChunkContainer, OsclMemAllocator>::iterator it;
1048             for (it = iParentChunkContainerVec.begin();
1049                     it != iParentChunkContainerVec.end();
1050                     it++)
1051             {
1052                 totalsize += it->iParentChunkSize;
1053             }
1054             return (totalsize);
1055         }
1056 
getTotalAvailableBufferSpace()1057         uint32 getTotalAvailableBufferSpace()
1058         {
1059             uint32 freespace = 0;
1060             Oscl_Vector<ParentChunkContainer, OsclMemAllocator>::iterator it;
1061             if ((iNumOutStandingBuffers == 1) &&
1062                     (iDecKeepAliveCalled == false))
1063             {
1064                 // all outstanding buffers have been freed
1065                 freespace = getTotalBufferSize();
1066                 for (it = iParentChunkContainerVec.begin();
1067                         it != iParentChunkContainerVec.end();
1068                         it++)
1069                 {
1070                     it->iEndOfLastDeallocatedBlock = NULL;
1071                     it->iAllocationPtr = it->iParentChunkStart;
1072                 }
1073             }
1074             else
1075             {
1076                 for (it = iParentChunkContainerVec.begin();
1077                         it != iParentChunkContainerVec.end();
1078                         it++)
1079                 {
1080                     freespace += FindLargestContiguousFreeBlock(it);
1081                 }
1082             }
1083             return (freespace);
1084         }
1085 
getActualDataSize()1086         uint32 getActualDataSize()
1087         {
1088             return iJJDataSize;
1089         }
1090 
getTrueBufferSpace()1091         uint32 getTrueBufferSpace()
1092         {
1093             uint32 truespace = 0;
1094             Oscl_Vector<ParentChunkContainer, OsclMemAllocator>::iterator it;
1095             if ((iNumOutStandingBuffers == 1) &&
1096                     (iDecKeepAliveCalled == false))
1097             {
1098                 // all outstanding buffers have been freed
1099                 truespace = getTotalBufferSize();
1100                 for (it = iParentChunkContainerVec.begin();
1101                         it != iParentChunkContainerVec.end();
1102                         it++)
1103                 {
1104                     it->iEndOfLastDeallocatedBlock = NULL;
1105                     it->iAllocationPtr = it->iParentChunkStart;
1106                 }
1107             }
1108             else
1109             {
1110                 for (it = iParentChunkContainerVec.begin();
1111                         it != iParentChunkContainerVec.end();
1112                         it++)
1113                 {
1114                     uint32 maxSize = 0;
1115                     if (it != NULL)
1116                     {
1117                         if (it->iEndOfLastDeallocatedBlock == NULL)
1118                         {
1119                             /*
1120                              * Implies that there is no deallocations have happenned
1121                              */
1122                             maxSize =
1123                                 (it->iParentChunkEnd - it->iAllocationPtr);
1124                         }
1125                         else
1126                         {
1127                             if (it->iAllocationPtr <= it->iEndOfLastDeallocatedBlock)
1128                             {
1129                                 maxSize =
1130                                     (it->iEndOfLastDeallocatedBlock - it->iAllocationPtr);
1131                             }
1132                             else
1133                             {
1134                                 uint32 free_end =
1135                                     (it->iParentChunkEnd - it->iAllocationPtr);
1136                                 uint32 free_begin =
1137                                     (it->iEndOfLastDeallocatedBlock - it->iParentChunkStart);
1138                                 maxSize = free_end + free_begin;
1139                             }
1140                         }
1141                     }
1142                     truespace += maxSize;
1143                 }
1144             }
1145             PVMF_SOCKALLOC_LOG_AVAILABILITY((0, "SM alloc space new1 %d new2 %d kspace %d Ln %d", iJJDataSize, iJJDataDbgSize, truespace, __LINE__));
1146             return (truespace);
1147         }
1148 
1149 
FindLargestContiguousFreeBlock(ParentChunkContainer * aPtr)1150         uint32 FindLargestContiguousFreeBlock(ParentChunkContainer* aPtr)
1151         {
1152             ParentChunkContainer* it = aPtr;
1153             uint32 maxSize = 0;
1154             if (it != NULL)
1155             {
1156                 if (it->iEndOfLastDeallocatedBlock == NULL)
1157                 {
1158                     /*
1159                      * Implies that there is no deallocations have happenned
1160                      */
1161                     maxSize =
1162                         (it->iParentChunkEnd - it->iAllocationPtr);
1163                 }
1164                 else
1165                 {
1166                     /*
1167                      * There are two possibilites:
1168                      * 1) iAllocationPtr < iEndOfLastDeallocatedBlock - This means
1169                      * that a wrap around has happenned, and we need to check
1170                      * if there is a large enough block between the two ptrs.
1171                      * Please note that we assume that the space between
1172                      * iAllocationPtr and iEndOfLastDeallocatedBlock is all free.
1173                      * Reason being that blocks are deallocated in the same
1174                      * order in which they are allocated.
1175                      *
1176                      * 2) iAllocationPtr > iEndOfLastDeallocatedBlock - This means
1177                      * we are ok.
1178                      *
1179                      */
1180                     if (it->iAllocationPtr <= it->iEndOfLastDeallocatedBlock)
1181                     {
1182                         maxSize =
1183                             (it->iEndOfLastDeallocatedBlock - it->iAllocationPtr);
1184                     }
1185                     else
1186                     {
1187                         uint32 free_end =
1188                             (it->iParentChunkEnd - it->iAllocationPtr);
1189                         uint32 free_begin =
1190                             (it->iEndOfLastDeallocatedBlock - it->iParentChunkStart);
1191                         if (free_end > free_begin)
1192                         {
1193                             maxSize = free_end;
1194                         }
1195                         else
1196                         {
1197                             maxSize = free_begin;
1198                         }
1199                     }
1200                 }
1201             }
1202             return (maxSize);
1203         }
1204 
1205 
1206         uint32 getAvailableBufferSpace(bool aFirstParentChunkOnly = false)
1207         {
1208             uint32 freespace = 0;
1209             Oscl_Vector<ParentChunkContainer, OsclMemAllocator>::iterator it;
1210             if (aFirstParentChunkOnly)
1211             {
1212                 /*
1213                  * Since we cannot inform the server about buffer growth, we
1214                  * should only send free space from the first allocated chunk.
1215                  */
1216                 it = iParentChunkContainerVec.begin();
1217                 freespace = FindLargestContiguousFreeBlock(it);
1218             }
1219             else
1220             {
1221                 for (it = iParentChunkContainerVec.begin();
1222                         it != iParentChunkContainerVec.end();
1223                         it++)
1224                 {
1225                     uint32 size = FindLargestContiguousFreeBlock(it);
1226                     if (size > freespace)
1227                     {
1228                         freespace = size;
1229                     }
1230                 }
1231             }
1232             return (freespace);
1233         }
1234 
1235         void notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver& aObserver,
1236                                       uint32 aSize,
1237                                       OsclAny* aContextData = NULL)
1238         {
1239             PVMF_SOCKALLOC_LOG_MEMCALLBACK((0, "notifyfreechunkavailable - reqSize=%d", (aSize + PVMF_RESIZE_ALLOC_OVERHEAD)));
1240             iCallbackPending = true;
1241             iCallbackRequestSize = aSize + PVMF_RESIZE_ALLOC_OVERHEAD;
1242             iObserver = &aObserver;
1243             iNextAvailableContextData = aContextData;
1244         }
1245 
CancelFreeChunkAvailableCallback()1246         void CancelFreeChunkAvailableCallback()
1247         {
1248             iCallbackPending = false;
1249             iCallbackRequestSize = 0;
1250             iObserver = NULL;
1251         }
1252 
CheckAndNotifyFreeChunkAvailable()1253         void CheckAndNotifyFreeChunkAvailable()
1254         {
1255             if (iCallbackPending == true)
1256             {
1257                 uint32 availSize = getTrueBufferSpace();
1258 
1259                 PVMF_SOCKALLOC_LOG_MEMCALLBACK((0, "CheckAndNotifyFreeChunkAvailable() availSize %d", availSize));
1260                 if (availSize > iCallbackRequestSize)
1261                 {
1262                     PVMF_SOCKALLOC_LOG_MEMCALLBACK((0, "CheckAndNotifyFreeChunkAvailable() availSize(%d) > iCallbackRequestSize(%d)", availSize, iCallbackRequestSize));
1263                     if (iObserver == NULL)
1264                         return;
1265                     OsclMemPoolFixedChunkAllocatorObserver* MyObserver = iObserver;
1266                     PVMF_SOCKALLOC_LOG_MEMCALLBACK((0, "CheckAndNotifyFreeChunkAvailable() MyObserver(0x%x) iObserver(0x%x) ", MyObserver, iObserver));
1267                     CancelFreeChunkAvailableCallback();
1268                     PVMF_SOCKALLOC_LOG_MEMCALLBACK((0, "CheckAndNotifyFreeChunkAvailable MyObserver(0x%x)", MyObserver));
1269                     MyObserver->freechunkavailable(iNextAvailableContextData);
1270                     PVMF_SOCKALLOC_LOG_MEMCALLBACK((0, "CheckAndNotifyFreeChunkAvailable() iNextAvailableContextData %d out", iNextAvailableContextData));
1271                 }
1272             }
1273         }
1274 
1275         void NotifyDeallocations(PVMFSMSharedBufferAllocWithReSizeAllocDeallocObserver& aObserver,
1276                                  OsclAny* aContextData = NULL)
1277         {
1278             iDeallocObserver = &aObserver;
1279             iDeallocNotificationContextData = aContextData;
1280         }
1281 
CancelDeallocationNotifications()1282         void CancelDeallocationNotifications()
1283         {
1284             iDeallocObserver = NULL;
1285             iDeallocNotificationContextData = NULL;
1286         }
1287 
1288     private:
1289         Oscl_Vector<ParentChunkContainer, OsclMemAllocator> iParentChunkContainerVec;
1290 
1291         OsclMemAllocator alloc;
1292 
1293         uint32 iNumOutOfOrderDeallocs;
1294         Oscl_Vector<OutOfOrderBlockContainer, OsclMemAllocator> iOutofOrderBlockVec;
1295 
1296         int32 iLastDeallocatedSeqNum;
1297         uint32 iSeqCount;
1298         uint32 iNumOutStandingBuffers;
1299         PVLogger *iLogger;
1300         PVLogger *iSizeLogger;
1301         PVLogger *iCallBackLogger;
1302         PVLogger *iOOOLogger;
1303         uint32 iJJDataSize;
1304         uint32 iJJDataDbgSize;
1305         OSCL_HeapString<OsclMemAllocator> iName;
1306         ReassemblyBlockList iOutOfOrderBlocks;
1307 
1308         // buffer resize parameters
1309         uint iiMaxNumGrows;
1310         uint iiNumGrows;
1311         uint iiRegrowthSize;
1312 
1313         //callback related params
1314         bool iCallbackPending;
1315         uint32 iCallbackRequestSize;
1316         OsclMemPoolFixedChunkAllocatorObserver* iObserver;
1317         OsclAny* iNextAvailableContextData;
1318 
1319         bool iDecKeepAliveCalled;
1320 
1321         PVMFSMSharedBufferAllocWithReSizeAllocDeallocObserver* iDeallocObserver;
1322         OsclAny* iDeallocNotificationContextData;
1323 };
1324 
1325 class PVMFSMSharedBufferAllocWithReSizeCleanupDA : public OsclDestructDealloc
1326 {
1327     public:
PVMFSMSharedBufferAllocWithReSizeCleanupDA(Oscl_DefAlloc * in_gen_alloc)1328         PVMFSMSharedBufferAllocWithReSizeCleanupDA(Oscl_DefAlloc* in_gen_alloc) :
1329                 gen_alloc(in_gen_alloc) {};
1330 
~PVMFSMSharedBufferAllocWithReSizeCleanupDA()1331         virtual ~PVMFSMSharedBufferAllocWithReSizeCleanupDA() {};
1332 
destruct_and_dealloc(OsclAny * ptr)1333         virtual void destruct_and_dealloc(OsclAny* ptr)
1334         {
1335             /*
1336              * get number of outstanding buffers from the allocator
1337              */
1338             Oscl_DefAlloc* myalloc = gen_alloc;
1339             PVMFSMSharedBufferAllocWithReSize* socketDataAllocator =
1340                 reinterpret_cast<PVMFSMSharedBufferAllocWithReSize*>(myalloc);
1341             gen_alloc->deallocate(ptr);
1342 
1343             uint32 numBuffers = socketDataAllocator->getNumOutStandingBuffers();
1344 
1345             /*
1346              * get the number of buffers deallocated, after the pointer has
1347              * been deallocated. A single dealloc call can potentially deallocate
1348              * multiple buffers (if there are many out of order blocks).
1349              */
1350             /*
1351              * in case there are no outstanding buffers delete the allocator
1352              */
1353             if (numBuffers == 0)
1354             {
1355                 OSCL_DELETE((socketDataAllocator));
1356             }
1357         }
1358 
1359     private:
1360         Oscl_DefAlloc* gen_alloc;
1361 };
1362 
1363 class PVMFSharedSocketDataBufferAlloc
1364 {
1365     public:
PVMFSharedSocketDataBufferAlloc(Oscl_DefAlloc * in_gen_alloc)1366         PVMFSharedSocketDataBufferAlloc(Oscl_DefAlloc* in_gen_alloc)
1367         {
1368             iResizeAlloc = false;
1369             if (in_gen_alloc)
1370             {
1371                 gen_alloc = in_gen_alloc;
1372                 iBufferOverhead = 0;
1373             }
1374             else
1375             {
1376                 OSCL_LEAVE(OsclErrArgument);
1377             }
1378         }
1379 
PVMFSharedSocketDataBufferAlloc(PVMFSMSharedBufferAllocWithReSize * in_gen_alloc)1380         PVMFSharedSocketDataBufferAlloc(PVMFSMSharedBufferAllocWithReSize* in_gen_alloc)
1381         {
1382             iResizeAlloc = false;
1383             if (in_gen_alloc)
1384             {
1385                 iResizeAlloc = true;
1386                 gen_alloc = in_gen_alloc;
1387                 iBufferOverhead = 0;
1388                 uint aligned_class_size =
1389                     oscl_mem_aligned_size(sizeof(PVMFSimpleMediaBuffer));
1390                 uint aligned_cleanup_size =
1391                     oscl_mem_aligned_size(sizeof(PVMFSMSharedBufferAllocWithReSizeCleanupDA));
1392                 uint aligned_refcnt_size =
1393                     oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
1394                 iBufferOverhead = (aligned_refcnt_size +
1395                                    aligned_cleanup_size +
1396                                    aligned_class_size);
1397 
1398             }
1399             else
1400             {
1401                 OSCL_LEAVE(OsclErrArgument);
1402             }
1403         };
1404 
~PVMFSharedSocketDataBufferAlloc()1405         virtual ~PVMFSharedSocketDataBufferAlloc()
1406         {
1407         };
1408 
createSharedBuffer(uint32 size)1409         OsclSharedPtr<PVMFMediaDataImpl> createSharedBuffer(uint32 size)
1410         {
1411             if (size == 0)
1412             {
1413                 size = PVMF_SOCKET_BUF_DEFAULT_SIZE;
1414             }
1415 
1416             uint aligned_in_size = oscl_mem_aligned_size(size);
1417 
1418             if (iResizeAlloc)
1419             {
1420                 uint8* my_ptr;
1421                 OsclRefCounter* my_refcnt;
1422 
1423                 uint aligned_class_size =
1424                     oscl_mem_aligned_size(sizeof(PVMFSimpleMediaBuffer));
1425 
1426                 uint aligned_cleanup_size =
1427                     oscl_mem_aligned_size(sizeof(PVMFSMSharedBufferAllocWithReSizeCleanupDA));
1428 
1429                 uint aligned_refcnt_size =
1430                     oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
1431 
1432                 my_ptr = (uint8*) gen_alloc->allocate(aligned_refcnt_size +
1433                                                       aligned_cleanup_size +
1434                                                       aligned_class_size +
1435                                                       aligned_in_size);
1436 
1437                 PVMFSMSharedBufferAllocWithReSizeCleanupDA *my_cleanup =
1438                     OSCL_PLACEMENT_NEW(my_ptr + aligned_refcnt_size, PVMFSMSharedBufferAllocWithReSizeCleanupDA(gen_alloc));
1439 
1440                 my_refcnt =
1441                     OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(my_ptr, my_cleanup));
1442 
1443                 my_ptr += aligned_refcnt_size + aligned_cleanup_size;
1444 
1445                 void* ptr;
1446                 ptr = my_ptr + aligned_class_size;
1447 
1448                 PVMFMediaDataImpl* media_data_ptr =
1449                     new(my_ptr) PVMFSimpleMediaBuffer(ptr,
1450                                                       aligned_in_size,
1451                                                       my_refcnt);
1452 
1453                 OsclSharedPtr<PVMFMediaDataImpl> shared_media_data(media_data_ptr,
1454                         my_refcnt);
1455                 return shared_media_data;
1456             }
1457             else
1458             {
1459                 uint8* my_ptr;
1460                 OsclRefCounter* my_refcnt;
1461 
1462                 uint aligned_class_size =
1463                     oscl_mem_aligned_size(sizeof(PVMFSimpleMediaBuffer));
1464 
1465                 uint aligned_cleanup_size =
1466                     oscl_mem_aligned_size(sizeof(PVMFSocketBufferCleanupDA));
1467 
1468                 uint aligned_refcnt_size =
1469                     oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
1470 
1471                 my_ptr = (uint8*) gen_alloc->allocate(aligned_refcnt_size +
1472                                                       aligned_cleanup_size +
1473                                                       aligned_class_size +
1474                                                       aligned_in_size);
1475 
1476                 PVMFSocketBufferCleanupDA *my_cleanup =
1477                     OSCL_PLACEMENT_NEW(my_ptr + aligned_refcnt_size, PVMFSocketBufferCleanupDA(gen_alloc));
1478 
1479                 my_refcnt =
1480                     OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(my_ptr, my_cleanup));
1481 
1482                 my_ptr += aligned_refcnt_size + aligned_cleanup_size;
1483 
1484                 void* ptr;
1485                 ptr = my_ptr + aligned_class_size;
1486 
1487                 PVMFMediaDataImpl* media_data_ptr =
1488                     new(my_ptr) PVMFSimpleMediaBuffer(ptr,
1489                                                       aligned_in_size,
1490                                                       my_refcnt);
1491 
1492                 OsclSharedPtr<PVMFMediaDataImpl> shared_media_data(media_data_ptr,
1493                         my_refcnt);
1494                 return shared_media_data;
1495             }
1496         }
1497 
ResizeMemoryFragment(OsclSharedPtr<PVMFMediaDataImpl> & aSharedBuffer)1498         void ResizeMemoryFragment(OsclSharedPtr<PVMFMediaDataImpl>& aSharedBuffer)
1499         {
1500             if (iResizeAlloc)
1501             {
1502                 OsclRefCounterMemFrag memFrag;
1503                 aSharedBuffer->getMediaFragment(0, memFrag);
1504                 uint32 currCapacity = memFrag.getCapacity();
1505                 uint32 bytesUsed = memFrag.getMemFragSize();
1506 
1507                 //uint32 alignedBytesUsed = bytesUsed;
1508                 uint32 alignedBytesUsed = oscl_mem_aligned_size(bytesUsed);
1509 
1510                 if (alignedBytesUsed < currCapacity)
1511                 {
1512                     uint32 bytesToReclaim = (currCapacity - alignedBytesUsed);
1513                     PVMFSMSharedBufferAllocWithReSize* socketDataAllocator =
1514                         reinterpret_cast<PVMFSMSharedBufferAllocWithReSize*>(gen_alloc);
1515                     /* Account for the overhead */
1516                     uint8* memFragPtr = (uint8*)(memFrag.getMemFragPtr());
1517                     uint8* ptr = (memFragPtr - iBufferOverhead);
1518                     socketDataAllocator->resize((OsclAny*)ptr, bytesToReclaim);
1519                     aSharedBuffer->setCapacity(alignedBytesUsed);
1520                 }
1521             }
1522         }
1523 
1524         uint32 getAvailableBufferSpace(bool aFirstParentChunkOnly = false)
1525         {
1526             if (iResizeAlloc)
1527             {
1528                 PVMFSMSharedBufferAllocWithReSize* socketDataAllocator =
1529                     reinterpret_cast<PVMFSMSharedBufferAllocWithReSize*>(gen_alloc);
1530                 return (socketDataAllocator->getAvailableBufferSpace(aFirstParentChunkOnly));
1531             }
1532             else
1533             {
1534                 PVMFSocketBufferAllocator* socketDataAllocator =
1535                     reinterpret_cast<PVMFSocketBufferAllocator*>(gen_alloc);
1536                 return (socketDataAllocator->getAvailableBufferSpace(aFirstParentChunkOnly));
1537             }
1538         }
1539         void notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver& aObserver,
1540                                       uint32 aSize,
1541                                       OsclAny* aContextData = NULL)
1542         {
1543             if (iResizeAlloc)
1544             {
1545                 PVMFSMSharedBufferAllocWithReSize* socketDataAllocator =
1546                     reinterpret_cast<PVMFSMSharedBufferAllocWithReSize*>(gen_alloc);
1547                 socketDataAllocator->notifyfreechunkavailable(aObserver, (aSize + iBufferOverhead), aContextData);
1548             }
1549             else
1550             {
1551                 PVMFSocketBufferAllocator* socketDataAllocator =
1552                     reinterpret_cast<PVMFSocketBufferAllocator*>(gen_alloc);
1553                 socketDataAllocator->notifyfreechunkavailable(aObserver, (aSize + iBufferOverhead), aContextData);
1554             }
1555         }
1556 
CancelFreeChunkAvailableCallback()1557         void CancelFreeChunkAvailableCallback()
1558         {
1559             if (iResizeAlloc)
1560             {
1561                 PVMFSMSharedBufferAllocWithReSize* socketDataAllocator =
1562                     reinterpret_cast<PVMFSMSharedBufferAllocWithReSize*>(gen_alloc);
1563                 socketDataAllocator->CancelFreeChunkAvailableCallback();
1564             }
1565             else
1566             {
1567                 PVMFSocketBufferAllocator* socketDataAllocator =
1568                     reinterpret_cast<PVMFSocketBufferAllocator*>(gen_alloc);
1569                 socketDataAllocator->CancelFreeChunkAvailableCallback();
1570             }
1571         }
1572 
1573     private:
1574         bool iResizeAlloc;
1575         uint iBufferOverhead;
1576         Oscl_DefAlloc* gen_alloc;
1577 };
1578 
1579 class PVMFSharedSocketDataBufferAllocCleanupSA : public OsclDestructDealloc
1580 {
1581     public:
~PVMFSharedSocketDataBufferAllocCleanupSA()1582         virtual ~PVMFSharedSocketDataBufferAllocCleanupSA() {};
1583 
destruct_and_dealloc(OsclAny * ptr)1584         virtual void destruct_and_dealloc(OsclAny* ptr)
1585         {
1586             uint8* tmp_ptr = (uint8*) ptr;
1587 
1588             uint aligned_refcnt_size =
1589                 oscl_mem_aligned_size(sizeof(OsclRefCounterSA<PVMFSharedSocketDataBufferAllocCleanupSA>));
1590 
1591             tmp_ptr += aligned_refcnt_size;
1592             PVMFSharedSocketDataBufferAlloc* socketDataBufferAlloc =
1593                 reinterpret_cast<PVMFSharedSocketDataBufferAlloc*>(tmp_ptr);
1594 
1595             socketDataBufferAlloc->~PVMFSharedSocketDataBufferAlloc();
1596             OsclMemAllocator alloc;
1597             alloc.deallocate(ptr);
1598         }
1599 };
1600 
1601 
1602 #endif //PVMF_STREAMING_BUFFER_ALLOCATORS_H_INCLUDED
1603