This source file includes following definitions.
- ion_alloc
- ion_map
- ion_free
- halide_hexagon_host_malloc_init
- halide_hexagon_host_malloc_deinit
- halide_hexagon_host_malloc
- halide_hexagon_host_free
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <android/log.h>
namespace {
enum ion_heap_id {
system_heap_id = 25,
};
enum ion_flags {
ion_flag_cached = 1,
};
typedef int ion_user_handle_t;
struct ion_allocation_data {
size_t len;
size_t align;
unsigned int heap_id_mask;
unsigned int flags;
ion_user_handle_t handle;
};
struct ion_fd_data {
ion_user_handle_t handle;
int fd;
};
struct ion_handle_data {
ion_user_handle_t handle;
};
#define ION_IOC_ALLOC _IOWR('I', 0, ion_allocation_data)
#define ION_IOC_FREE _IOWR('I', 1, ion_handle_data)
#define ION_IOC_MAP _IOWR('I', 2, ion_fd_data)
ion_user_handle_t ion_alloc(int ion_fd, size_t len, size_t align, unsigned int heap_id_mask, unsigned int flags) {
ion_allocation_data alloc = {
len,
align,
heap_id_mask,
flags,
0
};
if (ioctl(ion_fd, ION_IOC_ALLOC, &alloc) < 0) {
return -1;
}
return alloc.handle;
}
int ion_map(int ion_fd, ion_user_handle_t handle) {
ion_fd_data data = {
handle,
0
};
if (ioctl(ion_fd, ION_IOC_MAP, &data) < 0) {
return -1;
}
return data.fd;
}
int ion_free(int ion_fd, ion_user_handle_t ion_handle) {
if(ioctl(ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
return -1;
}
return 0;
}
struct allocation_record {
allocation_record *next;
ion_user_handle_t handle;
int buf_fd;
void *buf;
size_t size;
};
allocation_record allocations = { NULL, };
pthread_mutex_t allocations_mutex = PTHREAD_MUTEX_INITIALIZER;
int ion_fd = -1;
}
extern "C" {
__attribute__((weak)) void remote_register_buf(void* buf, int size, int fd);
void halide_hexagon_host_malloc_init() {
pthread_mutex_init(&allocations_mutex, NULL);
ion_fd = open("/dev/ion", O_RDONLY, 0);
if (ion_fd < 0) {
__android_log_print(ANDROID_LOG_ERROR, "halide", "open('/dev/ion') failed");
}
}
void halide_hexagon_host_malloc_deinit() {
close(ion_fd);
ion_fd = -1;
pthread_mutex_destroy(&allocations_mutex);
}
void *halide_hexagon_host_malloc(size_t size) {
const int heap_id = system_heap_id;
const int ion_flags = ion_flag_cached;
static const size_t alignments[] = { 0x1000, 0x4000, 0x10000, 0x40000, 0x100000 };
size_t alignment = alignments[0];
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;
}
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;
}
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;
}
if (remote_register_buf) {
remote_register_buf(buf, size, buf_fd);
}
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;
pthread_mutex_lock(&allocations_mutex);
rec->next = allocations.next;
allocations.next = rec;
pthread_mutex_unlock(&allocations_mutex);
return buf;
}
void halide_hexagon_host_free(void *ptr) {
if (!ptr) {
return;
}
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;
}
if (remote_register_buf) {
remote_register_buf(rec->buf, rec->size, -1);
}
munmap(rec->buf, rec->size);
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);
}
}