⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bget.c

📁 最新版IAR FOR ARM(EWARM)5.11中的代码例子
💻 C
📖 第 1 页 / 共 4 页
字号:
    }
    b = BH(((char *) buf) - sizeof(struct bhead));
    osize = -b->bsize;
#ifdef BECtl
    if (osize == 0) {
    /*  Buffer acquired directly through acqfcn. */
    struct bdhead *bd;

    bd = BDH(((char *) buf) - sizeof(struct bdhead));
    osize = bd->tsize - sizeof(struct bdhead);
    } else
#endif
    osize -= sizeof(struct bhead);
    ASSERT(osize > 0);
    V memcpy((char *) nbuf, (char *) buf, /* Copy the data */
         (MemSize) ((size < osize) ? size : osize));
    brel(buf);
    return nbuf;
}

/*  BREL  --  Release a buffer.  */

void brel(
  void *buf)
{
    struct bfhead *b, *bn;

    b = BFH(((char *) buf) - sizeof(struct bhead));
#ifdef BufStats
    numrel++;                  /* Increment number of brel() calls */
#endif
    ASSERT(buf != NULL);

#ifdef BECtl
    if (b->bh.bsize == 0) {          /* Directly-acquired buffer? */
    struct bdhead *bdh;

    bdh = BDH(((char *) buf) - sizeof(struct bdhead));
    ASSERT(b->bh.prevfree == 0);
#ifdef BufStats
    totalloc -= bdh->tsize;
    ASSERT(totalloc >= 0);
    numdrel++;              /* Number of direct releases */
#endif /* BufStats */
#ifdef FreeWipe
    V memset((char *) buf, 0x55,
         (MemSize) (bdh->tsize - sizeof(struct bdhead)));
#endif /* FreeWipe */
    ASSERT(relfcn != NULL);
    (*relfcn)((void *) bdh);      /* Release it directly. */
    return;
    }
#endif /* BECtl */

    /* Buffer size must be negative, indicating that the buffer is
       allocated. */

    if (b->bh.bsize >= 0) {
    bn = NULL;
    }
    ASSERT(b->bh.bsize < 0);

    /*    Back pointer in next buffer must be zero, indicating the
    same thing: */

    ASSERT(BH((char *) b - b->bh.bsize)->prevfree == 0);

#ifdef BufStats
    totalloc += b->bh.bsize;
    ASSERT(totalloc >= 0);
#endif

    /* If the back link is nonzero, the previous buffer is free.  */

    if (b->bh.prevfree != 0) {

    /* The previous buffer is free.  Consolidate this buffer  with    it
       by  adding  the  length  of    this  buffer  to the previous free
       buffer.  Note that we subtract the size  in    the  buffer  being
           released,  since  it's  negative to indicate that the buffer is
       allocated. */

    register bufsize size = b->bh.bsize;

        /* Make the previous buffer the one we're working on. */
    ASSERT(BH((char *) b - b->bh.prevfree)->bsize == b->bh.prevfree);
    b = BFH(((char *) b) - b->bh.prevfree);
    b->bh.bsize -= size;
    } else {

        /* The previous buffer isn't allocated.  Insert this buffer
       on the free list as an isolated free block. */

    ASSERT(freelist.ql.blink->ql.flink == &freelist);
    ASSERT(freelist.ql.flink->ql.blink == &freelist);
    b->ql.flink = &freelist;
    b->ql.blink = freelist.ql.blink;
    freelist.ql.blink = b;
    b->ql.blink->ql.flink = b;
    b->bh.bsize = -b->bh.bsize;
    }

    /* Now we look at the next buffer in memory, located by advancing from
       the  start  of  this  buffer  by its size, to see if that buffer is
       free.  If it is, we combine  this  buffer  with    the  next  one    in
       memory, dechaining the second buffer from the free list. */

    bn =  BFH(((char *) b) + b->bh.bsize);
    if (bn->bh.bsize > 0) {

    /* The buffer is free.    Remove it from the free list and add
       its size to that of our buffer. */

    ASSERT(BH((char *) bn + bn->bh.bsize)->prevfree == bn->bh.bsize);
    ASSERT(bn->ql.blink->ql.flink == bn);
    ASSERT(bn->ql.flink->ql.blink == bn);
    bn->ql.blink->ql.flink = bn->ql.flink;
    bn->ql.flink->ql.blink = bn->ql.blink;
    b->bh.bsize += bn->bh.bsize;

    /* Finally,  advance  to   the    buffer    that   follows    the  newly
       consolidated free block.  We must set its  backpointer  to  the
       head  of  the  consolidated free block.  We know the next block
       must be an allocated block because the process of recombination
       guarantees  that  two  free    blocks will never be contiguous in
       memory.  */

    bn = BFH(((char *) b) + b->bh.bsize);
    }
#ifdef FreeWipe
    V memset(((char *) b) + sizeof(struct bfhead), 0x55,
        (MemSize) (b->bh.bsize - sizeof(struct bfhead)));
#endif
    ASSERT(bn->bh.bsize < 0);

    /* The next buffer is allocated.  Set the backpointer in it  to  point
       to this buffer; the previous free buffer in memory. */

    bn->bh.prevfree = b->bh.bsize;

#ifdef BECtl

    /*    If  a  block-release function is defined, and this free buffer
    constitutes the entire block, release it.  Note that  pool_len
    is  defined  in  such a way that the test will fail unless all
    pool blocks are the same size.    */

    if (relfcn != NULL &&
    ((bufsize) b->bh.bsize) == (pool_len - sizeof(struct bhead))) {

    ASSERT(b->bh.prevfree == 0);
    ASSERT(BH((char *) b + b->bh.bsize)->bsize == ESent);
    ASSERT(BH((char *) b + b->bh.bsize)->prevfree == b->bh.bsize);
    /*  Unlink the buffer from the free list  */
    b->ql.blink->ql.flink = b->ql.flink;
    b->ql.flink->ql.blink = b->ql.blink;

    (*relfcn)(b);
#ifdef BufStats
    numprel++;              /* Nr of expansion block releases */
    numpblk--;              /* Total number of blocks */
    ASSERT(numpblk == numpget - numprel);
#endif /* BufStats */
    }
#endif /* BECtl */
}

