checkpoint
1.) add a simple configuration file to the runtime (see sample.config for example) 2.) bug fixes to ARP worker thread 3.) bug fix to DPDK so completions aren't held too long (still WIP) 4.) print more useful startup messages in runtime 5.) remove shm delete hack, it didn't work as intended
This commit is contained in:
parent
5e4c8254fe
commit
9efe8bddb1
|
@ -182,12 +182,6 @@ void *mem_map_shm(mem_key_t key, void *base, size_t len, size_t pgsize,
|
|||
if (addr == MAP_FAILED)
|
||||
return MAP_FAILED;
|
||||
|
||||
/* mark the shm segment for destruction after the process dies */
|
||||
if (exclusive) {
|
||||
if (shmctl(shmid, IPC_RMID, NULL) == 1)
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
touch_mapping(addr, len, pgsize);
|
||||
return addr;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
#define IP_ADDR_STR_LEN 16
|
||||
|
||||
extern void ip_addr_to_str(uint32_t addr, char *str);
|
||||
extern char *ip_addr_to_str(uint32_t addr, char *str);
|
||||
|
||||
/*
|
||||
* Structure of an internet header, naked of options.
|
||||
|
|
|
@ -42,4 +42,4 @@ extern int thread_spawn(thread_fn_t fn, void *arg);
|
|||
extern void thread_exit(void) __noreturn;
|
||||
|
||||
/* main initialization */
|
||||
extern int runtime_init(thread_fn_t main_fn, void *arg, unsigned int cores);
|
||||
extern int runtime_init(const char *cfgpath, thread_fn_t main_fn, void *arg);
|
||||
|
|
|
@ -201,7 +201,7 @@ static struct rte_mempool *dpdk_pktmbuf_completion_pool_create(const char *name,
|
|||
mbp_priv.mbuf_data_room_size = 0;
|
||||
mbp_priv.mbuf_priv_size = priv_size;
|
||||
|
||||
mp = rte_mempool_create_empty(name, n, elt_size, cache_size,
|
||||
mp = rte_mempool_create_empty(name, n, elt_size, 0,
|
||||
sizeof(struct rte_pktmbuf_pool_private), socket_id, 0);
|
||||
if (mp == NULL)
|
||||
return NULL;
|
||||
|
|
|
@ -116,11 +116,12 @@ void dump_udp_pkt(int loglvl, uint32_t saddr, struct udp_hdr *udp_hdr,
|
|||
*
|
||||
* The buffer must be IP_ADDR_STR_LEN in size.
|
||||
*/
|
||||
void ip_addr_to_str(uint32_t addr, char *str)
|
||||
char *ip_addr_to_str(uint32_t addr, char *str)
|
||||
{
|
||||
snprintf(str, IP_ADDR_STR_LEN, "%d.%d.%d.%d",
|
||||
((addr >> 24) & 0xff),
|
||||
((addr >> 16) & 0xff),
|
||||
((addr >> 8) & 0xff),
|
||||
(addr & 0xff));
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* cfg.c - configuration file support
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <base/stddef.h>
|
||||
#include <base/bitmap.h>
|
||||
#include <base/log.h>
|
||||
#include <base/cpu.h>
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
|
||||
/*
|
||||
* Configuration Options
|
||||
*/
|
||||
|
||||
static int str_to_ip(const char *str, uint32_t *addr)
|
||||
{
|
||||
uint8_t a, b, c, d;
|
||||
if(sscanf(str, "%hhu.%hhu.%hhu.%hhu", &a, &b, &c, &d) != 4) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*addr = MAKE_IP_ADDR(a, b, c, d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int str_to_long(const char *str, long *val)
|
||||
{
|
||||
char *endptr;
|
||||
|
||||
*val = strtol(str, &endptr, 10);
|
||||
if (endptr == str || (*endptr != '\0' && *endptr != '\n') ||
|
||||
((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_host_ip(const char *name, const char *val)
|
||||
{
|
||||
uint32_t *addr;
|
||||
int ret;
|
||||
|
||||
if (!strcmp(name, "host_addr"))
|
||||
addr = &netcfg.addr;
|
||||
else if (!strcmp(name, "host_netmask"))
|
||||
addr = &netcfg.netmask;
|
||||
else if (!strcmp(name, "host_gateway"))
|
||||
addr = &netcfg.gateway;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
ret = str_to_ip(val, addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!strcmp(name, "host_netmask") &&
|
||||
(!*addr || ((~*addr + 1) & ~*addr))) {
|
||||
log_err("invalid netmask");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (*addr >> 24 == 127) {
|
||||
log_err("IP address can't be local subnet");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_runtime_kthreads(const char *name, const char *val)
|
||||
{
|
||||
long tmp;
|
||||
int ret;
|
||||
|
||||
ret = str_to_long(val, &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tmp < 1 || tmp > cpu_count - 1) {
|
||||
log_err("invalid number of kthreads requested, '%ld'", tmp);
|
||||
log_err("must be > 0 and < %d (number of CPUs)", cpu_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
maxks = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parsing Infrastructure
|
||||
*/
|
||||
|
||||
typedef int (*cfg_fn_t)(const char *name, const char *val);
|
||||
|
||||
struct cfg_handler {
|
||||
const char *name;
|
||||
cfg_fn_t fn;
|
||||
bool required;
|
||||
};
|
||||
|
||||
static const struct cfg_handler cfg_handlers[] = {
|
||||
{ "host_addr", parse_host_ip, true },
|
||||
{ "host_netmask", parse_host_ip, true },
|
||||
{ "host_gateway", parse_host_ip, true },
|
||||
{ "runtime_kthreads", parse_runtime_kthreads, true },
|
||||
};
|
||||
|
||||
/**
|
||||
* cfg_load - loads the configuration file
|
||||
* @path: a path to the configuration file
|
||||
*
|
||||
* Returns 0 if successful, otherwise fail.
|
||||
*/
|
||||
int cfg_load(const char *path)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[BUFSIZ];
|
||||
DEFINE_BITMAP(parsed, ARRAY_SIZE(cfg_handlers));
|
||||
const char *name, *val;
|
||||
int i, ret = 0, line = 0;
|
||||
|
||||
bitmap_init(parsed, ARRAY_SIZE(cfg_handlers), 0);
|
||||
|
||||
log_info("loading configuration from '%s'", path);
|
||||
|
||||
f = fopen(path, "r");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
if (buf[0] == '#' || buf[0] == '\n') {
|
||||
line++;
|
||||
continue;
|
||||
}
|
||||
name = strtok(buf, " ");
|
||||
if (!name)
|
||||
break;
|
||||
val = strtok(NULL, " ");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cfg_handlers); i++) {
|
||||
const struct cfg_handler *h = &cfg_handlers[i];
|
||||
if (!strncmp(name, h->name, BUFSIZ)) {
|
||||
ret = h->fn(name, val);
|
||||
if (ret) {
|
||||
log_err("bad config option on line %d",
|
||||
line);
|
||||
goto out;
|
||||
}
|
||||
bitmap_set(parsed, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
line++;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cfg_handlers); i++) {
|
||||
const struct cfg_handler *h = &cfg_handlers[i];
|
||||
if (h->required && !bitmap_test(parsed, i)) {
|
||||
log_err("missing required config option '%s'", h->name);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
fclose(f);
|
||||
return ret;
|
||||
}
|
|
@ -274,6 +274,7 @@ static inline struct kthread *myk(void)
|
|||
}
|
||||
|
||||
DECLARE_SPINLOCK(klock);
|
||||
extern unsigned int maxks;
|
||||
extern unsigned int nrks;
|
||||
extern struct kthread *ks[NCPU];
|
||||
|
||||
|
@ -315,12 +316,12 @@ struct net_cfg {
|
|||
uint32_t addr;
|
||||
uint32_t netmask;
|
||||
uint32_t gateway;
|
||||
uint32_t broadcast;
|
||||
uint32_t network;
|
||||
struct eth_addr mac;
|
||||
uint8_t pad[6];
|
||||
uint8_t pad[14];
|
||||
} __packed;
|
||||
|
||||
BUILD_ASSERT(sizeof(struct net_cfg) == CACHE_LINE_SIZE);
|
||||
|
||||
extern struct net_cfg netcfg;
|
||||
|
||||
extern thread_t *net_run(struct kthread *k, unsigned int budget);
|
||||
|
@ -371,6 +372,9 @@ extern int usocket_init(void);
|
|||
/* late initialization */
|
||||
extern int arp_init_late(void);
|
||||
|
||||
/* configuration loading */
|
||||
extern int cfg_load(const char *path);
|
||||
|
||||
/* runtime entry helpers */
|
||||
extern void sched_start(void) __noreturn;
|
||||
extern int thread_spawn_main(thread_fn_t fn, void *arg);
|
||||
|
|
|
@ -64,7 +64,7 @@ static int run_init_handlers(const char *phase,
|
|||
|
||||
log_debug("entering '%s' init phase", phase);
|
||||
for (i = 0; i < nr; i++) {
|
||||
log_debug("init -> %s", h[0].name);
|
||||
log_debug("init -> %s", h[i].name);
|
||||
ret = h[i].init();
|
||||
if (ret) {
|
||||
log_debug("failed, ret = %d", ret);
|
||||
|
@ -106,13 +106,13 @@ static void *pthread_entry(void *data)
|
|||
|
||||
/**
|
||||
* runtime_init - starts the runtime
|
||||
* @cfgpath: the path to the configuration file
|
||||
* @main_fn: the first function to run as a thread
|
||||
* @arg: an argument to @main_fn
|
||||
* @threads: the number of threads to use
|
||||
*
|
||||
* Does not return if successful, otherwise return < 0 if an error.
|
||||
*/
|
||||
int runtime_init(thread_fn_t main_fn, void *arg, unsigned int threads)
|
||||
int runtime_init(const char *cfgpath, thread_fn_t main_fn, void *arg)
|
||||
{
|
||||
pthread_t tid[NCPU];
|
||||
int ret, i;
|
||||
|
@ -123,13 +123,11 @@ int runtime_init(thread_fn_t main_fn, void *arg, unsigned int threads)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (threads < 1 || threads > cpu_count - 1) {
|
||||
log_err("invalid number of kthreads, requested %d, detected %d",
|
||||
threads, cpu_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = cfg_load(cfgpath);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ioqueues_init(threads);
|
||||
ret = ioqueues_init(maxks);
|
||||
if (ret) {
|
||||
log_err("couldn't connect to iokernel, ret = %d", ret);
|
||||
return ret;
|
||||
|
@ -142,7 +140,8 @@ int runtime_init(thread_fn_t main_fn, void *arg, unsigned int threads)
|
|||
|
||||
/* point of no return starts here */
|
||||
|
||||
for (i = 1; i < threads; i++) {
|
||||
log_info("spawning %d kthreads", maxks);
|
||||
for (i = 1; i < maxks; i++) {
|
||||
ret = pthread_create(&tid[i], NULL, pthread_entry, NULL);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
/* protects @ks and @nrks below */
|
||||
DEFINE_SPINLOCK(klock);
|
||||
/* the maximum number of kthreads */
|
||||
unsigned int maxks;
|
||||
/* the total number of kthreads (i.e. the size of @ks) */
|
||||
unsigned int nrks;
|
||||
/* an array of all the kthreads (for work-stealing) */
|
||||
|
@ -59,7 +61,7 @@ int kthread_init_thread(void)
|
|||
void kthread_attach(void)
|
||||
{
|
||||
spin_lock(&klock);
|
||||
assert(nrks < cpu_count - 1);
|
||||
assert(nrks < maxks);
|
||||
ks[nrks++] = mykthread;
|
||||
rcu_tlgen = rcu_gen;
|
||||
spin_unlock(&klock);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#define ARP_TABLE_CAPACITY 1024
|
||||
#define ARP_RETRIES 3
|
||||
#define ARP_RETRY_TIME ONE_SECOND
|
||||
#define ARP_REPROBE_TIME (5 * ONE_SECOND)
|
||||
#define ARP_REPROBE_TIME (10 * ONE_SECOND)
|
||||
|
||||
enum {
|
||||
/* the MAC address is being probed */
|
||||
|
@ -130,8 +130,8 @@ static void arp_send(uint16_t op, struct eth_addr dhost, uint32_t daddr)
|
|||
static void arp_age_entry(uint64_t now_us, struct arp_entry *e)
|
||||
{
|
||||
/* check if this entry has timed out */
|
||||
if (now_us - e->ts < (e->state == ARP_STATE_VALID) ?
|
||||
ARP_REPROBE_TIME : ARP_RETRY_TIME)
|
||||
if (now_us - e->ts < ((e->state == ARP_STATE_VALID) ?
|
||||
ARP_REPROBE_TIME : ARP_RETRY_TIME))
|
||||
return;
|
||||
|
||||
switch (e->state) {
|
||||
|
@ -162,11 +162,13 @@ static void arp_worker(void *arg)
|
|||
{
|
||||
struct arp_entry *e;
|
||||
struct rcu_hlist_node *node;
|
||||
uint64_t now_us = microtime();
|
||||
uint64_t now_us;
|
||||
int i;
|
||||
|
||||
/* wake up each second and update the ARP table */
|
||||
while (true) {
|
||||
now_us = microtime();
|
||||
|
||||
spin_lock(&arp_lock);
|
||||
for (i = 0; i < ARP_TABLE_CAPACITY; i++) {
|
||||
rcu_hlist_for_each(&arp_tbl[i], node, true) {
|
||||
|
|
|
@ -15,10 +15,6 @@
|
|||
/* the maximum number of packets to process per scheduler invocation */
|
||||
#define MAX_BUDGET 512
|
||||
|
||||
#define TEMP_IP_ADDR 3232235781 // 192.168.1.5
|
||||
#define TEMP_NETMASK 0xffffff00 // 255.255.255.0
|
||||
#define TEMP_GATEWAY 0
|
||||
|
||||
/* important global state */
|
||||
struct net_cfg netcfg __aligned(CACHE_LINE_SIZE);
|
||||
|
||||
|
@ -390,7 +386,7 @@ int net_tx_ip(struct mbuf *m, uint8_t proto, uint32_t daddr)
|
|||
m->txflags |= OLFLAG_IP_CHKSUM | OLFLAG_IPV4;
|
||||
|
||||
/* simple IP routing */
|
||||
if ((daddr & netcfg.netmask) != netcfg.network)
|
||||
if ((daddr & netcfg.netmask) != (netcfg.addr & netcfg.netmask))
|
||||
daddr = netcfg.gateway;
|
||||
|
||||
/* need to use ARP to resolve dhost */
|
||||
|
@ -423,6 +419,20 @@ int net_init_thread(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void net_dump_config(void)
|
||||
{
|
||||
char buf[IP_ADDR_STR_LEN];
|
||||
|
||||
log_info("net: using the following configuration:");
|
||||
log_info(" addr:\t%s", ip_addr_to_str(netcfg.addr, buf));
|
||||
log_info(" netmask:\t%s", ip_addr_to_str(netcfg.netmask, buf));
|
||||
log_info(" gateway:\t%s", ip_addr_to_str(netcfg.gateway, buf));
|
||||
log_info(" mac:\t%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
netcfg.mac.addr[0], netcfg.mac.addr[1], netcfg.mac.addr[2],
|
||||
netcfg.mac.addr[3], netcfg.mac.addr[4], netcfg.mac.addr[5]);
|
||||
}
|
||||
|
||||
/**
|
||||
* net_init - initializes the network stack
|
||||
*
|
||||
|
@ -452,12 +462,7 @@ int net_init(void)
|
|||
if (!net_tx_buf_tcache)
|
||||
return -ENOMEM;
|
||||
|
||||
netcfg.addr = TEMP_IP_ADDR;
|
||||
netcfg.netmask = TEMP_NETMASK;
|
||||
netcfg.gateway = TEMP_GATEWAY;
|
||||
netcfg.network = netcfg.addr & netcfg.netmask;
|
||||
netcfg.broadcast = netcfg.network | ~netcfg.netmask;
|
||||
|
||||
BUILD_ASSERT(sizeof(struct net_cfg) == CACHE_LINE_SIZE);
|
||||
log_info("net: started network stack");
|
||||
net_dump_config();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# an example runtime config file
|
||||
host_addr 192.168.1.5
|
||||
host_netmask 255.255.255.0
|
||||
host_gateway 192.168.1.1
|
||||
runtime_kthreads 3
|
|
@ -1,3 +1,4 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <base/stddef.h>
|
||||
#include <base/log.h>
|
||||
|
@ -43,9 +44,14 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = runtime_init(main_handler, NULL, NCORES);
|
||||
if (argc < 2) {
|
||||
printf("arg must be config file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = runtime_init(argv[1], main_handler, NULL);
|
||||
if (ret) {
|
||||
log_err("failed to start runtime");
|
||||
printf("failed to start runtime");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* test_multiple_runtimes.c - tests initialization of multiple runtimes
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <base/log.h>
|
||||
|
@ -19,12 +20,17 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
int i, pid, ret;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("arg must be config file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < N_RUNTIMES; i++) {
|
||||
pid = fork();
|
||||
BUG_ON(pid == -1);
|
||||
|
||||
if (pid == 0) {
|
||||
ret = runtime_init(main_handler, NULL, 1);
|
||||
ret = runtime_init(argv[1], main_handler, NULL);
|
||||
BUG_ON(ret < 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <base/log.h>
|
||||
#include <base/time.h>
|
||||
|
@ -38,9 +39,14 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = runtime_init(main_handler, NULL, 1);
|
||||
if (argc < 2) {
|
||||
printf("arg must be config file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = runtime_init(argv[1], main_handler, NULL);
|
||||
if (ret) {
|
||||
log_err("failed to start runtime");
|
||||
printf("failed to start runtime\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <base/stddef.h>
|
||||
#include <base/log.h>
|
||||
|
@ -6,8 +7,8 @@
|
|||
#include <runtime/thread.h>
|
||||
#include <runtime/sync.h>
|
||||
|
||||
#define N 1000000
|
||||
#define NCORES 4
|
||||
#define N 1000000
|
||||
|
||||
struct test_args {
|
||||
chan_t *chan;
|
||||
|
@ -304,9 +305,14 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = runtime_init(main_handler, NULL, NCORES);
|
||||
if (argc < 2) {
|
||||
printf("arg must be config file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = runtime_init(argv[1], main_handler, NULL);
|
||||
if (ret) {
|
||||
log_err("failed to start runtime");
|
||||
printf("failed to start runtime\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <base/stddef.h>
|
||||
#include <base/log.h>
|
||||
|
@ -139,9 +140,14 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = runtime_init(main_handler, NULL, NCORES);
|
||||
if (argc < 2) {
|
||||
printf("arg must be config file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = runtime_init(argv[1], main_handler, NULL);
|
||||
if (ret) {
|
||||
log_err("failed to start runtime");
|
||||
printf("failed to start runtime\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <base/stddef.h>
|
||||
#include <base/log.h>
|
||||
|
@ -90,9 +91,14 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = runtime_init(main_handler, NULL, NCORES);
|
||||
if (argc < 2) {
|
||||
printf("arg must be config file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = runtime_init(argv[1], main_handler, NULL);
|
||||
if (ret) {
|
||||
log_err("failed to start runtime");
|
||||
printf("failed to start runtime\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* test_runtime_thread.c - tests basic thread spawning
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <base/stddef.h>
|
||||
#include <base/log.h>
|
||||
#include <base/time.h>
|
||||
|
@ -13,8 +15,8 @@
|
|||
|
||||
static void leaf_handler(void *arg)
|
||||
{
|
||||
delay_us(1);
|
||||
waitgroup_t *wg_parent = (waitgroup_t *)arg;
|
||||
delay_us(1);
|
||||
waitgroup_done(wg_parent);
|
||||
}
|
||||
|
||||
|
@ -58,16 +60,21 @@ static void main_handler(void *arg)
|
|||
threads_per_second = (double)(NCORES * N) /
|
||||
((microtime() - start_us) * 0.000001);
|
||||
log_info("spawned %f threads / second, efficiency %f",
|
||||
threads_per_second, threads_per_second / (NCORES * 1000000));
|
||||
threads_per_second, threads_per_second / 1000000);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = runtime_init(main_handler, NULL, NCORES);
|
||||
if (argc < 2) {
|
||||
printf("arg must be config file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = runtime_init(argv[1], main_handler, NULL);
|
||||
if (ret) {
|
||||
log_err("failed to start runtime");
|
||||
printf("failed to start runtime\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* test_runtime_thread.c - tests basic thread spawning
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <base/stddef.h>
|
||||
#include <base/log.h>
|
||||
#include <base/time.h>
|
||||
|
@ -11,7 +13,6 @@
|
|||
|
||||
#define WORKERS 1000
|
||||
#define N 100000
|
||||
#define NCORES 4
|
||||
|
||||
static void work_handler(void *arg)
|
||||
{
|
||||
|
@ -44,17 +45,21 @@ static void main_handler(void *arg)
|
|||
waitgroup_wait(&wg);
|
||||
timeouts_per_second = (double)(WORKERS * N) /
|
||||
((microtime() - start_us) * 0.000001);
|
||||
log_info("handled %f timeouts / second / core",
|
||||
timeouts_per_second / NCORES);
|
||||
log_info("handled %f timeouts / second", timeouts_per_second);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = runtime_init(main_handler, NULL, NCORES);
|
||||
if (argc < 2) {
|
||||
printf("arg must be config file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = runtime_init(argv[1], main_handler, NULL);
|
||||
if (ret) {
|
||||
log_err("failed to start runtime");
|
||||
printf("failed to start runtime\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
/*
|
||||
* test_runtime_thread.c - tests basic thread spawning
|
||||
* test_udp_echo.c - echoes UDP packets
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <base/stddef.h>
|
||||
#include <base/log.h>
|
||||
|
@ -54,9 +55,14 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = runtime_init(main_handler, NULL, NCORES);
|
||||
if (argc < 2) {
|
||||
printf("arg must be config file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = runtime_init(argv[1], main_handler, NULL);
|
||||
if (ret) {
|
||||
log_err("failed to start runtime");
|
||||
printf("failed to start runtime\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue