~ubuntu-branches/ubuntu/karmic/gnustep-base/karmic

« back to all changes in this revision

Viewing changes to Source/NSZone.m

  • Committer: Bazaar Package Importer
  • Author(s): Eric Heintzmann
  • Date: 2005-04-17 00:14:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050417001438-enf0y07c9tku85z1
Tags: 1.10.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
23
23
 
24
24
   <title>NSZone class reference</title>
25
 
   $Date: 2001/12/18 16:54:15 $ $Revision: 1.46 $
 
25
   $Date: 2005/02/22 11:22:44 $ $Revision: 1.53 $
26
26
*/
27
27
 
28
28
/*  Design goals:
38
38
   - The default zone uses objc_malloc() and friends.  We assume that
39
39
   they're thread safe and that they return NULL if we're out of
40
40
   memory (glibc malloc does this, what about other mallocs? FIXME).
41
 
   
 
41
 
42
42
    - The OpenStep spec says that when a zone is recycled, any memory in
43
43
   use is returned to the default zone.
44
44
   Since, in general, we have no control over the system malloc, we can't
85
85
 
86
86
#define IN_NSZONE_M 1
87
87
 
88
 
#include <config.h>
89
 
#include <base/preface.h>
 
88
#include "config.h"
 
89
#include "GNUstepBase/preface.h"
90
90
#include <stddef.h>
91
91
#include <string.h>
92
 
#include <Foundation/NSObjCRuntime.h>
93
 
#include <Foundation/NSException.h>
94
 
#include <Foundation/NSString.h>
95
 
#include <Foundation/NSZone.h>
96
 
#include <Foundation/NSLock.h>
97
 
 
98
 
 
99
 
/*
100
 
 *      Try to get more memory - the normal process has failed.
101
 
 *      If we can't do anything, bomb out.
 
92
#include "Foundation/NSObjCRuntime.h"
 
93
#include "Foundation/NSException.h"
 
94
#include "Foundation/NSString.h"
 
95
#include "Foundation/NSZone.h"
 
96
#include "Foundation/NSLock.h"
 
97
 
 
98
/**
 
99
 * Try to get more memory - the normal process has failed.
 
100
 * If we can't do anything, just return a null pointer.
 
101
 * Try to do some logging if possible.
102
102
 */
103
103
void *
104
104
GSOutOfMemory(size_t size, BOOL retry)
105
105
{
106
 
  /*
107
 
   *    It would be nice to raise an exception - but how can we if there is
108
 
   *    no memory available?
109
 
   */
110
 
  abort();
 
106
  fprintf(stderr, "GSOutOfMemory ... wanting %u bytes.\n", size);
 
107
  return 0;
111
108
}
112
109
 
113
110
#if     GS_WITH_GC == 0
415
412
 */
416
413
static NSZone   *zone_list = 0;
417
414
 
 
415
/**
 
416
 * Searches and finds the zone ptr was allocated from.  The speed depends
 
417
 * upon the number of zones and their size.
 
418
 */
