creole interface
This commit is contained in:
parent
5b390929f5
commit
1911d58725
2
creole
2
creole
|
@ -1 +1 @@
|
|||
Subproject commit 13c67aba9a3ed72326cfa308b7c3e77e3e9934ed
|
||||
Subproject commit dc1abae13a7d8d50043dfbf22b8c8592692617f8
|
|
@ -0,0 +1,368 @@
|
|||
/* Verilog access control.
|
||||
*
|
||||
* Mutex management for hardware resources.
|
||||
* Each mutex has a thread-local lock counter associated with it, since in
|
||||
* Zephyr the recursive lock counter is not publically accessable.
|
||||
*
|
||||
* On the final unlock for a thread, the code will always take steps to
|
||||
* reset the state of the Verilog module so that another thread will
|
||||
* see a consistent start state.
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include "converters.h"
|
||||
#include "pin_io.h"
|
||||
|
||||
static inline uint32_t
|
||||
sign_extend(uint32_t in, unsigned len)
|
||||
{
|
||||
if (in >> (len - 1) & 1) {
|
||||
uint32_t mask = (1 << len) - 1;
|
||||
return ~mask | (in & mask);
|
||||
} else {
|
||||
return in;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************
|
||||
* DAC
|
||||
*********************/
|
||||
|
||||
static struct k_mutex_t dac_mutex[DAC_MAX];
|
||||
static __thread int dac_locked[DAC_MAX];
|
||||
|
||||
int
|
||||
dac_take(int dac, k_timeout_t timeout)
|
||||
{
|
||||
if (dac < 0 || dac >= DAC_MAX)
|
||||
return -EFAULT;
|
||||
|
||||
int e = k_mutex_lock(dac_mutex + dac, timeout);
|
||||
if (e == 0) {
|
||||
dac_locked[dac] += 1;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
int
|
||||
dac_release(int dac)
|
||||
{
|
||||
if (dac < 0 || dac >= DAC_MAX)
|
||||
return -EFAULT;
|
||||
|
||||
if (dac_locked[dac] == 1) {
|
||||
*dac_arm[dac] = 0;
|
||||
while (!*dac_finished[dac]);
|
||||
}
|
||||
|
||||
int e = k_mutex_unlock(dac_mutex + dac);
|
||||
if (e == 0) {
|
||||
dac_locked[dac] -= 1;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
int
|
||||
dac_read_write(int dac, creole_word send, k_timeout_t timeout,
|
||||
creole_word *recv)
|
||||
{
|
||||
int e = dac_take(dac, timeout);
|
||||
if (e != 0)
|
||||
return e;
|
||||
|
||||
*to_dac[dac] = send;
|
||||
*dac_arm[adc] = 1;
|
||||
|
||||
/* Recursive locks should busy wait. */
|
||||
/* 10ns * (2 * 10 cycles per half DAC cycle)
|
||||
* 24 bits
|
||||
*/
|
||||
if (dac_locked[dac] > 1)
|
||||
k_sleep(K_NSEC(10*2*10*24));
|
||||
while (!*dac_finished[dac]);
|
||||
|
||||
if (recv)
|
||||
*recv = sign_extend(*from_dac[dac], 20);
|
||||
*dac_arm[dac] = 0;
|
||||
|
||||
dac_release(dac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* adc read
|
||||
*********************/
|
||||
|
||||
static struct k_mutex_t adc_mutex[ADC_MAX];
|
||||
static __thread int adc_locked[ADC_MAX];
|
||||
|
||||
int
|
||||
adc_take(int adc, int timeout)
|
||||
{
|
||||
if (adc < 0 || adc >= ADC_MAX)
|
||||
return -EFAULT;
|
||||
|
||||
int e = k_mutex_lock(adc_mutex + adc, timeout);
|
||||
if (e == 0) {
|
||||
adc_locked[adc] += 1;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
int
|
||||
adc_release(int adc)
|
||||
{
|
||||
if (adc < 0 || adc >= ADC_MAX)
|
||||
return -EFAULT;
|
||||
|
||||
if (adc_locked[adc] == 1) {
|
||||
*adc_arm[adc] = 0;
|
||||
while (!*adc_finished[adc]);
|
||||
}
|
||||
|
||||
int e = k_mutex_unlock(adc_mutex + adc);
|
||||
if (e == 0) {
|
||||
adc_locked[adc] -= 1;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
int
|
||||
adc_read(int adc, int timeout, creole_word *wrd)
|
||||
{
|
||||
int e;
|
||||
if ((e = adc_take(adc, timeout)) != 0)
|
||||
return e;
|
||||
|
||||
*adc_arm[adc] = 1;
|
||||
|
||||
/* Recursive locks should busy wait. */
|
||||
if (adc_locked[adc] > 1)
|
||||
k_sleep(K_NSEC(550 + 24*2*10*10));
|
||||
while (!*adc_finished[adc]);
|
||||
|
||||
*wrd = sign_extend(*from_adc[adc]);
|
||||
*adc_arm[adc] = 0;
|
||||
|
||||
adc_release(adc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********
|
||||
* Control loop
|
||||
*******/
|
||||
|
||||
static struct k_mutex_t cloop_mutex;
|
||||
static __thread cloop_locked;
|
||||
|
||||
int
|
||||
cloop_take(k_timeout_t timeout)
|
||||
{
|
||||
int e = k_mutex_lock(&cloop_mutex, timeout);
|
||||
if (e == 0) {
|
||||
cloop_locked++;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
int
|
||||
cloop_release(void)
|
||||
{
|
||||
/* If being unlocked for the last time. */
|
||||
if (cloop_locked == 1) {
|
||||
*cl_cmd = CONTROL_LOOP_WRITE_BIT | CONTROL_LOOP_STATUS;
|
||||
cl_word_out[0] = 0;
|
||||
cl_word_out[1] = 0;
|
||||
*cl_start_cmd = 1;
|
||||
while (!*cl_finish_cmd);
|
||||
*cl_start_cmd = 0;
|
||||
}
|
||||
int e = k_mutex_unlock(&cloop_mutex);
|
||||
if (e == 0) {
|
||||
cloop_locked--;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
int
|
||||
cloop_read(int code, uint32_t *high_reg, uint32_t *low_reg,
|
||||
k_timeout_t timeout)
|
||||
{
|
||||
if (cloop_take(timeout) != 0)
|
||||
return 0;
|
||||
|
||||
*cl_cmd = code;
|
||||
*cl_start_cmd = 1;
|
||||
while (!*cl_finish_cmd);
|
||||
*high_reg = cl_word_out[0];
|
||||
*low_reg = cl_word_out[1];
|
||||
*cl_start_cmd = 0;
|
||||
|
||||
cloop_release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cloop_write(int code, uint32_t high_reg, uint32_t low_reg,
|
||||
k_timeout_t timeout)
|
||||
{
|
||||
if (cloop_take(timeout) != 0)
|
||||
return 0;
|
||||
|
||||
*cl_cmd = code;
|
||||
cl_word_in[0] = high_val;
|
||||
cl_word_in[1] = low_val;
|
||||
|
||||
*cl_start_cmd = 1;
|
||||
while (!*cl_finish_cmd);
|
||||
*cl_start_cmd = 0;
|
||||
|
||||
cloop_release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************
|
||||
* Waveforms
|
||||
***********/
|
||||
|
||||
static struct k_mutex_t waveform_mutex[DAC_MAX];
|
||||
static __thread int waveform_locked[DAC_MAX];
|
||||
|
||||
int
|
||||
waveform_take(int waveform, k_timeout_t timeout)
|
||||
{
|
||||
if (waveform < 0 || waveform >= DAC_MAX)
|
||||
return -EFAULT;
|
||||
|
||||
int e = k_mutex_lock(waveform_mutex + waveform, timeout);
|
||||
if (e == 0) {
|
||||
waveform_locked[e]++;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
int
|
||||
waveform_release(int waveform)
|
||||
{
|
||||
if (waveform < 0 || waveform >= DAC_MAX)
|
||||
return -EFAULT;
|
||||
|
||||
if (waveform_locked[waveform] == 1) {
|
||||
*wf_arm[waveform] = 0;
|
||||
while (*wf_running[waveform]);
|
||||
}
|
||||
|
||||
int e k_mutex_unlock(waveform_mutex + waveform);
|
||||
if (e == 0) {
|
||||
waveform_locked[e]--;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
creole_to_array(const struct creole_reader *start, creole_word *buf, size_t buflen)
|
||||
{
|
||||
size_t i = 0;
|
||||
struct creole_word w;
|
||||
struct creole_reader r = start;
|
||||
|
||||
while (creole_decode(&r, &w) && i < buflen) {
|
||||
buf[i++] = w.word;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
waveform_load(uint32_t buf[MAX_WL_SIZE], int slot, k_timeout_t timeout)
|
||||
{
|
||||
if (waveform_take(slot, timeout) != 0)
|
||||
return 0;
|
||||
|
||||
if (load_into_array(env->dats[db], buf, ARRAY_SIZE(buf))
|
||||
!= MAX_WL_SIZE)
|
||||
goto ret;
|
||||
|
||||
*wf_start_addr[slot] = &buf;
|
||||
*wf_refresh_start[slot] = 1;
|
||||
while (!*wf_refresh_finished[slot]);
|
||||
*wf_refresh_start[slot] = 0;
|
||||
|
||||
waveform_release(slot);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
waveform_arm(int slot, bool halt_on_finish, uint32_t wait, k_timeout_t timeout)
|
||||
{
|
||||
if (waveform_take(slot, timeout) != 0)
|
||||
return 0;
|
||||
if (dac_take(slot, timeout) != 0) {
|
||||
waveform_release(slot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*wf_halt_on_finished[slot] = halt_on_finish;
|
||||
*wf_time_to_wait[slot] = wait;
|
||||
*wf_arm[slot] = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
waveform_disarm(int slot)
|
||||
{
|
||||
*wf_arm[slot] = 0;
|
||||
while (*wf_running[slot]);
|
||||
waveform_release(slot);
|
||||
dac_release(slot);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**********
|
||||
* Init and deinit
|
||||
*********/
|
||||
|
||||
void
|
||||
access_release_thread(void)
|
||||
{
|
||||
while (cloop_release() == 0);
|
||||
|
||||
for (int i = 0; i < DAC_NUM; i++) {
|
||||
while (dac_release(i) == 0);
|
||||
while (waveform_release(i) == 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ADC_NUM; i++) {
|
||||
while (adc_release(i) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
access_thread_init(void)
|
||||
{
|
||||
cloop_locked = 0;
|
||||
|
||||
for (int i = 0; i < DAC_NUM; i++) {
|
||||
dac_locked[i] = 0;
|
||||
waveform_locked[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ADC_NUM; i++) {
|
||||
adc_locked[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
access_init(void)
|
||||
{
|
||||
k_mutex_init(cloop_mutex);
|
||||
|
||||
for (int i = 0; i < DAC_NUM; i++) {
|
||||
k_mutex_init(dac_mutex + i);
|
||||
k_mutex_init(waveform_mutex + i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ADC_NUM; i++) {
|
||||
k_mutex_init(adc_mutex + i);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
|
||||
int dac_release(int dac);
|
||||
int dac_read_write(int dac, creole_word send, k_timeout_t timeout,
|
||||
creole_word *recv);
|
||||
|
||||
int adc_take(int adc, int timeout);
|
||||
int adc_release(int adc);
|
||||
int adc_read(int adc, int timeout, creole_word *wrd);
|
||||
|
||||
int cloop_take(k_timeout_t timeout);
|
||||
int cloop_release(void);
|
||||
|
||||
int waveform_take(int waveform, k_timeout_t timeout);
|
||||
int waveform_release(int waveform);
|
||||
|
||||
#define MAX_WL_SIZE 4096
|
||||
int waveform_load(uint32_t buf[MAX_WL_SIZE], int slot, k_timeout_t timeout);
|
||||
int waveform_arm(int slot, bool halt_on_finish, uint32_t wait, k_timeout_t timeout);
|
||||
int waveform_disarm(int slot);
|
||||
|
||||
|
||||
/* Zephyr OS does not automatically clean up mutex resources.
|
||||
* This will release all held locks.
|
||||
*/
|
||||
void access_release_thread(void);
|
||||
|
||||
/* Initialize thread local data, which might be non-zero due
|
||||
* to reusing threads.
|
||||
*/
|
||||
void access_thread_init(void);
|
||||
|
||||
/* Called once on initializion. */
|
||||
int access_init(void);
|
|
@ -1,75 +1,39 @@
|
|||
#include <sys_clock.h>
|
||||
#include <sys/util.h>
|
||||
#include <zephyr/sys_clock.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include "control_loop_cmds.h"
|
||||
#include "creole.h"
|
||||
#include "creole_upsilon.h"
|
||||
#include "pin_io.h"
|
||||
#include "creole.h"
|
||||
|
||||
static inline uint32_t
|
||||
sign_extend(uint32_t in, unsigned len)
|
||||
creole_word
|
||||
upsilon_get_adc(creole_word adc, creole_word *ret)
|
||||
{
|
||||
if (in >> (len - 1) & 1) {
|
||||
uint32_t mask = (1 << len) - 1;
|
||||
return ~mask | (in & mask);
|
||||
} else {
|
||||
return in;
|
||||
}
|
||||
return adc_read(adc, K_FOREVER, ret);
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_get_adc(creole_word adc)
|
||||
upsilon_get_dac(creole_word dac, creole_word *ret)
|
||||
{
|
||||
if (adc < 0 || adc >= ADC_MAX)
|
||||
return 0;
|
||||
|
||||
*adc_arm[adc] = 1;
|
||||
/* TODO: sleep 550 ns */
|
||||
while (!*adc_finished[adc]);
|
||||
|
||||
creole_word w = sign_extend(*from_adc[adc]);
|
||||
*adc_arm[adc] = 0;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
send_dac(creole_word dac, uint32_t val)
|
||||
{
|
||||
*to_dac[dac] = val;
|
||||
*dac_arm[dac] = 1;
|
||||
/* TODO: sleep */
|
||||
while (!*dac_finished[dac]);
|
||||
uint32_t w = sign_extend(*from_dac[dac], 20);
|
||||
*dac_arm[dac] = 0;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_get_dac(creole_word dac)
|
||||
{
|
||||
if (dac < 0 || dac >= DAC_MAX)
|
||||
return 0;
|
||||
|
||||
send_dac(dac, 0x1 << 23 | 0x1 << 20);
|
||||
return send_dac(dac, 0);
|
||||
int e;
|
||||
e = dac_read_write(dac, 0x1 << 23 | 0x1 << 20, K_FOREVER, NULL);
|
||||
if (e != 0)
|
||||
return e;
|
||||
return dac_read_write(dac, 0, K_FOREVER, ret);
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_write_dac(creole_word dac, creole_word val)
|
||||
{
|
||||
if (dac < 0 || dac >= DAC_MAX)
|
||||
return 0;
|
||||
send_dac(dac, 0x1 << 20 | val);
|
||||
return 1;
|
||||
return dac_read_write(dac, 0x1 << 20 | val, K_FOREVER, NULL);
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_usec(creole_word usec)
|
||||
{
|
||||
k_sleep(K_USEC(usec));
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
creole_word
|
||||
|
@ -77,14 +41,7 @@ upsilon_control_loop_read(creole_word *high_reg,
|
|||
creole_word *low_reg,
|
||||
creole_word code)
|
||||
{
|
||||
*cl_cmd = code;
|
||||
*cl_start_cmd = 1;
|
||||
while (!*cl_finish_cmd);
|
||||
*high_reg = cl_word_out[0];
|
||||
*low_reg = cl_word_out[1];
|
||||
*cl_start_cmd = 0;
|
||||
|
||||
return 1;
|
||||
return cloop_read(code, high_reg, low_reg, K_FOREVER);
|
||||
}
|
||||
|
||||
creole_word
|
||||
|
@ -92,14 +49,7 @@ upsilon_control_loop_write(creole_word high_val,
|
|||
creole_word low_val,
|
||||
creole_word code)
|
||||
{
|
||||
*cl_cmd = CONTROL_LOOP_WRITE_BIT | code;
|
||||
cl_word_in[0] = high_val;
|
||||
cl_word_in[1] = low_val;
|
||||
*cl_start_cmd = 1;
|
||||
while (!*cl_finish_cmd);
|
||||
*cl_start_cmd = 0;
|
||||
|
||||
return 1;
|
||||
return cloop_write(code, high_val, low_val, K_FOREVER);
|
||||
}
|
||||
|
||||
static size_t
|
||||
|
@ -123,37 +73,21 @@ upsilon_load_waveform(struct creole_env *env, creole_word slot,
|
|||
{
|
||||
creole_word buf[MAX_WL_SIZE];
|
||||
size_t len = load_into_array(env->dats[db], buf, ARRAY_SIZE(buf));
|
||||
|
||||
if (len != MAX_WL_SIZE)
|
||||
if (len < MAX_WL_SIZE)
|
||||
return 0;
|
||||
|
||||
*wf_start_addr[slot] = &buf;
|
||||
*wf_refresh_start[slot] = 1;
|
||||
while (!*wf_refresh_finished[slot]);
|
||||
*wf_refresh_start[slot] = 0;
|
||||
|
||||
return 1;
|
||||
return waveform_load(buf, slot, K_FOREVER);
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_arm_waveform(creole_word slot, creole_word hof, creole_word wait)
|
||||
{
|
||||
*wf_halt_on_finished[slot] = hof;
|
||||
*wf_time_to_wait[slot] = wait;
|
||||
*wf_arm[slot] = 1;
|
||||
|
||||
if (wait) {
|
||||
while (!*wf_finished[slot]);
|
||||
*wf_arm[slot] = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return waveform_arm(slot, hof, wait, K_FOREVER);
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_disarm_waveform(creole_word slot)
|
||||
{
|
||||
*wf_arm[slot] = 0;
|
||||
return 1;
|
||||
return waveform_disarm(slot);
|
||||
}
|
||||
|
||||
creole_word
|
||||
|
@ -181,3 +115,51 @@ upsilon_senddat(struct creole_env *env, creole_word db)
|
|||
|
||||
return sock_write_buf(env->fd, &bp);
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_take_adc(creole_word slot, creole_word timeout)
|
||||
{
|
||||
return adc_take(slot, K_USEC(timeout));
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_release_adc(creole_word slot)
|
||||
{
|
||||
return adc_release(slot);
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_take_dac(creole_word slot, creole_word timeout)
|
||||
{
|
||||
return dac_take(slot, K_USEC(timeout));
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_release_dac(creole_word slot)
|
||||
{
|
||||
return dac_release(slot);
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_take_wf(creole_word slot, creole_word timeout)
|
||||
{
|
||||
return waveform_take(slot, K_USEC(timeout));
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_release_wf(creole_word slot)
|
||||
{
|
||||
return waveform_release(slot);
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_take_cloop(creole_word timeout)
|
||||
{
|
||||
return cloop_take(K_USEC(timeout));
|
||||
}
|
||||
|
||||
creole_word
|
||||
upsilon_release_cloop(void)
|
||||
{
|
||||
return cloop_release();
|
||||
}
|
||||
|
|
|
@ -9,36 +9,107 @@
|
|||
|
||||
LOG_MODULE_REGISTER(main);
|
||||
|
||||
static void
|
||||
process_client(int cli)
|
||||
#define THREAD_STACK_SIZ 1024*32
|
||||
#define THREADNUM 32
|
||||
static K_KERNEL_STACK_ARRAY_DEFINE(stacks, THREADNUM, THREAD_STACK_SIZ);
|
||||
|
||||
#define READBUF_SIZ 0xFFFF
|
||||
static unsigned char readbuf[THREADNUM][READBUF_SIZ];
|
||||
static struct kthread_t threads[THREADNUM];
|
||||
static bool thread_ever_used[THREADNUM];
|
||||
|
||||
static int
|
||||
read_size(int s)
|
||||
{
|
||||
enum fds {
|
||||
CLIENT_FD,
|
||||
SCANDATA_FD,
|
||||
MAXFDS
|
||||
char buf[2];
|
||||
struct bufptr bp = {buf, sizeof(buf)};
|
||||
|
||||
if (!sock_read_buf(s, &bp, true))
|
||||
return -1;
|
||||
return (unsigned char)buf[0] | (unsigned char) buf[1] << 8;
|
||||
}
|
||||
|
||||
static void
|
||||
exec_creole(unsigned char *buf, int size, int sock)
|
||||
{
|
||||
#define DATLEN 64
|
||||
struct creole_reader dats[DATSLEN];
|
||||
#define REGLEN 32
|
||||
creole_word reg[REGLEN];
|
||||
#define STKLEN 1024
|
||||
creole_word stk[STKLEN];
|
||||
|
||||
struct creole_env env = {
|
||||
.dats = dats,
|
||||
.datlen = DATLEN,
|
||||
.reg = reg,
|
||||
.reglen = REGLEN,
|
||||
.stk = stk,
|
||||
.stklen = STKLEN,
|
||||
|
||||
.r_current = {buf, size},
|
||||
.r_start = {buf, size},
|
||||
.sock = sock
|
||||
};
|
||||
struct zsock_pollfd fds[MAXFDS] = {0};
|
||||
|
||||
fds[CLIENT_FD].fd = cli;
|
||||
fds[CLIENT_FD].events = ZSOCK_POLLIN;
|
||||
// Currently not used
|
||||
fds[SCANDATA_FD].fd = -1;
|
||||
}
|
||||
|
||||
while (zsock_poll(fds, MAXFDS, 0) >= 0) {
|
||||
if (fds[CLIENT_FD].revents | POLLIN)
|
||||
client_parse(cli);
|
||||
/* TODO: error messages */
|
||||
|
||||
static void
|
||||
exec_entry(void *client_p, void *threadnum_p,
|
||||
void *unused __attribute__((unused)))
|
||||
{
|
||||
intptr_t client = client_p;
|
||||
intptr_t threadnum = threadnum_p;
|
||||
int size = read_size(client);
|
||||
|
||||
if (size < 0) {
|
||||
zsock_close(client);
|
||||
return;
|
||||
}
|
||||
|
||||
struct bufptr bp = {readbuf[threadnum], size};
|
||||
if (!sock_read_buf(client, &bp, true)) {
|
||||
zsock_close(client);
|
||||
return;
|
||||
}
|
||||
|
||||
exec_creole(size);
|
||||
zsock_close(client);
|
||||
}
|
||||
|
||||
/* TODO: main thread must be higher priority than execution threads */
|
||||
static void
|
||||
main_loop(int srvsock)
|
||||
{
|
||||
for (;;) {
|
||||
int client = server_accept_client(srvsock);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < THREADNUM; i++) {
|
||||
if (!thread_ever_used[i]
|
||||
|| k_thread_join(threads[i], 0) == 0) {
|
||||
k_thread_create(threads[i], stacks[i],
|
||||
THREAD_STACK_SIZ, exec_entry,
|
||||
(uintptr_t) client, (uintptr_t) i, NULL,
|
||||
1, 0, K_NO_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
if (i == THREADNUM) {
|
||||
LOG_INF("Too many connections (max %d)",
|
||||
THREADNUM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
int srv = server_init_sock(6626);
|
||||
|
||||
for (;;) {
|
||||
int cli = server_get_client(server_sock);
|
||||
process_client(cli);
|
||||
LOG_INF("Closing client socket");
|
||||
zsock_close(cli);
|
||||
int sock = server_init_sock(6626);
|
||||
main_loop(sock);
|
||||
close(sock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,25 +63,22 @@ server_accept_client(int server)
|
|||
return client;
|
||||
}
|
||||
|
||||
bool
|
||||
int
|
||||
sock_read_buf(int sock, struct bufptr *bp, bool entire)
|
||||
{
|
||||
if (bp->left < 2)
|
||||
return false;
|
||||
|
||||
do {
|
||||
ssize_t l = zsock_recv(sock, bp->p, bp->left - 1, 0);
|
||||
if (l < 0)
|
||||
return false;
|
||||
return -errno;
|
||||
|
||||
bp->left -= l;
|
||||
bp->p += l;
|
||||
} while (entire && bp->left > 0);
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
int
|
||||
sock_write_buf(int sock, struct bufptr *bp)
|
||||
{
|
||||
/* Since send may not send all data in the buffer at once,
|
||||
|
@ -90,12 +87,12 @@ sock_write_buf(int sock, struct bufptr *bp)
|
|||
while (bp->left) {
|
||||
ssize_t l = zsock_send(sock, bp->p, bp->left, 0);
|
||||
if (l < 0)
|
||||
return false;
|
||||
return -errno;
|
||||
bp->p += l;
|
||||
bp->left -= l;
|
||||
}
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -10,15 +10,16 @@ int server_init_sock(int port);
|
|||
*/
|
||||
int server_accept_client(int server);
|
||||
|
||||
/* Read data into buffer. Returns false if error occurs. This is
|
||||
/* Read data into buffer. Returns 0 if buffer is filled. This is
|
||||
* raw binary (no NUL termination).
|
||||
*/
|
||||
bool sock_read_buf(int sock, struct bufptr *bp, bool entire);
|
||||
int sock_read_buf(int sock, struct bufptr *bp, bool entire);
|
||||
|
||||
/* Write raw buffer data into socket. This data is raw binary and
|
||||
* does not have to be NUL terminated.
|
||||
* does not have to be NUL terminated. Returns 0 when all data has
|
||||
* been written.
|
||||
*/
|
||||
bool sock_write_buf(int sock, struct bufptr *bp);
|
||||
int sock_write_buf(int sock, struct bufptr *bp);
|
||||
|
||||
/* Write formatted string into socket. The user must provide a
|
||||
* buffer into which the formatted string is written. These return
|
||||
|
|
Loading…
Reference in New Issue