[RFC PATCH 21/28] lkl tools: host lib: posix host operations

From: Octavian Purdila
Date: Tue Nov 03 2015 - 15:26:45 EST


Implement LKL host operations for POSIX hosts.

Signed-off-by: Octavian Purdila <octavian.purdila@xxxxxxxxx>
---
tools/lkl/Makefile | 6 ++
tools/lkl/lib/posix-host.c | 206 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 212 insertions(+)
create mode 100644 tools/lkl/lib/posix-host.c

diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile
index b13472b..cf97d27 100644
--- a/tools/lkl/Makefile
+++ b/tools/lkl/Makefile
@@ -3,9 +3,15 @@ CFLAGS := -Iinclude -Wall -g
ifdef CROSS_COMPILE
CC=$(CROSS_COMPILE)gcc
AR=$(CROSS_COMPILE)ar
+LD=$(CROSS_COMPILE)ld
endif

lib_source = $(filter-out %-host.c,$(wildcard lib/*.c))
+ifneq (,$(filter $(shell $(LD) -r -print-output-format),elf64-x86-64 elf32-i386))
+lib_source += lib/posix-host.c
+LDFLAGS += -lpthread -lrt
+endif
+
lib_objs = $(patsubst %.c,%.o, $(lib_source)) lib/lkl.o

all: lib/liblkl.a
diff --git a/tools/lkl/lib/posix-host.c b/tools/lkl/lib/posix-host.c
new file mode 100644
index 0000000..4bc1de7
--- /dev/null
+++ b/tools/lkl/lib/posix-host.c
@@ -0,0 +1,206 @@
+#include <pthread.h>
+#include <malloc.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <execinfo.h>
+#include <stdint.h>
+#include <sys/uio.h>
+#include <lkl_host.h>
+#include "iomem.h"
+
+static void print(const char *str, int len)
+{
+ write(STDOUT_FILENO, str, len);
+}
+
+struct pthread_sem {
+ pthread_mutex_t lock;
+ int count;
+ pthread_cond_t cond;
+};
+
+static void *sem_alloc(int count)
+{
+ struct pthread_sem *sem;
+
+ sem = malloc(sizeof(*sem));
+ if (!sem)
+ return NULL;
+
+ pthread_mutex_init(&sem->lock, NULL);
+ sem->count = count;
+ pthread_cond_init(&sem->cond, NULL);
+
+ return sem;
+}
+
+static void sem_free(void *sem)
+{
+ free(sem);
+}
+
+static void sem_up(void *_sem)
+{
+ struct pthread_sem *sem = (struct pthread_sem *)_sem;
+
+ pthread_mutex_lock(&sem->lock);
+ sem->count++;
+ if (sem->count > 0)
+ pthread_cond_signal(&sem->cond);
+ pthread_mutex_unlock(&sem->lock);
+}
+
+static void sem_down(void *_sem)
+{
+ struct pthread_sem *sem = (struct pthread_sem *)_sem;
+
+ pthread_mutex_lock(&sem->lock);
+ while (sem->count <= 0)
+ pthread_cond_wait(&sem->cond, &sem->lock);
+ sem->count--;
+ pthread_mutex_unlock(&sem->lock);
+}
+
+static int thread_create(void (*fn)(void *), void *arg)
+{
+ pthread_t thread;
+
+ return pthread_create(&thread, NULL, (void* (*)(void *))fn, arg);
+}
+
+static void thread_exit(void)
+{
+ pthread_exit(NULL);
+}
+
+static unsigned long long time_ns(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ULL;
+}
+
+static void *timer_alloc(void (*fn)(void *), void *arg)
+{
+ int err;
+ timer_t timer;
+ struct sigevent se = {
+ .sigev_notify = SIGEV_THREAD,
+ .sigev_value = {
+ .sival_ptr = arg,
+ },
+ .sigev_notify_function = (void (*)(union sigval))fn,
+ };
+
+ err = timer_create(CLOCK_REALTIME, &se, &timer);
+ if (err)
+ return NULL;
+
+ return (void *)(long)timer;
+}
+
+static int timer_set_oneshot(void *_timer, unsigned long ns)
+{
+ timer_t timer = (timer_t)(long)_timer;
+ struct itimerspec ts = {
+ .it_value = {
+ .tv_sec = ns / 1000000000,
+ .tv_nsec = ns % 1000000000,
+ },
+ };
+
+ if (!ts.it_value.tv_nsec)
+ ts.it_value.tv_nsec++;
+
+ return timer_settime(timer, 0, &ts, NULL);
+}
+
+static void timer_free(void *_timer)
+{
+ timer_t timer = (timer_t)(long)_timer;
+
+ timer_delete(timer);
+}
+
+static void panic(void)
+{
+ assert(0);
+}
+
+struct lkl_host_operations lkl_host_ops = {
+ .panic = panic,
+ .thread_create = thread_create,
+ .thread_exit = thread_exit,
+ .sem_alloc = sem_alloc,
+ .sem_free = sem_free,
+ .sem_up = sem_up,
+ .sem_down = sem_down,
+ .time = time_ns,
+ .timer_alloc = timer_alloc,
+ .timer_set_oneshot = timer_set_oneshot,
+ .timer_free = timer_free,
+ .print = print,
+ .mem_alloc = malloc,
+ .mem_free = free,
+ .ioremap = lkl_ioremap,
+ .iomem_access = lkl_iomem_access,
+ .virtio_devices = lkl_virtio_devs,
+};
+
+int fd_get_capacity(union lkl_disk_backstore bs, unsigned long long *res)
+{
+ off_t off;
+
+ off = lseek(bs.fd, 0, SEEK_END);
+ if (off < 0)
+ return -1;
+
+ *res = off;
+ return 0;
+}
+
+void fd_do_rw(union lkl_disk_backstore bs, unsigned int type, unsigned int prio,
+ unsigned long long sector, struct lkl_dev_buf *bufs, int count)
+{
+ int err = 0;
+ struct iovec *iovec = (struct iovec *)bufs;
+
+ if (count > 1)
+ lkl_printf("%s: %d\n", __func__, count);
+
+ /* TODO: handle short reads/writes */
+ switch (type) {
+ case LKL_DEV_BLK_TYPE_READ:
+ err = preadv(bs.fd, iovec, count, sector * 512);
+ break;
+ case LKL_DEV_BLK_TYPE_WRITE:
+ err = pwritev(bs.fd, iovec, count, sector * 512);
+ break;
+ case LKL_DEV_BLK_TYPE_FLUSH:
+ case LKL_DEV_BLK_TYPE_FLUSH_OUT:
+ err = fdatasync(bs.fd);
+ break;
+ default:
+ lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_UNSUP, 0);
+ return;
+ }
+
+ if (err < 0)
+ lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_IOERR, 0);
+ else
+ lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_OK, err);
+}
+
+struct lkl_dev_blk_ops lkl_dev_blk_ops = {
+ .get_capacity = fd_get_capacity,
+ .request = fd_do_rw,
+};
--
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/