source: git/omalloc/omAlloc.c @ 212fc04

spielwiese
Last change on this file since 212fc04 was 212fc04, checked in by Olaf Bachmann <obachman@…>, 24 years ago
* as we go along git-svn-id: file:///usr/local/Singular/svn/trunk@3878 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 17.4 KB
Line 
1/*******************************************************************
2 *  File:    omAlloc.c
3 *  Purpose: implementation of main omalloc functions
4 *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
5 *  Created: 11/99
6 *  Version: $Id: omAlloc.c,v 1.2 1999-11-22 18:12:57 obachman Exp $
7 *******************************************************************/
8#ifndef OM_ALLOC_C
9#define OM_ALLOC_C
10#include <string.h>
11#include <stdio.h>
12
13#include "omConfig.h"
14#include "omPrivate.h"
15#include "omLocal.h"
16#include "omList.h"
17
18
19omBinPage_t om_ZeroPage[] = {{0, NULL, NULL, NULL, NULL}};
20omBinPage_t om_CheckPage[] = {{0, NULL, NULL, NULL, NULL}};
21omBinPage_t om_LargePage[] = {{0, NULL, NULL, NULL, NULL}};
22omBin_t     om_LargeBin[] = {{om_LargePage, NULL, NULL, 0, 0, 0}};
23omBin_t     om_CheckBin[] = {{om_CheckPage, NULL, NULL, 0, 0, 0}};
24omSpecBin om_SpecBin = NULL;
25
26
27#include <stdlib.h>
28#define AllocSizeOf(x) _omAllocBlock(sizeof(x))
29#define FreeSizeOf(addr, x) _omFreeBin(addr)
30
31/* Get new page and initialize */
32static omBinPage omAllocNewBinPage(omBin bin)
33{
34  omBinPage newpage;
35  void* tmp;
36  int i = 1;
37
38  if (bin->max_blocks > 0) newpage = omGetPage();
39  else newpage = omVallocFromSystem(bin->sizeW * SIZEOF_LONG);
40   
41  omAssume(omIsAddrPageAligned((void*) newpage));
42
43  omSetTopBinAndStickyOfPage(newpage, bin, bin->sticky);
44  newpage->used_blocks = -1;
45  newpage->current = (void*) (((void*)newpage) + SIZEOF_OM_BIN_PAGE_HEADER);
46  tmp = newpage->current;
47  while (i < bin->max_blocks)
48  {
49    tmp = *((void**)tmp) = ((void**) tmp) + bin->sizeW;
50    i++;
51  }
52  *((void**)tmp) = NULL;
53  omAssume(omListLength(newpage->current) == 
54           (bin->max_blocks > 1 ? bin->max_blocks : 1));
55  return newpage;
56}
57
58OM_INLINE void omFreeBinPage(omBinPage page, omBin bin)
59{
60  if (bin->max_blocks > 0)
61    omFreePage(page);
62  else
63    omVfreeToSystem(page, bin->sizeW * SIZEOF_LONG);
64}
65
66   
67/* primitives for handling of list of pages */
68OM_INLINE void omTakeOutBinPage(omBinPage page, omBin bin)
69{
70  if (bin->current_page == page) 
71  {
72    if (page->next == NULL) 
73    {
74      if (page->prev == NULL)
75      {
76        omAssume(bin->last_page == page);
77        bin->last_page = NULL;
78        bin->current_page = om_ZeroPage;
79        return;
80      }
81      bin->current_page = page->prev;
82    }
83    else
84      bin->current_page = page->next;
85  }
86  if (bin->last_page == page)
87  {
88    omAssume(page->prev != NULL && page->next == NULL);
89    bin->last_page = page->prev;
90  }
91  else
92  {
93    page->next->prev = page->prev;
94  }
95  if (page->prev != NULL) page->prev->next = page->next;
96}
97
98OM_INLINE void omInsertBinPage(omBinPage after, omBinPage page, omBin bin)
99{
100  if (bin->current_page == om_ZeroPage)
101  {
102    omAssume(bin->last_page == NULL);
103    page->next = NULL;
104    page->prev = NULL;
105    bin->current_page = page;
106    bin->last_page = page;
107  }
108  else
109  {
110    omAssume(after != NULL && bin->last_page != NULL);
111    if (after == bin->last_page) 
112    {
113      bin->last_page = page;
114    }
115    else
116    {
117      omAssume(after->next != NULL);
118      after->next->prev = page;
119    }
120    page->next = after->next;
121    after->next = page;
122    page->prev = after;
123  }
124}
125
126/* bin->current_page is empty, get new bin->current_page, return addr*/
127void* omAllocBinFromFullPage(omBin bin)
128{
129  void* addr;
130  omBinPage newpage;
131  omAssume(bin->current_page->current == NULL);
132 
133  if (bin->current_page != om_ZeroPage)
134  {
135    omAssume(bin->last_page != NULL);
136    bin->current_page->used_blocks = 0;
137  }
138
139  if (bin->current_page->next != NULL)
140  {
141    omAssume(bin->current_page->next->current != NULL);
142    newpage = bin->current_page->next;
143  }
144  else
145  {
146    // need to Allocate new page
147    newpage = omAllocNewBinPage(bin);
148    omInsertBinPage(bin->current_page, newpage, bin);
149  }
150  bin->current_page = newpage;
151 
152  omAssume(newpage != NULL && newpage != om_ZeroPage && 
153           newpage->current != NULL);
154  __omTypeAllocFromPage(void*, addr, newpage);
155  return addr;
156}
157
158
159/* page->used_blocks == 0, so, either free page or reallocate to
160   the right of current_page */
161/*
162 * Now: there are three different strategies here, on what to do with
163 * pages which were full and now have a free block:
164 * 1.) Insert at the end (default)
165 * 2.) Insert after current_page  => #define PAGE_AFTER_CURRENT
166 * 3.) Let it be new current_page => #define PAGE_BEFORE_CURRENT
167 * Still need to try out which is best
168 */
169void  omFreeToPageFault(omBinPage page, void* addr)
170{
171  omBin bin;
172  omAssume(page->used_blocks == 0);
173
174  if (page == om_LargePage)
175  {
176    omFreeToSystem(addr);
177  }
178  else
179  {
180    bin = omGetBinOfPage(page);
181    if (page->current != NULL || bin->max_blocks <= 1)
182    {
183      // all blocks of page are now collected
184      omTakeOutBinPage(page, bin);
185      // page can be freed
186      omFreeBinPage(page, bin);
187    }
188    else
189    {
190      // page was full
191      page->current = addr;
192      page->used_blocks = bin->max_blocks - 2;
193      *((void**)addr) = NULL;
194
195      omTakeOutBinPage(page, bin);
196#if defined(PAGE_BEFORE_CURRENT)
197      if (bin->current_page->prev != NULL)
198        omInsertBinPage(bin->current_page->prev, page);
199      else
200        omInsertBinPage(bin->current_page, page, bin);
201      bin->current_page = page;
202#elsif defined(PAGE_AFTER_CURRENT)
203      omInsertBinPage(bin->current_page, page, bin);
204#else
205      omInsertBinPage(bin->last_page, page, bin);
206#endif   
207    }
208  }
209}
210
211/*****************************************************************
212 *
213 * SpecBin business
214 *
215 *****************************************************************/
216omBin omGetSpecBin(size_t size)
217{
218  omBin om_new_specBin;
219  long max_blocks;
220  long sizeW;
221
222
223  size = OM_ALIGN_SIZE(size);
224 
225  if (size > SIZEOF_OM_BIN_PAGE)
226  {
227    /* need page header */
228    max_blocks = - (long) 
229      ((size+(SIZEOF_SYSTEM_PAGE-SIZEOF_OM_BIN_PAGE))+SIZEOF_SYSTEM_PAGE-1)
230      / SIZEOF_SYSTEM_PAGE;
231    sizeW = ((-max_blocks*SIZEOF_SYSTEM_PAGE) - 
232             (SIZEOF_SYSTEM_PAGE - SIZEOF_OM_BIN_PAGE)) / SIZEOF_LONG;
233    om_new_specBin = om_LargeBin;
234  }
235  else
236  {
237    max_blocks = SIZEOF_OM_BIN_PAGE / size;
238    sizeW = (SIZEOF_OM_BIN_PAGE / max_blocks) / SIZEOF_LONG;
239    om_new_specBin = omSize2Bin( size );
240  }
241
242  if (om_new_specBin == om_LargeBin ||
243      om_new_specBin->max_blocks < max_blocks)
244  {
245    omSpecBin s_bin
246      = omFindInSortedGList(om_SpecBin, next, max_blocks, max_blocks);
247
248    if (s_bin != NULL) 
249    {
250      (s_bin->ref)++;
251      omAssume(s_bin->bin != NULL && 
252             s_bin->bin->max_blocks == s_bin->max_blocks &&
253             s_bin->bin->sizeW == sizeW);
254      return s_bin->bin;
255    }
256    s_bin = (omSpecBin) AllocSizeOf(omSpecBin_t);
257    s_bin->ref = 1;
258    s_bin->next = NULL;
259    s_bin->max_blocks = max_blocks;
260    s_bin->bin = (omBin) AllocSizeOf(omBin_t);
261    s_bin->bin->current_page = om_ZeroPage;
262    s_bin->bin->last_page = NULL;
263    s_bin->bin->next = NULL;
264    s_bin->bin->sizeW = sizeW;
265    s_bin->bin->max_blocks = max_blocks;
266    s_bin->bin->sticky = 0;
267    om_SpecBin = omInsertInSortedGList(om_SpecBin, next, max_blocks, s_bin);
268    return s_bin->bin;
269  }
270  else
271  {
272    return om_new_specBin;
273  }
274}
275
276int omIsStaticBin(omBin bin)
277{
278  return ((unsigned long) bin >= ((unsigned long) &om_StaticBin[0]) &&
279          (unsigned long) bin <= ((unsigned long) &om_StaticBin[OM_MAX_BIN_INDEX]));
280}
281 
282void omUnGetSpecBin(omBin *bin_p)
283{
284  omBin bin = *bin_p;
285  if (! omIsStaticBin(bin))
286  {
287    omSpecBin s_bin
288      = omFindInSortedGList(om_SpecBin, next, max_blocks, bin->max_blocks);
289    omAssume(s_bin != NULL);
290    if (s_bin != NULL)
291    {
292      (s_bin->ref)--;
293      if (s_bin->ref == 0)
294      {
295        if(s_bin->bin->last_page == NULL)
296        {
297          om_SpecBin = omRemoveFromSortedGList(om_SpecBin, next, max_blocks,
298                                               s_bin);
299          FreeSizeOf(s_bin->bin, omBin_t);
300          FreeSizeOf(s_bin, omSpecBin_t);
301        }
302      }
303    }
304  }
305  *bin_p = NULL;
306}
307
308/*****************************************************************
309 *
310 * Statistics
311 *
312 *****************************************************************/
313static void omGetBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
314                          int *free_blocks_p)
315{
316  int pages = 0, used_blocks = 0, free_blocks = 0;
317  int where = 1;
318 
319  omBinPage page = bin->last_page;
320  while (page != NULL)
321  {
322    pages++;
323    if (where == 1) 
324    {
325      used_blocks += page->used_blocks + 1;
326      if (bin->max_blocks > 0)
327        free_blocks += bin->max_blocks - page->used_blocks -1;
328    }
329    else 
330    {
331      if (bin->max_blocks > 1)
332        used_blocks += bin->max_blocks;
333      else
334        used_blocks++;
335    }
336    if (page == bin->current_page) where = -1;
337    page = page->prev;
338  }
339  *pages_p = pages;
340  *used_blocks_p = used_blocks;
341  *free_blocks_p = free_blocks;
342}
343
344static void omGetTotalBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
345                               int *free_blocks_p)
346{
347  int t_pages = 0, t_used_blocks = 0, t_free_blocks = 0;
348  int pages = 0, used_blocks = 0, free_blocks = 0;
349 
350  while (bin != NULL)
351  {
352    omGetBinStat(bin, &pages, &used_blocks, &free_blocks);
353    t_pages += pages;
354    t_used_blocks += used_blocks;
355    t_free_blocks += free_blocks;
356    bin = bin->next;
357  }
358  *pages_p = t_pages;
359  *used_blocks_p = t_used_blocks;
360  *free_blocks_p = t_free_blocks;
361}
362
363void omGetBinUsage()
364{
365  int pages = 0, used_blocks = 0, free_blocks = 0;
366  size_t bytes;
367  int i;
368  omSpecBin s_bin = om_SpecBin;
369 
370  for(i=0; i<=OM_MAX_BIN_INDEX; i++)
371  {
372    omGetTotalBinStat(&om_StaticBin[i], &pages, &used_blocks, &free_blocks);
373    bytes += used_blocks*om_StaticBin[i].sizeW*SIZEOF_LONG;
374  }
375  while(s_bin != NULL)
376  {
377    omGetTotalBinStat(s_bin->bin, &pages, &used_blocks, &free_blocks);
378    bytes +=  s_bin->bin->sizeW*used_blocks*SIZEOF_LONG;
379    s_bin = s_bin->next;
380  }
381}
382
383void omPrintBinStat(FILE * fd, omBin bin)
384{
385  int pages = 0, used_blocks = 0, free_blocks = 0;
386  fprintf(fd, "%ld\t%ld\t", bin->sizeW, bin->max_blocks);
387  omGetTotalBinStat(bin, &pages, &used_blocks, &free_blocks);
388  fprintf(fd, "%d\t%d\t%d\n", pages, free_blocks, used_blocks);
389  if (bin->next != NULL)
390  {
391    while (bin != NULL)
392    {
393      omGetBinStat(bin, &pages, &used_blocks, &free_blocks);
394      fprintf(fd, " \t \t%d\t%d\t%d\t%d\n", pages, free_blocks, used_blocks, 
395              (int) bin->sticky);
396      bin = bin->next;
397    }
398  }
399}
400 
401void omPrintBinStats(FILE* fd)
402{
403  int i;
404  omSpecBin s_bin = om_SpecBin;
405 
406  fprintf(fd, "SizeW\tMBlocks\tUPages\tFBlocks\tUBlocks\tSticky\n");
407  fflush(fd);
408  for(i=0; i<=OM_MAX_BIN_INDEX; i++)
409  {
410    omPrintBinStat(fd, &om_StaticBin[i]);
411  }
412  while(s_bin != NULL)
413  {
414    omPrintBinStat(fd, s_bin->bin);
415    s_bin = s_bin->next;
416  }
417}
418 
419/*****************************************************************
420 *
421 * Sticky business
422 *
423 *****************************************************************/
424#define omGetStickyBin(bin, sticky_tag) \
425   omFindInGList(bin, next, sticky, sticky_tag)
426
427static omBin omCreateStickyBin(omBin bin, unsigned long sticky)
428{
429  omBin s_bin = (omBin) AllocSizeOf(omBin_t);
430  s_bin->sticky = sticky;
431  s_bin->current_page = om_ZeroPage;
432  s_bin->last_page = NULL;
433  s_bin->max_blocks = bin->max_blocks;
434  s_bin->sizeW = bin->sizeW;
435  s_bin->next = bin->next;
436  bin->next = s_bin;
437  return s_bin;
438}
439
440unsigned long omGetMaxStickyBinTag(omBin bin)
441{
442  unsigned long sticky = 0;
443  do
444  {
445    if (bin->sticky > sticky) sticky = bin->sticky;
446    bin = bin->next;
447  }
448  while (bin != NULL);
449  return sticky;
450}
451
452unsigned long omGetNewStickyBinTag(omBin bin)
453{
454  unsigned long sticky = omGetMaxStickyBinTag(bin);
455  if (sticky < BIT_SIZEOF_LONG - 2)
456  {
457    sticky++;
458    omCreateStickyBin(bin, sticky);
459    return sticky;
460  }
461  else
462  {
463    omAssume(sticky == BIT_SIZEOF_LONG - 1);
464  }
465  return sticky;
466}
467
468void omSetStickyBinTag(omBin bin, unsigned long sticky_tag)
469{
470  omBin s_bin;
471  s_bin = omGetStickyBin(bin, sticky_tag);
472 
473  if (s_bin != bin)
474  {
475    omBinPage tc, tl;
476    unsigned long ts;
477   
478    if (s_bin == NULL) s_bin = omCreateStickyBin(bin, sticky_tag);
479    ts = bin->sticky;
480    tl = bin->last_page;
481    tc = bin->current_page;
482    bin->sticky = s_bin->sticky;
483    bin->current_page = s_bin->current_page;
484    bin->last_page = s_bin->last_page;
485    s_bin->sticky = ts;
486    s_bin->last_page = tl;
487    s_bin->current_page = tc;
488  }
489}
490
491void omUnSetStickyBinTag(omBin bin, unsigned long sticky)
492{
493  omAssume(omGetStickyBin(bin, 0) != NULL);
494  if (bin->sticky == sticky)
495    omSetStickyBinTag(bin, 0);
496}
497
498static void omMergeStickyPages(omBin to_bin, omBin from_bin)
499{
500#ifdef HAVE_OM_ASSUME
501  int length = omGListLength(to_bin->last_page, prev) +
502    omGListLength(from_bin->last_page, prev);
503#endif 
504 
505  omBinPage page = from_bin->last_page;
506  omAssume(to_bin->sticky == 0);
507  omAssume(to_bin->sizeW == from_bin->sizeW);
508  omAssume(to_bin != from_bin);
509  omAssume(omIsOnGList(to_bin->next, next, from_bin) 
510           || 
511           omIsOnGList(from_bin->next, next, to_bin));
512
513  if (page == NULL) return;
514  do
515  {
516    omSetStickyOfPage(page, 0);
517    if (page->prev == NULL) break;
518    page = page->prev;
519  }
520  while(1);
521
522  if (to_bin->last_page == NULL)
523  {
524    omAssume(to_bin->current_page == om_ZeroPage);
525    to_bin->last_page = from_bin->last_page;
526    to_bin->current_page = from_bin->current_page;
527    return;
528  }
529 
530  omAssume(to_bin->current_page != om_ZeroPage && 
531           to_bin->current_page != NULL);
532
533  if (to_bin->current_page->current != NULL)
534  {
535    if (to_bin->current_page->prev == NULL)
536    {
537      from_bin->last_page->next = to_bin->current_page;
538      to_bin->current_page->prev = from_bin->last_page;
539      to_bin->current_page = from_bin->current_page;
540      return;
541    }
542    to_bin->current_page = to_bin->current_page->prev;
543  }
544  else
545  {
546    /* need to reset this here, since new current_page is going to be
547       from_bin->current_page, and only for current_page may we have
548       used_blocks != 0 && current == NULL */
549    to_bin->current_page->used_blocks = 0;
550  }
551 
552
553  omAssume(to_bin->current_page != NULL && 
554           to_bin->current_page->current == NULL &&
555           to_bin->current_page->used_blocks == 0);
556
557  from_bin->last_page->next = to_bin->current_page->next;
558  if (to_bin->current_page->next != NULL) 
559    to_bin->current_page->next->prev =  from_bin->last_page;
560  else
561  {
562    omAssume(to_bin->current_page == to_bin->last_page);
563    to_bin->last_page = from_bin->last_page;
564  }
565  to_bin->current_page->next = page;
566  page->prev = to_bin->current_page;
567  to_bin->current_page = from_bin->current_page;
568 
569#ifdef HAVE_OM_ASSUME
570  omAssume(omGListLength(to_bin->last_page, prev) == length);
571#endif
572}
573
574#include "omDebug.h"
575 
576void omDeleteStickyBinTag(omBin bin, unsigned long sticky)
577{
578  omBin no_sticky_bin = NULL;
579  omBin sticky_bin = NULL;
580
581  omdCheckBin(bin, 10);
582  if (sticky == 0)
583  {
584    omAssume(0);
585    return;
586  }
587 
588  sticky_bin = omGetStickyBin(bin, sticky);
589  if (sticky_bin != NULL)
590  {
591    no_sticky_bin = omGetStickyBin(bin, 0);
592    omAssume(no_sticky_bin != NULL && sticky_bin != no_sticky_bin);
593
594    omMergeStickyPages(no_sticky_bin, sticky_bin);
595
596    if (bin == sticky_bin) 
597    {
598      sticky_bin = no_sticky_bin;
599      omSetStickyBinTag(bin, 0);
600    }
601    bin->next = omRemoveFromGList(bin->next, next, sticky_bin);
602    FreeSizeOf(sticky_bin, omBin_t);
603  }
604  omdCheckBin(bin, 10);
605}
606
607
608 
609/*****************************************************************
610*
611* AllBin business
612*
613*****************************************************************/
614unsigned long omGetNewStickyAllBinTag()
615{
616  unsigned long sticky = 0, new_sticky;
617  int i;
618  omSpecBin s_bin;
619  // first, find new sticky tag
620  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
621  {
622    new_sticky = omGetMaxStickyBinTag(&(om_StaticBin[i]));
623    if (new_sticky > sticky) sticky = new_sticky;
624  }
625  s_bin = om_SpecBin;
626  while (s_bin != NULL) 
627  {
628    new_sticky = omGetMaxStickyBinTag(s_bin->bin);
629    if (new_sticky > sticky) sticky = new_sticky;
630    s_bin = s_bin->next;
631  }
632  if (sticky < BIT_SIZEOF_LONG - 2) 
633  {
634    sticky++;
635    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
636    {
637      omCreateStickyBin(&(om_StaticBin[i]), sticky);
638    }
639    s_bin = om_SpecBin;
640    while (s_bin != NULL) 
641    {
642      omCreateStickyBin(s_bin->bin, sticky);
643      s_bin = s_bin->next;
644    }
645    return sticky;
646  }
647  else
648  {
649    omBin bin;
650    omAssume(sticky == BIT_SIZEOF_LONG - 1);
651    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
652    {
653      bin = &om_StaticBin[i];
654      if (omGetStickyBin(bin, BIT_SIZEOF_LONG -1) == NULL)
655        omCreateStickyBin(bin, BIT_SIZEOF_LONG -1);
656    }
657    s_bin = om_SpecBin;
658    while (s_bin != NULL) 
659    {
660      if (omGetStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1) == NULL)
661        omCreateStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1);
662      s_bin = s_bin->next;
663    }
664    return BIT_SIZEOF_LONG - 1;
665  }
666}
667
668void omSetStickyAllBinTag(unsigned long sticky)
669{
670  omSpecBin s_bin = om_SpecBin;
671  int i;
672  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
673  {
674    omSetStickyBinTag(&(om_StaticBin[i]), sticky);
675  }
676  while (s_bin != NULL) 
677  {
678    omSetStickyBinTag(s_bin->bin, sticky);
679    s_bin = s_bin->next;
680  }
681}
682
683void omUnSetStickyAllBinTag(unsigned long sticky)
684{
685  omSpecBin s_bin = om_SpecBin;
686  int i;
687  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
688  {
689    omUnSetStickyBinTag(&(om_StaticBin[i]), sticky);
690  }
691  while (s_bin != NULL) 
692  {
693    omUnSetStickyBinTag(s_bin->bin, sticky);
694    s_bin = s_bin->next;
695  }
696}
697
698void omDeleteStickyAllBinTag(unsigned long sticky)
699{
700  omSpecBin s_bin = om_SpecBin;
701  int i;
702  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
703  {
704    omDeleteStickyBinTag(&(om_StaticBin[i]), sticky);
705  }
706  while (s_bin != NULL) 
707  {
708    omDeleteStickyBinTag(s_bin->bin, sticky);
709    s_bin = s_bin->next;
710  }
711}
712
713#endif /* OM_ALLOC_C */
Note: See TracBrowser for help on using the repository browser.