#include <stdint.h>
#include <string.h>
#include "ckb_syscalls.h"
#include "spawn_utils.h"
const uint64_t SYSCALL_CYCLES_BASE = 500;
const uint64_t SPAWN_EXTRA_CYCLES_BASE = 100000;
const uint64_t SPAWN_SPAWN_YIELD_CYCLES_BASE = 800;
int tic() {
static uint64_t tic = 0;
uint64_t cur_cycles = ckb_current_cycles();
uint64_t toc = cur_cycles - tic;
tic = cur_cycles;
return toc;
}
uint64_t cal_cycles(uint64_t nbase, uint64_t yield, uint64_t extra) {
uint64_t r = 0;
r += SYSCALL_CYCLES_BASE * nbase;
r += SPAWN_SPAWN_YIELD_CYCLES_BASE * yield;
r += SPAWN_EXTRA_CYCLES_BASE * extra;
return r;
}
uint64_t cal_cycles_floor(uint64_t nbase, uint64_t yield, uint64_t extra) {
return cal_cycles(nbase, yield, extra);
}
uint64_t cal_cycles_upper(uint64_t nbase, uint64_t yield, uint64_t extra) {
return cal_cycles(nbase, yield, extra) + 8192;
}
int main() {
int err = 0;
int toc = 0;
uint64_t cid = ckb_process_id();
uint64_t pid[5] = {0};
uint64_t fds[5][2][3] = {0};
uint64_t buf[256] = {0};
uint64_t len = 0;
switch (cid) {
case 0:
const char* argv[1] = {0};
for (int i = 1; i < 5; i++) {
toc = tic();
err = ckb_pipe(buf);
CHECK(err);
toc = tic();
CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon);
fds[i][0][0] = buf[0];
fds[i][1][1] = buf[1];
toc = tic();
err = ckb_pipe(buf);
CHECK(err);
toc = tic();
CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon);
fds[i][0][1] = buf[1];
fds[i][1][0] = buf[0];
}
for (int i = 1; i < 5; i++) {
toc = tic();
spawn_args_t spgs = {.argc = 0, .argv = argv, .process_id = &pid[i], .inherited_fds = fds[i][1]};
err = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &spgs);
CHECK(err);
toc = tic();
if (i < 4) {
CHECK2(toc > cal_cycles_floor(1, 1, 1), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 1), ErrorCommon);
} else {
CHECK2(toc > cal_cycles_floor(1, 1, 4), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 4), ErrorCommon);
}
}
for (int i = 1; i < 5; i++) {
len = 12;
toc = tic();
err = ckb_write(fds[i][0][1], "Hello World!", &len);
toc = tic();
CHECK(err);
if (i < 3) {
CHECK2(toc > cal_cycles_floor(1, 1, 2), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 2), ErrorCommon);
} else {
CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon);
}
err = ckb_close(fds[i][0][1]);
CHECK(err);
toc = tic();
CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon);
}
for (int i = 1; i < 5; i++) {
len = 1024;
toc = tic();
err = ckb_read_all(fds[i][0][0], buf, &len);
CHECK(err);
toc = tic();
if (i == 1) {
CHECK2(toc > cal_cycles_floor(1, 1, 2), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 2), ErrorCommon);
}
if (i == 2) {
CHECK2(toc > cal_cycles_floor(1, 1, 1), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 1), ErrorCommon);
}
if (i >= 3) {
CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon);
}
CHECK2(len == 12, ErrorCommon);
err = memcmp("Hello World!", buf, len);
CHECK(err);
}
for (int i = 1; i < 5; i++) {
int8_t exit_code = 255;
toc = tic();
err = ckb_wait(pid[i], &exit_code);
CHECK(err);
toc = tic();
CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon);
CHECK(exit_code);
}
break;
case 1:
case 2:
case 3:
case 4:
len = 2;
toc = tic();
err = ckb_inherited_fds(fds[cid][1], &len);
CHECK(err);
toc = tic();
CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon);
CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon);
CHECK2(len == 2, ErrorCommon);
len = 1024;
err = ckb_read_all(fds[cid][1][0], buf, &len);
CHECK(err);
CHECK2(len == 12, ErrorCommon);
err = memcmp("Hello World!", buf, len);
CHECK(err);
err = ckb_write(fds[cid][1][1], buf, &len);
CHECK(err);
err = ckb_close(fds[cid][1][1]);
CHECK(err);
break;
}
exit:
return err;
}