source: git/omalloc/omBin.c @ 91c4012

fieker-DuValspielwiese
Last change on this file since 91c4012 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: 16.3 KB
Line 
1/*******************************************************************
2 *  File:    omBin.c
3 *  Purpose: definitions of routines for working with bins
4 *  Author:  obachman (Olaf Bachmann)
5 *  Created: 11/99
6 *  Version: $Id: omBin.c,v 1.3 2000-08-14 12:26:40 obachman Exp $
7 *******************************************************************/
8
9#include "omAlloc.h"
10/* this should go away */
11
12#ifdef OM_INTERNAL_DEBUG
13size_t omSizeOfBinAddr(void* addr)
14{
15  return _omSizeOfBinAddr(addr);
16}
17#endif
18
19/*****************************************************************
20 *
21 * SpecBin business
22 *
23 *****************************************************************/
24#define om_LargeBin ((omBin) 1)
25omBin _omGetSpecBin(size_t size, int align, int track)
26
27{
28  omBin om_new_specBin;
29  long max_blocks;
30  long sizeW;
31
32
33  size = OM_ALIGN_SIZE(size);
34#ifdef OM_ALIGNMENT_NEEDS_WORK
35  if (align || size >= OM_SIZEOF_UNIQUE_MAX_BLOCK_THRESHOLD)
36  {
37    align = 1;
38    size = OM_STRICT_ALIGN_SIZE(size);
39  }
40#else
41  align = 0;
42#endif 
43 
44  if (size > SIZEOF_OM_BIN_PAGE)
45  {
46    /* need page header */
47    max_blocks = - (long) 
48      ((size+(SIZEOF_SYSTEM_PAGE-SIZEOF_OM_BIN_PAGE))+SIZEOF_SYSTEM_PAGE-1)
49      / SIZEOF_SYSTEM_PAGE;
50    sizeW = ((-max_blocks*SIZEOF_SYSTEM_PAGE) - 
51             (SIZEOF_SYSTEM_PAGE - SIZEOF_OM_BIN_PAGE)) / SIZEOF_LONG;
52    om_new_specBin = om_LargeBin;
53  }
54  else
55  {
56    /* SIZEOF_OM_BIN_PAGE == max_blocks*size + r1; r1 < size */
57    /* r1 = max_blocks*(size_padding) + r2; r2 < max_blocks */
58    max_blocks = SIZEOF_OM_BIN_PAGE / size;
59    sizeW = (SIZEOF_OM_BIN_PAGE % size) / max_blocks;
60#ifdef OM_ALIGNMENT_NEEDS_WORK
61    if (align)
62      sizeW = ((size + sizeW) & ~ (SIZEOF_STRICT_ALIGNMENT - 1));
63    else
64#endif
65      sizeW = ((size + sizeW) & ~ (SIZEOF_OM_ALIGNMENT - 1));
66   
67    omAssume(sizeW >= size);
68    omAssume(max_blocks*sizeW <= SIZEOF_OM_BIN_PAGE);
69    omAssume((max_blocks+1)*sizeW > SIZEOF_OM_BIN_PAGE ||
70             max_blocks*(sizeW + SIZEOF_STRICT_ALIGNMENT) > SIZEOF_OM_BIN_PAGE);
71
72    sizeW = sizeW >> LOG_SIZEOF_LONG;
73    if (size > OM_MAX_BLOCK_SIZE)
74    {
75      om_new_specBin = om_LargeBin;
76    }
77#ifdef OM_ALIGNMENT_NEEDS_WORK
78    else if (align)
79    {
80      om_new_specBin = omSmallSize2AlignedBin( size );
81    }
82#endif
83#ifdef OM_HAVE_TRACK
84    else if (track)
85    {
86      om_new_specBin = omSmallSize2TrackBin( size );
87    }
88#endif
89    else 
90    {
91      om_new_specBin = omSmallSize2Bin( size );
92    }
93  }
94
95  if (om_new_specBin == om_LargeBin ||
96      om_new_specBin->max_blocks < max_blocks)
97  {
98    omSpecBin s_bin;
99#ifdef OM_HAVE_TRACK
100    if (track)
101      s_bin = omFindInSortedGList(om_SpecTrackBin, next, max_blocks, max_blocks);
102    else
103#endif
104      s_bin = omFindInSortedGList(om_SpecBin, next, max_blocks, max_blocks);
105
106    if (s_bin != NULL) 
107    {
108      (s_bin->ref)++;
109      omAssume(s_bin->bin != NULL && 
110             s_bin->bin->max_blocks == s_bin->max_blocks &&
111             s_bin->bin->sizeW == sizeW);
112      return s_bin->bin;
113    }
114    s_bin = (omSpecBin) omAlloc(sizeof(omSpecBin_t));
115    s_bin->ref = 1;
116    s_bin->next = NULL;
117    s_bin->max_blocks = max_blocks;
118    s_bin->bin = (omBin) omAlloc(sizeof(omBin_t));
119    s_bin->bin->current_page = om_ZeroPage;
120    s_bin->bin->last_page = NULL;
121    s_bin->bin->next = NULL;
122    s_bin->bin->sizeW = sizeW;
123    s_bin->bin->max_blocks = max_blocks;
124    s_bin->bin->sticky = 0;
125#ifdef OM_HAVE_TRACK
126    if (track)
127    {
128      om_SpecTrackBin = omInsertInSortedGList(om_SpecTrackBin, next, max_blocks, s_bin);
129    }
130    else
131#endif
132      om_SpecBin = omInsertInSortedGList(om_SpecBin, next, max_blocks, s_bin);
133    return s_bin->bin;
134  }
135  else
136  {
137    return om_new_specBin;
138  }
139}
140
141void _omUnGetSpecBin(omBin *bin_p, int force)
142{
143  omBin bin = *bin_p;
144  if (! omIsStaticBin(bin))
145  {
146#ifdef OM_HAVE_TRACK
147    int track_bin = 0;
148#endif
149    omSpecBin s_bin;
150
151#ifdef OM_HAVE_TRACK
152    s_bin = omFindInGList(om_SpecTrackBin, next, bin, bin);
153    if (s_bin != NULL)
154      track_bin = 1;
155    else
156#endif
157        s_bin = omFindInSortedGList(om_SpecBin, next, max_blocks, bin->max_blocks);
158       
159    omAssume(s_bin != NULL);
160    if (s_bin != NULL)
161    {
162      (s_bin->ref)--;
163      if (s_bin->ref == 0 || force)
164      {
165        if(s_bin->bin->last_page == NULL || force)
166        {
167#ifdef OM_HAVE_TRACK
168          if (track_bin)
169            om_SpecTrackBin = omRemoveFromSortedGList(om_SpecTrackBin, next, max_blocks, s_bin);
170          else
171#endif
172            om_SpecBin = omRemoveFromSortedGList(om_SpecBin, next, max_blocks, s_bin);
173          omFreeSize(s_bin->bin, sizeof(omBin_t));
174          omFreeSize(s_bin, sizeof(omSpecBin_t));
175        }
176      }
177    }
178  }
179  *bin_p = NULL;
180}
181
182/*****************************************************************
183 *
184 * Statistics
185 *
186 *****************************************************************/
187static void omGetBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
188                          int *free_blocks_p)
189{
190  int pages = 0, used_blocks = 0, free_blocks = 0;
191  int where = 1;
192 
193  omBinPage page = bin->last_page;
194  while (page != NULL)
195  {
196    pages++; if (where == 1) 
197    {
198      used_blocks += omGetUsedBlocksOfPage(page) + 1;
199      if (bin->max_blocks > 0)
200        free_blocks += bin->max_blocks - omGetUsedBlocksOfPage(page) -1;
201    }
202    else 
203    {
204      if (bin->max_blocks > 1)
205        used_blocks += bin->max_blocks;
206      else
207        used_blocks++;
208    }
209    if (page == bin->current_page) where = -1;
210    page = page->prev;
211  }
212  *pages_p = pages;
213  *used_blocks_p = used_blocks;
214  *free_blocks_p = free_blocks;
215}
216
217static void omGetTotalBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
218                               int *free_blocks_p)
219{
220  int t_pages = 0, t_used_blocks = 0, t_free_blocks = 0;
221  int pages = 0, used_blocks = 0, free_blocks = 0;
222 
223  while (bin != NULL)
224  {
225    omGetBinStat(bin, &pages, &used_blocks, &free_blocks);
226    t_pages += pages;
227    t_used_blocks += used_blocks;
228    t_free_blocks += free_blocks;
229    bin = bin->next;
230  }
231  *pages_p = t_pages;
232  *used_blocks_p = t_used_blocks;
233  *free_blocks_p = t_free_blocks;
234}
235
236static void omPrintBinStat(FILE * fd, omBin bin, int track, int* pages, int* used_blocks, int* free_blocks)
237{
238  if (track)
239  {
240    fprintf(fd, "T \t \t");
241  }
242  else
243  {
244    fprintf(fd, "%s%u\t%ld\t", (omIsStaticNormalBin(bin) ? " " : (omIsTrackBin(bin) ? "T" : "*")),
245            bin->sizeW, bin->max_blocks);
246  }
247  omGetTotalBinStat(bin, pages, used_blocks, free_blocks);
248  fprintf(fd, "%d\t%d\t%d\n", *pages, *free_blocks, *used_blocks);
249  if (bin->next != NULL)
250  {
251    int s_pages, s_free_blocks, s_used_blocks;
252    while (bin != NULL)
253    {
254      omGetBinStat(bin, &s_pages, &s_used_blocks, &s_free_blocks);
255      fprintf(fd, " \t \t%d\t%d\t%d\t%d\n", s_pages, s_free_blocks, s_used_blocks, 
256              (int) bin->sticky);
257      bin = bin->next;
258      *pages += s_pages;
259      *used_blocks += s_used_blocks;
260      *free_blocks += s_free_blocks;
261    }
262  }
263}
264 
265void omPrintBinStats(FILE* fd)
266{
267  int i = OM_MAX_BIN_INDEX, pages=0, used_blocks=0, free_blocks=0;
268  int pages_p, used_blocks_p, free_blocks_p;
269  omSpecBin s_bin = om_SpecBin;
270 
271  fprintf(fd, " SizeW\tBlocks\tUPages\tFBlocks\tUBlocks\tSticky\n");
272  fflush(fd);
273  while (s_bin != NULL || i >= 0)
274  {
275    if (s_bin == NULL || (i >= 0 && (unsigned long) om_StaticBin[i].max_blocks < (unsigned long) s_bin->bin->max_blocks))
276    {
277       omPrintBinStat(fd, &om_StaticBin[i], 0, &pages_p, &used_blocks_p, &free_blocks_p);
278       pages += pages_p;
279       used_blocks += used_blocks_p;
280       free_blocks += free_blocks_p;
281#ifdef OM_HAVE_TRACK
282       if (om_StaticTrackBin[i].current_page != om_ZeroPage) 
283       {
284         omPrintBinStat(fd, &om_StaticTrackBin[i], 1, &pages_p, &used_blocks_p, &free_blocks_p);
285         pages += pages_p;
286         used_blocks += used_blocks_p;
287         free_blocks += free_blocks_p;
288       }
289#endif       
290       i--;
291    }
292    else
293    {
294      omPrintBinStat(fd, s_bin->bin,0, &pages_p, &used_blocks_p, &free_blocks_p);
295      pages += pages_p;
296      used_blocks += used_blocks_p;
297      free_blocks += free_blocks_p;
298      s_bin = s_bin->next;
299    }
300  }
301#ifdef OM_HAVE_TRACK
302  s_bin = om_SpecTrackBin;
303  while (s_bin != NULL)
304  {
305    omPrintBinStat(fd, s_bin->bin, 0,  &pages_p, &used_blocks_p, &free_blocks_p);
306    s_bin = s_bin->next;
307    pages += pages_p;
308    used_blocks += used_blocks_p;
309    free_blocks += free_blocks_p;
310  }
311#endif
312  fprintf(fd, "----------------------------------------\n");
313  fprintf(fd, "      \t      \t%d\t%d\t%d\n", pages, free_blocks, used_blocks);
314}
315 
316/*****************************************************************
317 *
318 * Sticky business
319 *
320 *****************************************************************/
321#define omGetStickyBin(bin, sticky_tag) \
322   omFindInGList(bin, next, sticky, sticky_tag)
323
324static omBin omCreateStickyBin(omBin bin, unsigned long sticky)
325{
326  omBin s_bin = (omBin) omAlloc(sizeof(omBin_t));
327  s_bin->sticky = sticky;
328  s_bin->current_page = om_ZeroPage;
329  s_bin->last_page = NULL;
330  s_bin->max_blocks = bin->max_blocks;
331  s_bin->sizeW = bin->sizeW;
332  s_bin->next = bin->next;
333  bin->next = s_bin;
334  return s_bin;
335}
336
337unsigned long omGetMaxStickyBinTag(omBin bin)
338{
339  unsigned long sticky = 0;
340  do
341  {
342    if (bin->sticky > sticky) sticky = bin->sticky;
343    bin = bin->next;
344  }
345  while (bin != NULL);
346  return sticky;
347}
348
349unsigned long omGetNewStickyBinTag(omBin bin)
350{
351  unsigned long sticky = omGetMaxStickyBinTag(bin);
352  if (sticky < BIT_SIZEOF_LONG - 2)
353  {
354    sticky++;
355    omCreateStickyBin(bin, sticky);
356    return sticky;
357  }
358  else
359  {
360    omAssume(sticky == BIT_SIZEOF_LONG - 1);
361  }
362  return sticky;
363}
364
365void omSetStickyBinTag(omBin bin, unsigned long sticky_tag)
366{
367  omBin s_bin;
368  s_bin = omGetStickyBin(bin, sticky_tag);
369 
370  if (s_bin != bin)
371  {
372    omBinPage tc, tl;
373    unsigned long ts;
374   
375    if (s_bin == NULL) s_bin = omCreateStickyBin(bin, sticky_tag);
376    ts = bin->sticky;
377    tl = bin->last_page;
378    tc = bin->current_page;
379    bin->sticky = s_bin->sticky;
380    bin->current_page = s_bin->current_page;
381    bin->last_page = s_bin->last_page;
382    s_bin->sticky = ts;
383    s_bin->last_page = tl;
384    s_bin->current_page = tc;
385  }
386}
387
388void omUnSetStickyBinTag(omBin bin, unsigned long sticky)
389{
390  omAssume(omGetStickyBin(bin, 0) != NULL);
391  if (bin->sticky == sticky)
392    omSetStickyBinTag(bin, 0);
393}
394
395static void omMergeStickyPages(omBin to_bin, omBin from_bin)
396{
397#ifdef HAVE_OM_ASSUME
398  int length = omGListLength(to_bin->last_page, prev) +
399    omGListLength(from_bin->last_page, prev);
400#endif 
401 
402  omBinPage page = from_bin->last_page;
403  omAssume(to_bin->sticky == 0);
404  omAssume(to_bin->sizeW == from_bin->sizeW);
405  omAssume(to_bin != from_bin);
406  omAssume(omIsOnGList(to_bin->next, next, from_bin) 
407           || 
408           omIsOnGList(from_bin->next, next, to_bin));
409
410  if (page == NULL) return;
411  do
412  {
413    omSetStickyOfPage(page, 0);
414    if (page->prev == NULL) break;
415    page = page->prev;
416  }
417  while(1);
418
419  if (to_bin->last_page == NULL)
420  {
421    omAssume(to_bin->current_page == om_ZeroPage);
422    to_bin->last_page = from_bin->last_page;
423    to_bin->current_page = from_bin->current_page;
424    return;
425  }
426 
427  omAssume(to_bin->current_page != om_ZeroPage && 
428           to_bin->current_page != NULL);
429
430  if (to_bin->current_page->current != NULL)
431  {
432    if (to_bin->current_page->prev == NULL)
433    {
434      from_bin->last_page->next = to_bin->current_page;
435      to_bin->current_page->prev = from_bin->last_page;
436      to_bin->current_page = from_bin->current_page;
437      return;
438    }
439    to_bin->current_page = to_bin->current_page->prev;
440  }
441  else
442  {
443    /* need to reset this here, since new current_page is going to be
444       from_bin->current_page, and only for current_page may we have
445       used_blocks != 0 && current == NULL */
446    to_bin->current_page->used_blocks = 0;
447  }
448 
449
450  omAssume(to_bin->current_page != NULL && 
451           to_bin->current_page->current == NULL &&
452           to_bin->current_page->used_blocks == 0);
453
454  from_bin->last_page->next = to_bin->current_page->next;
455  if (to_bin->current_page->next != NULL) 
456    to_bin->current_page->next->prev =  from_bin->last_page;
457  else
458  {
459    omAssume(to_bin->current_page == to_bin->last_page);
460    to_bin->last_page = from_bin->last_page;
461  }
462  to_bin->current_page->next = page;
463  page->prev = to_bin->current_page;
464  to_bin->current_page = from_bin->current_page;
465 
466#ifdef HAVE_OM_ASSUME
467  omAssume(omGListLength(to_bin->last_page, prev) == length);
468#endif
469}
470
471void omDeleteStickyBinTag(omBin bin, unsigned long sticky)
472{
473  omBin no_sticky_bin = NULL;
474  omBin sticky_bin = NULL;
475
476  if (sticky == 0)
477  {
478    omAssume(0);
479    return;
480  }
481 
482  sticky_bin = omGetStickyBin(bin, sticky);
483  if (sticky_bin != NULL)
484  {
485    no_sticky_bin = omGetStickyBin(bin, 0);
486    omAssume(no_sticky_bin != NULL && sticky_bin != no_sticky_bin);
487
488    omMergeStickyPages(no_sticky_bin, sticky_bin);
489
490    if (bin == sticky_bin) 
491    {
492      sticky_bin = no_sticky_bin;
493      omSetStickyBinTag(bin, 0);
494    }
495    bin->next = omRemoveFromGList(bin->next, next, sticky_bin);
496    omFreeSize(sticky_bin, sizeof(omBin_t));
497  }
498}
499
500
501 
502/*****************************************************************
503*
504* AllBin business
505*
506*****************************************************************/
507unsigned long omGetNewStickyAllBinTag()
508{
509  unsigned long sticky = 0, new_sticky;
510  int i;
511  omSpecBin s_bin;
512  // first, find new sticky tag
513  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
514  {
515    new_sticky = omGetMaxStickyBinTag(&(om_StaticBin[i]));
516    if (new_sticky > sticky) sticky = new_sticky;
517  }
518  s_bin = om_SpecBin;
519  while (s_bin != NULL) 
520  {
521    new_sticky = omGetMaxStickyBinTag(s_bin->bin);
522    if (new_sticky > sticky) sticky = new_sticky;
523    s_bin = s_bin->next;
524  }
525  if (sticky < BIT_SIZEOF_LONG - 2) 
526  {
527    sticky++;
528    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
529    {
530      omCreateStickyBin(&(om_StaticBin[i]), sticky);
531    }
532    s_bin = om_SpecBin;
533    while (s_bin != NULL) 
534    {
535      omCreateStickyBin(s_bin->bin, sticky);
536      s_bin = s_bin->next;
537    }
538    return sticky;
539  }
540  else
541  {
542    omBin bin;
543    omAssume(sticky == BIT_SIZEOF_LONG - 1);
544    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
545    {
546      bin = &om_StaticBin[i];
547      if (omGetStickyBin(bin, BIT_SIZEOF_LONG -1) == NULL)
548        omCreateStickyBin(bin, BIT_SIZEOF_LONG -1);
549    }
550    s_bin = om_SpecBin;
551    while (s_bin != NULL) 
552    {
553      if (omGetStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1) == NULL)
554        omCreateStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1);
555      s_bin = s_bin->next;
556    }
557    return BIT_SIZEOF_LONG - 1;
558  }
559}
560
561void omSetStickyAllBinTag(unsigned long sticky)
562{
563  omSpecBin s_bin = om_SpecBin;
564  int i;
565  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
566  {
567    omSetStickyBinTag(&(om_StaticBin[i]), sticky);
568  }
569  while (s_bin != NULL) 
570  {
571    omSetStickyBinTag(s_bin->bin, sticky);
572    s_bin = s_bin->next;
573  }
574}
575
576void omUnSetStickyAllBinTag(unsigned long sticky)
577{
578  omSpecBin s_bin = om_SpecBin;
579  int i;
580  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
581  {
582    omUnSetStickyBinTag(&(om_StaticBin[i]), sticky);
583  }
584  while (s_bin != NULL) 
585  {
586    omUnSetStickyBinTag(s_bin->bin, sticky);
587    s_bin = s_bin->next;
588  }
589}
590
591void omDeleteStickyAllBinTag(unsigned long sticky)
592{
593  omSpecBin s_bin = om_SpecBin;
594  int i;
595  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
596  {
597    omDeleteStickyBinTag(&(om_StaticBin[i]), sticky);
598  }
599  while (s_bin != NULL) 
600  {
601    omDeleteStickyBinTag(s_bin->bin, sticky);
602    s_bin = s_bin->next;
603  }
604}
605
606#if 0
607void omPrintMissing(omBin bin)
608{
609  omBinPage page = bin->last_page;
610 
611  while (page != NULL)
612  {
613    void* addr = (void*) page + SIZEOF_OM_BIN_PAGE_HEADER;
614    int i;
615   
616    for (i=0; i<bin->max_blocks; i++)
617    {
618      if (! omIsOnList(page->current, addr))
619        printf("%d:%p\n", i, addr);
620      addr += bin->sizeW*SIZEOF_LONG;
621    }
622    page = page->prev;
623  }
624}
625#endif
626
627static  int omGetUsedBytesOfBin(omBin bin)
628{
629  int pages = 0, used_blocks = 0, free_blocks = 0;
630  omGetTotalBinStat(bin, &pages, &used_blocks, &free_blocks);
631  return used_blocks*bin->sizeW*SIZEOF_LONG;
632}
633
634size_t omGetUsedBinBytes()
635{
636  int i = OM_MAX_BIN_INDEX;
637  omSpecBin s_bin = om_SpecBin;
638  size_t used = 0;
639 
640  for (; i>=0; i--)
641  {
642    used += omGetUsedBytesOfBin(&om_StaticBin[i]);
643  }
644  while (s_bin != NULL)
645  {
646    used += omGetUsedBytesOfBin(s_bin->bin);
647    s_bin = s_bin->next;
648  }
649#ifdef OM_HAVE_TRACK
650  for (i=OM_MAX_BIN_INDEX; i>=0; i--)
651  {
652    used += omGetUsedBytesOfBin(&om_StaticTrackBin[i]);
653  }
654  s_bin = om_SpecTrackBin;
655  while (s_bin != NULL)
656  {
657    used += omGetUsedBytesOfBin(s_bin->bin);
658    s_bin = s_bin->next;
659  }
660#endif
661
662  return used;
663}
664
Note: See TracBrowser for help on using the repository browser.