2023-01-18 09:29:08 +01:00
|
|
|
/*
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
UMKa - User-Mode KolibriOS developer tools
|
|
|
|
io - input/output platform specific code
|
|
|
|
|
|
|
|
Copyright (C) 2023 Ivan Baravy <dunkaist@gmail.com>
|
|
|
|
*/
|
|
|
|
|
2023-02-03 00:52:35 +01:00
|
|
|
#include <stdatomic.h>
|
2023-01-18 09:29:08 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <inttypes.h>
|
2023-02-03 00:52:35 +01:00
|
|
|
#include "umka.h"
|
2023-02-01 19:30:44 +01:00
|
|
|
#include "umkaio.h"
|
2023-02-03 00:52:35 +01:00
|
|
|
|
|
|
|
#define IOT_QUEUE_DEPTH 1
|
|
|
|
|
2023-02-10 23:33:22 +01:00
|
|
|
enum {
|
|
|
|
IOT_CMD_STATUS_EMPTY,
|
|
|
|
IOT_CMD_STATUS_READY,
|
|
|
|
IOT_CMD_STATUS_DONE,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
IOT_CMD_READ,
|
|
|
|
IOT_CMD_WRITE,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iot_cmd_read_arg {
|
|
|
|
int fd;
|
|
|
|
void *buf;
|
|
|
|
size_t count;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iot_cmd_read_ret {
|
|
|
|
ssize_t val;
|
|
|
|
};
|
|
|
|
|
|
|
|
union iot_cmd_read {
|
|
|
|
struct iot_cmd_read_arg arg;
|
|
|
|
struct iot_cmd_read_ret ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iot_cmd_write_arg {
|
|
|
|
int fd;
|
|
|
|
void *buf;
|
|
|
|
size_t count;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iot_cmd_write_ret {
|
|
|
|
ssize_t val;
|
|
|
|
};
|
|
|
|
|
|
|
|
union iot_cmd_write {
|
|
|
|
struct iot_cmd_write_arg arg;
|
|
|
|
struct iot_cmd_write_ret ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct iot_cmd {
|
|
|
|
pthread_cond_t iot_cond;
|
|
|
|
pthread_mutex_t iot_mutex;
|
|
|
|
pthread_mutex_t mutex;
|
|
|
|
int type;
|
|
|
|
atomic_int status;
|
|
|
|
union {
|
|
|
|
union iot_cmd_read read;
|
|
|
|
union iot_cmd_write write;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-02-03 00:52:35 +01:00
|
|
|
struct iot_cmd iot_cmd_buf[IOT_QUEUE_DEPTH];
|
|
|
|
|
|
|
|
static void *
|
|
|
|
thread_io(void *arg) {
|
|
|
|
(void)arg;
|
|
|
|
for (size_t i = 0; i < IOT_QUEUE_DEPTH; i++) {
|
2023-02-10 23:33:22 +01:00
|
|
|
iot_cmd_buf[i].status = IOT_CMD_STATUS_EMPTY;
|
2023-02-03 00:52:35 +01:00
|
|
|
iot_cmd_buf[i].type = 0;
|
|
|
|
pthread_cond_init(&iot_cmd_buf[i].iot_cond, NULL);
|
|
|
|
pthread_mutex_init(&iot_cmd_buf[i].iot_mutex, NULL);
|
|
|
|
pthread_mutex_lock(&iot_cmd_buf[i].iot_mutex);
|
|
|
|
pthread_mutex_init(&iot_cmd_buf[i].mutex, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct iot_cmd *cmd = iot_cmd_buf;
|
|
|
|
ssize_t ret;
|
|
|
|
while (1) {
|
|
|
|
pthread_cond_wait(&cmd->iot_cond, &cmd->iot_mutex);
|
|
|
|
// status must be ready
|
|
|
|
switch (cmd->type) {
|
2023-02-10 23:33:22 +01:00
|
|
|
case IOT_CMD_READ:
|
2023-02-03 00:52:35 +01:00
|
|
|
ret = read(cmd->read.arg.fd, cmd->read.arg.buf, cmd->read.arg.count);
|
2023-02-03 05:39:32 +01:00
|
|
|
cmd->read.ret.val = ret;
|
2023-02-03 00:52:35 +01:00
|
|
|
break;
|
2023-02-10 23:33:22 +01:00
|
|
|
case IOT_CMD_WRITE:
|
2023-02-03 00:52:35 +01:00
|
|
|
cmd->read.ret.val = write(cmd->read.arg.fd, cmd->read.arg.buf,
|
|
|
|
cmd->read.arg.count);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-02-10 23:33:22 +01:00
|
|
|
atomic_store_explicit(&cmd->status, IOT_CMD_STATUS_DONE, memory_order_release);
|
2023-02-03 00:52:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t
|
2023-02-03 05:39:32 +01:00
|
|
|
io_async_submit_wait_test(void) {
|
2023-02-03 00:52:35 +01:00
|
|
|
// appdata_t *app;
|
|
|
|
// __asm__ __volatile__ ("":"=b"(app)::);
|
|
|
|
// struct io_uring_queue *q = app->wait_param;
|
|
|
|
int done = pthread_mutex_trylock(&iot_cmd_buf[0].mutex);
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t
|
2023-02-03 05:39:32 +01:00
|
|
|
io_async_complete_wait_test(void) {
|
2023-02-03 00:52:35 +01:00
|
|
|
// appdata_t *app;
|
|
|
|
// __asm__ __volatile__ ("":"=b"(app)::);
|
|
|
|
// struct io_uring_queue *q = app->wait_param;
|
|
|
|
int status = atomic_load_explicit(&iot_cmd_buf[0].status, memory_order_acquire);
|
2023-02-10 23:33:22 +01:00
|
|
|
return status == IOT_CMD_STATUS_DONE;
|
2023-02-03 00:52:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t
|
|
|
|
io_async_read(int fd, void *buf, size_t count, void *arg) {
|
|
|
|
(void)arg;
|
|
|
|
|
|
|
|
kos_wait_events(io_async_submit_wait_test, NULL);
|
|
|
|
// status must be empty
|
|
|
|
struct iot_cmd *cmd = iot_cmd_buf;
|
2023-02-10 23:33:22 +01:00
|
|
|
cmd->type = IOT_CMD_READ;
|
2023-02-03 00:52:35 +01:00
|
|
|
cmd->read.arg.fd = fd;
|
|
|
|
cmd->read.arg.buf = buf;
|
|
|
|
cmd->read.arg.count = count;
|
2023-02-10 23:33:22 +01:00
|
|
|
atomic_store_explicit(&cmd->status, IOT_CMD_STATUS_READY, memory_order_release);
|
2023-02-03 00:52:35 +01:00
|
|
|
|
|
|
|
pthread_cond_signal(&cmd->iot_cond);
|
|
|
|
kos_wait_events(io_async_complete_wait_test, NULL);
|
|
|
|
|
2023-02-03 05:39:32 +01:00
|
|
|
ssize_t res = cmd->read.ret.val;
|
2023-02-03 00:52:35 +01:00
|
|
|
|
2023-02-10 23:33:22 +01:00
|
|
|
atomic_store_explicit(&cmd->status, IOT_CMD_STATUS_EMPTY, memory_order_release);
|
2023-02-03 00:52:35 +01:00
|
|
|
pthread_mutex_unlock(&cmd->mutex);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t
|
|
|
|
io_async_write(int fd, const void *buf, size_t count, void *arg) {
|
|
|
|
(void)fd;
|
|
|
|
(void)buf;
|
|
|
|
(void)count;
|
|
|
|
(void)arg;
|
|
|
|
return -1;
|
|
|
|
}
|
2023-01-18 09:29:08 +01:00
|
|
|
|
|
|
|
struct umka_io *
|
2023-02-03 05:39:32 +01:00
|
|
|
io_init(atomic_int *running) {
|
2023-01-18 09:29:08 +01:00
|
|
|
struct umka_io *io = malloc(sizeof(struct umka_io));
|
|
|
|
io->running = running;
|
2023-02-03 00:52:35 +01:00
|
|
|
if (running) {
|
|
|
|
pthread_create(&io->iot, NULL, thread_io, NULL);
|
|
|
|
}
|
2023-01-18 09:29:08 +01:00
|
|
|
return io;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
io_close(struct umka_io *io) {
|
|
|
|
free(io);
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t
|
2023-02-06 17:01:37 +01:00
|
|
|
io_read(int fd, void *buf, size_t count, const struct umka_io *io) {
|
2023-01-18 09:29:08 +01:00
|
|
|
ssize_t res;
|
2023-02-10 23:33:22 +01:00
|
|
|
if (*io->running < UMKA_RUNNING_YES) {
|
2023-01-18 09:29:08 +01:00
|
|
|
res = read(fd, buf, count);
|
|
|
|
} else {
|
2023-02-03 00:52:35 +01:00
|
|
|
res = io_async_read(fd, buf, count, NULL);
|
2023-01-18 09:29:08 +01:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t
|
2023-02-06 17:01:37 +01:00
|
|
|
io_write(int fd, const void *buf, size_t count, const struct umka_io *io) {
|
2023-01-18 09:29:08 +01:00
|
|
|
ssize_t res;
|
2023-02-10 23:33:22 +01:00
|
|
|
if (*io->running < UMKA_RUNNING_YES) {
|
2023-01-18 20:46:44 +01:00
|
|
|
res = write(fd, buf, count);
|
|
|
|
} else {
|
2023-02-03 00:52:35 +01:00
|
|
|
res = io_async_write(fd, buf, count, NULL);
|
2023-01-18 09:29:08 +01:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|