(file) Return to suballoc.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

   1 mday  1.1 //%//////////////////////////////////////////////////////////////////////////
   2           //
   3           // Copyright (c) 2000 - 2002 The Open group, BMC Software, Tivoli Systems, IBM
   4           //
   5           // Permission is hereby granted, free of charge, to any person obtaining a copy
   6           // of this software and associated documentation files (the "Software"), to 
   7           // deal in the Software without restriction, including without limitation the 
   8           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
   9           // sell copies of the Software, and to permit persons to whom the Software is
  10           // furnished to do so, subject to the following conditions:
  11           // 
  12           // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN 
  13           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
  14           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  15           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
  16           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
  17           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
  18           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  19           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20           // 
  21           //==============================================================================
  22 mday  1.1 //
  23           // Author: Mike Day (mdday@us.ibm.com)
  24           //
  25           // Modified By: 
  26           //
  27           //%/////////////////////////////////////////////////////////////////////////////
  28           
  29           #include <Pegasus/Common/suballoc.h>
  30           #include <Pegasus/Common/Tracer.h>
  31           #include <new.h>
  32           PEGASUS_NAMESPACE_BEGIN
  33           
  34           peg_suballocator *peg_suballocator::_suballoc_instance = 0;
  35           
  36           PEGASUS_SUBALLOC_LINKAGE peg_suballocator *peg_suballocator::get_instance(void)
  37           {
  38              if(peg_suballocator::_suballoc_instance == 0)
  39              {
  40                 peg_suballocator::_suballoc_instance = new((void *)malloc(sizeof(peg_suballocator))) peg_suballocator(true);
  41              }
  42              return peg_suballocator::_suballoc_instance;
  43 mday  1.1 }
  44           
  45           #if defined(PEGASUS_DEBUG_MEMORY)
  46           PEGASUS_SUBALLOC_LINKAGE void * pegasus_alloc(size_t size, 
  47           					      void * handle,
  48           					      int type,
  49           					      const Sint8 *classname, 
  50           					      Sint8 *file,
  51           					      Uint32 line)
  52           {
  53              return peg_suballocator::get_instance()->vs_malloc(size, 
  54            				       ((handle == NULL) ? &(peg_suballocator::get_instance()->get_handle()) : handle),
  55           				       type, 
  56           				       classname, 
  57           				       file,  
  58           				       line) ;
  59           }
  60           
  61           PEGASUS_SUBALLOC_LINKAGE void pegasus_free(void * dead,
  62           					   void * handle,
  63           					   int type, 
  64 mday  1.1 					   Sint8 *classname, 
  65           					   Sint8 * file, 
  66           					   Uint32 line) 
  67           {
  68              if ( dead == 0 )
  69                 return;
  70              
  71              peg_suballocator::get_instance()->vs_free(dead,  				       
  72           			      ((handle == NULL) ? &(peg_suballocator::get_instance()->get_handle()) : handle),
  73           			      type, 
  74           			      classname, 
  75           			      file, 
  76           			      line); 
  77           }
  78           
  79           #else
  80           
  81           PEGASUS_SUBALLOC_LINKAGE void * pegasus_alloc(size_t size)
  82           {
  83              return peg_suballocator::get_instance()->vs_malloc(size);
  84           }
  85 mday  1.1 
  86           PEGASUS_SUBALLOC_LINKAGE void pegasus_free(void *dead)
  87           {
  88              peg_suballocator::get_instance()->vs_free(dead);
  89           }
  90           
  91           #endif
  92           
  93           PEGASUS_NAMESPACE_END
  94           
  95           PEGASUS_USING_PEGASUS;
  96           
  97           void * operator new(size_t size) throw(PEGASUS_STD(bad_alloc))
  98           {
  99              if( size == 0 )
 100                 size = 1;
 101              void *p;
 102              
 103              while(1)
 104              {
 105           #if defined(PEGASUS_DEBUG_MEMORY)
 106 mday  1.1       p = peg_suballocator::get_instance()->vs_malloc(size, 
 107           				       &(peg_suballocator::get_instance()->get_handle()),
 108           				       NORMAL, 
 109           				       "BUILTIN NEW", 
 110           				       __FILE__, __LINE__) ;
 111           
 112                 
 113           #else
 114                 p = peg_suballocator::get_instance()->vs_malloc(size);
 115           #endif
 116                 if( p )
 117           	 return p;
 118                 new_handler global = set_new_handler(0);
 119                 set_new_handler(global);
 120                 if( global) 
 121           	 (*global)();
 122                 else
 123           	 throw PEGASUS_STD(bad_alloc());
 124              }
 125           }
 126           
 127 mday  1.1 
 128           void operator delete(void *dead) throw()
 129           {
 130              if( dead == 0 )
 131                 return;
 132           #if defined(PEGASUS_DEBUG_MEMORY)
 133              peg_suballocator::get_instance()->vs_free(dead,  
 134           			      &(peg_suballocator::get_instance()->get_handle()), 
 135           			      NORMAL, 
 136           			      "internal", 
 137           			      __FILE__, 
 138           			      __LINE__);
 139              free(dead);
 140              
 141           
 142           #else
 143              peg_suballocator::get_instance()->vs_free(dead);
 144           #endif 
 145              return;
 146           }
 147           
 148 mday  1.1 void * operator new [] (size_t size) throw(PEGASUS_STD(bad_alloc))
 149           {
 150              if( size == 0 )
 151                 size = 1;
 152               void *p;  
 153              
 154              while(1)
 155              {
 156           #if defined(PEGASUS_DEBUG_MEMORY)
 157                 p = peg_suballocator::get_instance()->vs_malloc(size, 
 158           				       &(peg_suballocator::get_instance()->get_handle()), 
 159           				       ARRAY, 
 160           				       "BUILTIN ARRAY NEW", 
 161           				       __FILE__, __LINE__) ;
 162           
 163           #else
 164                 p = peg_suballocator::get_instance()->vs_malloc(size);
 165           #endif
 166                 if( p )
 167           	 return p;
 168                 new_handler global = set_new_handler(0);
 169 mday  1.1       set_new_handler(global);
 170                 if( global)  
 171           	 (*global)();
 172                 else 
 173           	 throw PEGASUS_STD(bad_alloc());
 174              }
 175           }
 176           
 177           void operator delete [] (void *dead) throw()
 178           {
 179              if( dead == 0 )
 180                 return;
 181           #if defined(PEGASUS_DEBUG_MEMORY)
 182              peg_suballocator::get_instance()->vs_free(dead, 
 183           			      &(peg_suballocator::get_instance()->get_handle()), 
 184           			      ARRAY, 
 185           			      "internal",
 186           			      __FILE__, 
 187           			      __LINE__);
 188           
 189           #else
 190 mday  1.1    peg_suballocator::get_instance()->vs_free(dead);
 191           #endif
 192              return;
 193           }
 194           
 195           
 196           PEGASUS_NAMESPACE_BEGIN
 197           
 198           #if defined(PEGASUS_DEBUG_MEMORY)
 199           const Uint8 peg_suballocator::guard[] = {0x01, 0x02, 0x03, 0x04, 0x05, 
 200           					 0x06, 0x07, 0x08, 0x09, 0x09, 
 201           					 0x08, 0x07, 0x06, 0x05, 0x04, 
 202           					 0x03};
 203           const Uint8 peg_suballocator::alloc_pattern = 0xaa;
 204           const Uint8 peg_suballocator::delete_pattern = 0xee;
 205           #endif
 206           
 207           const Sint32 peg_suballocator::nodeSizes[3][16] = 
 208           {
 209              {
 210                 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 
 211 mday  1.1       0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff
 212              },
 213              {
 214                 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 
 215                 0x800, 0x900, 0xa00, 0xb00, 0xc00, 0xd00, 0xe00, 
 216                 0xf00, 0xfff
 217              },
 218              {
 219                 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 
 220                 0x7000, 0x8000, 0x9000, 0xa000, 0xb000, 0xc000, 
 221                 0xd000, 0xe000, 0xf000, 
 222                 2 * sizeof(void *)
 223              }
 224           };	
 225           
 226           
 227           // prototypes that begin with an underscore do not attempt to 
 228           // gain ownership of semaphores and can be safely called
 229           // by a process that owns a semaphore
 230           
 231           
 232 mday  1.1 const Uint32 peg_suballocator::preAlloc[3][16] = 
 233           {
 234              {20, 20, 20, 20, 20, 20, 20, 10, 10, 10, 10, 10, 10, 10, 10, 10 },
 235              {	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 236              {	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 237           };	
 238           
 239           const Uint32 peg_suballocator::step[3][16] = 
 240           {
 241              {20, 20, 20, 20, 20, 20, 20, 10, 10, 10, 10, 10, 10, 10, 10, 10 },
 242              {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 },
 243              {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
 244           };
 245           
 246           peg_suballocator::peg_suballocator(void)
 247              : debug_mode(true), 
 248                abort_on_error(true), 
 249                check_for_leaks(false),
 250                internal_handle("internal_suballoc_log")
 251                
 252           { 
 253 mday  1.1    sprintf(internal_handle.classname, "internal");
 254              InitializeSubAllocator();
 255              return;
 256           }
 257           
 258           peg_suballocator::peg_suballocator(Boolean mode)
 259              : debug_mode(mode), 
 260                abort_on_error(true), 
 261                check_for_leaks(false),
 262                internal_handle("internal_suballoc_log")
 263                
 264           { 
 265              sprintf(internal_handle.classname, "internal");
 266              InitializeSubAllocator();
 267              return;
 268           }
 269           
 270           peg_suballocator::~peg_suballocator(void)
 271           { 
 272              DeInitSubAllocator(&internal_handle);
 273           }
 274 mday  1.1 
 275           peg_suballocator::SUBALLOC_HANDLE *peg_suballocator::InitializeProcessHeap(Sint8 *f)
 276           {
 277              return new SUBALLOC_HANDLE(f);
 278           }	
 279           
 280           /****************************************************************
 281            *  InitializeSubAllocator
 282            *
 283            *
 284            *  PARAMETERS: none
 285            *
 286            *  DESCRIPTION: If suballocator is already initialized, returns
 287            *				 true immediately. Otherwise, allocates node list 
 288            *				 heads and performs pre-allocations. 
 289            *
 290            *  RETURNS: true if successful, false otherwise
 291            *
 292            ***************************************************************/
 293           Boolean peg_suballocator::InitializeSubAllocator(void)
 294           {
 295 mday  1.1    SUBALLOC_NODE *temp;
 296              Sint32 i, o;
 297              Boolean ccode = true;
 298              Sint32 waitCode;
 299              
 300              if(initialized)
 301                 return true;
 302              
 303              if(CREATE_MUTEX(&globalSemHandle))
 304                 return(false);
 305              
 306              WAIT_MUTEX(&globalSemHandle, 1000, &waitCode);
 307           
 308              // check to see if we are already initialized
 309              // gain ownership of global semaphore here
 310           
 311              for (o = 0; o < 3; o++)
 312              {
 313                 for (i = 0; i < 16; i++)
 314                 {
 315           	 // allocate our list heads
 316 mday  1.1 	 if (0 == ((Sint32)(CREATE_MUTEX(&(semHandles[o][i])))))
 317           	 {
 318           	    nodeListHeads[o][i] = (SUBALLOC_NODE *)calloc(1, sizeof (SUBALLOC_NODE));
 319           	    if ( nodeListHeads[o][i] == NULL )
 320           	    {
 321           	       while (o >= 0)
 322           	       {
 323           		  while (i >= 0)
 324           		  {
 325           		     if (nodeListHeads[o][i] != NULL)
 326           		     {
 327           			free(nodeListHeads[o][i]);
 328           			nodeListHeads[o][i] = NULL;
 329            		     }
 330           		     CLOSE_MUTEX(&(semHandles[o][i]));
 331           		     i--;
 332           		  }
 333           		  o--;
 334           	       }
 335           	       RELEASE_MUTEX(&globalSemHandle);
 336           	       RELEASE_MUTEX(&init_mutex);
 337 mday  1.1 	       
 338           	       return(false);
 339           	    }
 340           
 341           	    temp = nodeListHeads[o][i];
 342           	    temp->next = temp->prev = temp;
 343           	    temp->flags |= (IS_HEAD_NODE );
 344           #if defined(PEGASUS_DEBUG_MEMORY)
 345           	    memcpy(temp->guardPre, guard, GUARD_SIZE);
 346           #endif
 347           	    if (preAlloc[o][i])
 348           	       ccode = _Allocate(o, i, PRE_ALLOCATE);
 349           	    
 350           	    if (ccode == false)
 351           	    {
 352           	       while (o >= 0)
 353           	       {
 354           		  while (i >= 0)
 355           		  {
 356           		     if (nodeListHeads[o][i] != NULL)
 357           		     {
 358 mday  1.1 			free(nodeListHeads[o][i]);
 359           			nodeListHeads[o][i] = NULL;
 360           		     }
 361           
 362           		     CLOSE_MUTEX(&(semHandles[o][i]));
 363           
 364           		     i--;
 365           		  }
 366           		  o--;
 367           	       }
 368           	       RELEASE_MUTEX(&globalSemHandle);
 369           	       RELEASE_MUTEX(&init_mutex);
 370           	       return(false);
 371           	    }
 372           	 }
 373                 }	
 374              }
 375              initialized = 1;
 376              // release global concurrency semaphore here
 377              RELEASE_MUTEX(&globalSemHandle);
 378              return(true);
 379 mday  1.1 }	
 380           
 381           
 382           /****************************************************************
 383            *  _Allocate
 384            *
 385            *
 386            *  PARAMETERS: IN index is a selector for the correct
 387            *					node head.
 388            *				IN code is a control code that determines if we
 389            *					are doing a pre-allocation or a step-allocation.
 390            *
 391            *  DESCRIPTION: Creates new memory nodes, initializes them, 
 392            *				 and links them to the appropriate list head. 
 393            *				 A pre-allocation creates nodes at init time, while
 394            *				 a step-allocation creates nodes at run time when all
 395            *  			 existing nodes are unavailable.
 396            *
 397            *				 INTERNAL CALL ONLY - caller must own the semaphore
 398            *				 for the list indicated by index; or, alternatively,
 399            *				 caller must own the global semaphore. 
 400 mday  1.1  *
 401            *  RETURNS: true if successful, false otherwise
 402            *
 403            ***************************************************************/
 404           Boolean peg_suballocator::_Allocate(Sint32 vector, Sint32 index, Sint32 code)
 405           {
 406           
 407           
 408              // no semaphores - this internal routine must only be
 409              // called by threads owning the list head indicated by index
 410              SUBALLOC_NODE *temp, *temp2;
 411              Sint32 i;
 412              Sint8 *g;
 413           
 414              temp = nodeListHeads[vector][index];
 415              if (code == PRE_ALLOCATE) // this is a preallocation
 416                 i = preAlloc[vector][index];
 417              else
 418                 i = step[vector][index]; // this is a step allocation
 419           #if defined(PEGASUS_DEBUG_MEMORY)
 420              size_t chunk_size = (i * (sizeof(SUBALLOC_NODE) + GUARD_SIZE + nodeSizes[vector][index]));
 421 mday  1.1 #else
 422              size_t chunk_size = (i * (sizeof(SUBALLOC_NODE) + nodeSizes[vector][index]));
 423           #endif 
 424              
 425              temp2 = (SUBALLOC_NODE *)malloc(chunk_size);
 426              if(temp2 == NULL)
 427                 return false;
 428              for ( ; i > 0; i--)
 429              {
 430                 temp2->flags |= AVAIL;
 431                 temp2->concurrencyHandle = &internal_handle;
 432                 
 433           #if defined(PEGASUS_DEBUG_MEMORY)
 434                 memcpy(temp2->guardPre, guard, GUARD_SIZE);
 435           #endif
 436                 g = (Sint8 *)temp2;
 437                 g+= sizeof(SUBALLOC_NODE);
 438                 g+= nodeSizes[vector][index];
 439           #if defined(PEGASUS_DEBUG_MEMORY)
 440           	 memcpy(g, guard, GUARD_SIZE);
 441           	 g += GUARD_SIZE;
 442 mday  1.1 #endif
 443                 INSERT(temp2, temp);
 444                 temp2 = (SUBALLOC_NODE *)g;
 445              }
 446              return(true);
 447           }	
 448           
 449           /****************************************************************
 450            *  DeInitSubAllocator
 451            *
 452            *
 453            *  PARAMETERS:
 454            *
 455            *  DESCRIPTION: Locks suballocator and destroys all of its data
 456            *				 structures. Checks for unfreed nodes, which
 457            *				 represent memory leaks. 
 458            *
 459            *  RETURNS:
 460            *
 461            ***************************************************************/
 462           void peg_suballocator::DeInitSubAllocator(void *handle)
 463 mday  1.1 {
 464              Sint32 i, o, waitCode;
 465              assert(handle != 0);
 466           //   _UnfreedNodes(handle); 
 467              if( handle != (void *) &internal_handle)
 468                 free((void *)handle);
 469              
 470              init_count--;
 471              if (! init_count)
 472              {
 473                 initialized = 0;
 474                 WAIT_MUTEX(&globalSemHandle, 1000, &waitCode);
 475                  for (o = 0; o < 3; o++)
 476                 {
 477           	 for (i = 0; i < 16; i++)
 478           	 {
 479           	    WAIT_MUTEX(&(semHandles[o][i]), 1000, &waitCode);
 480           	    CLOSE_MUTEX(&(semHandles[o][i]));
 481           	    _DeAllocate(o, i);
 482           	    free(nodeListHeads[o][i]);
 483           	    nodeListHeads[o][i] = NULL;
 484 mday  1.1 	 }
 485                 }
 486                 CLOSE_MUTEX(&(globalSemHandle));
 487                 initialized = 0;
 488              }
 489              
 490              return;
 491           }	
 492           
 493           /****************************************************************
 494            *  _DeAllocate
 495            *
 496            *
 497            *  PARAMETERS: IN index is a selector for the correct
 498            *				list to destroy
 499            *
 500            *  DESCRIPTION: INTERNAL CALL ONLY - caller must own the semaphore
 501            *					for the list head, or, alternatively, the 
 502            *					global semaphore. 
 503            *				After calling this function, be certain to close
 504            *				the semaphore handle corresponding to index.
 505 mday  1.1  *
 506            *  RETURNS:
 507            *
 508            ***************************************************************/
 509           void peg_suballocator::_DeAllocate(Sint32 vector, Sint32 index)
 510           {
 511              // caller owns semHandles[vector][index]
 512              SUBALLOC_NODE *temp, *temp2;
 513              temp = nodeListHeads[vector][index];
 514              while ( ! IS_EMPTY(temp) )
 515              {
 516                 temp2 = temp->next;
 517                 _DELETE(temp2);
 518                 free(temp2); 
 519              }
 520              return;
 521           }
 522           
 523           /****************************************************************
 524            *  GetNode
 525            *
 526 mday  1.1  *
 527            *  PARAMETERS:	IN index is a selector for the listHead from which
 528            *				   we want to get a node.
 529            *
 530            *  DESCRIPTION: Allocates a node from the selected list. If the 
 531            *				list is fully utilized, allocates some new nodes
 532            *				and returns one of those. 
 533            *
 534            *  RETURNS: pointer to an allocated node. the node remains linked
 535            *		     its list but is marked as not being available. 
 536            *
 537            ***************************************************************/
 538           peg_suballocator::SUBALLOC_NODE *peg_suballocator::GetNode(Sint32 vector, Sint32 index)
 539           {
 540              SUBALLOC_NODE *temp;
 541              Sint32 waitCode;
 542              if(initialized == 0 )
 543              {
 544                 InitializeSubAllocator();
 545              }
 546              WAIT_MUTEX(&(semHandles[vector][index]), 1000, &waitCode);
 547 mday  1.1    temp = (nodeListHeads[vector][index])->next;
 548              // if list is empty we will fall through
 549              
 550              while (! IS_HEAD(temp) )
 551              {
 552                 if ((temp->flags & AVAIL) && (false == IS_HEAD(temp)))
 553                 {
 554           	 temp->flags &= ~(AVAIL) ;
 555           	 // release semHandles[index] 
 556           	 RELEASE_MUTEX(&(semHandles[vector][index]));
 557           	 return(temp);
 558                 }
 559                 temp = temp->next;
 560              }
 561              // the list is either empty or fully allocated
 562              if (! _Allocate(vector, index, STEP_ALLOCATE))
 563              {
 564                 // release semHandles[index];
 565                 RELEASE_MUTEX(&(semHandles[vector][index]));
 566                 return(NULL);
 567              }
 568 mday  1.1    // Allocate always links new nodes at the front of the list
 569              // we can just grab the first node and go
 570              temp = (nodeListHeads[vector][index])->next;
 571              temp->flags &= ~(AVAIL);
 572              if( check_for_leaks == true )
 573                 temp->flags |= CHECK_LEAK;
 574              
 575              // release semHandles[vector][index];
 576              RELEASE_MUTEX(&(semHandles[vector][index]));
 577              return(temp);
 578           }	
 579           
 580           /****************************************************************
 581            *  GetHugeNode
 582            *
 583            *
 584            *  PARAMETERS:	IN size is the amount of memory requested by the 
 585            *				caller. 
 586            *
 587            *  DESCRIPTION: Allocates a node from the "huge" list. This list is 
 588            *				 maintained specifically for memory allocations that
 589 mday  1.1  *				 are greater than 32K bytes. If the list is fully
 590            *				 utilized, will allocate some new nodes and return
 591            *				 one of those. 
 592            *
 593            *  RETURNS: pointer to an allocated node. the node remains linked
 594            *		     its list but is marked as not being available. 
 595            *
 596            ***************************************************************/
 597           peg_suballocator::SUBALLOC_NODE * peg_suballocator::GetHugeNode(Sint32 size)
 598           {
 599              SUBALLOC_NODE *temp;
 600              Sint8 *g;
 601              
 602              
 603              Sint32 waitCode;
 604              if(initialized == 0 )
 605              {
 606                 InitializeSubAllocator();
 607              }
 608              
 609           
 610 mday  1.1    WAIT_MUTEX(&(semHandles[2][15]), 1000, &waitCode);
 611              temp = (nodeListHeads[2][15])->next;
 612              while (! IS_HEAD(temp) )
 613              {
 614                 if ((temp->flags & AVAIL) && (false == IS_HEAD(temp)))
 615                 {
 616           	 if(temp->nodeSize >= (Uint32)size)
 617           	 {
 618           	    temp->flags &= ~(AVAIL) ;
 619           	    temp->allocSize = size;
 620           	    break;
 621           	 }
 622                 }
 623                 temp = temp->next;
 624              }
 625           
 626              if( IS_HEAD(temp))
 627              {
 628           #if defined(PEGASUS_DEBUG_MEMORY)
 629                 size_t chunk_size = (sizeof(SUBALLOC_NODE) + GUARD_SIZE + size);
 630           #else
 631 mday  1.1       size_t chunk_size = (sizeof(SUBALLOC_NODE) + size);
 632           #endif 
 633                 temp = (SUBALLOC_NODE *)malloc(chunk_size);
 634                 if(temp == NULL)
 635                 {
 636           	 RELEASE_MUTEX(&(semHandles[2][15]));
 637           	 return temp;
 638                 }
 639                 
 640                 temp->allocSize = temp->nodeSize = size;
 641                 INSERT(temp, nodeListHeads[2][15]);
 642              }
 643              temp->concurrencyHandle = &internal_handle;
 644           #if defined(PEGASUS_DEBUG_MEMORY)
 645              memcpy(temp->guardPre, guard, GUARD_SIZE);
 646           #endif
 647           
 648              RELEASE_MUTEX(&(semHandles[2][15]));
 649              return(temp);
 650           }
 651           
 652 mday  1.1 /****************************************************************
 653            *  PutNode
 654            *
 655            *
 656            *  PARAMETERS:	IN index is a selector for the correct listhead.
 657            *				IN node is the node that we need to "put" back 
 658            *				on to the list.
 659            *
 660            *  DESCRIPTION: "put" is a misnomer because the node never 
 661            *				 leaves its list. However, we do unlink the node
 662            *				 and insert it at the front of the list before marking
 663            *				 it as being available. We do this to speed up allocation
 664            *				 of the node next time someone needs it. We want
 665            *				 to keep all available nodes at the front of the list. 
 666            *
 667            *  RETURNS:
 668            *
 669            ***************************************************************/
 670           void peg_suballocator::PutNode(Sint32 vector, Sint32 index, SUBALLOC_NODE *node)
 671           {
 672              Sint32 waitCode;
 673 mday  1.1    WAIT_MUTEX(&(semHandles[vector][index]), 1000, &waitCode);
 674           
 675              // mark the node as available, unlink it, and relink it
 676              // to the front of the list
 677              assert(node != NULL);
 678              // gain ownership of semHandles[index];
 679              // delete insert the node at the front of the list - 
 680              // this will make it faster to get the node
 681              _DELETE(node);
 682              node->concurrencyHandle = &internal_handle;
 683              node->flags |= AVAIL;
 684              INSERT(node, nodeListHeads[vector][index]);
 685              RELEASE_MUTEX(&(semHandles[vector][index]));
 686              return;
 687           }	
 688           
 689           /****************************************************************
 690            *  PutHugeNode
 691            *
 692            *
 693            *  PARAMETERS:	IN node is the node that we need to "put" back 
 694 mday  1.1  *				on to the "huge" list.
 695            *
 696            *  DESCRIPTION: "put" is a misnomer because the node never 
 697            *				 leaves its list. However, we do unlink the node
 698            *				 and insert it at the front of the list before marking
 699            *				 it as being available. We do this to speed up allocation
 700            *				 of the node next time someone needs it. We want
 701            *				 to keep all available nodes at the front of the list. 
 702            *
 703            *  RETURNS:
 704            *
 705            ***************************************************************/
 706           void peg_suballocator::PutHugeNode(SUBALLOC_NODE *node)
 707           {
 708              // mark the node as available, unlink it, and relink it
 709              // to the front of the list
 710              PutNode(2, 15, node);
 711           }	
 712           
 713           
 714           /****************************************************************
 715 mday  1.1  *  vs_malloc
 716            *
 717            *
 718            *  PARAMETERS: IN size is the amount of memory requested
 719            *
 720            *  DESCRIPTION: initializes the suballocator if neccesary. 
 721            *				 gets an appropriately sized memory node and
 722            *				 returns a pointer to the caller. 
 723            *
 724            *  RETURNS: pointer to memory available for use by the caller,
 725            *   		 or NULL. 
 726            *
 727            ***************************************************************/
 728           
 729           #if defined(PEGASUS_DEBUG_MEMORY)
 730           void *peg_suballocator::vs_malloc(size_t size, void *handle, int type, const Sint8 *classname, const Sint8 *f, Uint32 l)
 731           {
 732              // we don't need to grab any semaphores, 
 733              // called routines will do that for us
 734              SUBALLOC_NODE *temp;
 735              Sint8 *g;
 736 mday  1.1    
 737              assert(size != 0);
 738                
 739              if (! (size >> 8))
 740              {
 741                 temp = GetNode(0, (size >> 4));
 742              }
 743              else if (! (size >> 12))
 744              {
 745                 temp = GetNode(1, (size >> 8));
 746              }
 747              else if (! (size >> 16))
 748              {
 749                 temp = GetNode(2, (size >> 12));
 750              }
 751              else
 752              {
 753                 temp = GetHugeNode(size);
 754              }
 755              
 756              temp->allocSize = size;
 757 mday  1.1    temp->concurrencyHandle = (void *)handle;
 758              if(type == ARRAY)
 759                 temp->flags |= ARRAY_NODE;
 760              if(classname)
 761                 strncpy(temp->classname, classname, MAX_CLASS_LEN);
 762              else
 763                 temp->classname[0] = 0x00;
 764              
 765              if(f)
 766                 strncpy(temp->file, f, MAX_PATH_LEN);
 767              else 
 768                 temp->file[0] = 0x00;
 769              
 770              if(l)
 771                 sprintf(temp->line, "%d", l);
 772              else
 773                 temp->line[0] = 0x00;
 774              g = (Sint8 *)temp;
 775              g += sizeof(SUBALLOC_NODE);
 776              memcpy(g + size, guard, GUARD_SIZE);
 777              return((void *)g);
 778 mday  1.1 }	
 779           #else
 780           void *peg_suballocator::vs_malloc(size_t size)
 781           {
 782              SUBALLOC_NODE *temp;
 783              Sint8 *g;
 784              assert(size != 0);
 785                
 786              if (! (size >> 8))
 787              {
 788                 temp = GetNode(0, (size >> 4));
 789              }
 790              else if (! (size >> 12))
 791              {
 792                 temp = GetNode(1, (size >> 8));
 793              }
 794              else if (! (size >> 16))
 795              {
 796                 temp = GetNode(2, (size >> 12));
 797              }
 798              else
 799 mday  1.1       temp = GetHugeNode(size);
 800              temp->allocSize = size;
 801              temp->concurrencyHandle = (void *)&internal_handle;
 802              g = (Sint8 *)temp;
 803              g += sizeof(SUBALLOC_NODE);
 804              return((void *)g);
 805           }
 806           #endif
 807           
 808           
 809           /****************************************************************
 810            *  vs_calloc
 811            *
 812            *
 813            *  PARAMETERS: IN num is the number of memory units requested.
 814            *				IN size is the size of each memory unit. result
 815            *				is a contigious area of memory that is 
 816            *				num * size bytes.
 817            *
 818            *  DESCRIPTION: initializes the suballocator if neccesary. 
 819            *				 gets an appropriately sized memory node, zeros
 820 mday  1.1  *				 caller's memory block and returns a 
 821            *				 pointer to the caller. 
 822            *
 823            *  RETURNS: pointer to zero'ed memory available for use by the 
 824            *	caller, or NULL. 
 825            ***************************************************************/
 826           
 827           #if defined(PEGASUS_DEBUG_MEMORY)
 828           void *peg_suballocator::vs_calloc(size_t num, size_t s, void *handle, int type, Sint8 *f, Uint32 l)
 829           {
 830              void *g = vs_malloc((unsigned)num * s, handle, type, "internal", f, l);
 831              memset(g, 0x00, num * s);
 832              return(g);
 833           }
 834           	
 835           #else
 836           
 837           void *peg_suballocator::vs_calloc(size_t num, size_t s)
 838           {
 839              void *g = vs_malloc((unsigned)num * s);
 840              memset(g, 0x00, num * s);
 841 mday  1.1    return(g);
 842           }
 843           
 844           
 845           #endif
 846           
 847           /****************************************************************
 848            *  vs_free
 849            *
 850            *
 851            *  PARAMETERS: IN pointer to memory that the caller wants freed.
 852            *
 853            *  DESCRIPTION: marks the node as available. in debug mode, 
 854            *				 checks for memory under and over -writes. 
 855            *
 856            *  RETURNS:
 857            *
 858            ***************************************************************/
 859           
 860           #if defined(PEGASUS_DEBUG_MEMORY)
 861           void peg_suballocator::vs_free(void *m, 
 862 mday  1.1 			       void *handle,
 863           			       int type , 
 864           			       Sint8 *classname, 
 865           			       Sint8* file, 
 866           			       Uint32 line)
 867           {
 868              // we don't need to grab any semaphores - 
 869              // called routines will do that for us
 870              assert( m != NULL);
 871              
 872              SUBALLOC_NODE *temp = _CheckNode(m, type, file, line);
 873              memset(temp->d_classname, 0x00, MAX_CLASS_LEN + 1);
 874              strncpy(temp->d_classname, classname, MAX_CLASS_LEN);
 875              memset(temp->d_file, 0x00, MAX_PATH_LEN + 1);
 876              strncpy(temp->d_file, file, MAX_PATH_LEN);
 877              memset(temp->d_line, 0x00, MAX_LINE_LEN + 1);
 878              sprintf(temp->d_line, "%d", line); 
 879              
 880              if (! (temp->allocSize >> 8))
 881              {
 882                 PutNode(0, (temp->allocSize >> 4), temp);
 883 mday  1.1    }
 884              else if (! (temp->allocSize >> 12))
 885              {
 886                 PutNode(1, (temp->allocSize >> 8), temp);
 887              }
 888              else if (! (temp->allocSize >> 16))
 889              {
 890                 PutNode(2, (temp->allocSize >> 12), temp);
 891              }
 892              else
 893                 PutHugeNode(temp);
 894              return;
 895           }
 896           
 897           #else
 898           void peg_suballocator::vs_free(void *m)
 899           {
 900              // we don't need to grab any semaphores - 
 901              // called routines will do that for us
 902              assert( m != 0 );
 903              SUBALLOC_NODE *temp = (SUBALLOC_NODE *)m;
 904 mday  1.1    temp--;
 905              
 906              if (! (temp->allocSize >> 8))
 907              {
 908                 PutNode(0, (temp->allocSize >> 4), temp);
 909              }
 910              else if (! (temp->allocSize >> 12))
 911              {
 912                 PutNode(1, (temp->allocSize >> 8), temp);
 913              }
 914              else if (! (temp->allocSize >> 16))
 915              {
 916                 PutNode(2, (temp->allocSize >> 12), temp);
 917              }
 918              else
 919                 PutHugeNode(temp);
 920              return;
 921           }
 922           
 923           #endif
 924           
 925 mday  1.1 
 926           #if defined(PEGASUS_DEBUG_MEMORY)
 927           
 928           void *peg_suballocator::vs_realloc(void *pblock, size_t newsize, void *handle, int type, Sint8 *f, Uint32 l)
 929           {
 930              if (pblock == NULL) {
 931                 return(vs_malloc(newsize, handle, type, 0, f, l));	
 932              }
 933              if (newsize == 0) {
 934                 vs_free(pblock, handle, type, "INTERNAL", f, l);
 935                 return(NULL);
 936              }
 937           
 938              {
 939                 void *newblock;
 940                 newblock = vs_calloc(newsize, sizeof(char), handle, type, f, l);
 941                 if (newblock != NULL) {
 942           	 SUBALLOC_NODE *temp;
 943           	 Sint8 *g;
 944           	 int copysize;
 945           	 temp = (SUBALLOC_NODE *)pblock;
 946 mday  1.1 	 temp--;
 947           	 if(newsize > temp->allocSize)
 948           	    copysize = temp->allocSize;
 949           	 else
 950           	    copysize = newsize;
 951           
 952           	 /* get the actual data size of the old block - only copy that much */
 953           	 /* if newsize is smaller than oldsize, only copy newsize */
 954           	 memcpy(newblock, pblock, copysize);
 955           	 vs_free(pblock, handle, type, "INTERNAL", f, l);
 956           	 return(newblock);
 957                 }
 958                 else
 959           	 return(pblock);
 960              }
 961           }	
 962           
 963           #else
 964           
 965           void *peg_suballocator::vs_realloc(void *pblock, size_t newsize)
 966           {
 967 mday  1.1    if (pblock == NULL) {
 968                 return(vs_malloc(newsize));	
 969              }
 970              if (newsize == 0) {
 971                 vs_free(pblock);
 972                 return(NULL);
 973              }
 974           
 975              {
 976                 void *newblock;
 977                 newblock = vs_calloc(newsize, sizeof(char));
 978                 if (newblock != NULL) {
 979           	 SUBALLOC_NODE *temp;
 980           	 Sint8 *g;
 981           	 int copysize;
 982           	 temp = (SUBALLOC_NODE *)pblock;
 983           	 temp--;
 984           	 if(newsize > temp->allocSize)
 985           	    copysize = temp->allocSize;
 986           	 else
 987           	    copysize = newsize;
 988 mday  1.1 
 989           	 /* get the actual data size of the old block - only copy that much */
 990           	 /* if newsize is smaller than oldsize, only copy newsize */
 991           	 memcpy(newblock, pblock, copysize);
 992           	 vs_free(pblock);
 993           	 return(newblock);
 994                 }
 995                 else
 996           	 return(pblock);
 997              }
 998           }	
 999           
1000           #endif
1001           	
1002           
1003           #if defined(PEGASUS_DEBUG_MEMORY)
1004           Sint8 * peg_suballocator::vs_strdup(const Sint8 *string, void *handle, int type, Sint8 *f, Uint32 l)
1005           {
1006           
1007              Sint8 *memory;
1008           
1009 mday  1.1    if (!string)
1010                 return(NULL);
1011              if ((memory = (Sint8 *)vs_malloc(strlen(string) + 1, handle, type, 0, f, l)))
1012                 return(strcpy(memory,string));
1013              
1014              return(NULL);
1015           }
1016           
1017           #else
1018           
1019           Sint8 * peg_suballocator::vs_strdup(const Sint8 *string)
1020           {
1021           
1022              Sint8 *memory;
1023           
1024              if (!string)
1025                 return(NULL);
1026              if ((memory = (Sint8 *)vs_malloc(strlen(string) + 1)))
1027                 return(strcpy(memory,string));
1028              return(NULL);
1029           }
1030 mday  1.1 #endif
1031           
1032           
1033           /****************************************************************
1034            *  _UnfreedNodes
1035            *
1036            *
1037            *  PARAMETERS: IN index is a selector for the correct listhead.
1038            *
1039            *  DESCRIPTION:  Checks the list for unfreed nodes. These are nodes
1040            *				  that are marked as available. Call this routine
1041            *				  to check for memory leaks.
1042            *				  INTERNAL call only - caller must own the semaphore
1043            *				  for the list indicated by index. 
1044            *
1045            *  RETURNS: true if there are unfreed nodes on the list, 
1046            *	false otherwise
1047            *
1048            ***************************************************************/
1049           #if defined(PEGASUS_DEBUG_MEMORY)
1050           Boolean peg_suballocator::_UnfreedNodes(void * handle)
1051 mday  1.1 {
1052              Sint8 i, y;  
1053              Sint32 waitCode;
1054              SUBALLOC_NODE *temp;
1055              Boolean ccode = false;
1056              SUBALLOC_HANDLE *h = (SUBALLOC_HANDLE *)handle;
1057           
1058              WAIT_MUTEX(&(globalSemHandle), 1000, &waitCode);
1059              for (y = 0; y < 3; y++ )
1060              {
1061                 for (i = 0; i < 16; i++)
1062                 {
1063           	 WAIT_MUTEX(&(semHandles[y][i]), 1000, &waitCode);
1064           	 temp = (nodeListHeads[y][i])->next;
1065           	 // if list is empty we will fall through
1066           	 while (! IS_HEAD(temp) )
1067           	 {
1068           	    if (!(temp->flags & AVAIL) && temp->concurrencyHandle == (void *)handle)
1069           	    {
1070           	       if( temp->flags & CHECK_LEAK)
1071           	       {
1072 mday  1.1 		  h = (SUBALLOC_HANDLE *)temp->concurrencyHandle;
1073           		  RELEASE_MUTEX(&(semHandles[y][i]));
1074           		  Tracer::trace(__FILE__, __LINE__, TRC_MEMORY, Tracer::LEVEL2, 
1075           				"Memory Leak: %d bytes class %s allocated memory in source file %s at " \
1076           				"line %s", temp->allocSize, temp->classname, temp->file, temp->line);
1077           		  WAIT_MUTEX(&(semHandles[y][i]), 1000, &waitCode);
1078           		  ccode = true;
1079           	       }
1080           	    }
1081           	    temp = temp->next;	
1082           	 }
1083           	 RELEASE_MUTEX(&(semHandles[y][i]));
1084                 }
1085              }
1086              RELEASE_MUTEX(&(globalSemHandle));
1087              return(ccode);
1088           }
1089           	
1090           /****************************************************************
1091            *  _CheckGuard
1092            *
1093 mday  1.1  *
1094            *  PARAMETERS: IN node is a node that we want to check for 
1095            *				under and over -writes. 
1096            *
1097            *  DESCRIPTION: checks node for under and over -writes
1098            *	
1099            *	NOTE: only available in debug mode. 
1100            *
1101            *  RETURNS: true if node is intact, false if node has been 
1102            *			 stomped upon.
1103            *
1104            ***************************************************************/
1105           Boolean peg_suballocator::_CheckGuard(SUBALLOC_NODE *node)
1106           {
1107              Sint32 ccode;
1108           
1109              ccode = memcmp(node->guardPre, guard, GUARD_SIZE);
1110              if (ccode == 0)
1111              {
1112                 Sint8 *g = (Sint8 *)node;
1113                 g += sizeof(SUBALLOC_NODE);
1114 mday  1.1       g += node->allocSize;
1115                 ccode = memcmp(g, guard, GUARD_SIZE);
1116                 if (ccode == 0)
1117                 { 
1118           	 return(true); 
1119                 }
1120              }
1121              return(false);
1122           }
1123           
1124           Uint32 peg_suballocator::CheckMemory(void *m)
1125           {
1126              return _CheckNode(m);
1127           }
1128           
1129           Uint32 peg_suballocator::_CheckNode(void *m)
1130           {
1131              assert(m != NULL);
1132              SUBALLOC_NODE *temp = (SUBALLOC_NODE *)m;
1133              temp--;
1134              
1135 mday  1.1    if(temp->flags & AVAIL)
1136                 return ALREADY_DELETED;
1137              if(false == _CheckGuard(temp))
1138                 return OVERWRITE;
1139              return 0;
1140           }
1141           
1142           peg_suballocator::SUBALLOC_NODE *peg_suballocator::_CheckNode(void *m, 
1143           							      int type,  
1144           							      Sint8 *file, 
1145           							      Uint32 line)
1146           {
1147              assert(m != NULL);
1148              SUBALLOC_NODE *temp = (SUBALLOC_NODE *)m;
1149              temp--;
1150              if( (temp->flags & AVAIL ) )
1151              {
1152                 Tracer::trace(file, line, TRC_MEMORY, Tracer::LEVEL2, 
1153           		    "Doubly freed memory, already deleted by class %s at " \
1154           		    "source file %s line number %s; this deletion is from " \
1155           		    "source file %s line number %d",
1156 mday  1.1 		    temp->d_classname, temp->d_file, temp->d_line, file, line);
1157                 temp->flags |= CHECK_FAILED;
1158                 if( abort_on_error)
1159           	 abort(); 
1160              }
1161              if( type == ARRAY )
1162              {
1163                 if( false == IS_ARRAY(temp))
1164                 {
1165           	 Tracer::trace(file, line, TRC_MEMORY, Tracer::LEVEL2,
1166           		       "Array delete called with non-array object at " \
1167           		       "source file %s line number %d. Object was originally allocated " \
1168           		       " by class %s in source file %s at line number %s",
1169           		       file, line, temp->classname, temp->file, temp->line);
1170           	 temp->flags |= CHECK_FAILED;
1171           	 if( abort_on_error)
1172           	    abort();
1173                 }
1174              }
1175              else if( true == IS_ARRAY(temp))
1176              {
1177 mday  1.1       Tracer::trace(file, line, TRC_MEMORY, Tracer::LEVEL2,
1178           		    "Normal delete called with array object at " \
1179           		    "source file %s line number %d. Object was originally allocated " \
1180           		    " by class %s in source file %s at line number %s",
1181           		    file, line, temp->classname, temp->file, temp->line);
1182                 temp->flags |= CHECK_FAILED;
1183                 if( abort_on_error)
1184           	 abort();
1185              }
1186              if(false == _CheckGuard(temp))
1187              {
1188                 Tracer::trace(file, line, TRC_MEMORY, Tracer::LEVEL2,
1189           		    "Memory overwritten. Allocated by %s in source file %s at line number %s",
1190           		    temp->classname, temp->file, temp->line);
1191                 temp->flags |= CHECK_FAILED;
1192                 if( abort_on_error)
1193           	 abort();
1194              }
1195              return temp;
1196           }
1197           
1198 mday  1.1 #endif
1199           
1200           
1201           
1202           
1203           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2