418
419
GS_DECLARE NSZone*
419
420
NSZoneFromPointer(void *ptr)
420
421
{
526
527
default_stats (NSZone *zone)
527
528
{
528
529
  struct NSZoneStats dummy;
529
 
  
 
530
 
530
531
  /* We can't obtain statistics from the memory managed by objc_malloc(). */
531
532
  [NSException raise: NSGenericException
532
533
              format: @"No statistics for default zone"];
533
534
  return dummy;
534
535
}
535
 
 
 
536
 
536
537
/* Search the buffer to see if there is any memory chunks large enough
537
538
   to satisfy request using first fit.  If the memory chunk found has
538
539
   a size exactly equal to the one requested, remove it from the buffer
640
641
 
641
642
  NSAssert(chunkIsInUse(chunkhead), NSInternalInconsistencyException);
642
643
  NSAssert((realsize % MINCHUNK) == 0, NSInternalInconsistencyException);
643
 
  
 
644
 
644
645
  chunkClrLive(chunkhead);
645
646
  if (chunksize < realsize)
646
647
    {
664
665
      nextsize = chunkSize(nextchunk);
665
666
 
666
667
      NSAssert((nextsize % MINCHUNK) == 0, NSInternalInconsistencyException);
667
 
      
 
668
 
668
669
      if (!chunkIsInUse(nextchunk) && (nextsize+realsize >= chunksize))
669
670
        /* Expand to next chunk. */
670
671
        {
687
688
        /* Get new chunk and copy. */
688
689
        {
689
690
          ff_block *newchunk;
690
 
          
 
691
 
691
692
          newchunk = get_chunk(zptr, chunksize);
692
693
          if (newchunk == NULL)
693
694
            {
753
754
              while (tmp->next != block)
754
755
                tmp = tmp->next;
755
756
              tmp->next = block->next;
756
 
            } 
 
757
            }
757
758
          objc_free((void*)block);
758
759
        }
759
760
      block = nextblock;
809
810
  size_t i;
810
811
  ffree_zone *zptr = (ffree_zone*)zone;
811
812
  ff_block *block;
812
 
  
 
813
 
813
814
  objc_mutex_lock(zptr->lock);
814
815
  /* Check integrity of each block the zone owns. */
815
816
  block = zptr->blocks;
1026
1027
  ff_link *link = zone->segheadlist[class];
1027
1028
 
1028
1029
  NSAssert(size%MINCHUNK == 0, NSInternalInconsistencyException);
1029
 
  
 
1030
 
1030
1031
  while ((link != NULL) && (chunkSize((ff_block*)link) < size))
1031
1032
    link = link->next;
1032
1033
  if (link == NULL)
1089
1090
          NSAssert(size < chunkSize(chunk), NSInternalInconsistencyException);
1090
1091
          NSAssert((chunkSize(chunk) % MINCHUNK) == 0,
1091
1092
            NSInternalInconsistencyException);
1092
 
          
 
1093
 
1093
1094
          take_chunk(zone, chunk);
1094
1095
          slack = chunkChop(chunk, size);
1095
1096
          put_chunk(zone, slack);
1107
1108
      NSAssert(chunkIsPrevInUse(chunk), NSInternalInconsistencyException);
1108
1109
      NSAssert(chunkIsInUse(chunkNext(chunk)),
1109
1110
        NSInternalInconsistencyException);
1110
 
      
 
1111
 
1111
1112
      take_chunk(zone, chunk);
1112
1113
      if (chunksize > size)
1113
1114
        {
1114
1115
          ff_block *slack;
1115
 
          
 
1116
 
1116
1117
          slack = chunkChop(chunk, size);
1117
1118
          put_chunk(zone, slack);
1118
1119
        }
1145
1146
 
1146
1147
  NSAssert((size % MINCHUNK) == 0, NSInternalInconsistencyException);
1147
1148
  NSAssert(!chunkIsInUse(chunk), NSInternalInconsistencyException);
1148
 
  
 
1149
 
1149
1150
  if (links->prev == NULL)
1150
1151
    zone->segheadlist[class] = links->next;
1151
1152
  else
1181
1182
  NSAssert(!chunkIsInUse(chunk), NSInternalInconsistencyException);
1182
1183
  NSAssert(chunkIsPrevInUse(chunk), NSInternalInconsistencyException);
1183
1184
  NSAssert(chunkIsInUse(chunkNext(chunk)), NSInternalInconsistencyException);
1184
 
  
 
1185
 
1185
1186
  chunkMakeLink(chunk);
1186
1187
  if (zone->segtaillist[class] == NULL)
1187
1188
    {
1188
1189
      NSAssert(zone->segheadlist[class] == NULL,
1189
1190
        NSInternalInconsistencyException);
1190
 
      
 
1191
 
1191
1192
      zone->segheadlist[class] = zone->segtaillist[class] = links;
1192
1193
      links->prev = links->next = NULL;
1193
1194
    }
1194
1195
  else
1195
1196
    {
1196
1197
      ff_link *prevlink = zone->segtaillist[class];
1197
 
      
 
1198
 
1198
1199
      NSAssert(zone->segheadlist[class] != NULL,
1199
1200
        NSInternalInconsistencyException);
1200
1201
 
1218
1219
  NSAssert((chunkSize(chunk) % MINCHUNK) == 0,
1219
1220
    NSInternalInconsistencyException);
1220
1221
  NSAssert(chunkSize(chunk) >= MINCHUNK, NSInternalInconsistencyException);
1221
 
  
 
1222
 
1222
1223
  zone->bufsize++;
1223
1224
  zone->size_buf[bufsize] = chunkSize(chunk);
1224
1225
  zone->ptr_buf[bufsize] = chunk;
1238
1239
  ff_block **ptr_buf = zone->ptr_buf;
1239
1240
 
1240
1241
  NSAssert(bufsize <= BUFFER, NSInternalInconsistencyException);
1241
 
  
 
1242
 
1242
1243
  for (i = 0; i < bufsize; i++)
1243
1244
    {
1244
1245
      size = size_buf[i];
1309
1310
  if (freesize >= chunksize)
1310
1311
    {
1311
1312
      chunkhead = (void*)(block)+top;
1312
 
      block += chunksize;
 
1313
      block->top += chunksize;
1313
1314
    }
1314
1315
  else
1315
1316
    {
1425
1426
        {
1426
1427
          nf_block *block;
1427
1428
          size_t old = 0;
1428
 
  
 
1429
 
1429
1430
          for (block = zptr->blocks; block != NULL; block = block->next) {
1430
1431
            if (ptr >= (void*)block && ptr < ((void*)block)+block->size) {
1431
1432
                old = ((void*)block)+block->size - ptr;
1539
1540
  while (block != NULL)
1540
1541
    {
1541
1542
      size_t *chunk;
1542
 
      
 
1543
 
1543
1544
      stats.bytes_total += block->size;
1544
1545
      chunk = (void*)block+NF_HEAD;
1545
1546
      while ((void*)chunk < (void*)block+block->top)
1585
1586
 
1586
1587
static void rnfree (NSZone *zone, void *ptr);
1587
1588
 
 
1589
/**
 
1590
 * Creates a new zone of start bytes, which will grow and shrink by
 
1591
 * granularity bytes.  If canFree is 0, memory in zone is allocated but
 
1592
 * never freed, meaning allocation will be very fast.  The whole zone can
 
1593
 * still be freed with NSRecycleZone(), and you should still call NSZoneFree
 
1594
 * on memory in the zone that is no longer needed, since a count of allocated
 
1595
 * pointers is kept and must reach zero before freeing the zone.
 
1596
 */
1588
1597
NSZone*
1589
1598
NSCreateZone (size_t start, size_t gran, BOOL canFree)
1590
1599
{
1700
1709
    return newZone;
1701
1710
}
1702
1711
 
 
1712
/**
 
1713
 *  Allocates and returns cleared memory for elems items of size bytes, in the
 
1714
 *  given zone.  Returns NULL if allocation of size 0 requested.  Raises
 
1715
 *  <code>NSMallocException</code> if not enough free memory in zone to
 
1716
 *  allocate and no more can be obtained from system.
 
1717
 */
1703
1718
void*
1704
1719
NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes)
1705
1720
{
1706
1721
  return memset(NSZoneMalloc(zone, elems*bytes), 0, elems*bytes);
1707
1722
}
1708
1723
 
 
1724
/**
 
1725
 * Sets name of the given zone (useful for debugging and logging).
 
1726
 */
1709
1727
void
1710
1728
NSSetZoneName (NSZone *zone, NSString *name)
1711
1729
{