📄 heap.c
字号:
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; struct group *pGroupInfo; D_DEBUG_AT( Fusion_SHMHeap, "%s( %p, '%s', %p, %p )\n", __FUNCTION__, shm, filename, addr_base, ret_fd ); 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_group) { // obtain the group id # pGroupInfo = getgrnam(fusion_config->shmfile_group); // chgrp the SH_FILE dev entry if (fchown(fd, -1, pGroupInfo->gr_gid) != 0) { D_WARN("Fusion/SHM: changing permissions on /dev/shm/fusion.# failed... continuing on."); } } 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; } close( fd ); fd = -1; 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; } close( fd ); fd = -1; 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 file size (%dk) exceeded (%dk by %dk) in '%s'!", shared->max_size >> 10, new_size >> 10, increment >> 10, pool->filename ); fusion_dbg_print_memleaks( shared ); return NULL; } if (truncate( pool->filename, new_size ) < 0) { D_PERROR( "Fusion/SHM: truncating shared memory file '%s' from %dkb to %dkb failed!\n", pool->filename, heap->size >> 10, new_size >> 10 ); return NULL; } heap->size = new_size; } return shared->addr_base + heap->size - increment;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -