home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dbmalloc.zip / malign.c < prev    next >
C/C++ Source or Header  |  1993-01-04  |  5KB  |  267 lines

  1. /*
  2.  * (c) Copyright 1990, 1991, 1992 Conor P. Cahill (cpcahil@virtech.vti.com)
  3.  *
  4.  * This software may be distributed freely as long as the following conditions
  5.  * are met:
  6.  *         * the distribution, or any derivative thereof, may not be
  7.  *          included as part of a commercial product
  8.  *        * full source code is provided including this copyright
  9.  *        * there is no charge for the software itself (there may be
  10.  *          a minimal charge for the copying or distribution effort)
  11.  *        * this copyright notice is not modified or removed from any
  12.  *          source file
  13.  */
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #include <sys/types.h>
  17. #include <signal.h>
  18.  
  19. #include "sysdefs.h"
  20.  
  21. /* 
  22.  * make sure mallocin.h doesn't include sys/types.h since we have already
  23.  * included it.
  24.  */
  25. #ifndef SYS_TYPES_H_INCLUDED
  26. #define SYS_TYPES_H_INCLUDED 1
  27. #endif
  28.  
  29. #include "mallocin.h"
  30. #include "tostring.h"
  31.  
  32. #include "debug.h"
  33.  
  34. #ifndef lint
  35. static char rcs_hdr[] = "$Id: malign.c,v 1.2 1992/08/22 16:27:13 cpcahil Exp $";
  36. #endif
  37.  
  38. /*
  39.  * Function:    mem_align()
  40.  *
  41.  * Purpose:    allocate memory aligned to a multiple of the specified 
  42.  *        alignment.
  43.  *
  44.  * Arguments:    size    - size of data area needed
  45.  *
  46.  * Returns:    whatever debug_malloc returns.
  47.  *
  48.  * Narrative:
  49.  *
  50.  */
  51. DATATYPE *
  52. memalign(align,size)
  53.     SIZETYPE      align;
  54.     SIZETYPE      size;
  55. {
  56.     return( DBmemalign(NULL,-1,align,size) );
  57. }
  58.  
  59. /*
  60.  * Function:    debug_malloc()
  61.  *
  62.  * Purpose:    the real memory allocator
  63.  *
  64.  * Arguments:    size    - size of data area needed
  65.  *
  66.  * Returns:    pointer to allocated area, or NULL if unable
  67.  *        to allocate addtional data.
  68.  *
  69.  * Narrative:
  70.  *
  71.  */
  72. DATATYPE *
  73. DBmemalign(file,line,align,size)
  74.     CONST char    * file;
  75.     int          line;
  76.     SIZETYPE      align;
  77.     SIZETYPE      size;
  78. {
  79.     SIZETYPE      bitcnt = 0;
  80.     static IDTYPE      call_counter;
  81.     SIZETYPE      i;
  82.  
  83.     /*
  84.      * increment the counter for the number of calls to this func.
  85.      */
  86.     call_counter++;
  87.  
  88.     /*
  89.      * perform some checks first 
  90.      */
  91.  
  92.     /*
  93.      * count up the number of bits that have been set (a number
  94.      * that is a power of two will only have one bit set)
  95.      */
  96.     for( i=0; i < (sizeof(align) * 8); i++)
  97.     {
  98.         if ( (align & (0x01 << i)) != 0 )
  99.         {
  100.             bitcnt++;
  101.         }
  102.     }
  103.  
  104.     /*
  105.      * if there is other than a single bit set, there was a problem,
  106.      * so return NULL.
  107.      */
  108.     if( bitcnt != 1 )
  109.     {
  110.         return( (DATATYPE *) NULL);
  111.     }
  112.  
  113.     /*
  114.      * if the alignment is too small, increase it until it is 
  115.      * large enough 
  116.      */
  117.     while( align < malloc_round )
  118.     {
  119.         align <<= 1;
  120.     }
  121.  
  122.     /*
  123.      * set the alignment value for this call
  124.      */
  125.     malloc_align = align;
  126.  
  127.     /*
  128.      * call the malloc function and return its result.
  129.      */
  130.     return( DBFmalloc("memalign",M_T_ALIGNED,call_counter,file,line,size) );
  131.  
  132. } /* DBmemalign(... */
  133.  
  134. /*
  135.  * AlignedFit() - determine how close the aligned requirement fits within
  136.  *          the specified malloc segment.
  137.  *
  138.  * This function takes into account the amount of offset into the specified
  139.  * segment the new malloc pointer will have to be in order to be aligned
  140.  * on the correct boundry.
  141.  */
  142. int
  143. AlignedFit(mptr,align,size)
  144.     struct mlist    * mptr;
  145.     SIZETYPE      align;
  146.     SIZETYPE      size;
  147. {
  148.     int          fit;
  149.     SIZETYPE      offset;
  150.  
  151.     offset = AlignedOffset(mptr,align);
  152.  
  153.     fit = mptr->s.size - (offset + size);
  154.  
  155.     return( fit );
  156.  
  157. } /* AlignedFit(... */
  158.  
  159. /*
  160.  * AlignedMakeSeg() - make a new segment at the correct offset within
  161.  *               the specified old segment such that this new 
  162.  *              segment will have it's data pointer aligned at the
  163.  *              correct offset.
  164.  */
  165.  
  166. struct mlist *
  167. AlignedMakeSeg(mptr,align)
  168.     struct mlist     * mptr;
  169.     SIZETYPE      align;
  170. {
  171.     struct mlist    * newptr;
  172.     SIZETYPE      offset;
  173.  
  174.     DEBUG2(10,"AlignedMakeSeg(0x%lx,%d) called...", mptr, align);
  175.  
  176.     /*
  177.      * get the offset of the pointer which will ensure that we have
  178.      * a new segment with the correct alignment.
  179.      */
  180.     offset = AlignedOffset(mptr,align);
  181.  
  182.     if( offset > mptr->s.size )
  183.     {
  184.         abort();
  185.     }
  186.     DEBUG2(20,"Adjusting space (0x%lx) by %d bytes to get alignment",
  187.         mptr->data, offset);
  188.  
  189.     /*
  190.      * get a pointer to the new segment
  191.      */
  192.     newptr = (struct mlist *) (((char *)mptr) + offset);
  193.  
  194.     /*
  195.      * initialize the new segment
  196.       */
  197.     InitMlist(newptr,M_T_SPLIT);
  198.  
  199.     /*
  200.      * link in the new segment
  201.      */
  202.     newptr->prev = mptr;
  203.     newptr->next = mptr->next;
  204.     if( newptr->next )
  205.     {
  206.         newptr->next->prev = newptr;
  207.     }
  208.     mptr->next   = newptr;
  209.  
  210.     /*
  211.      * set the size in the new segment
  212.      */
  213.     newptr->s.size = mptr->s.size - offset;
  214.     newptr->r_size = newptr->s.size;
  215.  
  216.     /*
  217.      * set the size in the old segment
  218.      */
  219.     DEBUG2(20,"Adjusting old segment size from %d to %d",
  220.             mptr->s.size, offset-M_SIZE);
  221.     mptr->s.size = offset - M_SIZE;
  222.     mptr->r_size = mptr->s.size;
  223.  
  224.     /*
  225.      * if mptr was the end of the list, newptr is the new end.
  226.      */
  227.     if( mptr == malloc_end )
  228.     {
  229.         malloc_end = newptr;
  230.     }
  231.  
  232.     return(newptr);
  233.  
  234. } /* AlignedMakeSeg(... */
  235.  
  236. /*
  237.  * AlignedOffset() - calculate the offset from the current data pointer to
  238.  *             a new data pointer that will have the specified
  239.  *             alignment
  240.  */
  241. SIZETYPE
  242. AlignedOffset(mptr,align)
  243.     struct mlist    * mptr;
  244.     SIZETYPE      align;
  245. {
  246.     SIZETYPE      offset;
  247.  
  248.     /*
  249.      * figure out the offset between the current data pointer and the next
  250.      * correctly aligned location
  251.      */
  252.     offset = align - (((SIZETYPE)mptr->data) & (align-1));
  253.  
  254.     /*
  255.      * keep incrementing the offset until we have at least the malloc
  256.      * struct overhead in the offset (so we can make a new segment at
  257.      * the begining of this segment
  258.      */
  259.     while( offset < sizeof(struct mlist) )
  260.     {
  261.         offset += align;
  262.     }
  263.  
  264.     return(offset);
  265. }
  266.  
  267.