#ifdef BECtl

/*  BECTL  --  Establish automatic pool expansion control  */

void bectl(
  int (*compact) _((bufsize sizereq, int sequence)),
  void *(*acquire) _((bufsize size)),
  void (*release) _((void *buf)),
  bufsize pool_incr)
{
    compfcn = compact;
    acqfcn = acquire;
    relfcn = release;
    exp_incr = pool_incr;
}
#endif

/*  BPOOL  --  Add a region of memory to the buffer pool.  */

void bpool(
  void *buf,
  bufsize len)
{
    struct bfhead *b = BFH(buf);
    struct bhead *bn;

#ifdef SizeQuant
    len &= ~(SizeQuant - 1);
#endif
#ifdef BECtl
    if (pool_len == 0) {
    pool_len = len;
    } else if (len != pool_len) {
    pool_len = -1;
    }
#ifdef BufStats
    numpget++;                  /* Number of block acquisitions */
    numpblk++;                  /* Number of blocks total */
    ASSERT(numpblk == numpget - numprel);
#endif /* BufStats */
#endif /* BECtl */

    /* Since the block is initially occupied by a single free  buffer,
       it  had    better    not  be  (much) larger than the largest buffer
       whose size we can store in bhead.bsize. */

    ASSERT(len - sizeof(struct bhead) <= -((bufsize) ESent + 1));

    /* Clear  the  backpointer at  the start of the block to indicate that
       there  is  no  free  block  prior  to  this   one.    That   blocks
       recombination when the first block in memory is released. */

    b->bh.prevfree = 0;

    /* Chain the new block to the free list. */

    ASSERT(freelist.ql.blink->ql.flink == &freelist);
    ASSERT(freelist.ql.flink->ql.blink == &freelist);
    b->ql.flink = &freelist;
    b->ql.blink = freelist.ql.blink;
    freelist.ql.blink = b;
    b->ql.blink->ql.flink = b;

    /* Create a dummy allocated buffer at the end of the pool.    This dummy
       buffer is seen when a buffer at the end of the pool is released and
       blocks  recombination  of  the last buffer with the dummy buffer at
       the end.  The length in the dummy buffer  is  set  to  the  largest
       negative  number  to  denote  the  end  of  the pool for diagnostic
       routines (this specific value is  not  counted  on  by  the  actual
       allocation and release functions). */

    len -= sizeof(struct bhead);
    b->bh.bsize = (bufsize) len;
#ifdef FreeWipe
    V memset(((char *) b) + sizeof(struct bfhead), 0x55,
         (MemSize) (len - sizeof(struct bfhead)));
#endif
    bn = BH(((char *) b) + len);
    bn->prevfree = (bufsize) len;
    /* Definition of ESent assumes two's complement! */
    ASSERT((~0) == -1);
    bn->bsize = ESent;
}

#ifdef BufStats

/*  BSTATS  --    Return buffer allocation free space statistics.  */

