source: git/omalloc/omAlloc.c @ e36e3a

spielwiese
Last change on this file since e36e3a was e36e3a, checked in by Olaf Bachmann <obachman@…>, 24 years ago
* .. git-svn-id: file:///usr/local/Singular/svn/trunk@3903 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 24.0 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.3 1999-11-23 20:40:12 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(((void*) 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(((void*) 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 * 
231 *  Local stuff
232 * 
233 *******************************************************************/
234/* this should go away */
235#define AllocSizeOf(x) _omAllocBlock(sizeof(x))
236#define FreeSizeOf(addr, x) _omFreeBin(addr)
237
238/* Get new page and initialize */
239static omBinPage omAllocNewBinPage(omBin bin)
240{
241  omBinPage newpage;
242  void* tmp;
243  int i = 1;
244
245  if (bin->max_blocks > 0) newpage = omGetPage();
246  else newpage = omVallocFromSystem(bin->sizeW * SIZEOF_LONG);
247   
248  omAssume(omIsAddrPageAligned((void*) newpage));
249
250  omSetTopBinAndStickyOfPage(newpage, bin, bin->sticky);
251  newpage->used_blocks = -1;
252  newpage->current = (void*) (((void*)newpage) + SIZEOF_OM_BIN_PAGE_HEADER);
253  tmp = newpage->current;
254  while (i < bin->max_blocks)
255  {
256    tmp = *((void**)tmp) = ((void**) tmp) + bin->sizeW;
257    i++;
258  }
259  *((void**)tmp) = NULL;
260  omAssume(omListLength(newpage->current) == 
261           (bin->max_blocks > 1 ? bin->max_blocks : 1));
262  return newpage;
263}
264
265OM_INLINE void omFreeBinPage(omBinPage page, omBin bin)
266{
267  if (bin->max_blocks > 0)
268    omFreePage(page);
269  else
270    omVfreeToSystem(page, bin->sizeW * SIZEOF_LONG);
271}
272
273   
274/* primitives for handling of list of pages */
275OM_INLINE void omTakeOutBinPage(omBinPage page, omBin bin)
276{
277  if (bin->current_page == page) 
278  {
279    if (page->next == NULL) 
280    {
281      if (page->prev == NULL)
282      {
283        omAssume(bin->last_page == page);
284        bin->last_page = NULL;
285        bin->current_page = om_ZeroPage;
286        return;
287      }
288      bin->current_page = page->prev;
289    }
290    else
291      bin->current_page = page->next;
292  }
293  if (bin->last_page == page)
294  {
295    omAssume(page->prev != NULL && page->next == NULL);
296    bin->last_page = page->prev;
297  }
298  else
299  {
300    page->next->prev = page->prev;
301  }
302  if (page->prev != NULL) page->prev->next = page->next;
303}
304
305OM_INLINE void omInsertBinPage(omBinPage after, omBinPage page, omBin bin)
306{
307  if (bin->current_page == om_ZeroPage)
308  {
309    omAssume(bin->last_page == NULL);
310    page->next = NULL;
311    page->prev = NULL;
312    bin->current_page = page;
313    bin->last_page = page;
314  }
315  else
316  {
317    omAssume(after != NULL && bin->last_page != NULL);
318    if (after == bin->last_page) 
319    {
320      bin->last_page = page;
321    }
322    else
323    {
324      omAssume(after->next != NULL);
325      after->next->prev = page;
326    }
327    page->next = after->next;
328    after->next = page;
329    page->prev = after;
330  }
331}
332
333/* bin->current_page is empty, get new bin->current_page, return addr*/
334void* omAllocBinFromFullPage(omBin bin)
335{
336  void* addr;
337  omBinPage newpage;
338  omAssume(bin->current_page->current == NULL);
339 
340  if (bin->current_page != om_ZeroPage)
341  {
342    omAssume(bin->last_page != NULL);
343    bin->current_page->used_blocks = 0;
344  }
345
346  if (bin->current_page->next != NULL)
347  {
348    omAssume(bin->current_page->next->current != NULL);
349    newpage = bin->current_page->next;
350  }
351  else
352  {
353    // need to Allocate new page
354    newpage = omAllocNewBinPage(bin);
355    omInsertBinPage(bin->current_page, newpage, bin);
356  }
357  bin->current_page = newpage;
358 
359  omAssume(newpage != NULL && newpage != om_ZeroPage && 
360           newpage->current != NULL);
361  __omTypeAllocFromPage(void*, addr, newpage);
362  return addr;
363}
364
365
366/* page->used_blocks == 0, so, either free page or reallocate to
367   the right of current_page */
368/*
369 * Now: there are three different strategies here, on what to do with
370 * pages which were full and now have a free block:
371 * 1.) Insert at the end (default)
372 * 2.) Insert after current_page  => #define PAGE_AFTER_CURRENT
373 * 3.) Let it be new current_page => #define PAGE_BEFORE_CURRENT
374 * Still need to try out which is best
375 */
376void  omFreeToPageFault(omBinPage page, void* addr)
377{
378  omBin bin;
379  omAssume(page->used_blocks == 0);
380
381  if (page == om_LargePage)
382  {
383    omFreeToSystem(addr);
384  }
385  else
386  {
387    bin = omGetBinOfPage(page);
388    if (page->current != NULL || bin->max_blocks <= 1)
389    {
390      // all blocks of page are now collected
391      omTakeOutBinPage(page, bin);
392      // page can be freed
393      omFreeBinPage(page, bin);
394    }
395    else
396    {
397      // page was full
398      page->current = addr;
399      page->used_blocks = bin->max_blocks - 2;
400      *((void**)addr) = NULL;
401
402      omTakeOutBinPage(page, bin);
403#if defined(PAGE_BEFORE_CURRENT)
404      if (bin->current_page->prev != NULL)
405        omInsertBinPage(bin->current_page->prev, page);
406      else
407        omInsertBinPage(bin->current_page, page, bin);
408      bin->current_page = page;
409#elsif defined(PAGE_AFTER_CURRENT)
410      omInsertBinPage(bin->current_page, page, bin);
411#else
412      omInsertBinPage(bin->last_page, page, bin);
413#endif   
414    }
415  }
416}
417
418/*****************************************************************
419 *
420 * SpecBin business
421 *
422 *****************************************************************/
423omBin omGetSpecBin(size_t size)
424{
425  omBin om_new_specBin;
426  long max_blocks;
427  long sizeW;
428
429
430  size = OM_ALIGN_SIZE(size);
431 
432  if (size > SIZEOF_OM_BIN_PAGE)
433  {
434    /* need page header */
435    max_blocks = - (long) 
436      ((size+(SIZEOF_SYSTEM_PAGE-SIZEOF_OM_BIN_PAGE))+SIZEOF_SYSTEM_PAGE-1)
437      / SIZEOF_SYSTEM_PAGE;
438    sizeW = ((-max_blocks*SIZEOF_SYSTEM_PAGE) - 
439             (SIZEOF_SYSTEM_PAGE - SIZEOF_OM_BIN_PAGE)) / SIZEOF_LONG;
440    om_new_specBin = om_LargeBin;
441  }
442  else
443  {
444    max_blocks = SIZEOF_OM_BIN_PAGE / size;
445    sizeW = (SIZEOF_OM_BIN_PAGE / max_blocks) / SIZEOF_LONG;
446    om_new_specBin = omSize2Bin( size );
447  }
448
449  if (om_new_specBin == om_LargeBin ||
450      om_new_specBin->max_blocks < max_blocks)
451  {
452    omSpecBin s_bin
453      = omFindInSortedGList(om_SpecBin, next, max_blocks, max_blocks);
454
455    if (s_bin != NULL) 
456    {
457      (s_bin->ref)++;
458      omAssume(s_bin->bin != NULL && 
459             s_bin->bin->max_blocks == s_bin->max_blocks &&
460             s_bin->bin->sizeW == sizeW);
461      return s_bin->bin;
462    }
463    s_bin = (omSpecBin) AllocSizeOf(omSpecBin_t);
464    s_bin->ref = 1;
465    s_bin->next = NULL;
466    s_bin->max_blocks = max_blocks;
467    s_bin->bin = (omBin) AllocSizeOf(omBin_t);
468    s_bin->bin->current_page = om_ZeroPage;
469    s_bin->bin->last_page = NULL;
470    s_bin->bin->next = NULL;
471    s_bin->bin->sizeW = sizeW;
472    s_bin->bin->max_blocks = max_blocks;
473    s_bin->bin->sticky = 0;
474    om_SpecBin = omInsertInSortedGList(om_SpecBin, next, max_blocks, s_bin);
475    return s_bin->bin;
476  }
477  else
478  {
479    return om_new_specBin;
480  }
481}
482
483int omIsStaticBin(omBin bin)
484{
485  return ((unsigned long) bin >= ((unsigned long) &om_StaticBin[0]) &&
486          (unsigned long) bin <= ((unsigned long) &om_StaticBin[OM_MAX_BIN_INDEX]));
487}
488 
489void omUnGetSpecBin(omBin *bin_p)
490{
491  omBin bin = *bin_p;
492  if (! omIsStaticBin(bin))
493  {
494    omSpecBin s_bin
495      = omFindInSortedGList(om_SpecBin, next, max_blocks, bin->max_blocks);
496    omAssume(s_bin != NULL);
497    if (s_bin != NULL)
498    {
499      (s_bin->ref)--;
500      if (s_bin->ref == 0)
501      {
502        if(s_bin->bin->last_page == NULL)
503        {
504          om_SpecBin = omRemoveFromSortedGList(om_SpecBin, next, max_blocks,
505                                               s_bin);
506          FreeSizeOf(s_bin->bin, omBin_t);
507          FreeSizeOf(s_bin, omSpecBin_t);
508        }
509      }
510    }
511  }
512  *bin_p = NULL;
513}
514
515/*****************************************************************
516 *
517 * Statistics
518 *
519 *****************************************************************/
520static void omGetBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
521                          int *free_blocks_p)
522{
523  int pages = 0, used_blocks = 0, free_blocks = 0;
524  int where = 1;
525 
526  omBinPage page = bin->last_page;
527  while (page != NULL)
528  {
529    pages++;
530    if (where == 1) 
531    {
532      used_blocks += page->used_blocks + 1;
533      if (bin->max_blocks > 0)
534        free_blocks += bin->max_blocks - page->used_blocks -1;
535    }
536    else 
537    {
538      if (bin->max_blocks > 1)
539        used_blocks += bin->max_blocks;
540      else
541        used_blocks++;
542    }
543    if (page == bin->current_page) where = -1;
544    page = page->prev;
545  }
546  *pages_p = pages;
547  *used_blocks_p = used_blocks;
548  *free_blocks_p = free_blocks;
549}
550
551static void omGetTotalBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
552                               int *free_blocks_p)
553{
554  int t_pages = 0, t_used_blocks = 0, t_free_blocks = 0;
555  int pages = 0, used_blocks = 0, free_blocks = 0;
556 
557  while (bin != NULL)
558  {
559    omGetBinStat(bin, &pages, &used_blocks, &free_blocks);
560    t_pages += pages;
561    t_used_blocks += used_blocks;
562    t_free_blocks += free_blocks;
563    bin = bin->next;
564  }
565  *pages_p = t_pages;
566  *used_blocks_p = t_used_blocks;
567  *free_blocks_p = t_free_blocks;
568}
569
570void omGetBinUsage()
571{
572  int pages = 0, used_blocks = 0, free_blocks = 0;
573  size_t bytes;
574  int i;
575  omSpecBin s_bin = om_SpecBin;
576 
577  for(i=0; i<=OM_MAX_BIN_INDEX; i++)
578  {
579    omGetTotalBinStat(&om_StaticBin[i], &pages, &used_blocks, &free_blocks);
580    bytes += used_blocks*om_StaticBin[i].sizeW*SIZEOF_LONG;
581  }
582  while(s_bin != NULL)
583  {
584    omGetTotalBinStat(s_bin->bin, &pages, &used_blocks, &free_blocks);
585    bytes +=  s_bin->bin->sizeW*used_blocks*SIZEOF_LONG;
586    s_bin = s_bin->next;
587  }
588}
589
590void omPrintBinStat(FILE * fd, omBin bin)
591{
592  int pages = 0, used_blocks = 0, free_blocks = 0;
593  fprintf(fd, "%ld\t%ld\t", bin->sizeW, bin->max_blocks);
594  omGetTotalBinStat(bin, &pages, &used_blocks, &free_blocks);
595  fprintf(fd, "%d\t%d\t%d\n", pages, free_blocks, used_blocks);
596  if (bin->next != NULL)
597  {
598    while (bin != NULL)
599    {
600      omGetBinStat(bin, &pages, &used_blocks, &free_blocks);
601      fprintf(fd, " \t \t%d\t%d\t%d\t%d\n", pages, free_blocks, used_blocks, 
602              (int) bin->sticky);
603      bin = bin->next;
604    }
605  }
606}
607 
608void omPrintBinStats(FILE* fd)
609{
610  int i;
611  omSpecBin s_bin = om_SpecBin;
612 
613  fprintf(fd, "SizeW\tMBlocks\tUPages\tFBlocks\tUBlocks\tSticky\n");
614  fflush(fd);
615  for(i=0; i<=OM_MAX_BIN_INDEX; i++)
616  {
617    omPrintBinStat(fd, &om_StaticBin[i]);
618  }
619  while(s_bin != NULL)
620  {
621    omPrintBinStat(fd, s_bin->bin);
622    s_bin = s_bin->next;
623  }
624}
625 
626/*****************************************************************
627 *
628 * Sticky business
629 *
630 *****************************************************************/
631#define omGetStickyBin(bin, sticky_tag) \
632   omFindInGList(bin, next, sticky, sticky_tag)
633
634static omBin omCreateStickyBin(omBin bin, unsigned long sticky)
635{
636  omBin s_bin = (omBin) AllocSizeOf(omBin_t);
637  s_bin->sticky = sticky;
638  s_bin->current_page = om_ZeroPage;
639  s_bin->last_page = NULL;
640  s_bin->max_blocks = bin->max_blocks;
641  s_bin->sizeW = bin->sizeW;
642  s_bin->next = bin->next;
643  bin->next = s_bin;
644  return s_bin;
645}
646
647unsigned long omGetMaxStickyBinTag(omBin bin)
648{
649  unsigned long sticky = 0;
650  do
651  {
652    if (bin->sticky > sticky) sticky = bin->sticky;
653    bin = bin->next;
654  }
655  while (bin != NULL);
656  return sticky;
657}
658
659unsigned long omGetNewStickyBinTag(omBin bin)
660{
661  unsigned long sticky = omGetMaxStickyBinTag(bin);
662  if (sticky < BIT_SIZEOF_LONG - 2)
663  {
664    sticky++;
665    omCreateStickyBin(bin, sticky);
666    return sticky;
667  }
668  else
669  {
670    omAssume(sticky == BIT_SIZEOF_LONG - 1);
671  }
672  return sticky;
673}
674
675void omSetStickyBinTag(omBin bin, unsigned long sticky_tag)
676{
677  omBin s_bin;
678  s_bin = omGetStickyBin(bin, sticky_tag);
679 
680  if (s_bin != bin)
681  {
682    omBinPage tc, tl;
683    unsigned long ts;
684   
685    if (s_bin == NULL) s_bin = omCreateStickyBin(bin, sticky_tag);
686    ts = bin->sticky;
687    tl = bin->last_page;
688    tc = bin->current_page;
689    bin->sticky = s_bin->sticky;
690    bin->current_page = s_bin->current_page;
691    bin->last_page = s_bin->last_page;
692    s_bin->sticky = ts;
693    s_bin->last_page = tl;
694    s_bin->current_page = tc;
695  }
696}
697
698void omUnSetStickyBinTag(omBin bin, unsigned long sticky)
699{
700  omAssume(omGetStickyBin(bin, 0) != NULL);
701  if (bin->sticky == sticky)
702    omSetStickyBinTag(bin, 0);
703}
704
705static void omMergeStickyPages(omBin to_bin, omBin from_bin)
706{
707#ifdef HAVE_OM_ASSUME
708  int length = omGListLength(to_bin->last_page, prev) +
709    omGListLength(from_bin->last_page, prev);
710#endif 
711 
712  omBinPage page = from_bin->last_page;
713  omAssume(to_bin->sticky == 0);
714  omAssume(to_bin->sizeW == from_bin->sizeW);
715  omAssume(to_bin != from_bin);
716  omAssume(omIsOnGList(to_bin->next, next, from_bin) 
717           || 
718           omIsOnGList(from_bin->next, next, to_bin));
719
720  if (page == NULL) return;
721  do
722  {
723    omSetStickyOfPage(page, 0);
724    if (page->prev == NULL) break;
725    page = page->prev;
726  }
727  while(1);
728
729  if (to_bin->last_page == NULL)
730  {
731    omAssume(to_bin->current_page == om_ZeroPage);
732    to_bin->last_page = from_bin->last_page;
733    to_bin->current_page = from_bin->current_page;
734    return;
735  }
736 
737  omAssume(to_bin->current_page != om_ZeroPage && 
738           to_bin->current_page != NULL);
739
740  if (to_bin->current_page->current != NULL)
741  {
742    if (to_bin->current_page->prev == NULL)
743    {
744      from_bin->last_page->next = to_bin->current_page;
745      to_bin->current_page->prev = from_bin->last_page;
746      to_bin->current_page = from_bin->current_page;
747      return;
748    }
749    to_bin->current_page = to_bin->current_page->prev;
750  }
751  else
752  {
753    /* need to reset this here, since new current_page is going to be
754       from_bin->current_page, and only for current_page may we have
755       used_blocks != 0 && current == NULL */
756    to_bin->current_page->used_blocks = 0;
757  }
758 
759
760  omAssume(to_bin->current_page != NULL && 
761           to_bin->current_page->current == NULL &&
762           to_bin->current_page->used_blocks == 0);
763
764  from_bin->last_page->next = to_bin->current_page->next;
765  if (to_bin->current_page->next != NULL) 
766    to_bin->current_page->next->prev =  from_bin->last_page;
767  else
768  {
769    omAssume(to_bin->current_page == to_bin->last_page);
770    to_bin->last_page = from_bin->last_page;
771  }
772  to_bin->current_page->next = page;
773  page->prev = to_bin->current_page;
774  to_bin->current_page = from_bin->current_page;
775 
776#ifdef HAVE_OM_ASSUME
777  omAssume(omGListLength(to_bin->last_page, prev) == length);
778#endif
779}
780
781void omDeleteStickyBinTag(omBin bin, unsigned long sticky)
782{
783  omBin no_sticky_bin = NULL;
784  omBin sticky_bin = NULL;
785
786  if (sticky == 0)
787  {
788    omAssume(0);
789    return;
790  }
791 
792  sticky_bin = omGetStickyBin(bin, sticky);
793  if (sticky_bin != NULL)
794  {
795    no_sticky_bin = omGetStickyBin(bin, 0);
796    omAssume(no_sticky_bin != NULL && sticky_bin != no_sticky_bin);
797
798    omMergeStickyPages(no_sticky_bin, sticky_bin);
799
800    if (bin == sticky_bin) 
801    {
802      sticky_bin = no_sticky_bin;
803      omSetStickyBinTag(bin, 0);
804    }
805    bin->next = omRemoveFromGList(bin->next, next, sticky_bin);
806    FreeSizeOf(sticky_bin, omBin_t);
807  }
808}
809
810
811 
812/*****************************************************************
813*
814* AllBin business
815*
816*****************************************************************/
817unsigned long omGetNewStickyAllBinTag()
818{
819  unsigned long sticky = 0, new_sticky;
820  int i;
821  omSpecBin s_bin;
822  // first, find new sticky tag
823  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
824  {
825    new_sticky = omGetMaxStickyBinTag(&(om_StaticBin[i]));
826    if (new_sticky > sticky) sticky = new_sticky;
827  }
828  s_bin = om_SpecBin;
829  while (s_bin != NULL) 
830  {
831    new_sticky = omGetMaxStickyBinTag(s_bin->bin);
832    if (new_sticky > sticky) sticky = new_sticky;
833    s_bin = s_bin->next;
834  }
835  if (sticky < BIT_SIZEOF_LONG - 2) 
836  {
837    sticky++;
838    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
839    {
840      omCreateStickyBin(&(om_StaticBin[i]), sticky);
841    }
842    s_bin = om_SpecBin;
843    while (s_bin != NULL) 
844    {
845      omCreateStickyBin(s_bin->bin, sticky);
846      s_bin = s_bin->next;
847    }
848    return sticky;
849  }
850  else
851  {
852    omBin bin;
853    omAssume(sticky == BIT_SIZEOF_LONG - 1);
854    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
855    {
856      bin = &om_StaticBin[i];
857      if (omGetStickyBin(bin, BIT_SIZEOF_LONG -1) == NULL)
858        omCreateStickyBin(bin, BIT_SIZEOF_LONG -1);
859    }
860    s_bin = om_SpecBin;
861    while (s_bin != NULL) 
862    {
863      if (omGetStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1) == NULL)
864        omCreateStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1);
865      s_bin = s_bin->next;
866    }
867    return BIT_SIZEOF_LONG - 1;
868  }
869}
870
871void omSetStickyAllBinTag(unsigned long sticky)
872{
873  omSpecBin s_bin = om_SpecBin;
874  int i;
875  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
876  {
877    omSetStickyBinTag(&(om_StaticBin[i]), sticky);
878  }
879  while (s_bin != NULL) 
880  {
881    omSetStickyBinTag(s_bin->bin, sticky);
882    s_bin = s_bin->next;
883  }
884}
885
886void omUnSetStickyAllBinTag(unsigned long sticky)
887{
888  omSpecBin s_bin = om_SpecBin;
889  int i;
890  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
891  {
892    omUnSetStickyBinTag(&(om_StaticBin[i]), sticky);
893  }
894  while (s_bin != NULL) 
895  {
896    omUnSetStickyBinTag(s_bin->bin, sticky);
897    s_bin = s_bin->next;
898  }
899}
900
901void omDeleteStickyAllBinTag(unsigned long sticky)
902{
903  omSpecBin s_bin = om_SpecBin;
904  int i;
905  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
906  {
907    omDeleteStickyBinTag(&(om_StaticBin[i]), sticky);
908  }
909  while (s_bin != NULL) 
910  {
911    omDeleteStickyBinTag(s_bin->bin, sticky);
912    s_bin = s_bin->next;
913  }
914}
915
916#endif /* OM_ALLOC_C */
Note: See TracBrowser for help on using the repository browser.