summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
09a69f0)
The interactive completion code must be able to run a second,
independent scheduler instance for generating the possible completions.
This is currently not possible because the pre_select and post_select
list heads of the scheduler are defined globally in sched.c.
This patch moves these list heads from sched.c to struct sched. This
leaves only the global "now" variable in sched.c, but it is OK to
update this from all scheduler instances, so it can stay.
Moving the two list heads to struct sched requires that several
public functions, among them register_task(), grow an additional
parameter. The (mostly trivial) changes that update all callers to
provide the new argument make the patch rather invasive, unfortunately.
23 files changed:
}
PARA_EMERG_LOG("terminating on signal %d\n", signum);
shutdown:
}
PARA_EMERG_LOG("terminating on signal %d\n", signum);
shutdown:
t->error = -E_AFS_SIGNAL;
}
t->error = -E_AFS_SIGNAL;
}
-static void register_signal_task(void)
+static void register_signal_task(struct sched *s)
{
struct signal_task *st = &signal_task_struct;
{
struct signal_task *st = &signal_task_struct;
st->task.pre_select = signal_pre_select;
st->task.post_select = afs_signal_post_select;
sprintf(st->task.status, "signal task");
st->task.pre_select = signal_pre_select;
st->task.post_select = afs_signal_post_select;
sprintf(st->task.status, "signal task");
- register_task(&st->task);
+ register_task(s, &st->task);
}
static struct list_head afs_client_list;
}
static struct list_head afs_client_list;
ret = execute_server_command(&s->rfds);
if (ret < 0) {
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
ret = execute_server_command(&s->rfds);
if (ret < 0) {
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
return;
}
/* Check the list of connected clients. */
return;
}
/* Check the list of connected clients. */
para_list_add(&client->node, &afs_client_list);
}
para_list_add(&client->node, &afs_client_list);
}
-static void register_command_task(uint32_t cookie)
+static void register_command_task(uint32_t cookie, struct sched *s)
{
struct command_task *ct = &command_task_struct;
ct->fd = setup_command_socket_or_die();
{
struct command_task *ct = &command_task_struct;
ct->fd = setup_command_socket_or_die();
ct->task.pre_select = command_pre_select;
ct->task.post_select = command_post_select;
sprintf(ct->task.status, "afs command task");
ct->task.pre_select = command_pre_select;
ct->task.post_select = command_post_select;
sprintf(ct->task.status, "afs command task");
- register_task(&ct->task);
+ register_task(s, &ct->task);
static struct sched s;
int i, ret;
static struct sched s;
int i, ret;
- register_signal_task();
+ register_signal_task(&s);
INIT_LIST_HEAD(&afs_client_list);
for (i = 0; i < NUM_AFS_TABLES; i++)
afs_tables[i].init(&afs_tables[i]);
INIT_LIST_HEAD(&afs_client_list);
for (i = 0; i < NUM_AFS_TABLES; i++)
afs_tables[i].init(&afs_tables[i]);
PARA_INFO_LOG("server_socket: %d, afs_socket_cookie: %u\n",
server_socket, (unsigned) cookie);
init_admissible_files(conf.afs_initial_mode_arg);
PARA_INFO_LOG("server_socket: %d, afs_socket_cookie: %u\n",
server_socket, (unsigned) cookie);
init_admissible_files(conf.afs_initial_mode_arg);
- register_command_task(cookie);
+ register_command_task(cookie, &s);
s.default_timeout.tv_sec = 0;
s.default_timeout.tv_usec = 999 * 1000;
ret = schedule(&s);
s.default_timeout.tv_sec = 0;
s.default_timeout.tv_usec = 999 * 1000;
ret = schedule(&s);
VSS_STATUS_FLAG_PLAYING = 2,
};
VSS_STATUS_FLAG_PLAYING = 2,
};
+struct sched sched = {.max_fileno = 0};
+
/**
* The task for obtaining para_server's status (para_client stat).
*
/**
* The task for obtaining para_server's status (para_client stat).
*
.handler = f->execute, .context = fn));
f->open(fn);
.handler = f->execute, .context = fn));
f->open(fn);
- register_task(&fn->task);
+ register_task(&sched, &fn->task);
parent = fn->btrn;
PARA_NOTICE_LOG("%s filter %d/%d (%s) started in slot %d\n",
audio_formats[s->format], i, nf, f->name, (int)(s - slot));
parent = fn->btrn;
PARA_NOTICE_LOG("%s filter %d/%d (%s) started in slot %d\n",
audio_formats[s->format], i, nf, f->name, (int)(s - slot));
wn = s->wns + i;
wn->conf = a->writer_conf[i];
wn->writer_num = a->writer_nums[i];
wn = s->wns + i;
wn->conf = a->writer_conf[i];
wn->writer_num = a->writer_nums[i];
- register_writer_node(wn, parent);
+ register_writer_node(wn, parent, &sched);
rn->task.pre_select = r->pre_select;
rn->task.post_select = r->post_select;
sprintf(rn->task.status, "%s receiver node", r->name);
rn->task.pre_select = r->pre_select;
rn->task.post_select = r->post_select;
sprintf(rn->task.status, "%s receiver node", r->name);
- register_task(&rn->task);
+ register_task(&sched, &rn->task);
if (a->num_filters)
open_filters(sl);
open_writers(sl);
if (a->num_filters)
open_filters(sl);
open_writers(sl);
- activate_grab_clients();
+ activate_grab_clients(&sched);
btr_log_tree(sl->receiver_node->btrn, LL_NOTICE);
}
btr_log_tree(sl->receiver_node->btrn, LL_NOTICE);
}
}
/* restart the client task if necessary */
}
/* restart the client task if necessary */
-static void status_post_select(__a_unused struct sched *s, struct task *t)
+static void status_post_select(struct sched *s, struct task *t)
{
struct status_task *st = container_of(t, struct status_task, task);
{
struct status_task *st = container_of(t, struct status_task, task);
int argc = 5;
PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count);
st->clock_diff_count--;
int argc = 5;
PARA_INFO_LOG("clock diff count: %d\n", st->clock_diff_count);
st->clock_diff_count--;
- client_open(argc, argv, &st->ct, NULL, NULL, st->btrn);
+ client_open(argc, argv, &st->ct, NULL, NULL, st->btrn, s);
set_stat_task_restart_barrier(2);
} else {
char *argv[] = {"audiod", "--", "stat", "-p", NULL};
int argc = 4;
set_stat_task_restart_barrier(2);
} else {
char *argv[] = {"audiod", "--", "stat", "-p", NULL};
int argc = 4;
- client_open(argc, argv, &st->ct, NULL, NULL, st->btrn);
+ client_open(argc, argv, &st->ct, NULL, NULL, st->btrn, s);
set_stat_task_restart_barrier(5);
}
free(stat_item_values[SI_BASENAME]);
set_stat_task_restart_barrier(5);
}
free(stat_item_values[SI_BASENAME]);
int main(int argc, char *argv[])
{
int ret, i;
int main(int argc, char *argv[])
{
int ret, i;
struct command_task command_task_struct, *cmd_task = &command_task_struct;
struct audiod_cmdline_parser_params params = {
.override = 0,
struct command_task command_task_struct, *cmd_task = &command_task_struct;
struct audiod_cmdline_parser_params params = {
.override = 0,
if (conf.daemon_given)
daemonize(false /* parent exits immediately */);
if (conf.daemon_given)
daemonize(false /* parent exits immediately */);
- register_task(&sig_task->task);
- register_task(&cmd_task->task);
- register_task(&stat_task->task);
- s.default_timeout.tv_sec = 2;
- s.default_timeout.tv_usec = 999 * 1000;
- ret = schedule(&s);
+ register_task(&sched, &sig_task->task);
+ register_task(&sched, &cmd_task->task);
+ register_task(&sched, &stat_task->task);
+ sched.default_timeout.tv_sec = 2;
+ sched.default_timeout.tv_usec = 999 * 1000;
+ ret = schedule(&sched);
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
return EXIT_FAILURE;
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
return EXIT_FAILURE;
#include "fd.h"
#include "audiod_command_list.h"
#include "fd.h"
#include "audiod_command_list.h"
+extern struct sched sched;
extern char *stat_item_values[NUM_STAT_ITEMS];
/** Iterate over the array of all audiod commands. */
extern char *stat_item_values[NUM_STAT_ITEMS];
/** Iterate over the array of all audiod commands. */
int com_tasks(int fd, __a_unused int argc, __a_unused char **argv)
{
int com_tasks(int fd, __a_unused int argc, __a_unused char **argv)
{
- char *tl = get_task_list();
+ char *tl = get_task_list(&sched);
int ret = 1;
if (tl)
ret = client_write(fd, tl);
int ret = 1;
if (tl)
ret = client_write(fd, tl);
int com_grab(int fd, int argc, char **argv)
{
int com_grab(int fd, int argc, char **argv)
{
- return grab_client_new(fd, argc, argv);
+ return grab_client_new(fd, argc, argv, &sched);
}
__noreturn int com_term(int fd, __a_unused int argc, __a_unused char **argv)
}
__noreturn int com_term(int fd, __a_unused int argc, __a_unused char **argv)
+static struct sched sched;
static struct client_task *ct;
static struct stdin_task sit;
static struct stdout_task sot;
static struct client_task *ct;
static struct stdin_task sit;
static struct stdout_task sot;
-static void supervisor_post_select(__a_unused struct sched *s, struct task *t)
+static void supervisor_post_select(struct sched *s, struct task *t)
{
if (ct->task.error < 0) {
t->error = ct->task.error;
{
if (ct->task.error < 0) {
t->error = ct->task.error;
}
if (ct->status == CL_SENDING) {
stdin_set_defaults(&sit);
}
if (ct->status == CL_SENDING) {
stdin_set_defaults(&sit);
- register_task(&sit.task);
+ register_task(s, &sit.task);
t->error = -E_TASK_STARTED;
return;
}
if (ct->status == CL_RECEIVING) {
stdout_set_defaults(&sot);
t->error = -E_TASK_STARTED;
return;
}
if (ct->status == CL_RECEIVING) {
stdout_set_defaults(&sot);
- register_task(&sot.task);
+ register_task(s, &sot.task);
t->error = -E_TASK_STARTED;
return;
}
t->error = -E_TASK_STARTED;
return;
}
init_random_seed_or_die();
s.default_timeout.tv_sec = 1;
s.default_timeout.tv_usec = 0;
init_random_seed_or_die();
s.default_timeout.tv_sec = 1;
s.default_timeout.tv_usec = 0;
/*
* We add buffer tree nodes for stdin and stdout even though
* only one of them will be needed. This simplifies the code
/*
* We add buffer tree nodes for stdin and stdout even though
* only one of them will be needed. This simplifies the code
*/
sit.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdin"));
*/
sit.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdin"));
- ret = client_open(argc, argv, &ct, &client_loglevel, sit.btrn, NULL);
+ ret = client_open(argc, argv, &ct, &client_loglevel, sit.btrn, NULL, &sched);
if (ret < 0)
goto out;
sot.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdout", .parent = ct->btrn));
if (ret < 0)
goto out;
sot.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdout", .parent = ct->btrn));
- register_task(&svt);
- ret = schedule(&s);
+ register_task(&sched, &svt);
+ ret = schedule(&sched);
out:
client_close(ct);
btr_free_node(sit.btrn);
out:
client_close(ct);
btr_free_node(sit.btrn);
void client_close(struct client_task *ct);
int client_open(int argc, char *argv[], struct client_task **ct_ptr,
void client_close(struct client_task *ct);
int client_open(int argc, char *argv[], struct client_task **ct_ptr,
- int *loglevel, struct btr_node *parent, struct btr_node *child);
+ int *loglevel, struct btr_node *parent, struct btr_node *child,
+ struct sched *sched);
}
/* connect to para_server and register the client task */
}
/* connect to para_server and register the client task */
-static int client_connect(struct client_task *ct)
+static int client_connect(struct sched *s, struct client_task *ct)
ct->task.pre_select = client_pre_select;
ct->task.post_select = client_post_select;
sprintf(ct->task.status, "client");
ct->task.pre_select = client_pre_select;
ct->task.post_select = client_post_select;
sprintf(ct->task.status, "client");
- register_task(&ct->task);
+ register_task(s, &ct->task);
return 1;
err_out:
close(ct->scc.fd);
return 1;
err_out:
close(ct->scc.fd);
* \param loglevel If not \p NULL, the number of the loglevel is stored here.
* \param parent Add the new buffer tree node as a child of this node.
* \param child Add the new buffer tree node as a parent of this node.
* \param loglevel If not \p NULL, the number of the loglevel is stored here.
* \param parent Add the new buffer tree node as a child of this node.
* \param child Add the new buffer tree node as a parent of this node.
+ * \param sched The scheduler instance to register the task to.
*
* Check the command line options given by \a argc and argv, set default values
* for user name and rsa key file, read further option from the config file.
*
* Check the command line options given by \a argc and argv, set default values
* for user name and rsa key file, read further option from the config file.
* \return Standard.
*/
int client_open(int argc, char *argv[], struct client_task **ct_ptr,
* \return Standard.
*/
int client_open(int argc, char *argv[], struct client_task **ct_ptr,
- int *loglevel, struct btr_node *parent, struct btr_node *child)
+ int *loglevel, struct btr_node *parent, struct btr_node *child,
+ struct sched *sched)
{
char *home = para_homedir();
int ret;
{
char *home = para_homedir();
int ret;
PARA_INFO_LOG("key_file: %s\n", ct->key_file);
PARA_NOTICE_LOG("connecting %s:%d\n", ct->conf.hostname_arg,
ct->conf.server_port_arg);
PARA_INFO_LOG("key_file: %s\n", ct->key_file);
PARA_NOTICE_LOG("connecting %s:%d\n", ct->conf.hostname_arg,
ct->conf.server_port_arg);
- ret = client_connect(ct);
+ ret = client_connect(sched, ct);
out:
free(home);
if (ret < 0) {
out:
free(home);
if (ret < 0) {
#include "server.h"
#include "list.h"
#include "send.h"
#include "server.h"
#include "list.h"
#include "send.h"
#include "vss.h"
#include "net.h"
#include "daemon.h"
#include "vss.h"
#include "net.h"
#include "daemon.h"
#include "user_list.h"
#include "server_command_list.h"
#include "afs_command_list.h"
#include "user_list.h"
#include "server_command_list.h"
#include "afs_command_list.h"
#include "signal.h"
#include "version.h"
#include "signal.h"
#include "version.h"
#include "net.h"
#include "list.h"
#include "send.h"
#include "net.h"
#include "list.h"
#include "send.h"
#include "vss.h"
#include "fd.h"
#include "close_on_fork.h"
#include "vss.h"
#include "fd.h"
#include "close_on_fork.h"
sit->btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdin"));
stdin_set_defaults(sit);
sit->btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdin"));
stdin_set_defaults(sit);
- register_task(&sit->task);
+ register_task(&s, &sit->task);
fns = para_malloc(conf.filter_given * sizeof(*fns));
for (i = 0, parent = sit->btrn; i < conf.filter_given; i++) {
fns = para_malloc(conf.filter_given * sizeof(*fns));
for (i = 0, parent = sit->btrn; i < conf.filter_given; i++) {
fn->task.pre_select = f->pre_select;
fn->task.post_select = f->post_select;
f->open(fn);
fn->task.pre_select = f->pre_select;
fn->task.post_select = f->post_select;
f->open(fn);
- register_task(&fn->task);
+ register_task(&s, &fn->task);
parent = fn->btrn;
}
sot->btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdout", .parent = parent));
stdout_set_defaults(sot);
parent = fn->btrn;
}
sot->btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdout", .parent = parent));
stdout_set_defaults(sot);
- register_task(&sot->task);
+ register_task(&s, &sot->task);
s.default_timeout.tv_sec = 1;
s.default_timeout.tv_usec = 0;
s.default_timeout.tv_sec = 1;
s.default_timeout.tv_usec = 0;
*
* \param gc The grab client to activate.
*/
*
* \param gc The grab client to activate.
*/
-static void gc_activate(struct grab_client *gc)
+static void gc_activate(struct grab_client *gc, struct sched *s)
{
struct btr_node *root = audiod_get_btr_root(), *parent;
char *name = gc->name? gc->name : "grab";
{
struct btr_node *root = audiod_get_btr_root(), *parent;
char *name = gc->name? gc->name : "grab";
snprintf(gc->task.status, sizeof(gc->task.status) - 1, "%s", name);
gc->task.status[sizeof(gc->task.status) - 1] = '\0';
gc->task.error = 0;
snprintf(gc->task.status, sizeof(gc->task.status) - 1, "%s", name);
gc->task.status[sizeof(gc->task.status) - 1] = '\0';
gc->task.error = 0;
- register_task(&gc->task);
+ register_task(s, &gc->task);
* This function also garbage collects all grab clients whose tasks have been
* unscheduled.
*/
* This function also garbage collects all grab clients whose tasks have been
* unscheduled.
*/
-void activate_grab_clients(void)
+void activate_grab_clients(struct sched *s)
{
struct grab_client *gc, *tmp;
{
struct grab_client *gc, *tmp;
* \param fd The file descriptor of the client.
* \param argc Argument count.
* \param argv Argument vector.
* \param fd The file descriptor of the client.
* \param argc Argument count.
* \param argv Argument vector.
+ * \param s The scheduler to register the grab client task to.
*
* If the command line options given by \a argc and \a argv are valid.
* allocate a struct grab_client and initialize it with this valid
*
* If the command line options given by \a argc and \a argv are valid.
* allocate a struct grab_client and initialize it with this valid
-int grab_client_new(int fd, int argc, char **argv)
+int grab_client_new(int fd, int argc, char **argv, struct sched *s)
{
int ret;
struct grab_client *gc = para_calloc(sizeof(struct grab_client));
{
int ret;
struct grab_client *gc = para_calloc(sizeof(struct grab_client));
goto err_out;
gc->fd = fd;
para_list_add(&gc->node, &inactive_grab_client_list);
goto err_out;
gc->fd = fd;
para_list_add(&gc->node, &inactive_grab_client_list);
return 1;
err_out:
free(gc);
return 1;
err_out:
free(gc);
/** \file grab_client.h exported symbols from grab_client.c */
/** \file grab_client.h exported symbols from grab_client.c */
-int grab_client_new(int fd, int argc, char **argv);
-void activate_grab_clients(void);
+int grab_client_new(int fd, int argc, char **argv, struct sched *s);
+void activate_grab_clients(struct sched *s);
#include "http.h"
#include "list.h"
#include "send.h"
#include "http.h"
#include "list.h"
#include "send.h"
#include "vss.h"
#include "close_on_fork.h"
#include "net.h"
#include "vss.h"
#include "close_on_fork.h"
#include "net.h"
sot.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.parent = rn.btrn, .name = "stdout"));
stdout_set_defaults(&sot);
sot.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.parent = rn.btrn, .name = "stdout"));
stdout_set_defaults(&sot);
- register_task(&sot.task);
+ register_task(&s, &sot.task);
rn.task.pre_select = r->pre_select;
rn.task.post_select = r->post_select;
sprintf(rn.task.status, "%s", r->name);
rn.task.pre_select = r->pre_select;
rn.task.post_select = r->post_select;
sprintf(rn.task.status, "%s", r->name);
- register_task(&rn.task);
+ register_task(&s, &rn.task);
#include "time.h"
#include "error.h"
#include "time.h"
#include "error.h"
-static struct list_head pre_select_list, post_select_list;
-static int initialized;
-
static struct timeval now_struct;
struct timeval *now = &now_struct;
static struct timeval now_struct;
struct timeval *now = &now_struct;
*/
static void unregister_task(struct task *t)
{
*/
static void unregister_task(struct task *t)
{
- if (!initialized)
- return;
assert(t->error < 0);
PARA_INFO_LOG("unregistering %s (%s)\n", t->status,
para_strerror(-t->error));
assert(t->error < 0);
PARA_INFO_LOG("unregistering %s (%s)\n", t->status,
para_strerror(-t->error));
static void sched_preselect(struct sched *s)
{
struct task *t, *tmp;
static void sched_preselect(struct sched *s)
{
struct task *t, *tmp;
- list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) {
+ list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
if (t->error < 0) {
unregister_task(t);
continue;
if (t->error < 0) {
unregister_task(t);
continue;
- list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) {
+ list_for_each_entry_safe(t, tmp, &s->post_select_list, post_select_node) {
if (t->error >= 0)
call_post_select(s, t);
// PARA_INFO_LOG("%s: %d\n", t->status, t->ret);
if (t->error >= 0)
call_post_select(s, t);
// PARA_INFO_LOG("%s: %d\n", t->status, t->ret);
* this case t has been unregistered already, so we must not
* unregister it again.
*/
* this case t has been unregistered already, so we must not
* unregister it again.
*/
- if (list_empty(&post_select_list))
+ if (list_empty(&s->post_select_list))
return;
unregister_task(t);
}
return;
unregister_task(t);
}
- if (!initialized)
- return -E_NOT_INITIALIZED;
if (!s->select_function)
s->select_function = para_select;
again:
if (!s->select_function)
s->select_function = para_select;
again:
s->max_fileno = -1;
gettimeofday(now, NULL);
sched_preselect(s);
s->max_fileno = -1;
gettimeofday(now, NULL);
sched_preselect(s);
- if (list_empty(&pre_select_list) && list_empty(&post_select_list))
+ if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
return 0;
if (!timeout_is_zero(s)) {
ret = s->select_function(s->max_fileno + 1, &s->rfds, &s->wfds,
return 0;
if (!timeout_is_zero(s)) {
ret = s->select_function(s->max_fileno + 1, &s->rfds, &s->wfds,
FD_ZERO(&s->wfds);
}
sched_post_select(s);
FD_ZERO(&s->wfds);
}
sched_post_select(s);
- if (list_empty(&pre_select_list) && list_empty(&post_select_list))
+ if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
-/*
- * Initialize the paraslash scheduler.
- */
-static void init_sched(void)
-{
- PARA_INFO_LOG("initializing scheduler\n");
- INIT_LIST_HEAD(&pre_select_list);
- INIT_LIST_HEAD(&post_select_list);
- initialized = 1;
-}
-
/**
* Add a task to the scheduler.
*
/**
* Add a task to the scheduler.
*
- * \param t the task to add
+ * \param t The task to add.
+ * \param s The scheduler instance to add the task to.
*
* If the pre_select pointer of \a t is not \p NULL, it is added to
* the pre_select list of the scheduler. Same goes for post_select.
*
* \sa task::pre_select, task::post_select
*/
*
* If the pre_select pointer of \a t is not \p NULL, it is added to
* the pre_select list of the scheduler. Same goes for post_select.
*
* \sa task::pre_select, task::post_select
*/
-void register_task(struct task *t)
+void register_task(struct sched *s, struct task *t)
- if (!initialized)
- init_sched();
PARA_INFO_LOG("registering %s (%p)\n", t->status, t);
PARA_INFO_LOG("registering %s (%p)\n", t->status, t);
+ if (!s->pre_select_list.next)
+ INIT_LIST_HEAD(&s->pre_select_list);
+ if (!s->post_select_list.next)
+ INIT_LIST_HEAD(&s->post_select_list);
if (t->pre_select) {
PARA_DEBUG_LOG("pre_select: %p\n", &t->pre_select);
if (t->pre_select) {
PARA_DEBUG_LOG("pre_select: %p\n", &t->pre_select);
- list_add_tail(&t->pre_select_node, &pre_select_list);
+ list_add_tail(&t->pre_select_node, &s->pre_select_list);
}
if (t->post_select) {
PARA_DEBUG_LOG("post_select: %p\n", &t->post_select);
}
if (t->post_select) {
PARA_DEBUG_LOG("post_select: %p\n", &t->post_select);
- list_add_tail(&t->post_select_node, &post_select_list);
+ list_add_tail(&t->post_select_node, &s->post_select_list);
* \a pre_select_list and the \a post_select_list are empty. This function
* must be called from the post_select (rather than the pre_select) method.
*/
* \a pre_select_list and the \a post_select_list are empty. This function
* must be called from the post_select (rather than the pre_select) method.
*/
-void sched_shutdown(void)
+void sched_shutdown(struct sched *s)
- if (!initialized)
- return;
- list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) {
+ list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
t->error = -E_SCHED_SHUTDOWN;
unregister_task(t);
}
t->error = -E_SCHED_SHUTDOWN;
unregister_task(t);
}
- list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) {
+ list_for_each_entry_safe(t, tmp, &s->post_select_list, post_select_node) {
t->error = -E_SCHED_SHUTDOWN;
unregister_task(t);
}
t->error = -E_SCHED_SHUTDOWN;
unregister_task(t);
}
* Each entry of the list contains an identifier which is simply a hex number.
* The result is dynamically allocated and must be freed by the caller.
*/
* Each entry of the list contains an identifier which is simply a hex number.
* The result is dynamically allocated and must be freed by the caller.
*/
-char *get_task_list(void)
+char *get_task_list(struct sched *s)
{
struct task *t, *tmp;
char *msg = NULL;
{
struct task *t, *tmp;
char *msg = NULL;
- if (!initialized)
- return NULL;
- list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) {
+ list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
char *tmp_msg;
tmp_msg = make_message("%s%p\tpre\t%s\n", msg? msg : "", t, t->status);
free(msg);
msg = tmp_msg;
}
char *tmp_msg;
tmp_msg = make_message("%s%p\tpre\t%s\n", msg? msg : "", t, t->status);
free(msg);
msg = tmp_msg;
}
- list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) {
+ list_for_each_entry_safe(t, tmp, &s->post_select_list, post_select_node) {
char *tmp_msg;
// if (t->pre_select)
// continue;
char *tmp_msg;
// if (t->pre_select)
// continue;
int max_fileno;
/** If non-NULL, use this function instead of para_select. */
int (*select_function)(int, fd_set *, fd_set *, struct timeval *);
int max_fileno;
/** If non-NULL, use this function instead of para_select. */
int (*select_function)(int, fd_set *, fd_set *, struct timeval *);
+ /** Currently active pre_select functions. */
+ struct list_head pre_select_list;
+ /** Currently active post_select functions. */
+ struct list_head post_select_list;
*/
extern struct timeval *now;
*/
extern struct timeval *now;
-void register_task(struct task *t);
+void register_task(struct sched *s, struct task *t);
int schedule(struct sched *s);
int schedule(struct sched *s);
-char *get_task_list(void);
-void sched_shutdown(void);
+char *get_task_list(struct sched *s);
+void sched_shutdown(struct sched *s);
void sched_min_delay(struct sched *s);
void sched_request_timeout(struct timeval *to, struct sched *s);
void sched_request_timeout_ms(long unsigned ms, struct sched *s);
void sched_min_delay(struct sched *s);
void sched_request_timeout(struct timeval *to, struct sched *s);
void sched_request_timeout_ms(long unsigned ms, struct sched *s);
#include "send.h"
#include "close_on_fork.h"
#include "chunk_queue.h"
#include "send.h"
#include "close_on_fork.h"
#include "chunk_queue.h"
#include "vss.h"
/** Clients will be kicked if there are more than that many bytes pending. */
#include "vss.h"
/** Clients will be kicked if there are more than that many bytes pending. */
#include "server.h"
#include "list.h"
#include "send.h"
#include "server.h"
#include "list.h"
#include "send.h"
#include "vss.h"
#include "config.h"
#include "close_on_fork.h"
#include "vss.h"
#include "config.h"
#include "close_on_fork.h"
#include "daemon.h"
#include "ipc.h"
#include "fd.h"
#include "daemon.h"
#include "ipc.h"
#include "fd.h"
#include "signal.h"
#include "user_list.h"
#include "color.h"
#include "signal.h"
#include "user_list.h"
#include "color.h"
/** The file containing user information (public key, permissions). */
static char *user_list_file = NULL;
/** The file containing user information (public key, permissions). */
static char *user_list_file = NULL;
+static struct sched sched;
/** The task responsible for server command handling. */
struct server_command_task {
/** The task responsible for server command handling. */
struct server_command_task {
para_install_sighandler(SIGCHLD);
para_sigaction(SIGPIPE, SIG_IGN);
add_close_on_fork_list(st->fd);
para_install_sighandler(SIGCHLD);
para_sigaction(SIGPIPE, SIG_IGN);
add_close_on_fork_list(st->fd);
- register_task(&st->task);
+ register_task(&sched, &st->task);
}
static void command_pre_select(struct sched *s, struct task *t)
}
static void command_pre_select(struct sched *s, struct task *t)
goto err;
add_close_on_fork_list(sct->listen_fd); /* child doesn't need the listener */
sprintf(sct->task.status, "server command task");
goto err;
add_close_on_fork_list(sct->listen_fd); /* child doesn't need the listener */
sprintf(sct->task.status, "server command task");
- register_task(&sct->task);
+ register_task(&sched, &sct->task);
return;
err:
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
return;
err:
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
init_signal_task();
para_unblock_signal(SIGCHLD);
PARA_NOTICE_LOG("initializing virtual streaming system\n");
init_signal_task();
para_unblock_signal(SIGCHLD);
PARA_NOTICE_LOG("initializing virtual streaming system\n");
- init_vss_task(afs_socket);
+ init_vss_task(afs_socket, &sched);
init_server_command_task(argc, argv);
if (conf.daemon_given)
kill(getppid(), SIGTERM);
init_server_command_task(argc, argv);
if (conf.daemon_given)
kill(getppid(), SIGTERM);
int main(int argc, char *argv[])
{
int ret;
int main(int argc, char *argv[])
{
int ret;
- static struct sched s = {
- .default_timeout = {
- .tv_sec = 1,
- .tv_usec = 0
- },
- .select_function = server_select
- };
+
+ sched.default_timeout.tv_sec = 1;
+ sched.select_function = server_select;
+
server_init(argc, argv);
mutex_lock(mmd_mutex);
server_init(argc, argv);
mutex_lock(mmd_mutex);
+ ret = schedule(&sched);
if (ret < 0) {
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
exit(EXIT_FAILURE);
if (ret < 0) {
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
exit(EXIT_FAILURE);
#include "server.h"
#include "list.h"
#include "send.h"
#include "server.h"
#include "list.h"
#include "send.h"
#include "vss.h"
#include "portable_io.h"
#include "net.h"
#include "fd.h"
#include "vss.h"
#include "portable_io.h"
#include "net.h"
#include "fd.h"
#include "close_on_fork.h"
/**
#include "close_on_fork.h"
/**
#include "server.cmdline.h"
#include "list.h"
#include "send.h"
#include "server.cmdline.h"
#include "list.h"
#include "send.h"
#include "vss.h"
#include "ipc.h"
#include "fd.h"
#include "vss.h"
#include "ipc.h"
#include "fd.h"
extern struct misc_meta_data *mmd;
extern struct misc_meta_data *mmd;
* Initialize the virtual streaming system task.
*
* \param afs_socket The fd for communication with afs.
* Initialize the virtual streaming system task.
*
* \param afs_socket The fd for communication with afs.
+ * \param s The scheduler to register the vss task to.
*
* This also initializes all supported senders and starts streaming
* if the --autoplay command line flag was given.
*/
*
* This also initializes all supported senders and starts streaming
* if the --autoplay command line flag was given.
*/
-void init_vss_task(int afs_socket)
+void init_vss_task(int afs_socket, struct sched *s)
{
static struct vss_task vss_task_struct, *vsst = &vss_task_struct;
int i;
{
static struct vss_task vss_task_struct, *vsst = &vss_task_struct;
int i;
&vsst->data_send_barrier);
}
sprintf(vsst->task.status, "vss task");
&vsst->data_send_barrier);
}
sprintf(vsst->task.status, "vss task");
- register_task(&vsst->task);
+ register_task(s, &vsst->task);
/** \file vss.h Exported functions from vss.c (para_server). */
/** \file vss.h Exported functions from vss.c (para_server). */
-void init_vss_task(int afs_socket);
+void init_vss_task(int afs_socket, struct sched *s);
unsigned int vss_playing(void);
unsigned int vss_next(void);
unsigned int vss_repos(void);
unsigned int vss_playing(void);
unsigned int vss_next(void);
unsigned int vss_repos(void);
* \return Standard.
*/
static void setup_writer_node(const char *arg, struct btr_node *parent,
* \return Standard.
*/
static void setup_writer_node(const char *arg, struct btr_node *parent,
- struct writer_node *wn)
+ struct writer_node *wn, struct sched *s)
{
if (arg)
wn->conf = check_writer_arg_or_die(arg, &wn->writer_num);
{
if (arg)
wn->conf = check_writer_arg_or_die(arg, &wn->writer_num);
wn->writer_num = DEFAULT_WRITER;
wn->conf = writers[DEFAULT_WRITER].parse_config_or_die("");
}
wn->writer_num = DEFAULT_WRITER;
wn->conf = writers[DEFAULT_WRITER].parse_config_or_die("");
}
- register_writer_node(wn, parent);
+ register_writer_node(wn, parent, s);
}
static int setup_and_schedule(void)
}
static int setup_and_schedule(void)
sit.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdin"));
stdin_set_defaults(&sit);
sit.btrn = btr_new_node(&(struct btr_node_description)
EMBRACE(.name = "stdin"));
stdin_set_defaults(&sit);
- register_task(&sit.task);
+ register_task(&s, &sit.task);
cwt->state = CWS_NEED_HEADER;
cwt->min_iqs = WAV_HEADER_LEN;
cwt->state = CWS_NEED_HEADER;
cwt->min_iqs = WAV_HEADER_LEN;
cwt->task.pre_select = check_wav_pre_select;
cwt->task.post_select = check_wav_post_select;
cwt->task.error = 0;
cwt->task.pre_select = check_wav_pre_select;
cwt->task.post_select = check_wav_post_select;
cwt->task.error = 0;
- register_task(&cwt->task);
+ register_task(&s, &cwt->task);
if (!conf.writer_given) {
wns = para_calloc(sizeof(*wns));
if (!conf.writer_given) {
wns = para_calloc(sizeof(*wns));
- setup_writer_node(NULL, cwt->btrn, wns);
+ setup_writer_node(NULL, cwt->btrn, wns, &s);
i = 1;
} else {
wns = para_calloc(conf.writer_given * sizeof(*wns));
for (i = 0; i < conf.writer_given; i++)
setup_writer_node(conf.writer_arg[i], cwt->btrn,
i = 1;
} else {
wns = para_calloc(conf.writer_given * sizeof(*wns));
for (i = 0; i < conf.writer_given; i++)
setup_writer_node(conf.writer_arg[i], cwt->btrn,
}
s.default_timeout.tv_sec = 10;
}
s.default_timeout.tv_sec = 10;
*
* \param wn The writer node to open.
* \param parent The parent btr node (the source for the writer node).
*
* \param wn The writer node to open.
* \param parent The parent btr node (the source for the writer node).
+ * \param s The scheduler instance to register the task to.
*
* The configuration of the writer node stored in \p wn->conf must be
* initialized before this function may be called.
*/
*
* The configuration of the writer node stored in \p wn->conf must be
* initialized before this function may be called.
*/
-void register_writer_node(struct writer_node *wn, struct btr_node *parent)
+void register_writer_node(struct writer_node *wn, struct btr_node *parent,
+ struct sched *s)
{
struct writer *w = writers + wn->writer_num;
char *name = make_message("%s writer", writer_names[wn->writer_num]);
{
struct writer *w = writers + wn->writer_num;
char *name = make_message("%s writer", writer_names[wn->writer_num]);
free(name);
wn->task.post_select = w->post_select;
wn->task.pre_select = w->pre_select;
free(name);
wn->task.post_select = w->post_select;
wn->task.pre_select = w->pre_select;
- register_task(&wn->task);
+ register_task(s, &wn->task);
void writer_init(void);
void *check_writer_arg_or_die(const char *wa, int *writer_num);
void print_writer_helps(int detailed);
void writer_init(void);
void *check_writer_arg_or_die(const char *wa, int *writer_num);
void print_writer_helps(int detailed);
-void register_writer_node(struct writer_node *wn, struct btr_node *parent);
+void register_writer_node(struct writer_node *wn, struct btr_node *parent,
+ struct sched *s);
void get_btr_sample_rate(struct btr_node *btrn, int32_t *result);
void get_btr_channels(struct btr_node *btrn, int32_t *result);
void get_btr_sample_format(struct btr_node *btrn, int32_t *result);
void get_btr_sample_rate(struct btr_node *btrn, int32_t *result);
void get_btr_channels(struct btr_node *btrn, int32_t *result);
void get_btr_sample_format(struct btr_node *btrn, int32_t *result);