void halide_hexagon_host_free(void *ptr) { if (!ptr) { return; } // Find the record for this allocation and remove it from the list. pthread_mutex_lock(&allocations_mutex); allocation_record *rec = &allocations; while (rec) { allocation_record *cur = rec; rec = rec->next; if (rec && rec->buf == ptr) { cur->next = rec->next; break; } } pthread_mutex_unlock(&allocations_mutex); if (!rec) { __android_log_print(ANDROID_LOG_WARN, "halide", "Allocation not found in allocation records"); return; } // Unregister the buffer. if (remote_register_buf) { remote_register_buf(rec->buf, rec->size, -1); } // Unmap the memory munmap(rec->buf, rec->size); // free the ION allocation close(rec->buf_fd); if (ion_free(ion_fd, rec->handle) < 0) { __android_log_print(ANDROID_LOG_WARN, "halide", "ion_free(%d, %d) failed", ion_fd, rec->handle); } free(rec); }
static void register_buf(void* buf, int size, int fd) { if(remote_register_buf) { remote_register_buf(buf, size, fd); } }
void *halide_hexagon_host_malloc(size_t size) { const int heap_id = system_heap_id; const int ion_flags = ion_flag_cached; // Hexagon can only access a small number of mappings of these // sizes. We reduce the number of mappings required by aligning // large allocations to these sizes. static const size_t alignments[] = { 0x1000, 0x4000, 0x10000, 0x40000, 0x100000 }; size_t alignment = alignments[0]; // Align the size up to the minimum alignment. size = (size + alignment - 1) & ~(alignment - 1); if (heap_id != system_heap_id) { for (size_t i = 0; i < sizeof(alignments) / sizeof(alignments[0]); i++) { if (size >= alignments[i]) { alignment = alignments[i]; } } } ion_user_handle_t handle = ion_alloc(ion_fd, size, alignment, 1 << heap_id, ion_flags); if (handle < 0) { __android_log_print(ANDROID_LOG_ERROR, "halide", "ion_alloc(%d, %d, %d, %d, %d) failed", ion_fd, size, alignment, 1 << heap_id, ion_flags); return NULL; } // Map the ion handle to a file buffer. int buf_fd = ion_map(ion_fd, handle); if (buf_fd < 0) { __android_log_print(ANDROID_LOG_ERROR, "halide", "ion_map(%d, %d) failed", ion_fd, handle); ion_free(ion_fd, handle); return NULL; } // Map the file buffer to a pointer. void *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, buf_fd, 0); if (buf == MAP_FAILED) { __android_log_print(ANDROID_LOG_ERROR, "halide", "mmap(NULL, %d, PROT_READ | PROT_WRITE, MAP_SHARED, %d, 0) failed", size, buf_fd); close(buf_fd); ion_free(ion_fd, handle); return NULL; } // Register the buffer, so we get zero copy. if (remote_register_buf) { remote_register_buf(buf, size, buf_fd); } // Build a record for this allocation. allocation_record *rec = (allocation_record *)malloc(sizeof(allocation_record)); if (!rec) { __android_log_print(ANDROID_LOG_ERROR, "halide", "malloc failed"); munmap(buf, size); close(buf_fd); ion_free(ion_fd, handle); return NULL; } rec->next = NULL; rec->handle = handle; rec->buf_fd = buf_fd; rec->buf = buf; rec->size = size; // Insert this record into the list of allocations. Insert it at // the front, since it's simpler, and most likely to be freed // next. pthread_mutex_lock(&allocations_mutex); rec->next = allocations.next; allocations.next = rec; pthread_mutex_unlock(&allocations_mutex); return buf; }