source: git/omalloc/omBinPage.c @ 4697a8a

fieker-DuValspielwiese
Last change on this file since 4697a8a was e70e45, checked in by Olaf Bachmann <obachman@…>, 24 years ago
* re-added files git-svn-id: file:///usr/local/Singular/svn/trunk@4521 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: omBinPage.c,v 1.3 2000-08-14 12:26:41 obachman Exp $
7 *******************************************************************/
8#include <limits.h>
9#include "omAlloc.h"
10#include "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  int   used_pages;     /* number of used pages */
25  omBinPageRegion next; /* nex/prev pointer in ring of regions */
26  omBinPageRegion prev;
27  void* init_addr;      /* pointer portion of inital chunk which is still free */
28  int   init_pages;   /* number of pages still available in init_chunk */ 
29  void* addr;         /* addr returned by alloc */
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)
113    {
114      bin_page = om_CurrentBinPageRegion->init_addr;
115      om_CurrentBinPageRegion->init_pages--;
116      if (om_CurrentBinPageRegion->init_pages) 
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  while (1);
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 = 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      void* page = 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  void* 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  void* addr;
298  int pages = (min_pages>om_Opts.PagesPerRegion ? min_pages : om_Opts.PagesPerRegion);
299  size_t size = pages*SIZEOF_SYSTEM_PAGE;
300 
301  addr = _omVallocFromSystem(size, 1);
302  if (addr == NULL) 
303  {
304    pages = min_pages;
305    size = min_pages*SIZEOF_SYSTEM_PAGE;
306    addr = omVallocFromSystem(size);
307  }
308 
309  omRegisterBinPages(addr, pages);
310  region->addr = addr;
311  region->pages = pages;
312  region->used_pages = 0;
313  region->init_addr = addr;
314  region->init_pages = pages;
315  region->current = NULL;
316  region->next = NULL;
317  region->prev = NULL;
318
319  om_Info.AvailPages += pages;
320
321  om_Info.CurrentRegionsAlloc++;
322  if (om_Info.CurrentRegionsAlloc > om_Info.MaxRegionsAlloc)
323    om_Info.MaxRegionsAlloc = om_Info.CurrentRegionsAlloc;
324
325  /* Update info so that max fields can be updated */
326  omUpdateInfo();
327
328  return region;
329}
330
331/* Free region */
332static void omFreeBinPagesRegion(omBinPageRegion region)
333{
334  omAssume(region != NULL && region->used_pages == 0);
335
336  om_Info.AvailPages -= region->pages;
337  om_Info.CurrentRegionsAlloc--;
338
339  omUnregisterBinPages(region->addr, region->pages);
340  omVfreeToSystem(region->addr, region->pages*SIZEOF_SYSTEM_PAGE);
341  omFreeSizeToSystem(region, sizeof(omBinPageRegion_t));
342}
343
344/*******************************************************************
345 * 
346 * BinPage registration
347 * 
348 *******************************************************************/
349
350static void omBinPageIndexFault(unsigned long low_index, unsigned long high_index)
351{
352  unsigned long index_diff = high_index - low_index;
353  long i;
354  omAssume(low_index <= high_index &&
355           (high_index > om_MaxBinPageIndex || low_index < om_MinBinPageIndex));
356 
357  if (om_BinPageIndicies == NULL)
358  {
359    om_BinPageIndicies = (unsigned long*) omAllocFromSystem((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    if (low_index < om_MinBinPageIndex)
373    {
374      unsigned long offset = new_length - old_length;
375      for (i=old_length - 1; i >= 0; i--) om_BinPageIndicies[i+offset] = om_BinPageIndicies[i];
376      for (i=0; i<offset; i++)  om_BinPageIndicies[i] = 0;
377      om_MinBinPageIndex = low_index;
378    }
379    else
380    {
381      for (i=old_length; i<new_length; i++) om_BinPageIndicies[i] = 0;
382      om_MaxBinPageIndex = high_index;
383    }
384  }
385}
386
387static void omRegisterBinPages(void* low_addr, int pages)
388{
389  unsigned long low_index = omGetPageIndexOfAddr(low_addr);
390  void* high_addr = low_addr + (pages-1)*SIZEOF_SYSTEM_PAGE;
391  unsigned long high_index = omGetPageIndexOfAddr(high_addr);
392  unsigned long shift;
393   
394  if (low_index < om_MinBinPageIndex || high_index > om_MaxBinPageIndex)
395    omBinPageIndexFault(low_index, high_index);
396
397  shift = omGetPageShiftOfAddr(low_addr);
398  if (low_index < high_index)
399  {
400    if (shift == 0)
401    {
402      om_BinPageIndicies[low_index-om_MinBinPageIndex] = ULONG_MAX;
403    }
404    else
405    {
406      om_BinPageIndicies[low_index-om_MinBinPageIndex] |= ~ (( 1<< shift) - 1);
407    }
408    for (shift = low_index+1; shift < high_index; shift++)
409    {
410      om_BinPageIndicies[shift-om_MinBinPageIndex] = ULONG_MAX;
411    }
412    shift = omGetPageShiftOfAddr(high_addr);
413    if (shift == BIT_SIZEOF_LONG - 1)
414    {
415      om_BinPageIndicies[high_index - om_MinBinPageIndex] = ULONG_MAX;
416    }
417    else
418    {
419      om_BinPageIndicies[high_index-om_MinBinPageIndex] |= ((1 << (shift + 1)) - 1);
420    }
421  }
422  else
423  {
424    high_index = omGetPageShiftOfAddr(high_addr);
425    while (high_index > shift)
426    {
427      om_BinPageIndicies[low_index-om_MinBinPageIndex] |= (1 << high_index);
428      high_index--;
429    }
430    om_BinPageIndicies[low_index-om_MinBinPageIndex] |= (1 << shift);
431  }
432}
433
434static void omUnregisterBinPages(void* low_addr, int pages)
435{
436  unsigned long low_index = omGetPageIndexOfAddr(low_addr);
437  void* high_addr = low_addr + (pages-1)*SIZEOF_SYSTEM_PAGE;
438  unsigned long high_index = omGetPageIndexOfAddr(high_addr);
439  unsigned long shift;
440 
441  shift = omGetPageShiftOfAddr(low_addr);
442  if (low_index < high_index)
443  {
444    if (shift == 0)
445    {
446      om_BinPageIndicies[low_index-om_MinBinPageIndex] = 0;
447    }
448    else
449    {
450      om_BinPageIndicies[low_index-om_MinBinPageIndex] &= (( 1<< shift) - 1);
451    }
452    for (shift = low_index+1; shift < high_index; shift++)
453    {
454      om_BinPageIndicies[shift-om_MinBinPageIndex] = 0;
455    }
456    shift = omGetPageShiftOfAddr(high_addr);
457    if (shift == BIT_SIZEOF_LONG - 1)
458    {
459      om_BinPageIndicies[high_index - om_MinBinPageIndex] = 0;
460    }
461    else
462    {
463      om_BinPageIndicies[high_index-om_MinBinPageIndex] &= ~ ((1 << (shift + 1)) - 1);
464    }
465  }
466  else
467  {
468     high_index = omGetPageShiftOfAddr(high_addr);
469     while (high_index > shift)
470     {
471       om_BinPageIndicies[low_index-om_MinBinPageIndex] &= ~(1 << high_index);
472       high_index--;
473     }
474     om_BinPageIndicies[low_index-om_MinBinPageIndex] &= ~(1 << shift);
475  }
476}
477   
478/***********************************************************************
479 *
480 * checking routines
481 *
482 *******************************************************************/
483#ifndef OM_NDEBUG
484#include "omDebug.h"
485
486int omIsKnownMemoryRegion(omBinPageRegion region)
487{
488  omBinPageRegion iter = om_CurrentBinPageRegion;
489 
490  if (region == NULL || iter == NULL) return 0;
491  iter = omGListLast(om_CurrentBinPageRegion, prev);
492  do
493  {
494    if (region == iter) return 1;
495    iter = iter->next;
496  }
497  while (iter != NULL);
498  return 0;
499}
500 
501
502omError_t omCheckBinPageRegion(omBinPageRegion region, int level, omError_t report, OM_FLR_DECL)
503{
504  if (level <= 0) return omError_NoError;
505 
506  omCheckReturn(omCheckPtr(region, report, OM_FLR_VAL));
507  omCheckReturnCorrupted(! omIsKnownMemoryRegion(region));
508  omCheckReturnCorrupted(! omIsAddrPageAligned(region->addr) || ! omIsAddrPageAligned(region->current));
509  omCheckReturnCorrupted(region->used_pages < 0);
510  omCheckReturnCorrupted(region->init_pages < 0 || region->init_pages > region->pages);
511 
512  if (region->init_pages)
513  {
514    omCheckReturnCorrupted(! omIsAddrPageAligned(region->init_addr));
515    omCheckReturnCorrupted(! (region->init_addr >= region->addr
516                              && region->init_addr <= region->addr + (region->pages -1)*SIZEOF_SYSTEM_PAGE));
517    omCheckReturnCorrupted(region->init_addr != 
518                           region->addr + (region->pages - region->init_pages)*SIZEOF_SYSTEM_PAGE);
519  }
520   
521  omCheckReturn(omCheckList(region->current, level, report, OM_FLR_VAL));
522  omCheckReturnCorrupted(region->current == NULL && region->used_pages + region->init_pages != region->pages);
523  omCheckReturnCorrupted(level > 1 && 
524                         omListLength(region->current)+region->used_pages+region->init_pages != region->pages);
525  return omError_NoError;
526}
527
528omError_t omCheckBinPageRegions(int level, omError_t report, OM_FLR_DECL)
529{
530  omBinPageRegion iter = om_CurrentBinPageRegion;
531
532  if (level <= 0) return omError_NoError;
533  if (iter == NULL) return omError_NoError;
534
535  omCheckReturnError(om_CurrentBinPageRegion->next != NULL && OM_IS_EMPTY_REGION(om_CurrentBinPageRegion->next),
536                     omError_InternalBug);
537  omCheckReturnError(om_CurrentBinPageRegion->prev != NULL && ! OM_IS_EMPTY_REGION(om_CurrentBinPageRegion->prev),
538                     omError_InternalBug);
539
540
541  if (level > 1)
542  {
543    omBinPageRegion prev_last = (omBinPageRegion) omGListLast(om_CurrentBinPageRegion, prev);
544    omBinPageRegion next_last = (omBinPageRegion) omGListLast(om_CurrentBinPageRegion, next);
545   
546    omCheckReturn(omCheckGList(iter, next, level, report, OM_FLR_VAL));
547    omCheckReturn(omCheckGList(iter, prev, level, report, OM_FLR_VAL));
548
549    omCheckReturnCorrupted(omGListLength(prev_last, next)
550                          != 
551                          omGListLength(next_last, prev));
552   
553    omCheckReturn(omCheckBinPageRegion(om_CurrentBinPageRegion, level - 1, report, OM_FLR_VAL));
554
555    iter = om_CurrentBinPageRegion->next;
556    while (iter)
557    {
558      omCheckReturnError(OM_IS_EMPTY_REGION(iter), omError_InternalBug);
559
560      omCheckReturn(omCheckBinPageRegion(iter, level - 1, report, OM_FLR_VAL));
561      iter = iter->next;
562    }
563
564    iter = om_CurrentBinPageRegion->prev;
565    while (iter)
566    {
567      omCheckReturnError( !OM_IS_EMPTY_REGION(iter), omError_InternalBug);
568      omCheckReturn(omCheckBinPageRegion(iter, level - 1, report, OM_FLR_VAL));
569      iter = iter->prev;
570    }
571  }
572  return omError_NoError;
573}
574
575omBinPageRegion omFindRegionOfAddr(void* addr)
576{
577  omBinPageRegion region = om_CurrentBinPageRegion;
578 
579  if (region == NULL) return 0;
580  region = omGListLast(region, prev);
581  do
582  {
583    if (addr >= region->addr && addr < region->addr + (region->pages)*SIZEOF_SYSTEM_PAGE)
584      return region;
585    region = region->next;
586  }
587  while (region != NULL);
588  return NULL;
589}
590
591int omIsAddrOnFreeBinPage(void* addr)
592{
593  omBinPageRegion region = om_CurrentBinPageRegion;
594 
595  if (region == NULL) return 0;
596  do
597  {
598    if (addr > region->addr && addr < region->addr + (region->pages)*SIZEOF_SYSTEM_PAGE)
599    {
600      if (omIsOnList(region->current, omGetPageOfAddr(addr))) return 1;
601      return 0;
602    }
603    region = region->next;
604  }
605  while (region != NULL);
606  return 0;
607}
608 
609#endif /* ! OM_NDEBUG */
Note: See TracBrowser for help on using the repository browser.