void bstats(
  bufsize *curalloc, bufsize *totfree, bufsize *maxfree,
  long *nget, long *nrel)
{
    struct bfhead *b = freelist.ql.flink;

    *nget = numget;
    *nrel = numrel;
    *curalloc = totalloc;
    *totfree = 0;
    *maxfree = -1;
    while (b != &freelist) {
    ASSERT(b->bh.bsize > 0);
    *totfree += b->bh.bsize;
    if (b->bh.bsize > *maxfree) {
        *maxfree = b->bh.bsize;
    }
    b = b->ql.flink;          /* Link to next buffer */
    }
}

#ifdef BECtl

/*  BSTATSE  --  Return extended statistics  */

void bstatse(
  bufsize *pool_incr,
  long *npool, long *npget, long *nprel, long *ndget, long *ndrel)
{
    *pool_incr = (pool_len < 0) ? -exp_incr : exp_incr;
    *npool = numpblk;
    *npget = numpget;
    *nprel = numprel;
    *ndget = numdget;
    *ndrel = numdrel;
}
#endif /* BECtl */
#endif /* BufStats */

#ifdef DumpData

/*  BUFDUMP  --  Dump the data in a buffer.  This is called with the  user
         data pointer, and backs up to the buffer header.  It will
         dump either a free block or an allocated one.    */

void bufdump(
  void *buf)
{
    struct bfhead *b;
    unsigned char *bdump;
    bufsize bdlen;

    b = BFH(((char *) buf) - sizeof(struct bhead));
    ASSERT(b->bh.bsize != 0);
    if (b->bh.bsize < 0) {
    bdump = (unsigned char *) buf;
    bdlen = (-b->bh.bsize) - sizeof(struct bhead);
    } else {
    bdump = (unsigned char *) (((char *) b) + sizeof(struct bfhead));
    bdlen = b->bh.bsize - sizeof(struct bfhead);
    }

    while (bdlen > 0) {
    int i, dupes = 0;
    bufsize l = bdlen;
    char bhex[50], bascii[20];

    if (l > 16) {
        l = 16;
    }

    for (i = 0; i < l; i++) {
            V sprintf(bhex + i * 3, "%02X ", bdump[i]);
            bascii[i] = isprint(bdump[i]) ? bdump[i] : ' ';
    }
    bascii[i] = 0;
        V printf("%-48s   %s\n", bhex, bascii);
    bdump += l;
    bdlen -= l;
    while ((bdlen > 16) && (memcmp((char *) (bdump - 16),
                       (char *) bdump, 16) == 0)) {
        dupes++;
        bdump += 16;
        bdlen -= 16;
    }
    if (dupes > 1) {
        V printf(
                "     (%d lines [%d bytes] identical to above line skipped)\n",
        dupes, dupes * 16);
    } else if (dupes == 1) {
        bdump -= 16;
        bdlen += 16;
    }
    }
}
#endif

#ifdef BufDump

/*  BPOOLD  --    Dump a buffer pool.  The buffer headers are always listed.
        If DUMPALLOC is nonzero, the contents of allocated buffers
        are  dumped.   If  DUMPFREE  is  nonzero,  free blocks are
        dumped as well.  If FreeWipe  checking    is  enabled,  free
        blocks    which  have  been clobbered will always be dumped. */

void bpoold(
  void *buf,
  int dumpalloc, int dumpfree)
{
    struct bfhead *b = BFH(buf);

    while (b->bh.bsize != ESent) {
    bufsize bs = b->bh.bsize;

    if (bs < 0) {
        bs = -bs;
            V printf("Allocated buffer: size %6ld bytes.\n", (long) bs);
        if (dumpalloc) {
        bufdump((void *) (((char *) b) + sizeof(struct bhead)));
        }
    } else {
            char *lerr = "";

        ASSERT(bs > 0);
        if ((b->ql.blink->ql.flink != b) ||
        (b->ql.flink->ql.blink != b)) {
                lerr = "  (Bad free list links)";
        }
            V printf("Free block:       size %6ld bytes.%s\n",
        (long) bs, lerr);
#ifdef FreeWipe
        lerr = ((char *) b) + sizeof(struct bfhead);
        if ((bs > sizeof(struct bfhead)) && ((*lerr != 0x55) ||
        (memcmp(lerr, lerr + 1,
          (MemSize) (bs - (sizeof(struct bfhead) + 1))) != 0))) {
        V printf(
                    "(Contents of above free block have been overstored.)\n");
        bufdump((void *) (((char *) b) + sizeof(struct bhead)));
        } else
#endif
        if (dumpfree) {
        bufdump((void *) (((char *) b) + sizeof(struct bhead)));
        }
    }
    b = BFH(((char *) b) + bs);
    }
}
#endif /* BufDump */

#ifdef BufValid

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -