Commit f42334ab authored by Philippe Gerum's avatar Philippe Gerum

lib/cobalt: turn environment variables into options

RT_PRINT_*_ENV variables are converted to command line base options,
with associated configuration tunables (include/cobalt/tunables.h).

RT_PRINT_BUFFER_ENV           =>    --print-buffer-size
RT_PRINT_BUFFERS_COUNT_ENV    =>    --print-buffer-count
RT_PRINT_PERIOD_ENV           =>    --print-sync-delay
parent f9227f35
......@@ -13,6 +13,7 @@ includesub_HEADERS = \
ticks.h \
time.h \
trace.h \
tunables.h \
unistd.h \
wrappers.h
......
......@@ -132,10 +132,6 @@ void cobalt_register_tsd_hook(struct cobalt_tsd_hook *th);
extern int __cobalt_control_bind;
extern int __cobalt_main_prio;
extern int __cobalt_print_bufsz;
#ifdef __cplusplus
}
#endif
......
/*
* Copyright (C) 2015 Philippe Gerum <rpm@xenomai.org>.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#ifndef _COBALT_TUNABLES_H
#define _COBALT_TUNABLES_H
#include <boilerplate/tunables.h>
#include <sys/cobalt.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int __cobalt_main_prio;
extern int __cobalt_print_bufsz;
extern int __cobalt_print_bufcount;
extern unsigned long long __cobalt_print_syncdelay;
static inline define_config_tunable(main_prio, int, prio)
{
__cobalt_main_prio = prio;
}
static inline read_config_tunable(main_prio, int)
{
return __cobalt_main_prio;
}
static inline define_config_tunable(print_buffer_size, int, size)
{
__cobalt_print_bufsz = size;
}
static inline read_config_tunable(print_buffer_size, int)
{
return __cobalt_print_bufsz;
}
static inline define_config_tunable(print_buffer_count, int, count)
{
__cobalt_print_bufcount = count;
}
static inline read_config_tunable(print_buffer_count, int)
{
return __cobalt_print_bufcount;
}
static inline define_config_tunable(print_sync_delay, unsigned long long, delay)
{
__cobalt_print_syncdelay = delay;
}
static inline read_config_tunable(print_sync_delay, unsigned long long)
{
return __cobalt_print_syncdelay;
}
#ifdef __cplusplus
}
#endif
#endif /* !_COBALT_TUNABLES_H */
......@@ -30,6 +30,7 @@
#include <boilerplate/setup.h>
#include <cobalt/uapi/kernel/heap.h>
#include <cobalt/ticks.h>
#include <cobalt/tunables.h>
#include <asm/xenomai/syscall.h>
#include <xenomai/init.h>
#include "umm.h"
......@@ -56,6 +57,21 @@ static const struct option cobalt_options[] = {
.name = "main-prio",
.has_arg = 1,
},
{
#define print_bufsz_opt 1
.name = "print-buffer-size",
.has_arg = 1,
},
{
#define print_bufcnt_opt 2
.name = "print-buffer-count",
.has_arg = 1,
},
{
#define print_syncdelay_opt 3
.name = "print-sync-delay",
.has_arg = 1,
},
{
/* sentinel */
}
......@@ -205,18 +221,61 @@ int cobalt_init(void)
ret = __RT(pthread_setschedparam(ptid, policy, &parm));
if (ret) {
early_warning("pthread_setschedparam failed");
early_warning("pthread_setschedparam failed (prio=%d)",
__cobalt_main_prio);
return ret;
}
return 0;
}
static int get_int_arg(const char *name, const char *arg,
unsigned long long *valp)
{
unsigned long long value;
char *p;
errno = 0;
value = strtoll(arg, &p, 10);
if (errno || *p) {
early_warning("invalid value for %s: %s", name, arg);
return -errno;
}
*valp = value;
return 0;
}
static int cobalt_parse_option(int optnum, const char *optarg)
{
unsigned long long value;
int ret;
switch (optnum) {
case main_prio_opt:
__cobalt_main_prio = atoi(optarg);
ret = get_int_arg("--main-prio", optarg, &value);
if (ret)
return ret;
__cobalt_main_prio = (int)value;
break;
case print_bufsz_opt:
ret = get_int_arg("--print-buffer-size", optarg, &value);
if (ret)
return ret;
__cobalt_print_bufsz = (int)value;
break;
case print_bufcnt_opt:
ret = get_int_arg("--print-buffer-count", optarg, &value);
if (ret)
return ret;
__cobalt_print_bufcount = (int)value;
break;
case print_syncdelay_opt:
ret = get_int_arg("--print-sync-delay", optarg, &value);
if (ret)
return ret;
__cobalt_print_syncdelay = value;
break;
default:
/* Paranoid, can't happen. */
......@@ -228,7 +287,10 @@ static int cobalt_parse_option(int optnum, const char *optarg)
static void cobalt_help(void)
{
fprintf(stderr, "--main-prio=<prio> set main thread priority\n");
fprintf(stderr, "--main-prio=<prio> main thread priority\n");
fprintf(stderr, "--print-buffer-size=<bytes> size of a print relay buffer (16k)\n");
fprintf(stderr, "--print-buffer-count=<num> number of print relay buffers (4)\n");
fprintf(stderr, "--print-buffer-syncdelay=<ms> max delay of output synchronization (100 ms)\n");
}
static struct setup_descriptor cobalt_interface = {
......
......@@ -28,16 +28,12 @@
#include <syslog.h>
#include <boilerplate/atomic.h>
#include <boilerplate/compiler.h>
#include <cobalt/tunables.h>
#include "current.h"
#include "internal.h"
#define RT_PRINT_BUFFER_ENV "RT_PRINT_BUFFER"
#define RT_PRINT_DEFAULT_BUFFER 16*1024
#define RT_PRINT_PERIOD_ENV "RT_PRINT_PERIOD"
#define RT_PRINT_DEFAULT_PERIOD 100 /* ms */
#define RT_PRINT_BUFFERS_COUNT_ENV "RT_PRINT_BUFFERS_COUNT"
#define RT_PRINT_DEFAULT_SYNCDELAY 100 /* ms */
#define RT_PRINT_DEFAULT_BUFFERS_COUNT 4
#define RT_PRINT_LINE_BREAK 256
......@@ -74,10 +70,14 @@ struct print_buffer {
__weak int __cobalt_print_bufsz = RT_PRINT_DEFAULT_BUFFER;
__weak int __cobalt_print_bufcount = RT_PRINT_DEFAULT_BUFFERS_COUNT;
__weak unsigned long long __cobalt_print_syncdelay = RT_PRINT_DEFAULT_SYNCDELAY;
static struct print_buffer *first_buffer;
static int buffers;
static uint32_t seq_no;
static struct timespec print_period;
static struct timespec syncdelay;
static pthread_mutex_t buffer_lock;
static pthread_cond_t printer_wakeup;
static pthread_key_t buffer_key;
......@@ -641,7 +641,7 @@ static void *printer_loop(void *arg)
pthread_mutex_unlock(&buffer_lock);
nanosleep(&print_period, NULL);
nanosleep(&syncdelay, NULL);
}
return NULL;
......@@ -688,81 +688,45 @@ void cobalt_print_init_atfork(void)
void cobalt_print_init(void)
{
const char *value_str;
unsigned long long period;
unsigned int i;
first_buffer = NULL;
seq_no = 0;
value_str = getenv(RT_PRINT_BUFFER_ENV);
if (value_str) {
errno = 0;
__cobalt_print_bufsz = strtol(value_str, NULL, 10);
if (errno || __cobalt_print_bufsz < RT_PRINT_LINE_BREAK)
early_panic("invalid %s=%s",
RT_PRINT_BUFFER_ENV, value_str);
}
period = RT_PRINT_DEFAULT_PERIOD;
value_str = getenv(RT_PRINT_PERIOD_ENV);
if (value_str) {
errno = 0;
period = strtoll(value_str, NULL, 10);
if (errno)
early_panic("invalid %s=%s",
RT_PRINT_BUFFER_ENV, value_str);
}
print_period.tv_sec = period / 1000;
print_period.tv_nsec = (period % 1000) * 1000000;
syncdelay.tv_sec = __cobalt_print_syncdelay / 1000ULL;
syncdelay.tv_nsec = (__cobalt_print_syncdelay % 1000ULL) * 1000000;
/* Fill the buffer pool */
{
unsigned buffers_count, i;
buffers_count = RT_PRINT_DEFAULT_BUFFERS_COUNT;
value_str = getenv(RT_PRINT_BUFFERS_COUNT_ENV);
if (value_str) {
errno = 0;
buffers_count = strtoul(value_str, NULL, 0);
if (errno)
early_panic("invalid %s=%s",
RT_PRINT_BUFFERS_COUNT_ENV, value_str);
}
pool_bitmap_len = (buffers_count + __WORDSIZE - 1)
/ __WORDSIZE;
if (!pool_bitmap_len)
goto done;
pool_bitmap = malloc(pool_bitmap_len * sizeof(*pool_bitmap));
if (!pool_bitmap)
early_panic("error allocating printf buffers");
pool_buf_size = sizeof(struct print_buffer) + __cobalt_print_bufsz;
pool_len = buffers_count * pool_buf_size;
pool_start = (unsigned long)malloc(pool_len);
if (!pool_start)
early_panic("error allocating printf buffers");
for (i = 0; i < buffers_count / __WORDSIZE; i++)
atomic_long_set(&pool_bitmap[i], ~0UL);
if (buffers_count % __WORDSIZE)
atomic_long_set(&pool_bitmap[i],
(1UL << (buffers_count % __WORDSIZE)) - 1);
for (i = 0; i < buffers_count; i++) {
struct print_buffer *buffer =
(struct print_buffer *)
(pool_start + i * pool_buf_size);
buffer->ring = (char *)(buffer + 1);
rt_print_init_inner(buffer, __cobalt_print_bufsz);
}
pool_bitmap_len = (__cobalt_print_bufcount+__WORDSIZE-1)/__WORDSIZE;
if (!pool_bitmap_len)
goto done;
pool_bitmap = malloc(pool_bitmap_len * sizeof(*pool_bitmap));
if (!pool_bitmap)
early_panic("error allocating print relay buffers");
pool_buf_size = sizeof(struct print_buffer) + __cobalt_print_bufsz;
pool_len = __cobalt_print_bufcount * pool_buf_size;
pool_start = (unsigned long)malloc(pool_len);
if (!pool_start)
early_panic("error allocating print relay buffers");
for (i = 0; i < __cobalt_print_bufcount / __WORDSIZE; i++)
atomic_long_set(&pool_bitmap[i], ~0UL);
if (__cobalt_print_bufcount % __WORDSIZE)
atomic_long_set(&pool_bitmap[i],
(1UL << (__cobalt_print_bufcount % __WORDSIZE)) - 1);
for (i = 0; i < __cobalt_print_bufcount; i++) {
struct print_buffer *buffer =
(struct print_buffer *)
(pool_start + i * pool_buf_size);
buffer->ring = (char *)(buffer + 1);
rt_print_init_inner(buffer, __cobalt_print_bufsz);
}
done:
done:
pthread_mutex_init(&buffer_lock, NULL);
pthread_key_create(&buffer_key, (void (*)(void*))cleanup_buffer);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment