source: git/omalloc/omBinPage.c @ b6647a7

spielwiese
Last change on this file since b6647a7 was db143c, checked in by Hans Schoenemann <hannes@…>, 5 years ago
integrate xalloc into omalloc (./configure --disable-omalloc)
  • Property mode set to 100644
File size: 17.8 KB
Line 
1/*******************************************************************
2 *  File:    omBinPage.c
3 *  Purpose: implementation of routines for primitve BinPage managment
4 *  Author:  obachman (Olaf Bachmann)
5 *  Created: 11/99
6 *******************************************************************/
7#include <limits.h>
8#include "omalloc.h"
9
10#ifdef HAVE_OMALLOC
11#include "omDefaultConfig.h"
12
13/*******************************************************************
14 *
15 * Local declarations
16 *
17 *******************************************************************/
18
19/* define if you want to keep regions approximately in order */
20#define OM_KEEP_REGIONS_ORDER
21
22struct omBinPageRegion_s
23{
24  void* current;        /* linked list of free pages */
25  omBinPageRegion next; /* nex/prev pointer in ring of regions */
26  omBinPageRegion prev;
27  char* init_addr;      /* pointer portion of inital chunk which is still free */
28  char* addr;         /* addr returned by alloc */
29  int   init_pages;   /* number of pages still available in init_chunk */
30  int   used_pages;     /* number of used pages */
31  int pages;          /* total size of region */
32};
33
34/* globale variable holding pointing int regions ring */
35static omBinPageRegion om_CurrentBinPageRegion = NULL;
36unsigned long om_MaxBinPageIndex = 0;
37unsigned long om_MinBinPageIndex = ULONG_MAX;
38unsigned long *om_BinPageIndicies = NULL;
39
40/* declaration of local procs */
41static void* omTakeOutConsecutivePages(omBinPageRegion region, int how_many);
42static omBinPageRegion omAllocNewBinPagesRegion(int min_pages);
43static void omFreeBinPagesRegion(omBinPageRegion region);
44
45static void omBinPageIndexFault(unsigned long low_index, unsigned long high_index);
46static void omRegisterBinPages(void* low_addr, int pages);
47static void omUnregisterBinPages(void* low_addr, int pages);
48
49OM_INLINE_LOCAL void omTakeOutRegion(omBinPageRegion region)
50{
51  omAssume(region != NULL);
52
53  if (region->prev != NULL)
54  {
55    omAssume(region->prev != region && region->prev != region->next);
56    region->prev->next = region->next;
57  }
58
59  if (region->next != NULL)
60  {
61    omAssume(region->next != region && region->prev != region->next);
62    region->next->prev = region->prev;
63  }
64}
65
66OM_INLINE_LOCAL void omInsertRegionAfter(omBinPageRegion insert, omBinPageRegion after)
67{
68  omAssume(insert != NULL && after != NULL && insert != after);
69  insert->next = after->next;
70  insert->prev = after;
71  after->next = insert;
72  if (insert->next != NULL)
73  {
74    omAssume(insert->next != insert && insert->next != after);
75    insert->next->prev = insert;
76  }
77}
78
79OM_INLINE_LOCAL void omInsertRegionBefore(omBinPageRegion insert, omBinPageRegion before)
80{
81  omAssume(insert != NULL && before != NULL && insert != before);
82  insert->prev = before->prev;
83  insert->next = before;
84  before->prev = insert;
85  if (insert->prev != NULL)
86    insert->prev->next = insert;
87}
88
89
90/*******************************************************************
91 *
92 * Alloc/Free of BinPages
93 *
94 *******************************************************************/
95#define NEXT_PAGE(page) *((void**) page)
96#define OM_IS_EMPTY_REGION(region) ((region)->current == NULL && (region->init_addr == NULL))
97
98omBinPage omAllocBinPage()
99{
100  omBinPage bin_page;
101
102  if (om_CurrentBinPageRegion == NULL)
103    om_CurrentBinPageRegion = omAllocNewBinPagesRegion(1);
104
105  while (1)
106  {
107    if (om_CurrentBinPageRegion->current != NULL)
108    {
109      bin_page = om_CurrentBinPageRegion->current;
110      om_CurrentBinPageRegion->current = NEXT_PAGE(bin_page);
111      goto Found;
112    }
113    if (om_CurrentBinPageRegion->init_pages > 0)
114    {
115      bin_page = (omBinPage)om_CurrentBinPageRegion->init_addr;
116      om_CurrentBinPageRegion->init_pages--;
117      if (om_CurrentBinPageRegion->init_pages > 0)
118        om_CurrentBinPageRegion->init_addr += SIZEOF_SYSTEM_PAGE;
119      else
120        om_CurrentBinPageRegion->init_addr = NULL;
121      goto Found;
122    }
123    if (om_CurrentBinPageRegion->next != NULL)
124    {
125      om_CurrentBinPageRegion = om_CurrentBinPageRegion->next;
126    }
127    else
128    {
129      omBinPageRegion new_region = omAllocNewBinPagesRegion(1);
130      new_region->prev = om_CurrentBinPageRegion;
131      om_CurrentBinPageRegion->next = new_region;
132      om_CurrentBinPageRegion = new_region;
133    }
134  }
135
136  Found:
137  bin_page->region = om_CurrentBinPageRegion;
138  om_CurrentBinPageRegion->used_pages++;
139
140  om_Info.UsedPages++;
141  om_Info.AvailPages--;
142  if (om_Info.UsedPages > om_Info.MaxPages)
143    om_Info.MaxPages = om_Info.UsedPages;
144
145  OM_ALLOC_BINPAGE_HOOK;
146  return bin_page;
147}
148
149omBinPage omAllocBinPages(int how_many)
150{
151  omBinPage bin_page;
152  omBinPageRegion region;
153
154  if (om_CurrentBinPageRegion == NULL)
155    om_CurrentBinPageRegion = omAllocNewBinPagesRegion(how_many);
156
157  region = om_CurrentBinPageRegion;
158  while (1)
159  {
160    if (region->init_pages >= how_many)
161    {
162      bin_page = (omBinPage)region->init_addr;
163      region->init_pages -= how_many;
164      if (region->init_pages)
165        region->init_addr += how_many*SIZEOF_SYSTEM_PAGE;
166      else
167        region->init_addr = NULL;
168      goto Found;
169    }
170    if ((bin_page = omTakeOutConsecutivePages(region, how_many)) != NULL)
171    {
172      goto Found;
173    }
174    if (region->next != NULL)
175    {
176      region = region->next;
177    }
178    else
179    {
180      omBinPageRegion new_region = omAllocNewBinPagesRegion(how_many);
181      region->next = new_region;
182      new_region->prev = region;
183      region = new_region;
184    }
185  }
186  /*while (1) */
187
188  Found:
189  bin_page->region = region;
190  region->used_pages += how_many;
191
192  if (region != om_CurrentBinPageRegion && OM_IS_EMPTY_REGION(region))
193  {
194    omTakeOutRegion(region);
195    omInsertRegionBefore(region, om_CurrentBinPageRegion);
196  }
197  om_Info.UsedPages += how_many;
198  om_Info.AvailPages -= how_many;
199  if (om_Info.UsedPages > om_Info.MaxPages)
200    om_Info.MaxPages = om_Info.UsedPages;
201
202  OM_ALLOC_BINPAGE_HOOK;
203  return bin_page;
204}
205
206void omFreeBinPages(omBinPage bin_page, int how_many)
207{
208  omBinPageRegion region = bin_page->region;
209
210  region->used_pages -= how_many;
211  if (region->used_pages == 0)
212  {
213    if (region == om_CurrentBinPageRegion)
214    {
215      if (region->next != NULL)
216        om_CurrentBinPageRegion = region->next;
217      else
218        om_CurrentBinPageRegion = region->prev;
219    }
220    omTakeOutRegion(region);
221    omFreeBinPagesRegion(region);
222  }
223  else
224  {
225    if (region != om_CurrentBinPageRegion && OM_IS_EMPTY_REGION(region))
226    {
227      omTakeOutRegion(region);
228      omInsertRegionAfter(region, om_CurrentBinPageRegion);
229    }
230    if (how_many > 1)
231    {
232      int i = how_many;
233      char* page = (char *)bin_page;
234
235      while (i > 1)
236      {
237        NEXT_PAGE(page) = page + SIZEOF_SYSTEM_PAGE;
238        page = NEXT_PAGE(page);
239        i--;
240      }
241      NEXT_PAGE(page) = region->current;
242    }
243    else
244    {
245      NEXT_PAGE(bin_page) = region->current;
246    }
247    region->current = (void*) bin_page;
248  }
249  om_Info.AvailPages += how_many;
250  om_Info.UsedPages -= how_many;
251  OM_FREE_BINPAGE_HOOK;
252}
253
254static void* omTakeOutConsecutivePages(omBinPageRegion region, int pages)
255{
256  void* current;
257  char* iter;
258  void* prev = NULL;
259  void* bin_page;
260  int found;
261  current = region->current;
262  while (current != NULL)
263  {
264    found = 1;
265    iter = current;
266    while (NEXT_PAGE(iter) == (iter + SIZEOF_SYSTEM_PAGE))
267    {
268      iter = NEXT_PAGE(iter);
269      /* handle pathological case that iter + SIZEOF_SYSTEM_PAGE == 0 */
270      if (iter == NULL) return NULL;
271      found++;
272      if (found == pages)
273      {
274        bin_page = current;
275        if (current == region->current)
276        {
277          region->current = NEXT_PAGE(iter);
278        }
279        else
280        {
281          omAssume(prev != NULL);
282          NEXT_PAGE(prev) = NEXT_PAGE(iter);
283        }
284        return bin_page;
285      }
286    }
287    prev = iter;
288    current = NEXT_PAGE(iter);
289  }
290  return NULL;
291}
292
293/* Alloc a new region and insert into regions ring, set current to new region */
294static omBinPageRegion omAllocNewBinPagesRegion(int min_pages)
295{
296  omBinPageRegion region = omAllocFromSystem(sizeof(omBinPageRegion_t));
297  om_Info.InternalUsedBytesMalloc+=sizeof(omBinPageRegion_t);
298  void* addr;
299  int pages = (min_pages>om_Opts.PagesPerRegion ? min_pages : om_Opts.PagesPerRegion);
300  size_t size = ((size_t)pages)*SIZEOF_SYSTEM_PAGE;
301
302  addr = _omVallocFromSystem(size, 1);
303  if (addr == NULL)
304  {
305    pages = min_pages;
306    size = min_pages*SIZEOF_SYSTEM_PAGE;
307    addr = omVallocFromSystem(size);
308  }
309
310  omRegisterBinPages(addr, pages);
311  region->addr = addr;
312  region->pages = pages;
313  region->used_pages = 0;
314  region->init_addr = addr;
315  region->init_pages = pages;
316  region->current = NULL;
317  region->next = NULL;
318  region->prev = NULL;
319
320  om_Info.AvailPages += pages;
321
322  om_Info.CurrentRegionsAlloc++;
323  if (om_Info.CurrentRegionsAlloc > om_Info.MaxRegionsAlloc)
324    om_Info.MaxRegionsAlloc = om_Info.CurrentRegionsAlloc;
325
326  return region;
327}
328
329/* Free region */
330static void omFreeBinPagesRegion(omBinPageRegion region)
331{
332  omAssume(region != NULL && region->used_pages == 0);
333
334  om_Info.AvailPages -= region->pages;
335  om_Info.CurrentRegionsAlloc--;
336
337  omUnregisterBinPages(region->addr, region->pages);
338  omVfreeToSystem(region->addr, region->pages*SIZEOF_SYSTEM_PAGE);
339  omFreeSizeToSystem(region, sizeof(omBinPageRegion_t));
340  om_Info.InternalUsedBytesMalloc-=sizeof(omBinPageRegion_t);
341}
342
343/*******************************************************************
344 *
345 * BinPage registration
346 *
347 *******************************************************************/
348
349static void omBinPageIndexFault(unsigned long low_index, unsigned long high_index)
350{
351  unsigned long index_diff = high_index - low_index;
352  omAssume(low_index <= high_index &&
353           (high_index > om_MaxBinPageIndex || low_index < om_MinBinPageIndex));
354
355  if (om_BinPageIndicies == NULL)
356  {
357    unsigned long i;
358    om_BinPageIndicies = (unsigned long*) omAllocFromSystem((index_diff + 1)*SIZEOF_LONG);
359    om_Info.InternalUsedBytesMalloc+=(index_diff + 1)*SIZEOF_LONG;
360    om_MaxBinPageIndex = high_index;
361    om_MinBinPageIndex = low_index;
362    for (i=0; i<=index_diff; i++) om_BinPageIndicies[i] = 0;
363  }
364  else
365  {
366    unsigned long old_length = om_MaxBinPageIndex - om_MinBinPageIndex + 1;
367    unsigned long new_length = (low_index < om_MinBinPageIndex ?
368                                om_MaxBinPageIndex - low_index :
369                                high_index - om_MinBinPageIndex) + 1;
370    om_BinPageIndicies  = (unsigned long*) omReallocSizeFromSystem(om_BinPageIndicies, old_length*SIZEOF_LONG,
371                                                                   new_length*SIZEOF_LONG);
372    om_Info.InternalUsedBytesMalloc+= (new_length-old_length)*SIZEOF_LONG;
373    if (low_index < om_MinBinPageIndex)
374    {
375      long i;
376      unsigned long offset = new_length - old_length;
377      for (i=old_length - 1; i >= 0; i--) om_BinPageIndicies[i+offset] = om_BinPageIndicies[i];
378      for (i=offset-1; i>=0; i--)  om_BinPageIndicies[i] = 0;
379      om_MinBinPageIndex = low_index;
380    }
381    else
382    {
383      unsigned long i;
384      for (i=old_length; i<new_length; i++) om_BinPageIndicies[i] = 0;
385      om_MaxBinPageIndex = high_index;
386    }
387  }
388}
389
390static void omRegisterBinPages(void* low_addr, int pages)
391{
392  unsigned long low_index = omGetPageIndexOfAddr(low_addr);
393  char* high_addr = (char *)low_addr + (pages-1)*SIZEOF_SYSTEM_PAGE;
394  unsigned long high_index = omGetPageIndexOfAddr(high_addr);
395  unsigned long shift;
396
397  if (low_index < om_MinBinPageIndex || high_index > om_MaxBinPageIndex)
398    omBinPageIndexFault(low_index, high_index);
399
400  shift = omGetPageShiftOfAddr(low_addr);
401  if (low_index < high_index)
402  {
403    if (shift == 0)
404    {
405      om_BinPageIndicies[low_index-om_MinBinPageIndex] = ULONG_MAX;
406    }
407    else
408    {
409      om_BinPageIndicies[low_index-om_MinBinPageIndex] |= ~ ((((unsigned long) 1) << shift) - 1);
410    }
411    for (shift = low_index+1; shift < high_index; shift++)
412    {
413      om_BinPageIndicies[shift-om_MinBinPageIndex] = ULONG_MAX;
414    }
415    shift = omGetPageShiftOfAddr(high_addr);
416    if (shift == BIT_SIZEOF_LONG - 1)
417    {
418      om_BinPageIndicies[high_index - om_MinBinPageIndex] = ULONG_MAX;
419    }
420    else
421    {
422      om_BinPageIndicies[high_index-om_MinBinPageIndex] |= ((((unsigned long) 1) << (shift + 1)) - 1);
423    }
424  }
425  else
426  {
427    high_index = omGetPageShiftOfAddr(high_addr);
428    while (high_index > shift)
429    {
430      om_BinPageIndicies[low_index-om_MinBinPageIndex] |= (((unsigned long) 1) << high_index);
431      high_index--;
432    }
433    om_BinPageIndicies[low_index-om_MinBinPageIndex] |= (((unsigned long) 1) << shift);
434  }
435}
436
437static void omUnregisterBinPages(void* low_addr, int pages)
438{
439  unsigned long low_index = omGetPageIndexOfAddr(low_addr);
440  char* high_addr = (char *)low_addr + (pages-1)*SIZEOF_SYSTEM_PAGE;
441  unsigned long high_index = omGetPageIndexOfAddr(high_addr);
442  unsigned long shift;
443
444  shift = omGetPageShiftOfAddr(low_addr);
445  if (low_index < high_index)
446  {
447    if (shift == 0)
448    {
449      om_BinPageIndicies[low_index-om_MinBinPageIndex] = 0;
450    }
451    else
452    {
453      om_BinPageIndicies[low_index-om_MinBinPageIndex] &= ((((unsigned long) 1) << shift) - 1);
454    }
455    for (shift = low_index+1; shift < high_index; shift++)
456    {
457      om_BinPageIndicies[shift-om_MinBinPageIndex] = 0;
458    }
459    shift = omGetPageShiftOfAddr(high_addr);
460    if (shift == BIT_SIZEOF_LONG - 1)
461    {
462      om_BinPageIndicies[high_index - om_MinBinPageIndex] = 0;
463    }
464    else
465    {
466      om_BinPageIndicies[high_index-om_MinBinPageIndex] &= ~ ((((unsigned long) 1) << (shift + 1)) - 1);
467    }
468  }
469  else
470  {
471     high_index = omGetPageShiftOfAddr(high_addr);
472     while (high_index > shift)
473     {
474       om_BinPageIndicies[low_index-om_MinBinPageIndex] &= ~(((unsigned long) 1) << high_index);
475       high_index--;
476     }
477     om_BinPageIndicies[low_index-om_MinBinPageIndex] &= ~(((unsigned long) 1) << shift);
478  }
479}
480
481/***********************************************************************
482 *
483 * checking routines
484 *
485 *******************************************************************/
486#ifndef OM_NDEBUG
487#include "omDebug.h"
488
489int omIsKnownMemoryRegion(omBinPageRegion region)
490{
491  omBinPageRegion iter = om_CurrentBinPageRegion;
492
493  if (region == NULL || iter == NULL) return 0;
494  iter = omGListLast(om_CurrentBinPageRegion, prev);
495  do
496  {
497    if (region == iter) return 1;
498    iter = iter->next;
499  }
500  while (iter != NULL);
501  return 0;
502}
503
504
505omError_t omCheckBinPageRegion(omBinPageRegion region, int level, omError_t report, OM_FLR_DECL)
506{
507  if (level <= 0) return omError_NoError;
508
509  omCheckReturn(omCheckPtr(region, report, OM_FLR_VAL));
510  omCheckReturnCorrupted(! omIsKnownMemoryRegion(region));
511  omCheckReturnCorrupted(! omIsAddrPageAligned(region->addr) || ! omIsAddrPageAligned(region->current));
512  omCheckReturnCorrupted(region->used_pages < 0);
513  omCheckReturnCorrupted(region->init_pages < 0 || region->init_pages > region->pages);
514
515  if (region->init_pages)
516  {
517    omCheckReturnCorrupted(! omIsAddrPageAligned(region->init_addr));
518    omCheckReturnCorrupted(! (region->init_addr >= region->addr
519                              && region->init_addr <= region->addr + (region->pages -1)*SIZEOF_SYSTEM_PAGE));
520    omCheckReturnCorrupted(region->init_addr !=
521                           region->addr + (region->pages - region->init_pages)*SIZEOF_SYSTEM_PAGE);
522  }
523
524  omCheckReturn(omCheckList(region->current, level, report, OM_FLR_VAL));
525  omCheckReturnCorrupted(region->current == NULL && region->used_pages + region->init_pages != region->pages);
526  omCheckReturnCorrupted(level > 1 &&
527                         omListLength(region->current)+region->used_pages+region->init_pages != region->pages);
528  return omError_NoError;
529}
530
531omError_t omCheckBinPageRegions(int level, omError_t report, OM_FLR_DECL)
532{
533  omBinPageRegion iter = om_CurrentBinPageRegion;
534
535  if (level <= 0) return omError_NoError;
536  if (iter == NULL) return omError_NoError;
537
538  omCheckReturnError(om_CurrentBinPageRegion->next != NULL && OM_IS_EMPTY_REGION(om_CurrentBinPageRegion->next),
539                     omError_InternalBug);
540  omCheckReturnError(om_CurrentBinPageRegion->prev != NULL && ! OM_IS_EMPTY_REGION(om_CurrentBinPageRegion->prev),
541                     omError_InternalBug);
542
543
544  if (level > 1)
545  {
546    omBinPageRegion prev_last = (omBinPageRegion) omGListLast(om_CurrentBinPageRegion, prev);
547    omBinPageRegion next_last = (omBinPageRegion) omGListLast(om_CurrentBinPageRegion, next);
548
549    omCheckReturn(omCheckGList(iter, next, level, report, OM_FLR_VAL));
550    omCheckReturn(omCheckGList(iter, prev, level, report, OM_FLR_VAL));
551
552    omCheckReturnCorrupted(omGListLength(prev_last, next)
553                          !=
554                          omGListLength(next_last, prev));
555
556    omCheckReturn(omCheckBinPageRegion(om_CurrentBinPageRegion, level - 1, report, OM_FLR_VAL));
557
558    iter = om_CurrentBinPageRegion->next;
559    while (iter)
560    {
561      omCheckReturnError(OM_IS_EMPTY_REGION(iter), omError_InternalBug);
562
563      omCheckReturn(omCheckBinPageRegion(iter, level - 1, report, OM_FLR_VAL));
564      iter = iter->next;
565    }
566
567    iter = om_CurrentBinPageRegion->prev;
568    while (iter)
569    {
570      omCheckReturnError( !OM_IS_EMPTY_REGION(iter), omError_InternalBug);
571      omCheckReturn(omCheckBinPageRegion(iter, level - 1, report, OM_FLR_VAL));
572      iter = iter->prev;
573    }
574  }
575  return omError_NoError;
576}
577
578omBinPageRegion omFindRegionOfAddr(void* addr)
579{
580  omBinPageRegion region = om_CurrentBinPageRegion;
581
582  if (region == NULL) return 0;
583  region = omGListLast(region, prev);
584  do
585  {
586    if ((char *)addr >= region->addr
587    && (char *)addr < region->addr + (region->pages)*SIZEOF_SYSTEM_PAGE)
588      return region;
589    region = region->next;
590  }
591  while (region != NULL);
592  return NULL;
593}
594
595int omIsAddrOnFreeBinPage(void* addr)
596{
597  char *c_addr=(char *)addr;
598  omBinPageRegion region = om_CurrentBinPageRegion;
599
600  if (region == NULL) return 0;
601  do
602  {
603    if (c_addr > region->addr && c_addr < region->addr + (region->pages)*SIZEOF_SYSTEM_PAGE)
604    {
605      if (omIsOnList(region->current, omGetPageOfAddr(addr))) return 1;
606      return 0;
607    }
608    region = region->next;
609  }
610  while (region != NULL);
611  return 0;
612}
613
614#endif /* ! OM_NDEBUG */
615#endif /* HAVE_OMALLOC*/
Note: See TracBrowser for help on using the repository browser.