#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/mman.h>
#define _GNU_SOURCE
#include <linux/mman.h>
#include <time.h>
#define PLAIN_DEV_PATH "/dev/mem"
#define PLAIN_PHSY_ADDR 0x800000000
#define DOORBELL_UIO_DEV_PATH "/dev/uio0"
#define PAGE_SIZE 4096
#define PLAIN_SIZE 1073741824
#define INTR_CMD 0x00
typedef struct ivshmem_uio_ptr{
struct ivshmem_uio_reg{
uint32_t intr_mask;
uint32_t intr_stat;
uint32_t iv_pos;
uint32_t doorbell;
uint32_t iv_livelist;
} registers;
uint8_t pad[4096-sizeof(struct ivshmem_uio_reg)];
}IVSHMEM_REG;
typedef struct ivshmem_fifo_meta{
struct ivshmem_fifo_offset{
uint32_t r_offset;
uint32_t w_offset;
uint32_t max_bound;
} offsets;
uint8_t pad[2097152-sizeof(struct ivshmem_fifo_offset)];
}IVSHMEM_FIFO_META;
int main(int argc, char *argv[]){
unsigned short dest_peer_id = (unsigned short)atoi(argv[1]);
const uint32_t intr_msg = ((dest_peer_id & 0xffff) << 16) + (INTR_CMD & 0xffff);
int plain_fd = -1, uio_fd = -1;
if((plain_fd = open(PLAIN_DEV_PATH, O_ASYNC | O_RDWR)) < 0){
perror("open(PLAIN_DEV_PATH)");
exit(EXIT_FAILURE);
}
if((uio_fd = open(DOORBELL_UIO_DEV_PATH, O_ASYNC | O_RDWR)) < 0){
perror("open(DOORBELL_UIO_DEV_PATH)");
exit(EXIT_FAILURE);
}
int plain_map_option = MAP_SHARED; // ???
if(PAGE_SIZE == 2097152){ // 2MB
plain_map_option = MAP_PRIVATE | MAP_HUGETLB | MAP_HUGE_2MB; // ???
}
else if(PAGE_SIZE == 1073741824){ // 1GB
plain_map_option = MAP_PRIVATE | MAP_HUGETLB | MAP_HUGE_1GB; // ???
}
int uio_map_option = MAP_SHARED; // ???
/*
if(PAGE_SIZE == 2097152){ // 2MB
uio_map_option = MAP_PRIVATE | MAP_HUGETLB | MAP_HUGE_2MB; // ???
}
else if(PAGE_SIZE == 1073741824){ // 1GB
uio_map_option = MAP_PRIVATE | MAP_HUGETLB | MAP_HUGE_1GB; // ???
}
*/
// Create epoll fd
int flags = fcntl(uio_fd, F_GETFL, 0);
fcntl(uio_fd, F_SETFL, flags | O_NONBLOCK);
int uio_epoll_fd = epoll_create(1);
struct epoll_event ev_epoll;
ev_epoll.events = EPOLLIN | EPOLLET;
ev_epoll.data.fd = uio_fd;
epoll_ctl(uio_epoll_fd, EPOLL_CTL_ADD, uio_fd, &ev_epoll);
struct epoll_event tmp_event[1];
int num_fds = 0;
void *plain_ptr = NULL;
IVSHMEM_FIFO_META *plain_meta_ptr = NULL;
void *plain_fifo_ptr = NULL;
IVSHMEM_REG *uio_ptr = NULL;
if((uio_ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, uio_map_option, uio_fd, 0)) == (void *) -1){
perror("mmap(uio_fd)");
exit(EXIT_FAILURE);
}
if((plain_ptr = mmap(NULL, PLAIN_SIZE, PROT_READ | PROT_WRITE, plain_map_option, plain_fd, PLAIN_PHSY_ADDR)) == (void *) -1){
perror("mmap(plain_fd)");
exit(EXIT_FAILURE);
}
plain_meta_ptr = plain_ptr;
plain_fifo_ptr = plain_ptr + 2097152;
plain_meta_ptr->offsets.r_offset = 0;
plain_meta_ptr->offsets.w_offset = 0;
plain_meta_ptr->offsets.max_bound = PLAIN_SIZE - 2097152;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct timespec begin, end;
double time;
void *buf_a, *buf_b;
buf_a = malloc(1073741824);
fprintf(stderr, "buf_a = malloc(1073741824)\n");
buf_b = malloc(1073741824);
fprintf(stderr, "buf_b = malloc(1073741824)\n");
memset(buf_a, 0xff, 1073741824);
fprintf(stderr, "memset(buf_a, 0xff, 1073741824)\n");
memset(buf_b, 0x00, 1073741824);
fprintf(stderr, "memset(buf_b, 0x00, 1073741824)\n");
memset(plain_ptr, 0x00, 1073741824);
fprintf(stderr, "memset(plain_ptr, 0x00, 1073741824)\n");
printf("[local->local memcpy()] Starting...\n");
clock_gettime(CLOCK_MONOTONIC, &begin);
memcpy(buf_b, buf_a, 1073741824);
clock_gettime(CLOCK_MONOTONIC, &end);
time = (double)(end.tv_sec - begin.tv_sec) + ((double)(end.tv_nsec - begin.tv_nsec))/1000000000;
printf("[local->local memcpy()] Elapsed time: %lf\n", time);
printf("[local->ivshmem memcpy()] Starting...\n");
clock_gettime(CLOCK_MONOTONIC, &begin);
memcpy(plain_ptr, buf_a, 1073741824);
clock_gettime(CLOCK_MONOTONIC, &end);
time = (double)(end.tv_sec - begin.tv_sec) + ((double)(end.tv_nsec - begin.tv_nsec))/1000000000;
printf("[local->ivshmem memcpy()] Elapsed time: %lf\n", time);
return 0;
}