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

📄 heap.c

📁 Linux操作系统的著名硬件加速绘图API软件。可以利用网卡提供的硬件加速功能完成绘图
💻 C
📖 第 1 页 / 共 2 页
字号:
          default:               /* Old size is a fragment; type is logarithm                  to base two of the fragment size.  */               if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))                    /* The new size is the same kind of fragment.  */                    result = ptr;               else {                    /* The new size is different; allocate a new space,                       and copy the lesser of the new size and the old. */                    result = _fusion_shmalloc( heap, size );                    if (result == NULL)                         return NULL;                    direct_memcpy (result, ptr, MIN (size, (size_t) 1 << type));                    _fusion_shfree( heap, ptr );               }               break;     }     return result;}/* Return memory to the heap. */void_fusion_shfree( shmalloc_heap *heap, void *ptr ){     int type;     size_t block, blocks;     register size_t i;     struct list *prev, *next;     D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %p )\n", __FUNCTION__, heap, ptr );     D_MAGIC_ASSERT( heap, shmalloc_heap );     if (ptr == NULL)          return;     block = BLOCK (ptr);     type = heap->heapinfo[block].busy.type;     switch (type) {          case 0:               /* Get as many statistics as early as we can.  */               heap->chunks_used--;               heap->bytes_used -= heap->heapinfo[block].busy.info.size * BLOCKSIZE;               heap->bytes_free += heap->heapinfo[block].busy.info.size * BLOCKSIZE;               /* Find the free cluster previous to this one in the free list.                  Start searching at the last block referenced; this may benefit                  programs with locality of allocation.  */               i = heap->heapindex;               if (i > block)                    while (i > block)                         i = heap->heapinfo[i].free.prev;               else {                    do                         i = heap->heapinfo[i].free.next;                    while (i > 0 && i < block);                    i = heap->heapinfo[i].free.prev;               }               /* Determine how to link this block into the free list.  */               if (block == i + heap->heapinfo[i].free.size) {                    /* Coalesce this block with its predecessor.  */                    heap->heapinfo[i].free.size += heap->heapinfo[block].busy.info.size;                    block = i;               }               else {                    /* Really link this block back into the free list.  */                    heap->heapinfo[block].free.size = heap->heapinfo[block].busy.info.size;                    heap->heapinfo[block].free.next = heap->heapinfo[i].free.next;                    heap->heapinfo[block].free.prev = i;                    heap->heapinfo[i].free.next = block;                    heap->heapinfo[heap->heapinfo[block].free.next].free.prev = block;                    heap->chunks_free++;               }               /* Now that the block is linked in, see if we can coalesce it                  with its successor (by deleting its successor from the list                  and adding in its size).  */               if (block + heap->heapinfo[block].free.size == heap->heapinfo[block].free.next) {                    heap->heapinfo[block].free.size                    += heap->heapinfo[heap->heapinfo[block].free.next].free.size;                    heap->heapinfo[block].free.next                    = heap->heapinfo[heap->heapinfo[block].free.next].free.next;                    heap->heapinfo[heap->heapinfo[block].free.next].free.prev = block;                    heap->chunks_free--;               }               blocks = heap->heapinfo[block].free.size;/* FIXME: as this is used when kernel is detected as >= 2.6.19.2 only, this fallback definition should be ok for now */#ifndef MADV_REMOVE#define MADV_REMOVE 9#endif               /* Punch a hole into the tmpfs file to really free RAM. */               if (fusion_config->madv_remove)                    madvise( ADDRESS(block), blocks * BLOCKSIZE, MADV_REMOVE );               /* Now see if we can truncate the end.  */               if (blocks >= FINAL_FREE_BLOCKS && block + blocks == heap->heaplimit                   && __shmalloc_brk( heap, 0 ) == ADDRESS (block + blocks))               {                    register size_t bytes = blocks * BLOCKSIZE;                    heap->heaplimit -= blocks;                    __shmalloc_brk( heap, -bytes );                    heap->heapinfo[heap->heapinfo[block].free.prev].free.next = heap->heapinfo[block].free.next;                    heap->heapinfo[heap->heapinfo[block].free.next].free.prev = heap->heapinfo[block].free.prev;                    block = heap->heapinfo[block].free.prev;                    heap->chunks_free--;                    heap->bytes_free -= bytes;               }               /* Set the next search to begin at this block.  */               heap->heapindex = block;               break;          default:               /* Do some of the statistics.  */               heap->chunks_used--;               heap->bytes_used -= 1 << type;               heap->chunks_free++;               heap->bytes_free += 1 << type;               /* Get the address of the first free fragment in this block.  */               prev = (struct list *) ((char *) ADDRESS (block) +                                       (heap->heapinfo[block].busy.info.frag.first << type));#if 1   /* Adapted from Mike */               if ((int)heap->heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1                   && heap->fragblocks[type] > 1)#else               if ((int)heap->heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)#endif               {                    /* If all fragments of this block are free, remove them                       from the fragment list and free the whole block.  */#if 1   /* Adapted from Mike */                    heap->fragblocks[type]--;#endif                    next = prev;                    for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)                         next = next->next;                    prev->prev->next = next;                    if (next != NULL)                         next->prev = prev->prev;                    heap->heapinfo[block].busy.type = 0;                    heap->heapinfo[block].busy.info.size = 1;                    /* Keep the statistics accurate.  */                    heap->chunks_used++;                    heap->bytes_used += BLOCKSIZE;                    heap->chunks_free -= BLOCKSIZE >> type;                    heap->bytes_free -= BLOCKSIZE;                    _fusion_shfree( heap, ADDRESS (block) );               }               else if (heap->heapinfo[block].busy.info.frag.nfree != 0) {                    /* If some fragments of this block are free, link this                       fragment into the fragment list after the first free                       fragment of this block. */                    next = (struct list *) ptr;                    next->next = prev->next;                    next->prev = prev;                    prev->next = next;                    if (next->next != NULL)                         next->next->prev = next;                    heap->heapinfo[block].busy.info.frag.nfree++;               }               else {                    /* No fragments of this block are free, so link this                       fragment into the fragment list and announce that                       it is the first free fragment of this block. */                    prev = (struct list *) ptr;                    heap->heapinfo[block].busy.info.frag.nfree = 1;                    heap->heapinfo[block].busy.info.frag.first = (unsigned long int)                                                                   ((unsigned long int) ((char *) ptr - (char *) NULL)                                                                    % BLOCKSIZE >> type);                    prev->next = heap->fraghead[type].next;                    prev->prev = &heap->fraghead[type];                    prev->prev->next = prev;                    if (prev->next != NULL)                         prev->next->prev = prev;               }               break;     }}/**********************************************************************************************************************/DirectResult__shmalloc_init_heap( FusionSHM  *shm,                      const char *filename,                      void       *addr_base,                      int         space,                      int        *ret_fd,                      int        *ret_size ){     DirectResult     ret;     int              size;     FusionSHMShared *shared;     int              heapsize = (space + BLOCKSIZE-1) / BLOCKSIZE;     int              fd       = -1;     shmalloc_heap   *heap     = NULL;     D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, '%s', %p, %d, %p, %p )\n",                 __FUNCTION__, shm, filename, addr_base, space, ret_fd, ret_size );     D_MAGIC_ASSERT( shm, FusionSHM );     D_ASSERT( filename != NULL );     D_ASSERT( addr_base != NULL );     D_ASSERT( ret_fd != NULL );     D_ASSERT( ret_size != NULL );     shared = shm->shared;     D_MAGIC_ASSERT( shared, FusionSHMShared );     D_ASSERT( shared->tmpfs[0] != 0 );     size = BLOCKALIGN(sizeof(shmalloc_heap)) + BLOCKALIGN( heapsize * sizeof(shmalloc_info) );     D_DEBUG_AT( Fusion_SHMHeap, "  -> opening shared memory file '%s'...\n", filename );     /* open the virtual file */     fd = open( filename, O_RDWR | O_CREAT | O_TRUNC, 0660 );     if (fd < 0) {          ret = errno2result(errno);          D_PERROR( "Fusion/SHM: Could not open shared memory file '%s'!\n", filename );          goto error;     }     if (fusion_config->shmfile_gid != (gid_t)-1) {          /* chgrp the SH_FILE dev entry */          if (fchown( fd, -1, fusion_config->shmfile_gid ) != 0)               D_WARN( "Fusion/SHM: Changing owner on %s failed... continuing on.", filename );     }     fchmod( fd, 0660 );     ftruncate( fd, size );     D_DEBUG_AT( Fusion_SHMHeap, "  -> mmaping shared memory file... (%d bytes)\n", size );     /* map it shared */     heap = mmap( addr_base, size + space, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0 );     if (heap == MAP_FAILED) {          ret = errno2result(errno);          D_PERROR( "Fusion/SHM: Could not mmap shared memory file '%s'!\n", filename );          goto error;     }     if (heap != addr_base) {          D_ERROR( "Fusion/SHM: mmap() returned address (%p) differs from requested (%p)\n", heap, addr_base );          ret = DFB_FUSION;          goto error;     }     D_DEBUG_AT( Fusion_SHMHeap, "  -> done.\n" );     heap->size     = size;     heap->heapsize = heapsize;     heap->heapinfo = (void*) heap + BLOCKALIGN(sizeof(shmalloc_heap));     heap->heapbase = (char*) heap->heapinfo;     D_MAGIC_SET( heap, shmalloc_heap );     *ret_fd   = fd;     *ret_size = size;     return DFB_OK;error:     if (heap)          munmap( heap, size );     if (fd != -1) {          close( fd );          unlink( filename );     }     return ret;}DirectResult__shmalloc_join_heap( FusionSHM  *shm,                      const char *filename,                      void       *addr_base,                      int         size,                      int        *ret_fd ){     DirectResult     ret;     FusionSHMShared *shared;     int              fd   = -1;     shmalloc_heap   *heap = NULL;     D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, '%s', %p, %d, %p )\n",                 __FUNCTION__, shm, filename, addr_base, size, ret_fd );     D_MAGIC_ASSERT( shm, FusionSHM );     D_ASSERT( filename != NULL );     D_ASSERT( addr_base != NULL );     D_ASSERT( size >= sizeof(shmalloc_heap) );     D_ASSERT( ret_fd != NULL );     shared = shm->shared;     D_MAGIC_ASSERT( shared, FusionSHMShared );     D_ASSERT( shared->tmpfs[0] != 0 );     D_DEBUG_AT( Fusion_SHMHeap, "  -> opening shared memory file '%s'...\n", filename );     /* open the virtual file */     fd = open( filename, O_RDWR );     if (fd < 0) {          ret = errno2result(errno);          D_PERROR( "Fusion/SHM: Could not open shared memory file '%s'!\n", filename );          goto error;     }     D_DEBUG_AT( Fusion_SHMHeap, "  -> mmaping shared memory file... (%d bytes)\n", size );     /* map it shared */     heap = mmap( addr_base, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0 );     if (heap == MAP_FAILED) {          ret = errno2result(errno);          D_PERROR( "Fusion/SHM: Could not mmap shared memory file '%s'!\n", filename );          goto error;     }     if (heap != addr_base) {          D_ERROR( "Fusion/SHM: mmap() returned address (%p) differs from requested (%p)\n", heap, addr_base );          ret = DFB_FUSION;          goto error;     }     D_MAGIC_ASSERT( heap, shmalloc_heap );     D_DEBUG_AT( Fusion_SHMHeap, "  -> done.\n" );     *ret_fd = fd;     return DFB_OK;error:     if (heap)          munmap( heap, size );     if (fd != -1)          close( fd );     return ret;}void *__shmalloc_brk( shmalloc_heap *heap, int increment ){     FusionSHMShared     *shm;     FusionWorld         *world;     FusionSHMPool       *pool;     FusionSHMPoolShared *shared;     D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, %d )\n", __FUNCTION__, heap, increment );     D_MAGIC_ASSERT( heap, shmalloc_heap );     shared = heap->pool;     D_MAGIC_ASSERT( shared, FusionSHMPoolShared );     shm = shared->shm;     D_MAGIC_ASSERT( shm, FusionSHMShared );     world = _fusion_world( shm->world );     D_MAGIC_ASSERT( world, FusionWorld );     pool = &world->shm.pools[shared->index];     D_MAGIC_ASSERT( pool, FusionSHMPool );     if (increment) {          int new_size = heap->size + increment;          if (new_size > shared->max_size) {               D_WARN( "maximum shared memory size exceeded!" );               fusion_dbg_print_memleaks( shared );               return NULL;          }          if (ftruncate( pool->fd, new_size ) < 0) {               D_PERROR( "Fusion/SHM: ftruncating shared memory file failed!\n" );               return NULL;          }          heap->size = new_size;     }     return shared->addr_base + heap->size - increment;}

⌨️ 快捷键说明

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