static bool createMarkStack(GcMarkStack *stack) { const Object **limit; size_t size; int fd; /* Create a stack big enough for the worst possible case, * where the heap is perfectly full of the smallest object. * TODO: be better about memory usage; use a smaller stack with * overflow detection and recovery. */ size = dvmHeapSourceGetIdealFootprint() / (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD); size = ALIGN_UP_TO_PAGE_SIZE(size); fd = ashmem_create_region("dalvik-heap-markstack", size); if (fd < 0) { LOGE_GC("Could not create %d-byte ashmem mark stack\n", size); return false; } limit = (const Object **)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); if (limit == MAP_FAILED) { LOGE_GC("Could not mmap %d-byte ashmem mark stack\n", size); return false; } memset(stack, 0, sizeof(*stack)); stack->limit = limit; stack->base = (const Object **)((uintptr_t)limit + size); stack->top = stack->base; return true; }
static jint android_util_MemoryIntArray_create(JNIEnv* env, jobject clazz, jstring name, jint size) { if (name == NULL) { jniThrowException(env, "java/io/IOException", "bad name"); return -1; } if (size <= 0) { jniThrowException(env, "java/io/IOException", "bad size"); return -1; } const char* nameStr = env->GetStringUTFChars(name, NULL); const int ashmemSize = sizeof(std::atomic_int) * size; int fd = ashmem_create_region(nameStr, ashmemSize); env->ReleaseStringUTFChars(name, nameStr); if (fd < 0) { jniThrowException(env, "java/io/IOException", "ashmem creation failed"); return -1; } int setProtResult = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); if (setProtResult < 0) { jniThrowException(env, "java/io/IOException", "cannot set ashmem prot mode"); return -1; } return fd; }
void MemArena::GrabLowMemSpace(size_t size) { #ifdef _WIN32 hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL); GetSystemInfo(&sysInfo); #elif ANDROID // Use ashmem so we don't have to allocate a file on disk! fd = ashmem_create_region("PPSSPP_RAM", size); // Note that it appears that ashmem is pinned by default, so no need to pin. if (fd < 0) { ERROR_LOG(MEMMAP, "Failed to grab ashmem space of size: %08x errno: %d", (int)size, (int)(errno)); return; } #else mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; fd = open(ram_temp_file.c_str(), O_RDWR | O_CREAT, mode); if (fd < 0) { ERROR_LOG(MEMMAP, "Failed to grab memory space as a file: %s of size: %08x errno: %d", ram_temp_file.c_str(), (int)size, (int)(errno)); return; } // delete immediately, we keep the fd so it still lives unlink(ram_temp_file.c_str()); if (ftruncate(fd, size) != 0) { ERROR_LOG(MEMMAP, "Failed to ftruncate %d to size %08x", (int)fd, (int)size); } return; #endif }
static int init_workspace(workspace *w, size_t size) { void *data; int fd; fd = ashmem_create_region("system_properties", size); if(fd < 0) return -1; data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(data == MAP_FAILED) goto out; /* allow the wolves we share with to do nothing but read */ ashmem_set_prot_region(fd, PROT_READ); w->data = data; w->size = size; w->fd = fd; return 0; out: close(fd); return -1; }
int createNewAshmem(const char *name, int size, u8 **addr) { int fd = ashmem_create_region(name, size + sizeof(u32)); if(fd >= 0) { LOGI("create ashmem name:%s size:%d fd:%d success!", name, size, fd); t_ashmBlock *ashm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(ashm != NULL) { t_ashmNode *newAshmNode = malloc(sizeof(t_ashmNode)); if(newAshmNode != NULL) { ashm->ashmStat = 0; if(addr != NULL) { *addr = ashm->data; } newAshmNode->ashmem = ashm; newAshmNode->fd = fd; strncpy(newAshmNode->name, name, ASHM_NAME_SIZE); newAshmNode->next = NULL; newAshmNode->size = size; if(ashmemChainHead == NULL) { ashmemChainHead = newAshmNode; } if(ashmemChainTail != NULL) { ashmemChainTail->next = newAshmNode; } ashmemChainTail = newAshmNode; LOGI("ashmem mmap %d to watchdog process success!", (u32)ashm); if(strcmp(name, "ashmTest") == 0) { int i; for(i = 0; i < 8; i++) { ashm->data[i] = i; } } } } } return fd; }
void shell_main(){ dlopen_t dlopen_f = (dlopen_t)getProcAddr(NULL,"dlopen"); dlsym_t dlsym_f = (dlsym_t)getProcAddr(NULL,"dlsym"); const char *so_name = "/data/local/tmp/testso.so"; char *code = (char*)get_so_buffer(so_name); int ashmem_len = *(int*)code; int fd_memory = ashmem_create_region("shmem", ashmem_len); ashmem_pin_region(fd_memory, 0, 0); uint8_t *shm = (uint8_t*)mmap(NULL, ashmem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_memory, 0); printf("first map address is %p\n",shm); memcpy(shm,code,ashmem_len); free(code); //ashmem_unpin_region(fd_memory, 0, 0); int pos[32]={12,2,12,fd_memory}; //shellcode(dlopen_f,pos); uint32_t libcbase = (uint32_t)getModuleBase("libc.so"); uint32_t mprotect_address = (uint32_t)getProcAddr("libc.so","mprotect"); uint32_t len = 0; void *buffer = get_shellcode(&len); uint32_t ropData[29]={libcbase+0x15056+1,1+libcbase+0x4c8ee,0xdeaddead,0xdeaddead,(uint32_t)buffer&0xfffff000,4096,0x7,(uint32_t)mprotect_address,(uint32_t)dlopen_f,(uint32_t)pos,2,(uint32_t)buffer+1}; //uint32_t ropData[29]={libcbase+0x15056+1,1+libcbase+0x4c8ee,0xdeaddead,0xdeaddead,(uint32_t)buffer&0xfffff000,4096,0x7,(uint32_t)mprotect_address,(uint32_t)dlopen_f,1,2,(uint32_t)shellcode}; asmm_test((uint32_t)ropData); free(buffer); exit(-1); }
static int createAshmemRegionWithData(JNIEnv* env, const void* data, size_t length) { int error = 0; int fd = ashmem_create_region(NULL, length); if (fd < 0) { error = errno; ALOGE("ashmem_create_region failed: %s", strerror(error)); } else { if (length > 0) { void* ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { error = errno; ALOGE("mmap failed: %s", strerror(error)); } else { memcpy(ptr, data, length); munmap(ptr, length); } } if (!error) { if (ashmem_set_prot_region(fd, PROT_READ) < 0) { error = errno; ALOGE("ashmem_set_prot_region failed: %s", strerror(errno)); } else { return fd; } } close(fd); } jniThrowIOException(env, error); return -1; }
void MemArena::GrabLowMemSpace(size_t size) { // Use ashmem so we don't have to allocate a file on disk! fd = ashmem_create_region("PPSSPP_RAM", size); // Note that it appears that ashmem is pinned by default, so no need to pin. if (fd < 0) { ERROR_LOG(MEMMAP, "Failed to grab ashmem space of size: %08x errno: %d", (int)size, (int)(errno)); return; } }
Overlay::Overlay(uint32_t width, uint32_t height, Format format, QueueBufferHook queueBufferHook, void *data) : mQueueBufferHook(queueBufferHook), mHookData(data), mNumFreeBuffers(0), mStatus(NO_INIT), mWidth(width), mHeight(height), mFormat(format) { ALOGD("%s: Init overlay, format=%d", __FUNCTION__, format); unsigned int mapped = 0; int bpp = getBppFromFormat(format); /* round up to next multiple of 8 */ if (bpp & 7) { bpp = (bpp & ~7) + 8; } const int requiredMem = width * height * bpp; const int bufferSize = (requiredMem + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1)); int fd = ashmem_create_region("Overlay_buffer_region", NUM_BUFFERS * bufferSize); if (fd < 0) { ALOGE("%s: Cannot create ashmem region", __FUNCTION__); return; } ALOGV("%s: allocated ashmem region for %d buffers of size %d", __FUNCTION__, NUM_BUFFERS, bufferSize); for (uint32_t i = 0; i < NUM_BUFFERS; i++) { mBuffers[i].fd = fd; mBuffers[i].length = bufferSize; mBuffers[i].offset = bufferSize * i; ALOGV("%s: mBuffers[%d].offset = 0x%x", __FUNCTION__, i, mBuffers[i].offset); mBuffers[i].ptr = mmap(NULL, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, bufferSize * i); if (mBuffers[i].ptr == MAP_FAILED) { ALOGE("%s: Failed to mmap buffer %d", __FUNCTION__, i); mBuffers[i].ptr = NULL; continue; } mQueued[i] = false; mapped++; } pthread_mutex_init(&mQueueMutex, NULL); ALOGD("%s: Init overlay complete, %u mapped", __FUNCTION__, mapped); mStatus = NO_ERROR; }
virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) { const size_t size = roundToPageSize(bm->getSize()); int fd = fRec->fFD; void* addr = fRec->fAddr; SkASSERT(!fRec->fPinned); if (-1 == fd) { SkASSERT(NULL == addr); SkASSERT(0 == fRec->fSize); fd = ashmem_create_region(fName, size); #ifdef DUMP_ASHMEM_LIFECYCLE SkDebugf("=== ashmem_create_region %s size=%d fd=%d\n", fName, size, fd); #endif if (-1 == fd) { SkDebugf("------- imageref_ashmem create failed <%s> %d\n", fName, size); return false; } int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); if (err) { SkDebugf("------ ashmem_set_prot_region(%d) failed %d\n", fd, err); close(fd); return false; } addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (-1 == (long)addr) { SkDebugf("---------- mmap failed for imageref_ashmem size=%d\n", size); close(fd); return false; } fRec->fFD = fd; fRec->fAddr = addr; fRec->fSize = size; } else { SkASSERT(addr); SkASSERT(size == fRec->fSize); (void)ashmem_pin_region(fd, 0, 0); } bm->setPixels(addr, ct); fRec->fPinned = true; return true; }
int cras_shm_open_rw (const char *name, size_t size) { int fd; /* Eliminate the / in the shm_name. */ if (name[0] == '/') name++; fd = ashmem_create_region(name, size); if (fd < 0) { fd = -errno; syslog(LOG_ERR, "failed to ashmem_create_region %s: %s\n", name, strerror(-fd)); } return fd; }
MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), mDevice(0), mNeedUnmap(false), mOffset(0) { const size_t pagesize = getpagesize(); size = ((size + pagesize-1) & ~(pagesize-1)); int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name, size); ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno)); if (fd >= 0) { if (mapfd(fd, size) == NO_ERROR) { if (flags & READ_ONLY) { ashmem_set_prot_region(fd, PROT_READ); } } } }
get_ashmem(backing_store_ptr info, long total_bytes_needed) { char path[1024]; snprintf(path, 1023, "%d.tmp.ashmem", getpid()); int fd = ashmem_create_region(path, total_bytes_needed); if (fd == -1) { return -1; } int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); if (err) { return -1; } info->addr = mmap(NULL, total_bytes_needed, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); info->size = total_bytes_needed; info->temp_file = fd; return fd; }
mspace create_contiguous_mspace_with_name(size_t starting_capacity, size_t max_capacity, int locked, char const *name) { int fd, ret; char buf[ASHMEM_NAME_LEN] = "mspace"; void *base; unsigned int pagesize; mstate m; if (starting_capacity > max_capacity) return (mspace)0; init_mparams(); pagesize = PAGESIZE; /* Create the anonymous memory that will back the mspace. * This reserves all of the virtual address space we could * ever need. Physical pages will be mapped as the memory * is touched. * * Align max_capacity to a whole page. */ max_capacity = (size_t)ALIGN_UP(max_capacity, pagesize); if (name) snprintf(buf, sizeof(buf), "mspace/%s", name); fd = ashmem_create_region(buf, max_capacity); if (fd < 0) return (mspace)0; base = mmap(NULL, max_capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); if (base == MAP_FAILED) return (mspace)0; /* Make sure that base is at the beginning of a page. */ assert(((uintptr_t)base & (pagesize-1)) == 0); m = create_contiguous_mspace_with_base(starting_capacity, max_capacity, locked, base); if (m == 0) { munmap(base, max_capacity); } return m; }
status_t CursorWindow::create(const String8& name, size_t size, CursorWindow** outCursorWindow) { String8 ashmemName("CursorWindow: "); ashmemName.append(name); status_t result; int ashmemFd = ashmem_create_region(ashmemName.string(), size); if (ashmemFd < 0) { ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::create, ashmem_create_region return errno = %d",errno); result = -errno; } else { result = ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE); if (result >= 0) { void* data = ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0); if (data == MAP_FAILED) { ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::create, mmap return errno = %d",errno); result = -errno; } else { result = ashmem_set_prot_region(ashmemFd, PROT_READ); if (result >= 0) { CursorWindow* window = new CursorWindow(name, ashmemFd, data, size, false /*readOnly*/); result = window->clear(); if (!result) { LOG_WINDOW("Created new CursorWindow: freeOffset=%d, " "numRows=%d, numColumns=%d, mSize=%d, mData=%p", window->mHeader->freeOffset, window->mHeader->numRows, window->mHeader->numColumns, window->mSize, window->mData); *outCursorWindow = window; return OK; } ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::create, window->clear return errno = %d",errno); delete window; } else { ALOG(LOG_ERROR,LOG_TAG,"CursorWindow::create, ashmeme_set_prot_region return errno = %d",errno); } } ::munmap(data, size); } ::close(ashmemFd); } *outCursorWindow = NULL; return result; }
int gpu_context_t::alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase, int* pOffset, int* pFd) { int err = 0; int fd = -1; void* base = 0; int offset = 0; char name[ASHMEM_NAME_LEN]; snprintf(name, ASHMEM_NAME_LEN, "gralloc-buffer-%x", postfix); int prot = PROT_READ | PROT_WRITE; fd = ashmem_create_region(name, size); if (fd < 0) { LOGE("couldn't create ashmem (%s)", strerror(errno)); err = -errno; } else { if (ashmem_set_prot_region(fd, prot) < 0) { LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)", fd, prot, strerror(errno)); close(fd); err = -errno; } else { base = mmap(0, size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0); if (base == MAP_FAILED) { LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)", fd, size, prot, strerror(errno)); close(fd); err = -errno; } else { memset((char*)base + offset, 0, size); } } } if(err == 0) { *pFd = fd; *pBase = base; *pOffset = offset; #ifdef HOST if (ioctl(fd, ASHMEM_CACHE_INV_RANGE, NULL)) { LOGE("ASHMEM_CACHE_INV_RANGE failed fd = %d", fd); } #endif } return err; }
int main(){ char dum[] = "test"; int id; char * addr; id = ashmem_create_region(dum, 40960); printf("id test %d\n", id); addr = (char *) ashmem_mmap(NULL, 10, 0, 0, id, 0); *addr = 'c'; printf("%c\n", *addr); return 0; }
static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length) { const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL); // round up length to page boundary length = (((length - 1) / getpagesize()) + 1) * getpagesize(); int result = ashmem_create_region(namestr, length); if (name) env->ReleaseStringUTFChars(name, namestr); if (result < 0) { jniThrowException(env, "java/io/IOException", "ashmem_create_region failed"); return NULL; } return jniCreateFileDescriptor(env, result); }
/* * Allocates a memory region using ashmem and mmap, initialized to * zero. Actual allocation rounded up to page multiple. Returns * NULL on failure. */ void *dvmAllocRegion(size_t byteCount, int prot, const char *name) { void *base; int fd, ret; byteCount = ALIGN_UP_TO_PAGE_SIZE(byteCount); fd = ashmem_create_region(name, byteCount); if (fd == -1) { return NULL; } base = mmap(NULL, byteCount, prot, MAP_PRIVATE, fd, 0); ret = close(fd); if (base == MAP_FAILED) { return NULL; } if (ret == -1) { return NULL; } return base; }
/* * Initialize a HeapBitmap so that it points to a bitmap large * enough to cover a heap at <base> of <maxSize> bytes, where * objects are guaranteed to be HB_OBJECT_ALIGNMENT-aligned. */ bool dvmHeapBitmapInit(HeapBitmap *hb, const void *base, size_t maxSize, const char *name) { void *bits; size_t bitsLen; size_t allocLen; int fd; char nameBuf[ASHMEM_NAME_LEN] = HB_ASHMEM_NAME; assert(hb != NULL); bitsLen = HB_OFFSET_TO_INDEX(maxSize) * sizeof(*hb->bits); allocLen = ALIGN_UP_TO_PAGE_SIZE(bitsLen); // required by ashmem if (name != NULL) { snprintf(nameBuf, sizeof(nameBuf), HB_ASHMEM_NAME "/%s", name); } fd = ashmem_create_region(nameBuf, allocLen); if (fd < 0) { LOGE("Could not create %zu-byte ashmem region \"%s\" to cover " "%zu-byte heap (%d)\n", allocLen, nameBuf, maxSize, fd); return false; } bits = mmap(NULL, bitsLen, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); if (bits == MAP_FAILED) { LOGE("Could not mmap %d-byte ashmem region \"%s\"\n", bitsLen, nameBuf); return false; } memset(hb, 0, sizeof(*hb)); hb->bits = bits; hb->bitsLen = bitsLen; hb->base = (uintptr_t)base; hb->max = hb->base - 1; return true; }
static mspace getMspace() { if (gExecutableStore == NULL) { int fd = ashmem_create_region("CodeFlinger code cache", kMaxCodeCacheCapacity); LOG_ALWAYS_FATAL_IF(fd < 0, "Creating code cache, ashmem_create_region " "failed with error '%s'", strerror(errno)); gExecutableStore = mmap(NULL, kMaxCodeCacheCapacity, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); LOG_ALWAYS_FATAL_IF(gExecutableStore == MAP_FAILED, "Creating code cache, mmap failed with error " "'%s'", strerror(errno)); close(fd); gMspace = create_mspace_with_base(gExecutableStore, kMaxCodeCacheCapacity, /*locked=*/ false); mspace_set_footprint_limit(gMspace, kMaxCodeCacheCapacity); } return gMspace; }
OMX_U8* OMXVideoDecoderAVCSecure::MemAllocDataBuffer(OMX_U32 nSizeBytes) { ALOGW_IF(nSizeBytes != INPORT_BUFFER_SIZE, "%s: size of memory to allocate is %" PRIu32 ", but will allocate %zu", __FUNCTION__, nSizeBytes, sizeof(ProtectedDataBuffer)); if (mNumInportBuffers >= INPORT_ACTUAL_BUFFER_COUNT) { ALOGE("%s: cannot allocate buffer: number of inport buffers is %u, which is already at maximum", __FUNCTION__, mNumInportBuffers); return NULL; } int fd = ashmem_create_region("protectd-content-buffer", sizeof(ProtectedDataBuffer)); if(fd < 0) { ALOGE("Unable to create ashmem region"); return NULL; } native_handle_t *native = native_handle_create(1, 2); native->data[0] = fd; ProtectedDataBuffer *pBuffer =(ProtectedDataBuffer *) mmap(NULL, sizeof(ProtectedDataBuffer), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (pBuffer == MAP_FAILED) { ALOGE("%s: mmap failed", __FUNCTION__); return NULL; } native->data[1] = (int) pBuffer; // Use a random value as the buffer id native->data[2] = rand(); ++mNumInportBuffers; Init_ProtectedDataBuffer(pBuffer); pBuffer->size = INPORT_BUFFER_SIZE; ALOGV("Allocating native=[%p] buffer = %#x, data = %#x data_end= %#x size=%d",(OMX_U8 *)native,(uint32_t)pBuffer, (uint32_t)pBuffer->data, (uint32_t)pBuffer->data + sizeof(ProtectedDataBuffer) ,sizeof(ProtectedDataBuffer)); return (OMX_U8 *) native; }
void MemArena::GrabLowMemSpace(size_t size) { #ifdef _WIN32 #ifndef _XBOX hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL); GetSystemInfo(&sysInfo); #endif #elif defined(ANDROID) // Use ashmem so we don't have to allocate a file on disk! fd = ashmem_create_region("PPSSPP_RAM", size); // Note that it appears that ashmem is pinned by default, so no need to pin. if (fd < 0) { ERROR_LOG(MEMMAP, "Failed to grab ashmem space of size: %08x errno: %d", (int)size, (int)(errno)); return; } #else // Try to find a non-existing filename for our shared memory. // In most cases the first one will be available, but it's nicer to search // a bit more. for (int i = 0; i < 10000; i++) { std::string file_name = Common::StringFromFormat("/citramem.%d", i); fd = shm_open(file_name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); if (fd != -1) { shm_unlink(file_name.c_str()); break; } else if (errno != EEXIST) { ERROR_LOG(MEMMAP, "shm_open failed: %s", strerror(errno)); return; } } if (ftruncate(fd, size) < 0) ERROR_LOG(MEMMAP, "Failed to allocate low memory space"); #endif }
/* * A helper for addNewHeap(). Remap the new heap so that it will have * a separate ashmem region with possibly a different name, etc. In * practice, this is used to give the app heap a separate ashmem * region from the zygote heap's. */ static bool remapNewHeap(HeapSource* hs, Heap* newHeap) { char* newHeapBase = newHeap->base; size_t rem_size = hs->heapBase + hs->heapLength - newHeapBase; munmap(newHeapBase, rem_size); int fd = ashmem_create_region("dalvik-heap", rem_size); if (fd == -1) { ALOGE("Unable to create an ashmem region for the new heap"); return false; } void* addr = mmap(newHeapBase, rem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0); int ret = close(fd); if (addr == MAP_FAILED) { ALOGE("Unable to map an ashmem region for the new heap"); return false; } if (ret == -1) { ALOGE("Unable to close fd for the ashmem region for the new heap"); munmap(newHeapBase, rem_size); return false; } return true; }
/* * Create a new linear allocation block. */ LinearAllocHdr* dvmLinearAllocCreate(Object* classLoader) { #ifdef DISABLE_LINEAR_ALLOC return (LinearAllocHdr*) 0x12345; #endif LinearAllocHdr* pHdr; pHdr = (LinearAllocHdr*) malloc(sizeof(*pHdr)); /* * "curOffset" points to the location of the next pre-block header, * which means we have to advance to the next BLOCK_ALIGN address and * back up. * * Note we leave the first page empty (see below), and start the * first entry on the second page at an offset that ensures the next * chunk of data will be properly aligned. */ assert(BLOCK_ALIGN >= HEADER_EXTRA); pHdr->curOffset = pHdr->firstOffset = (BLOCK_ALIGN-HEADER_EXTRA) + PAGESIZE; pHdr->mapLength = DEFAULT_MAX_LENGTH; #ifdef USE_ASHMEM int fd; fd = ashmem_create_region("dalvik-LinearAlloc", DEFAULT_MAX_LENGTH); if (fd < 0) { LOGE("ashmem LinearAlloc failed %s", strerror(errno)); free(pHdr); return NULL; } pHdr->mapAddr = mmap(NULL, pHdr->mapLength, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (pHdr->mapAddr == MAP_FAILED) { LOGE("LinearAlloc mmap(%d) failed: %s\n", pHdr->mapLength, strerror(errno)); free(pHdr); close(fd); return NULL; } close(fd); #else /*USE_ASHMEM*/ // MAP_ANON is listed as "deprecated" on Linux, // but MAP_ANONYMOUS is not defined under Mac OS X. pHdr->mapAddr = mmap(NULL, pHdr->mapLength, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (pHdr->mapAddr == MAP_FAILED) { LOGE("LinearAlloc mmap(%d) failed: %s\n", pHdr->mapLength, strerror(errno)); free(pHdr); return NULL; } #endif /*USE_ASHMEM*/ /* region expected to begin on a page boundary */ assert(((int) pHdr->mapAddr & (PAGESIZE-1)) == 0); /* the system should initialize newly-mapped memory to zero */ assert(*(u4*) (pHdr->mapAddr + pHdr->curOffset) == 0); /* * Disable access to all except starting page. We will enable pages * as we use them. This helps prevent bad pointers from working. The * pages start out PROT_NONE, become read/write while we access them, * then go to read-only after we finish our changes. * * We have to make the first page readable because we have 4 pad bytes, * followed by 4 length bytes, giving an initial offset of 8. The * generic code below assumes that there could have been a previous * allocation that wrote into those 4 pad bytes, therefore the page * must have been marked readable by the previous allocation. * * We insert an extra page in here to force a break in the memory map * so we can see ourselves more easily in "showmap". Otherwise this * stuff blends into the neighboring pages. [TODO: do we still need * the extra page now that we have ashmem?] */ if (mprotect(pHdr->mapAddr, pHdr->mapLength, PROT_NONE) != 0) { LOGW("LinearAlloc init mprotect failed: %s\n", strerror(errno)); free(pHdr); return NULL; } if (mprotect(pHdr->mapAddr + PAGESIZE, PAGESIZE, ENFORCE_READ_ONLY ? PROT_READ : PROT_READ|PROT_WRITE) != 0) { LOGW("LinearAlloc init mprotect #2 failed: %s\n", strerror(errno)); free(pHdr); return NULL; } if (ENFORCE_READ_ONLY) { /* allocate the per-page ref count */ int numPages = (pHdr->mapLength+PAGESIZE-1) / PAGESIZE; pHdr->writeRefCount = calloc(numPages, sizeof(short)); if (pHdr->writeRefCount == NULL) { free(pHdr); return NULL; } } dvmInitMutex(&pHdr->lock); LOGV("LinearAlloc: created region at %p-%p\n", pHdr->mapAddr, pHdr->mapAddr + pHdr->mapLength-1); return pHdr; }
// // gralloc device functions (alloc interface) // static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride) { D("gralloc_alloc w=%d h=%d usage=0x%x\n", w, h, usage); gralloc_device_t *grdev = (gralloc_device_t *)dev; if (!grdev || !pHandle || !pStride) { ALOGE("gralloc_alloc: Bad inputs (grdev: %p, pHandle: %p, pStride: %p", grdev, pHandle, pStride); return -EINVAL; } // // Note: in screen capture mode, both sw_write and hw_write will be on // and this is a valid usage // bool sw_write = (0 != (usage & GRALLOC_USAGE_SW_WRITE_MASK)); bool hw_write = (usage & GRALLOC_USAGE_HW_RENDER); bool sw_read = (0 != (usage & GRALLOC_USAGE_SW_READ_MASK)); bool hw_cam_write = usage & GRALLOC_USAGE_HW_CAMERA_WRITE; bool hw_cam_read = usage & GRALLOC_USAGE_HW_CAMERA_READ; bool hw_vid_enc_read = usage & GRALLOC_USAGE_HW_VIDEO_ENCODER; // Keep around original requested format for later validation int frameworkFormat = format; // Pick the right concrete pixel format given the endpoints as encoded in // the usage bits. Every end-point pair needs explicit listing here. if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { // Camera as producer if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) { if (usage & GRALLOC_USAGE_HW_TEXTURE) { // Camera-to-display is RGBA format = HAL_PIXEL_FORMAT_RGBA_8888; } else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { // Camera-to-encoder is NV21 format = HAL_PIXEL_FORMAT_YCrCb_420_SP; } else if ((usage & GRALLOC_USAGE_HW_CAMERA_MASK) == GRALLOC_USAGE_HW_CAMERA_ZSL) { // Camera-to-ZSL-queue is RGB_888 format = HAL_PIXEL_FORMAT_RGB_888; } } if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { ALOGE("gralloc_alloc: Requested auto format selection, " "but no known format for this usage: %d x %d, usage %x", w, h, usage); return -EINVAL; } } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) { // Flexible framework-accessible YUV format; map to NV21 for now if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) { format = HAL_PIXEL_FORMAT_YCrCb_420_SP; } if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) { ALOGE("gralloc_alloc: Requested YCbCr_420_888, but no known " "specific format for this usage: %d x %d, usage %x", w, h, usage); } } bool yuv_format = false; int ashmem_size = 0; int stride = w; GLenum glFormat = 0; GLenum glType = 0; int bpp = 0; int align = 1; switch (format) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_BGRA_8888: bpp = 4; glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break; case HAL_PIXEL_FORMAT_RGB_888: bpp = 3; glFormat = GL_RGB; glType = GL_UNSIGNED_BYTE; break; case HAL_PIXEL_FORMAT_RGB_565: bpp = 2; glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5; break; case HAL_PIXEL_FORMAT_RAW_SENSOR: bpp = 2; align = 16*bpp; if (! ((sw_read || hw_cam_read) && (sw_write || hw_cam_write) ) ) { // Raw sensor data only goes between camera and CPU return -EINVAL; } // Not expecting to actually create any GL surfaces for this glFormat = GL_LUMINANCE; glType = GL_UNSIGNED_SHORT; break; case HAL_PIXEL_FORMAT_BLOB: bpp = 1; if (! (sw_read && hw_cam_write) ) { // Blob data cannot be used by HW other than camera emulator return -EINVAL; } // Not expecting to actually create any GL surfaces for this glFormat = GL_LUMINANCE; glType = GL_UNSIGNED_BYTE; break; case HAL_PIXEL_FORMAT_YCrCb_420_SP: align = 1; bpp = 1; // per-channel bpp yuv_format = true; // Not expecting to actually create any GL surfaces for this break; case HAL_PIXEL_FORMAT_YV12: align = 16; bpp = 1; // per-channel bpp yuv_format = true; // Not expecting to actually create any GL surfaces for this break; default: ALOGE("gralloc_alloc: Unknown format %d", format); return -EINVAL; } if (usage & GRALLOC_USAGE_HW_FB) { // keep space for postCounter ashmem_size += sizeof(uint32_t); } if (sw_read || sw_write || hw_cam_write || hw_vid_enc_read) { // keep space for image on guest memory if SW access is needed // or if the camera is doing writing if (yuv_format) { size_t yStride = (w*bpp + (align - 1)) & ~(align-1); size_t uvStride = (yStride / 2 + (align - 1)) & ~(align-1); size_t uvHeight = h / 2; ashmem_size += yStride * h + 2 * (uvHeight * uvStride); stride = yStride / bpp; } else { size_t bpr = (w*bpp + (align-1)) & ~(align-1); ashmem_size += (bpr * h); stride = bpr / bpp; } } D("gralloc_alloc format=%d, ashmem_size=%d, stride=%d, tid %d\n", format, ashmem_size, stride, gettid()); // // Allocate space in ashmem if needed // int fd = -1; if (ashmem_size > 0) { // round to page size; ashmem_size = (ashmem_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); fd = ashmem_create_region("gralloc-buffer", ashmem_size); if (fd < 0) { ALOGE("gralloc_alloc failed to create ashmem region: %s\n", strerror(errno)); return -errno; } } cb_handle_t *cb = new cb_handle_t(fd, ashmem_size, usage, w, h, frameworkFormat, format, glFormat, glType); if (ashmem_size > 0) { // // map ashmem region if exist // void *vaddr; int err = map_buffer(cb, &vaddr); if (err) { close(fd); delete cb; return err; } cb->setFd(fd); } // // Allocate ColorBuffer handle on the host (only if h/w access is allowed) // Only do this for some h/w usages, not all. // if (usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_2D | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB) ) { DEFINE_HOST_CONNECTION; if (hostCon && rcEnc) { cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, glFormat); D("Created host ColorBuffer 0x%x\n", cb->hostHandle); } if (!cb->hostHandle) { // Could not create colorbuffer on host !!! close(fd); delete cb; return -EIO; } } // // alloc succeeded - insert the allocated handle to the allocated list // AllocListNode *node = new AllocListNode(); pthread_mutex_lock(&grdev->lock); node->handle = cb; node->next = grdev->allocListHead; node->prev = NULL; if (grdev->allocListHead) { grdev->allocListHead->prev = node; } grdev->allocListHead = node; pthread_mutex_unlock(&grdev->lock); *pHandle = cb; if (frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) { *pStride = 0; } else { *pStride = stride; } return 0; }
bool dvmCompilerSetupCodeCache(void) { int fd; /* Allocate the code cache */ fd = ashmem_create_region("dalvik-jit-code-cache", gDvmJit.codeCacheSize); if (fd < 0) { ALOGE("Could not create %u-byte ashmem region for the JIT code cache", gDvmJit.codeCacheSize); return false; } gDvmJit.codeCache = mmap(NULL, gDvmJit.codeCacheSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE , fd, 0); close(fd); if (gDvmJit.codeCache == MAP_FAILED) { ALOGE("Failed to mmap the JIT code cache of size %d: %s", gDvmJit.codeCacheSize, strerror(errno)); return false; } gDvmJit.pageSizeMask = getpagesize() - 1; /* This can be found through "dalvik-jit-code-cache" in /proc/<pid>/maps */ // ALOGD("Code cache starts at %p", gDvmJit.codeCache); #ifndef ARCH_IA32 /* Copy the template code into the beginning of the code cache */ int templateSize = (intptr_t) dvmCompilerTemplateEnd - (intptr_t) dvmCompilerTemplateStart; memcpy((void *) gDvmJit.codeCache, (void *) dvmCompilerTemplateStart, templateSize); /* * Work around a CPU bug by keeping the 32-bit ARM handler code in its own * page. */ if (dvmCompilerInstructionSet() == DALVIK_JIT_THUMB2) { templateSize = (templateSize + 4095) & ~4095; } gDvmJit.templateSize = templateSize; gDvmJit.codeCacheByteUsed = templateSize; /* Only flush the part in the code cache that is being used now */ dvmCompilerCacheFlush((intptr_t) gDvmJit.codeCache, (intptr_t) gDvmJit.codeCache + templateSize); #else gDvmJit.codeCacheByteUsed = 0; stream = (char*)gDvmJit.codeCache + gDvmJit.codeCacheByteUsed; ALOGV("codeCache = %p stream = %p before initJIT", gDvmJit.codeCache, stream); streamStart = stream; initJIT(NULL, NULL); gDvmJit.templateSize = (stream - streamStart); gDvmJit.codeCacheByteUsed = (stream - streamStart); ALOGV("stream = %p after initJIT", stream); #endif int result = mprotect(gDvmJit.codeCache, gDvmJit.codeCacheSize, PROTECT_CODE_CACHE_ATTRS); if (result == -1) { ALOGE("Failed to remove the write permission for the code cache"); dvmAbort(); } return true; }
status_t InputChannel::openInputChannelPair(const String8& name, sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) { status_t result; String8 ashmemName("InputChannel "); ashmemName.append(name); int serverAshmemFd = ashmem_create_region(ashmemName.string(), DEFAULT_MESSAGE_BUFFER_SIZE); if (serverAshmemFd < 0) { result = -errno; ALOGE("channel '%s' ~ Could not create shared memory region. errno=%d", name.string(), errno); } else { result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE); if (result < 0) { ALOGE("channel '%s' ~ Error %d trying to set protection of ashmem fd %d.", name.string(), result, serverAshmemFd); } else { // Dup the file descriptor because the server and client input channel objects that // are returned may have different lifetimes but they share the same shared memory region. int clientAshmemFd; clientAshmemFd = dup(serverAshmemFd); if (clientAshmemFd < 0) { result = -errno; ALOGE("channel '%s' ~ Could not dup() shared memory region fd. errno=%d", name.string(), errno); } else { int forward[2]; if (pipe(forward)) { result = -errno; ALOGE("channel '%s' ~ Could not create forward pipe. errno=%d", name.string(), errno); } else { int reverse[2]; if (pipe(reverse)) { result = -errno; ALOGE("channel '%s' ~ Could not create reverse pipe. errno=%d", name.string(), errno); } else { String8 serverChannelName = name; serverChannelName.append(" (server)"); outServerChannel = new InputChannel(serverChannelName, serverAshmemFd, reverse[0], forward[1]); String8 clientChannelName = name; clientChannelName.append(" (client)"); outClientChannel = new InputChannel(clientChannelName, clientAshmemFd, forward[0], reverse[1]); return OK; } ::close(forward[0]); ::close(forward[1]); } ::close(clientAshmemFd); } } ::close(serverAshmemFd); } outServerChannel.clear(); outClientChannel.clear(); return result; }
// // gralloc device functions (alloc interface) // static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride) { LOGD("gralloc_alloc w=%d h=%d usage=0x%x\n", w, h, usage); gralloc_device_t *grdev = (gralloc_device_t *)dev; if (!grdev || !pHandle || !pStride) return -EINVAL; // // Validate usage: buffer cannot be written both by s/w and h/w access. // bool sw_write = (0 != (usage & GRALLOC_USAGE_SW_WRITE_MASK)); bool hw_write = (usage & GRALLOC_USAGE_HW_RENDER); if (hw_write && sw_write) { return -EINVAL; } int ashmem_size = 0; *pStride = 0; GLenum glFormat = 0; int bpp = 0; switch (format) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_BGRA_8888: bpp = 4; glFormat = GL_RGBA; break; case HAL_PIXEL_FORMAT_RGB_888: bpp = 3; glFormat = GL_RGB; break; case HAL_PIXEL_FORMAT_RGB_565: bpp = 2; glFormat = GL_RGB565_OES; break; case HAL_PIXEL_FORMAT_RGBA_5551: bpp = 2; glFormat = GL_RGB5_A1_OES; break; case HAL_PIXEL_FORMAT_RGBA_4444: bpp = 2; glFormat = GL_RGBA4_OES; break; default: return -EINVAL; } if (usage & GRALLOC_USAGE_HW_FB) { // keep space for postCounter ashmem_size += sizeof(uint32_t); } if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { // keep space for image on guest memory if SW access is needed int align = 1; size_t bpr = (w*bpp + (align-1)) & ~(align-1); ashmem_size += (bpr * h); *pStride = bpr / bpp; } LOGD("gralloc_alloc ashmem_size=%d\n", ashmem_size); // // Allocate space in ashmem if needed // int fd = -1; if (ashmem_size > 0) { // round to page size; ashmem_size = (ashmem_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); fd = ashmem_create_region("gralloc-buffer", ashmem_size); if (fd < 0) { LOGE("gralloc_alloc failed to create ashmem region err=%d\n", errno); return -errno; } } cb_handle_t *cb = new cb_handle_t(fd, ashmem_size, usage, w, h, glFormat); if (ashmem_size > 0) { // // map ashmem region if exist // void *vaddr; int err = map_buffer(cb, &vaddr); if (err) { close(fd); delete cb; return err; } } // // Allocate ColorBuffer handle on the host (only if h/w access is allowed) // if (usage & GRALLOC_USAGE_HW_MASK) { DEFINE_HOST_CONNECTION; if (hostCon && rcEnc) { cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, glFormat); LOGD("Created host ColorBuffer 0x%x\n", cb->hostHandle); } if (!cb->hostHandle) { // Could not create colorbuffer on host !!! close(fd); delete cb; return -EIO; } } // // alloc succeeded - insert the allocated handle to the allocated list // AllocListNode *node = new AllocListNode(); pthread_mutex_lock(&grdev->lock); node->handle = cb; node->next = grdev->allocListHead; node->prev = NULL; if (grdev->allocListHead) { grdev->allocListHead->prev = node; } grdev->allocListHead = node; pthread_mutex_unlock(&grdev->lock); *pHandle = cb; return 0; }
int main(int argc, const char *argv[]) { int i; int count = 0; int fd; int ret; /* Open a file for writing. * - Creating the file if it doesn't exist. * - Truncating it to 0 size if it already exists. (not really needed) * * Note: "O_WRONLY" mode is not sufficient when mmaping. */ loop: fd = ashmem_create_region("zzytest", LEN); if (fd < 0) { perror("Error opening file for writing"); exit(EXIT_FAILURE); } char ash_name[ASHMEM_NAME_LEN] = {0}; ret = ioctl(fd, ASHMEM_GET_NAME, ash_name); if(ret >= 0) { printf("ash_name=%s\n", ash_name); } // Now the file is ready to be mmapped. char *map = mmap(0, LEN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { close(fd); perror("Error mmapping the file"); exit(EXIT_FAILURE); } char s[256], name[256]; memset(s, 0, 256); memset(name, 0, 256); snprintf(s, 255, "/proc/%d/fd/%d", getpid(), fd); readlink(s, name, 255); printf("Succeeded to mmap program binaries. File descriptor is %d, and path is %s\n", fd, name); printf("memset data\n"); memset(map, '1', LEN-1); //printf("%c\n", map[count%textsize]); // Write it now to disk if (msync(map, LEN, MS_SYNC) == -1) { perror("Could not sync the file to disk"); } sleep(1); printf("count=%d\n", count++); printf("fd=%d\n", fd); printf("map=%x\n", map); // close fd close(fd); // Don't forget to free the mmapped memory #if 1 if (munmap(map, LEN) == -1) { close(fd); perror("Error un-mmapping the file"); exit(EXIT_FAILURE); } #endif goto loop; return 0; }