source: git/omalloc/omAlloc.c @ ba6f0c

spielwiese
Last change on this file since ba6f0c was ba6f0c, checked in by Olaf Bachmann <obachman@…>, 24 years ago
as we go along git-svn-id: file:///usr/local/Singular/svn/trunk@3930 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 25.6 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.4 1999-11-26 17:57:51 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
19/*******************************************************************
20 * 
21 *  global variables
22 * 
23 *******************************************************************/
24
25omBinPage_t om_ZeroPage[] = {{0, NULL, NULL, NULL, NULL}};
26omBinPage_t om_CheckPage[] = {{0, NULL, NULL, NULL, NULL}};
27omBinPage_t om_LargePage[] = {{0, NULL, NULL, NULL, NULL}};
28omBin_t     om_LargeBin[] = {{om_LargePage, NULL, NULL, 0, 0, 0}};
29omBin_t     om_CheckBin[] = {{om_CheckPage, NULL, NULL, 0, 0, 0}};
30omSpecBin om_SpecBin = NULL;
31
32/*******************************************************************
33 * 
34 *  Alloc routines which we do not define as macros
35 * 
36 *******************************************************************/
37void* _omReallocBlock(void* old_addr, size_t old_size, size_t new_size)
38{
39  void* new_addr;
40  if (old_addr == NULL) __omTypeAllocBlock(void*, new_addr, new_size);
41  else
42  {
43    if (new_size <= OM_MAX_BLOCK_SIZE && old_size <= OM_MAX_BLOCK_SIZE)
44    {
45      omBin __om_new_bin = omSmallSize2Bin(new_size);
46      omBin __om_old_bin = omSmallSize2Bin(old_size);
47      if (__om_new_bin != __om_old_bin)
48      {
49        __omTypeAllocBlock(void*, new_addr, new_size);
50        omMemcpyW(new_addr, old_addr,
51                  (__om_old_bin->sizeW > __om_new_bin->sizeW ?
52                   __om_new_bin->sizeW : __om_old_bin->sizeW));
53        __omFreeBin(old_addr);
54      }
55    }
56    else if (new_size > OM_MAX_BLOCK_SIZE && old_size > OM_MAX_BLOCK_SIZE)
57    {
58      new_addr = (type) omLargeBlockRealloc(new_size, old_addr, old_size);
59    }
60    else
61    {
62      __omTypeAllocBlock(void*, new_addr, new_size);
63      memcpy(new_addr, old_addr, (old_size > new_size ? new_size : old_size));
64    }
65  }
66  return new_addr;
67}
68
69void* _omRealloc0Block(void* old_addr, size_t old_size, size_t new_size)
70{
71  void* new_addr;
72  int _om_fill = new_size - old_size;
73  new_addr = _omReallocBlock(void*, new_addr, new_size, old_addr, old_size);
74  if (_om_fill > 0) memset(new_addr + _om_fill, 0, _om_fill);
75  return new_addr;
76}
77
78#ifdef OM_ALIGNMENT_NEEDS_WORK     
79void* _omReallocAlignedBlock(void* old_addr, size_t old_size, size_t new_size)
80{
81  void* new_addr;
82  if (old_addr == NULL) __omTypeAllocAlignedBlock(void*, new_addr, new_size);
83  else
84  {
85    if (new_size <= OM_MAX_BLOCK_SIZE && old_size <= OM_MAX_BLOCK_SIZE)
86    {
87      omBin __om_new_bin = omSmallSize2AlignedBin(new_size);
88      omBin __om_old_bin = omSmallSize2AlignedBin(old_size);
89      if (__om_new_bin != __om_old_bin)
90      {
91        __omTypeAllocAlignedBlock(void*, new_addr, new_size);
92        omMemcpyW(new_addr, old_addr,
93                  (__om_old_bin->sizeW > __om_new_bin->sizeW ?
94                   __om_new_bin->sizeW : __om_old_bin->sizeW));
95        __omFreeBin(old_addr);
96      }
97    }
98    else if (new_size > OM_MAX_BLOCK_SIZE && old_size > OM_MAX_BLOCK_SIZE)
99    {
100      new_addr = (type) omLargeBlockRealloc(new_size, old_addr, old_size);
101    }
102    else
103    {
104      __omTypeAllocAllignedBlock(void*, new_addr, new_size);
105      memcpy(new_addr, old_addr, (old_size > new_size ? new_size : old_size));
106    }
107  }
108}
109
110void* _omRealloc0AlignedBlock(void* old_addr, size_t old_size, size_t new_size)
111{
112  void* new_addr;
113  int om_fill = new_size - old_size;
114  __omTypeReallocAlignedBlock(void*, new_addr, new_size, old_addr, old_size);
115  if (om_fill > 0) memset(new_addr + om_fill, 0, om_fill);
116  return new_addr;
117}
118#endif /* OM_ALIGNMENT_NEEDS_WORK */
119
120void* _omReallocChunk(void* old_addr, size_t new_size)
121{
122  void* new_addr;
123  if (old_addr == NULL) __omTypeAllocChunk(void*, new_addr, new_size);
124  else
125  {
126    void* __old_addr = ((void*) (old_addr)) - SIZEOF_OM_ALIGNMENT;
127    omBinPage __om_page = *((omBinPage*) __old_addr);
128    size_t __new_size = new_size + SIZEOF_OM_ALIGNMENT;
129    void* __new_addr;
130    if (__new_size <= MAX_BLOCK_SIZE && __om_page != om_LargePage)
131    {
132      omBin __om_old_bin = omGetTopBinOfPage(__om_page);
133      omBin __om_new_bin = omSmallSize2Bin(__new_size);
134      if (__om_old_bin != __om_new_bin)
135      {
136        __omTypeAllocBin(void*, __new_addr, __new_size);
137        omMemcpyW(__new_addr, __old_addr,                     
138                  (__om_old_bin->sizeW > __om_new_bin->sizeW ?
139                   __om_new_bin->sizeW : __om_old_bin->sizeW));
140        *((void**) __new_addr) = (void*) __om_new_bin->current_page;
141        __omFreeBin(__old_addr);
142        new_addr = (type) (__new_addr + SIZEOF_OM_ALIGNMENT);
143      }
144      else
145      {
146        new_addr = (type) old_addr;
147      }
148    }
149    else if (__new_size > MAX_BLOCK_SIZE && __om_page == om_LargePage)
150    {
151      __new_addr = omReallocLargeChunk(__old_addr, __new_size);
152      *((void**) __new_addr) = (void*) om_LargePage;
153      new_addr = (type) (__new_addr + SIZEOF_OM_ALIGNMENT);
154    }
155    else
156    {
157      __omTypeAllocChunk(void*, new_addr, new_size);
158      if (__om_page != om_LargePage)
159      {
160        omBin old_bin = omGetTopBinOfPage(__om_page);
161        omMemcpyW(new_addr, old_addr, old_bin->sizeW - 1);
162      }
163      else
164      {
165        memcpy(new_addr, old_addr, new_size);
166      }
167    }
168  }
169  return new_addr;
170}
171
172#ifdef OM_ALIGNMENT_NEEDS_WORK
173void* _omReallocAlignedChunk(void* old_addr, size_t new_size)
174{
175  void* new_addr;
176  if (old_addr == NULL) __omTypeAllocAlignedChunk(void*, new_addr, new_size);
177  else
178  {
179    void* __old_addr = ((void*) (old_addr)) - SIZEOF_OM_CHUNK_ALIGNMENT;
180    omBinPage __om_page = *((omBinPage*) __old_addr);
181    size_t __new_size = new_size + SIZEOF_OM_CHUNK_ALIGNMENT;
182    void* __new_addr;
183    if (__new_size <= MAX_BLOCK_SIZE && __om_page != om_LargePage)
184    {
185      omBin __om_old_bin = omGetTopBinOfPage(__om_page);
186      omBin __om_new_bin = omSmallSize2AlignedBin(__new_size);
187      if (__om_old_bin != __om_new_bin)
188      {
189        __omTypeAllocBin(void*, __new_addr, __new_size);
190        omMemcpyW(__new_addr, __old_addr,                     
191                  (__om_old_bin->sizeW > __om_new_bin->sizeW ?
192                   __om_new_bin->sizeW : __om_old_bin->sizeW));
193        *((void**) __new_addr) = (void*) __om_new_bin->current_page;
194        __omFreeBin(__old_addr);
195        new_addr = (type) (__new_addr + SIZEOF_OM_ALIGNMENT);
196      }
197      else
198      {
199        new_addr = (type) old_addr;
200      }
201    }
202    else if (__new_size > MAX_BLOCK_SIZE && __om_page == om_LargePage)
203    {
204      __new_addr = omReallocLargeChunk(__old_addr, __new_size);
205      *((void**) __new_addr) = (void*) om_LargePage;
206      new_addr = (type) (__new_addr + SIZEOF_OM_CHUNK_ALIGNMENT);
207    }
208    else
209    {
210      __omTypeAllocChunk(void*, new_addr, new_size);
211      if (__om_page != om_LargePage)
212      {
213        omBin old_bin = omGetTopBinOfPage(__om_page);
214        memcpy(new_addr, old_addr, 
215               old_bin->sizeW*SIZEOF_LONG - SIZEOF_OM_CHUNK_ALIGNMENT);
216      }
217      else
218      {
219        memcpy(new_addr, old_addr, new_size);
220      }
221      __omFreeAlignedChunk(old_addr);
222    }
223  }
224  return new_addr;
225}
226#endif /* OM_ALIGNMENT_NEEDS_WORK */
227
228/*******************************************************************
229 * 
230 *  Definition of Func
231 * 
232 *******************************************************************/
233
234#define ALLOCBIN_FUNC_WRAPPER(func)             \
235void* omFunc##func (omBin bin)                  \
236{                                               \
237  void* addr;                                   \
238  __omType##func (void*, addr, bin);            \
239  return addr;                                  \
240}
241
242#define ALLOCSIZE_FUNC_WRAPPER(func)            \
243void* omFunc##func (size_t size)                \
244{                                               \
245  void* addr;                                   \
246  __omType##func (void*, addr, size);           \
247  return addr;                                  \
248}
249
250#define FREE_FUNC_WRAPPER(func)                 \
251void omFunc##func (void* addr)                  \
252{                                               \
253  __om##func (addr);                            \
254}
255
256#define FREEBLOCK_FUNC_WRAPPER(func)            \
257void omFunc##func (void* addr, size_t size)     \
258{                                               \
259  __om##func (addr, size);                      \
260}
261
262ALLOCBIN_FUNC_WRAPPER(AllocBin)
263ALLOCBIN_FUNC_WRAPPER(Alloc0Bin)
264FREE_FUNC_WRAPPER(FreeBin)
265ALLOCSIZE_FUNC_WRAPPER(AllocBlock)
266ALLOCSIZE_FUNC_WRAPPER(Alloc0Block)
267FREEBLOCK_FUNC_WRAPPER(FreeBlock)
268ALLOCSIZE_FUNC_WRAPPER(AllocChunk)
269ALLOCSIZE_FUNC_WRAPPER(Alloc0Chunk)
270FREE_FUNC_WRAPPER(FreeChunk)
271
272#ifdef OM_ALIGNMENT_NEEDS_WORK
273ALLOCSIZE_FUNC_WRAPPER(AllocAlignedBlock)
274ALLOCSIZE_FUNC_WRAPPER(Alloc0AlignedBlock)
275ALLOCSIZE_FUNC_WRAPPER(AllocAlignedChunk)
276ALLOCSIZE_FUNC_WRAPPER(Alloc0AlignedChunk)
277FREE_FUNC_WRAPPER(FreeAlignedChunk)
278#endif
279
280/*******************************************************************
281 * 
282 *  Local stuff
283 * 
284 *******************************************************************/
285/* this should go away */
286#define AllocSizeOf(x) _omAllocBlock(sizeof(x))
287#define FreeSizeOf(addr, x) _omFreeBin(addr)
288
289/* Get new page and initialize */
290static omBinPage omAllocNewBinPage(omBin bin)
291{
292  omBinPage newpage;
293  void* tmp;
294  int i = 1;
295
296  if (bin->max_blocks > 0) newpage = omGetPage();
297  else newpage = omVallocFromSystem(bin->sizeW * SIZEOF_LONG);
298   
299  omAssume(omIsAddrPageAligned((void*) newpage));
300
301  omSetTopBinAndStickyOfPage(newpage, bin, bin->sticky);
302  newpage->used_blocks = -1;
303  newpage->current = (void*) (((void*)newpage) + SIZEOF_OM_BIN_PAGE_HEADER);
304  tmp = newpage->current;
305  while (i < bin->max_blocks)
306  {
307    tmp = *((void**)tmp) = ((void**) tmp) + bin->sizeW;
308    i++;
309  }
310  *((void**)tmp) = NULL;
311  omAssume(omListLength(newpage->current) == 
312           (bin->max_blocks > 1 ? bin->max_blocks : 1));
313  return newpage;
314}
315
316OM_INLINE void omFreeBinPage(omBinPage page, omBin bin)
317{
318  if (bin->max_blocks > 0)
319    omFreePage(page);
320  else
321    omVfreeToSystem(page, bin->sizeW * SIZEOF_LONG);
322}
323
324   
325/* primitives for handling of list of pages */
326OM_INLINE void omTakeOutBinPage(omBinPage page, omBin bin)
327{
328  if (bin->current_page == page) 
329  {
330    if (page->next == NULL) 
331    {
332      if (page->prev == NULL)
333      {
334        omAssume(bin->last_page == page);
335        bin->last_page = NULL;
336        bin->current_page = om_ZeroPage;
337        return;
338      }
339      bin->current_page = page->prev;
340    }
341    else
342      bin->current_page = page->next;
343  }
344  if (bin->last_page == page)
345  {
346    omAssume(page->prev != NULL && page->next == NULL);
347    bin->last_page = page->prev;
348  }
349  else
350  {
351    page->next->prev = page->prev;
352  }
353  if (page->prev != NULL) page->prev->next = page->next;
354}
355
356OM_INLINE void omInsertBinPage(omBinPage after, omBinPage page, omBin bin)
357{
358  if (bin->current_page == om_ZeroPage)
359  {
360    omAssume(bin->last_page == NULL);
361    page->next = NULL;
362    page->prev = NULL;
363    bin->current_page = page;
364    bin->last_page = page;
365  }
366  else
367  {
368    omAssume(after != NULL && bin->last_page != NULL);
369    if (after == bin->last_page) 
370    {
371      bin->last_page = page;
372    }
373    else
374    {
375      omAssume(after->next != NULL);
376      after->next->prev = page;
377    }
378    page->next = after->next;
379    after->next = page;
380    page->prev = after;
381  }
382}
383
384/* bin->current_page is empty, get new bin->current_page, return addr*/
385void* omAllocBinFromFullPage(omBin bin)
386{
387  void* addr;
388  omBinPage newpage;
389  omAssume(bin->current_page->current == NULL);
390 
391  if (bin->current_page != om_ZeroPage)
392  {
393    omAssume(bin->last_page != NULL);
394    bin->current_page->used_blocks = 0;
395  }
396
397  if (bin->current_page->next != NULL)
398  {
399    omAssume(bin->current_page->next->current != NULL);
400    newpage = bin->current_page->next;
401  }
402  else
403  {
404    // need to Allocate new page
405    newpage = omAllocNewBinPage(bin);
406    omInsertBinPage(bin->current_page, newpage, bin);
407  }
408  bin->current_page = newpage;
409 
410  omAssume(newpage != NULL && newpage != om_ZeroPage && 
411           newpage->current != NULL);
412  __omTypeAllocFromPage(void*, addr, newpage);
413  return addr;
414}
415
416
417/* page->used_blocks == 0, so, either free page or reallocate to
418   the right of current_page */
419/*
420 * Now: there are three different strategies here, on what to do with
421 * pages which were full and now have a free block:
422 * 1.) Insert at the end (default)
423 * 2.) Insert after current_page  => #define PAGE_AFTER_CURRENT
424 * 3.) Let it be new current_page => #define PAGE_BEFORE_CURRENT
425 * Still need to try out which is best
426 */
427void  omFreeToPageFault(omBinPage page, void* addr)
428{
429  omBin bin;
430  omAssume(page->used_blocks == 0);
431
432  if (page == om_LargePage)
433  {
434    omFreeToSystem(addr);
435  }
436  else
437  {
438    bin = omGetBinOfPage(page);
439    if (page->current != NULL || bin->max_blocks <= 1)
440    {
441      // all blocks of page are now collected
442      omTakeOutBinPage(page, bin);
443      // page can be freed
444      omFreeBinPage(page, bin);
445    }
446    else
447    {
448      // page was full
449      page->current = addr;
450      page->used_blocks = bin->max_blocks - 2;
451      *((void**)addr) = NULL;
452
453      omTakeOutBinPage(page, bin);
454#if defined(PAGE_BEFORE_CURRENT)
455      if (bin->current_page->prev != NULL)
456        omInsertBinPage(bin->current_page->prev, page);
457      else
458        omInsertBinPage(bin->current_page, page, bin);
459      bin->current_page = page;
460#elsif defined(PAGE_AFTER_CURRENT)
461      omInsertBinPage(bin->current_page, page, bin);
462#else
463      omInsertBinPage(bin->last_page, page, bin);
464#endif   
465    }
466  }
467}
468
469/*****************************************************************
470 *
471 * SpecBin business
472 *
473 *****************************************************************/
474omBin omGetSpecBin(size_t size)
475{
476  omBin om_new_specBin;
477  long max_blocks;
478  long sizeW;
479
480
481  size = OM_ALIGN_SIZE(size);
482 
483  if (size > SIZEOF_OM_BIN_PAGE)
484  {
485    /* need page header */
486    max_blocks = - (long) 
487      ((size+(SIZEOF_SYSTEM_PAGE-SIZEOF_OM_BIN_PAGE))+SIZEOF_SYSTEM_PAGE-1)
488      / SIZEOF_SYSTEM_PAGE;
489    sizeW = ((-max_blocks*SIZEOF_SYSTEM_PAGE) - 
490             (SIZEOF_SYSTEM_PAGE - SIZEOF_OM_BIN_PAGE)) / SIZEOF_LONG;
491    om_new_specBin = om_LargeBin;
492  }
493  else
494  {
495    max_blocks = SIZEOF_OM_BIN_PAGE / size;
496    sizeW = (SIZEOF_OM_BIN_PAGE / max_blocks) / SIZEOF_LONG;
497    om_new_specBin = omSize2Bin( size );
498  }
499
500  if (om_new_specBin == om_LargeBin ||
501      om_new_specBin->max_blocks < max_blocks)
502  {
503    omSpecBin s_bin
504      = omFindInSortedGList(om_SpecBin, next, max_blocks, max_blocks);
505
506    if (s_bin != NULL) 
507    {
508      (s_bin->ref)++;
509      omAssume(s_bin->bin != NULL && 
510             s_bin->bin->max_blocks == s_bin->max_blocks &&
511             s_bin->bin->sizeW == sizeW);
512      return s_bin->bin;
513    }
514    s_bin = (omSpecBin) AllocSizeOf(omSpecBin_t);
515    s_bin->ref = 1;
516    s_bin->next = NULL;
517    s_bin->max_blocks = max_blocks;
518    s_bin->bin = (omBin) AllocSizeOf(omBin_t);
519    s_bin->bin->current_page = om_ZeroPage;
520    s_bin->bin->last_page = NULL;
521    s_bin->bin->next = NULL;
522    s_bin->bin->sizeW = sizeW;
523    s_bin->bin->max_blocks = max_blocks;
524    s_bin->bin->sticky = 0;
525    om_SpecBin = omInsertInSortedGList(om_SpecBin, next, max_blocks, s_bin);
526    return s_bin->bin;
527  }
528  else
529  {
530    return om_new_specBin;
531  }
532}
533
534int omIsStaticBin(omBin bin)
535{
536  return ((unsigned long) bin >= ((unsigned long) &om_StaticBin[0]) &&
537          (unsigned long) bin <= ((unsigned long) &om_StaticBin[OM_MAX_BIN_INDEX]));
538}
539 
540void omUnGetSpecBin(omBin *bin_p)
541{
542  omBin bin = *bin_p;
543  if (! omIsStaticBin(bin))
544  {
545    omSpecBin s_bin
546      = omFindInSortedGList(om_SpecBin, next, max_blocks, bin->max_blocks);
547    omAssume(s_bin != NULL);
548    if (s_bin != NULL)
549    {
550      (s_bin->ref)--;
551      if (s_bin->ref == 0)
552      {
553        if(s_bin->bin->last_page == NULL)
554        {
555          om_SpecBin = omRemoveFromSortedGList(om_SpecBin, next, max_blocks,
556                                               s_bin);
557          FreeSizeOf(s_bin->bin, omBin_t);
558          FreeSizeOf(s_bin, omSpecBin_t);
559        }
560      }
561    }
562  }
563  *bin_p = NULL;
564}
565
566/*****************************************************************
567 *
568 * Statistics
569 *
570 *****************************************************************/
571static void omGetBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
572                          int *free_blocks_p)
573{
574  int pages = 0, used_blocks = 0, free_blocks = 0;
575  int where = 1;
576 
577  omBinPage page = bin->last_page;
578  while (page != NULL)
579  {
580    pages++;
581    if (where == 1) 
582    {
583      used_blocks += page->used_blocks + 1;
584      if (bin->max_blocks > 0)
585        free_blocks += bin->max_blocks - page->used_blocks -1;
586    }
587    else 
588    {
589      if (bin->max_blocks > 1)
590        used_blocks += bin->max_blocks;
591      else
592        used_blocks++;
593    }
594    if (page == bin->current_page) where = -1;
595    page = page->prev;
596  }
597  *pages_p = pages;
598  *used_blocks_p = used_blocks;
599  *free_blocks_p = free_blocks;
600}
601
602static void omGetTotalBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
603                               int *free_blocks_p)
604{
605  int t_pages = 0, t_used_blocks = 0, t_free_blocks = 0;
606  int pages = 0, used_blocks = 0, free_blocks = 0;
607 
608  while (bin != NULL)
609  {
610    omGetBinStat(bin, &pages, &used_blocks, &free_blocks);
611    t_pages += pages;
612    t_used_blocks += used_blocks;
613    t_free_blocks += free_blocks;
614    bin = bin->next;
615  }
616  *pages_p = t_pages;
617  *used_blocks_p = t_used_blocks;
618  *free_blocks_p = t_free_blocks;
619}
620
621void omGetBinUsage()
622{
623  int pages = 0, used_blocks = 0, free_blocks = 0;
624  size_t bytes;
625  int i;
626  omSpecBin s_bin = om_SpecBin;
627 
628  for(i=0; i<=OM_MAX_BIN_INDEX; i++)
629  {
630    omGetTotalBinStat(&om_StaticBin[i], &pages, &used_blocks, &free_blocks);
631    bytes += used_blocks*om_StaticBin[i].sizeW*SIZEOF_LONG;
632  }
633  while(s_bin != NULL)
634  {
635    omGetTotalBinStat(s_bin->bin, &pages, &used_blocks, &free_blocks);
636    bytes +=  s_bin->bin->sizeW*used_blocks*SIZEOF_LONG;
637    s_bin = s_bin->next;
638  }
639}
640
641void omPrintBinStat(FILE * fd, omBin bin)
642{
643  int pages = 0, used_blocks = 0, free_blocks = 0;
644  fprintf(fd, "%ld\t%ld\t", bin->sizeW, bin->max_blocks);
645  omGetTotalBinStat(bin, &pages, &used_blocks, &free_blocks);
646  fprintf(fd, "%d\t%d\t%d\n", pages, free_blocks, used_blocks);
647  if (bin->next != NULL)
648  {
649    while (bin != NULL)
650    {
651      omGetBinStat(bin, &pages, &used_blocks, &free_blocks);
652      fprintf(fd, " \t \t%d\t%d\t%d\t%d\n", pages, free_blocks, used_blocks, 
653              (int) bin->sticky);
654      bin = bin->next;
655    }
656  }
657}
658 
659void omPrintBinStats(FILE* fd)
660{
661  int i;
662  omSpecBin s_bin = om_SpecBin;
663 
664  fprintf(fd, "SizeW\tMBlocks\tUPages\tFBlocks\tUBlocks\tSticky\n");
665  fflush(fd);
666  for(i=0; i<=OM_MAX_BIN_INDEX; i++)
667  {
668    omPrintBinStat(fd, &om_StaticBin[i]);
669  }
670  while(s_bin != NULL)
671  {
672    omPrintBinStat(fd, s_bin->bin);
673    s_bin = s_bin->next;
674  }
675}
676 
677/*****************************************************************
678 *
679 * Sticky business
680 *
681 *****************************************************************/
682#define omGetStickyBin(bin, sticky_tag) \
683   omFindInGList(bin, next, sticky, sticky_tag)
684
685static omBin omCreateStickyBin(omBin bin, unsigned long sticky)
686{
687  omBin s_bin = (omBin) AllocSizeOf(omBin_t);
688  s_bin->sticky = sticky;
689  s_bin->current_page = om_ZeroPage;
690  s_bin->last_page = NULL;
691  s_bin->max_blocks = bin->max_blocks;
692  s_bin->sizeW = bin->sizeW;
693  s_bin->next = bin->next;
694  bin->next = s_bin;
695  return s_bin;
696}
697
698unsigned long omGetMaxStickyBinTag(omBin bin)
699{
700  unsigned long sticky = 0;
701  do
702  {
703    if (bin->sticky > sticky) sticky = bin->sticky;
704    bin = bin->next;
705  }
706  while (bin != NULL);
707  return sticky;
708}
709
710unsigned long omGetNewStickyBinTag(omBin bin)
711{
712  unsigned long sticky = omGetMaxStickyBinTag(bin);
713  if (sticky < BIT_SIZEOF_LONG - 2)
714  {
715    sticky++;
716    omCreateStickyBin(bin, sticky);
717    return sticky;
718  }
719  else
720  {
721    omAssume(sticky == BIT_SIZEOF_LONG - 1);
722  }
723  return sticky;
724}
725
726void omSetStickyBinTag(omBin bin, unsigned long sticky_tag)
727{
728  omBin s_bin;
729  s_bin = omGetStickyBin(bin, sticky_tag);
730 
731  if (s_bin != bin)
732  {
733    omBinPage tc, tl;
734    unsigned long ts;
735   
736    if (s_bin == NULL) s_bin = omCreateStickyBin(bin, sticky_tag);
737    ts = bin->sticky;
738    tl = bin->last_page;
739    tc = bin->current_page;
740    bin->sticky = s_bin->sticky;
741    bin->current_page = s_bin->current_page;
742    bin->last_page = s_bin->last_page;
743    s_bin->sticky = ts;
744    s_bin->last_page = tl;
745    s_bin->current_page = tc;
746  }
747}
748
749void omUnSetStickyBinTag(omBin bin, unsigned long sticky)
750{
751  omAssume(omGetStickyBin(bin, 0) != NULL);
752  if (bin->sticky == sticky)
753    omSetStickyBinTag(bin, 0);
754}
755
756static void omMergeStickyPages(omBin to_bin, omBin from_bin)
757{
758#ifdef HAVE_OM_ASSUME
759  int length = omGListLength(to_bin->last_page, prev) +
760    omGListLength(from_bin->last_page, prev);
761#endif 
762 
763  omBinPage page = from_bin->last_page;
764  omAssume(to_bin->sticky == 0);
765  omAssume(to_bin->sizeW == from_bin->sizeW);
766  omAssume(to_bin != from_bin);
767  omAssume(omIsOnGList(to_bin->next, next, from_bin) 
768           || 
769           omIsOnGList(from_bin->next, next, to_bin));
770
771  if (page == NULL) return;
772  do
773  {
774    omSetStickyOfPage(page, 0);
775    if (page->prev == NULL) break;
776    page = page->prev;
777  }
778  while(1);
779
780  if (to_bin->last_page == NULL)
781  {
782    omAssume(to_bin->current_page == om_ZeroPage);
783    to_bin->last_page = from_bin->last_page;
784    to_bin->current_page = from_bin->current_page;
785    return;
786  }
787 
788  omAssume(to_bin->current_page != om_ZeroPage && 
789           to_bin->current_page != NULL);
790
791  if (to_bin->current_page->current != NULL)
792  {
793    if (to_bin->current_page->prev == NULL)
794    {
795      from_bin->last_page->next = to_bin->current_page;
796      to_bin->current_page->prev = from_bin->last_page;
797      to_bin->current_page = from_bin->current_page;
798      return;
799    }
800    to_bin->current_page = to_bin->current_page->prev;
801  }
802  else
803  {
804    /* need to reset this here, since new current_page is going to be
805       from_bin->current_page, and only for current_page may we have
806       used_blocks != 0 && current == NULL */
807    to_bin->current_page->used_blocks = 0;
808  }
809 
810
811  omAssume(to_bin->current_page != NULL && 
812           to_bin->current_page->current == NULL &&
813           to_bin->current_page->used_blocks == 0);
814
815  from_bin->last_page->next = to_bin->current_page->next;
816  if (to_bin->current_page->next != NULL) 
817    to_bin->current_page->next->prev =  from_bin->last_page;
818  else
819  {
820    omAssume(to_bin->current_page == to_bin->last_page);
821    to_bin->last_page = from_bin->last_page;
822  }
823  to_bin->current_page->next = page;
824  page->prev = to_bin->current_page;
825  to_bin->current_page = from_bin->current_page;
826 
827#ifdef HAVE_OM_ASSUME
828  omAssume(omGListLength(to_bin->last_page, prev) == length);
829#endif
830}
831
832void omDeleteStickyBinTag(omBin bin, unsigned long sticky)
833{
834  omBin no_sticky_bin = NULL;
835  omBin sticky_bin = NULL;
836
837  if (sticky == 0)
838  {
839    omAssume(0);
840    return;
841  }
842 
843  sticky_bin = omGetStickyBin(bin, sticky);
844  if (sticky_bin != NULL)
845  {
846    no_sticky_bin = omGetStickyBin(bin, 0);
847    omAssume(no_sticky_bin != NULL && sticky_bin != no_sticky_bin);
848
849    omMergeStickyPages(no_sticky_bin, sticky_bin);
850
851    if (bin == sticky_bin) 
852    {
853      sticky_bin = no_sticky_bin;
854      omSetStickyBinTag(bin, 0);
855    }
856    bin->next = omRemoveFromGList(bin->next, next, sticky_bin);
857    FreeSizeOf(sticky_bin, omBin_t);
858  }
859}
860
861
862 
863/*****************************************************************
864*
865* AllBin business
866*
867*****************************************************************/
868unsigned long omGetNewStickyAllBinTag()
869{
870  unsigned long sticky = 0, new_sticky;
871  int i;
872  omSpecBin s_bin;
873  // first, find new sticky tag
874  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
875  {
876    new_sticky = omGetMaxStickyBinTag(&(om_StaticBin[i]));
877    if (new_sticky > sticky) sticky = new_sticky;
878  }
879  s_bin = om_SpecBin;
880  while (s_bin != NULL) 
881  {
882    new_sticky = omGetMaxStickyBinTag(s_bin->bin);
883    if (new_sticky > sticky) sticky = new_sticky;
884    s_bin = s_bin->next;
885  }
886  if (sticky < BIT_SIZEOF_LONG - 2) 
887  {
888    sticky++;
889    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
890    {
891      omCreateStickyBin(&(om_StaticBin[i]), sticky);
892    }
893    s_bin = om_SpecBin;
894    while (s_bin != NULL) 
895    {
896      omCreateStickyBin(s_bin->bin, sticky);
897      s_bin = s_bin->next;
898    }
899    return sticky;
900  }
901  else
902  {
903    omBin bin;
904    omAssume(sticky == BIT_SIZEOF_LONG - 1);
905    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
906    {
907      bin = &om_StaticBin[i];
908      if (omGetStickyBin(bin, BIT_SIZEOF_LONG -1) == NULL)
909        omCreateStickyBin(bin, BIT_SIZEOF_LONG -1);
910    }
911    s_bin = om_SpecBin;
912    while (s_bin != NULL) 
913    {
914      if (omGetStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1) == NULL)
915        omCreateStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1);
916      s_bin = s_bin->next;
917    }
918    return BIT_SIZEOF_LONG - 1;
919  }
920}
921
922void omSetStickyAllBinTag(unsigned long sticky)
923{
924  omSpecBin s_bin = om_SpecBin;
925  int i;
926  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
927  {
928    omSetStickyBinTag(&(om_StaticBin[i]), sticky);
929  }
930  while (s_bin != NULL) 
931  {
932    omSetStickyBinTag(s_bin->bin, sticky);
933    s_bin = s_bin->next;
934  }
935}
936
937void omUnSetStickyAllBinTag(unsigned long sticky)
938{
939  omSpecBin s_bin = om_SpecBin;
940  int i;
941  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
942  {
943    omUnSetStickyBinTag(&(om_StaticBin[i]), sticky);
944  }
945  while (s_bin != NULL) 
946  {
947    omUnSetStickyBinTag(s_bin->bin, sticky);
948    s_bin = s_bin->next;
949  }
950}
951
952void omDeleteStickyAllBinTag(unsigned long sticky)
953{
954  omSpecBin s_bin = om_SpecBin;
955  int i;
956  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
957  {
958    omDeleteStickyBinTag(&(om_StaticBin[i]), sticky);
959  }
960  while (s_bin != NULL) 
961  {
962    omDeleteStickyBinTag(s_bin->bin, sticky);
963    s_bin = s_bin->next;
964  }
965}
966
967#endif /* OM_ALLOC_C */
Note: See TracBrowser for help on using the repository browser.