// Include #include "packetpool.h" // Local definitions #define SetLeft(P,L) { (P)->left = L; if(L) (L)->parent = P; } #define SetRight(P,R) { (P)->right = R; if(R) (R)->parent = P; } // Global data // PacketPool Constructor PacketPool::PacketPool( ) { // Pool Usage Pointer mPagedPoolUsage = NULL; mNonPagedPoolUsage = NULL; // BST Root Pointer mBstRoot = NULL; // ¸Þ¸ð¸® Ä«¿îÅÍ. mQuotaPagedPoolUsage = 0; mQuotaNonPagedPoolUsage = 0; mWorkingSetSize = 0; } // ~PacketPool Destructor. PacketPool::~PacketPool(void) { // PacketPool¸¦ ÇØÁ¦. Shutdown(); } // Shutdown Method void PacketPool::Shutdown() { PacketBuffer* temp; // BST Shutdown while ( mBstRoot != NULL ) { DetachBst( mBstRoot ); } // Pool Usage Shutdown - PagedPoolUsage while ( mPagedPoolUsage != NULL ) { temp = mPagedPoolUsage; mPagedPoolUsage = mPagedPoolUsage->next; FreePacketBuffer( &temp ); } // Pool Usage Shutdown - NonPagedPoolUsage while ( mNonPagedPoolUsage != NULL ) { temp = mNonPagedPoolUsage; mNonPagedPoolUsage = mNonPagedPoolUsage->next; FreePacketBuffer( &temp ); } } // AllocPacketBuffer Method PacketBuffer* PacketPool::AllocPacketBuffer() { PacketBuffer* packetBuffer = (PacketBuffer*)GlobalAlloc( GPTR, sizeof(PacketBuffer) ); if ( packetBuffer != NULL ) { mWorkingSetSize++; // mWorkingSetSize¸¦ Áõ°¡. packetBuffer->pid = 0; // Packet ID packetBuffer->offset = 0; // Offset packetBuffer->prev = NULL; // ¼±Çü¸®½ºÆ®ÀÇ Æ÷ÀÎÅÍ - ÀÌÀü packetBuffer->next = NULL; // ¼±Çü¸®½ºÆ®ÀÇ Æ÷ÀÎÅÍ - ´ÙÀ½ packetBuffer->parent = NULL; // BST Æ÷ÀÎÅÍ - »óÀ§ packetBuffer->left = NULL; // BST Æ÷ÀÎÅÍ - ¿ÞÂÊ packetBuffer->right = NULL; // BST Æ÷ÀÎÅÍ - ¿À¸¥ÂÊ } return packetBuffer; } // FreePacketBuffer Method. void PacketPool::FreePacketBuffer(PacketBuffer** packetBuffer) { if ( (*packetBuffer) != NULL ) { GlobalFree( (*packetBuffer) ); (*packetBuffer) = NULL; // mWorkingSetSize¸¦ °¨¼Ò. mWorkingSetSize--; } } // Compare Method int PacketPool::Compare(long cid1, long cid2) { return (cid1 - cid2); } // AttachPool Method void PacketPool::AttachPool(PacketBuffer** pool, PacketBuffer* packetBuffer) { if ( (*pool) != NULL ) { (*pool)->prev = packetBuffer; packetBuffer->prev = NULL; packetBuffer->next = (*pool); } (*pool) = packetBuffer; } // DetachPool Method void PacketPool::DetachPool(PacketBuffer** pool, PacketBuffer* packetBuffer) { PacketBuffer* prev = packetBuffer->prev; PacketBuffer* next = packetBuffer->next; if ( prev == NULL && next == NULL ) { (*pool) = NULL; } else if ( prev == NULL && next != NULL ) { next->prev = NULL; (*pool) = next; } else if ( prev != NULL && next == NULL ) { prev->next = NULL; } else if ( prev != NULL && next != NULL ) { prev->next = next; next->prev = prev; } packetBuffer->prev = NULL; packetBuffer->next = NULL; } // AttachBst Method bool PacketPool::AttachBst(PacketBuffer* packetBuffer) { PacketBuffer* parent = NULL; PacketBuffer* child = mBstRoot; int result; while ( child != NULL ) { parent = child; result = Compare( child->pid, packetBuffer->pid ); if ( result == 0 ) return false; else if ( result > 0 ) child = child->left; else if ( result < 0 ) child = child->right; } if ( parent == NULL ) { mBstRoot = packetBuffer; } else if ( Compare( parent->pid, packetBuffer->pid ) > 0 ) { SetLeft( parent, packetBuffer ); } else /*if ( Compare( parent->pid, packetBuffer->pid ) < 0 )*/ { SetRight( parent, packetBuffer ); } return true; } // DetachBst Method bool PacketPool::DetachBst(PacketBuffer* packetBuffer) { PacketBuffer* parent = packetBuffer->parent; PacketBuffer* left = packetBuffer->left; PacketBuffer* right = packetBuffer->right; PacketBuffer* child = NULL; if ( left == NULL ) { child = right; } else if ( right == NULL ) { child = left; } else { child = right; while ( child->left != NULL ) child = child->left; if ( child->parent != packetBuffer ) { SetLeft( child->parent, child->right ); SetRight( child, right ); } child->parent = parent; SetLeft( child, left ); } if ( mBstRoot == packetBuffer ) { mBstRoot = child; if ( mBstRoot != NULL ) mBstRoot->parent = NULL; } else if ( packetBuffer == parent->left ) { SetLeft( parent, child ); } else { SetRight( parent, child ); } packetBuffer->parent = NULL; packetBuffer->left = NULL; packetBuffer->right = NULL; return true; } // GetPool Method PacketBuffer* PacketPool::GetPool(long pid) { PacketBuffer* packetBuffer = mNonPagedPoolUsage; if ( packetBuffer != NULL ) { // ÆäÀÌÁö ¾ÈµÈ Ç® »ç¿ë·®¸¦ Â÷°¨. DetachPool( &mNonPagedPoolUsage, packetBuffer ); mQuotaNonPagedPoolUsage--; } else { // ÆäÀÌÁö°¡ ¾øÀ» °æ¿ì »õ·Î »ý¼º. packetBuffer = AllocPacketBuffer( ); } if ( packetBuffer != NULL ) { packetBuffer->pid = pid; // BST - ¿¬°á½Ãµµ / ÆäÀÌÁö µÈ Ç® »ç¿ë·®À» Áõ°¨. if ( AttachBst( packetBuffer ) == true ) { AttachPool( &mPagedPoolUsage, packetBuffer ); mQuotaPagedPoolUsage++; return packetBuffer; } // BST - ¿¬°á½ÇÆÐ / ÆäÀÌÁö ¾ÈµÈ Ç® »ç¿ë·®À» Áõ°¨. else { AttachPool( &mNonPagedPoolUsage, packetBuffer ); mQuotaNonPagedPoolUsage++; return NULL; } } return packetBuffer; } // ReleasePool Method void PacketPool::ReleasePool(PacketBuffer* packetBuffer) { // BST - ¿¬°áÁ¾·á. DetachBst( packetBuffer ); // ÆäÀÌÁö µÈ Ç® »ç¿ë·®À» Â÷°¨. DetachPool( &mPagedPoolUsage, packetBuffer ); mQuotaPagedPoolUsage--; // ÆäÀÌÁö ¾ÈµÈ Ç® »ç¿ë·®À» Áõ°¨. AttachPool( &mNonPagedPoolUsage, packetBuffer ); mQuotaNonPagedPoolUsage++; } // SearchPacketBuffer Method PacketBuffer* PacketPool::SearchPacketBuffer(long pid) { PacketBuffer* ch = mBstRoot; int result; while ( ch != NULL ) { result = Compare( ch->pid, pid ); if ( result == 0 ) return ch; else if ( result > 0 ) ch = ch->left; else if ( result < 0 ) ch = ch->right; } return NULL; } // GetPacketBuffer Method - ¼±Çü¸®½ºÆ®ÀÇ HEAD¸¦ ³Ñ°ÜÁØ´Ù. // ReleasePacketBuffer¿Í ÇÔ²² LIFO¸¦ ÀÌ·é´Ù. LIFO´Â Context Switching¸¦ ÃÖ¼ÒÈ­ Çϱâ À§ÇØ »ç¿ë PacketBuffer* PacketPool::GetPacketBuffer(long pid) { return GetPool( pid ); } // ReleasePacketBuffer Method - ¼±Çü¸®½ºÆ®ÀÇ HEAD·Î ȸ¼öÇÑ´Ù. // GetPacketBuffer¿Í ÇÔ²² LIFO¸¦ ÀÌ·é´Ù. LIFO´Â Context Switching¸¦ ÃÖ¼ÒÈ­ Çϱâ À§ÇØ »ç¿ë void PacketPool::ReleasePacketBuffer(PacketBuffer* packetBuffer) { packetBuffer->seq = 0; packetBuffer->ack = 0; memset( packetBuffer->buffer, 0, sizeof(packetBuffer->buffer) ); packetBuffer->offset = 0; packetBuffer->update = 0; ReleasePool( packetBuffer ); }