source: git/omalloc/omBinPage.c @ 599326

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