mars/kernel/brick.h

724 lines
22 KiB
C
Raw Normal View History

2014-11-21 10:51:34 +00:00
/*
* MARS Long Distance Replication Software
*
* This file is part of MARS project: http://schoebel.github.io/mars/
*
* Copyright (C) 2010-2014 Thomas Schoebel-Theuer
* Copyright (C) 2011-2014 1&1 Internet AG
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
2010-07-23 11:55:18 +00:00
#ifndef BRICK_H
#define BRICK_H
2011-02-23 20:48:06 +00:00
#include <linux/list.h>
2010-07-30 05:46:22 +00:00
#include <linux/sched.h>
2011-02-23 20:48:06 +00:00
#include <linux/wait.h>
#include <linux/kthread.h>
2010-07-30 05:46:22 +00:00
2011-04-15 10:13:22 +00:00
#include <asm/atomic.h>
/* Adapt to 3f07c0144132e4f59d88055ac8ff3e691a5fa2b8
* and following commits.
*/
#ifndef SIGNAL_STOP_STOPPED
#include <linux/sched/signal.h>
#endif
2013-07-10 06:30:35 +00:00
#ifndef CONFIG_MARS_MODULE
// when unsure, include faked config file
#include "mars_config.h"
2013-07-10 06:30:35 +00:00
#endif
#include "brick_locks.h"
2011-07-20 13:11:44 +00:00
#include "meta.h"
2011-08-31 11:42:04 +00:00
#define MAX_BRICK_TYPES 64
#define brick_msleep(msecs) _brick_msleep(msecs, false)
extern int _brick_msleep(int msecs, bool shorten);
2020-06-12 07:46:58 +00:00
#define brick_yield() cond_resched()
2012-12-14 11:44:54 +00:00
/////////////////////////////////////////////////////////////////////////
// printk() replacements
2011-08-31 11:42:04 +00:00
#define SAFE_STR(str) ((str) ? (str) : "NULL")
2010-07-23 11:55:18 +00:00
#define _BRICK_MSG(_class, _dump, _fmt, _args...) \
brick_say(_class, _dump, "BRICK", __BASE_FILE__, __LINE__, __FUNCTION__, _fmt, ##_args)
2011-03-22 14:36:26 +00:00
#define BRICK_FAT(_fmt, _args...) _BRICK_MSG(SAY_FATAL, true, _fmt, ##_args)
2014-03-13 08:33:12 +00:00
#define BRICK_ERR(_fmt, _args...) _BRICK_MSG(SAY_ERROR, false, _fmt, ##_args)
#define BRICK_WRN(_fmt, _args...) _BRICK_MSG(SAY_WARN, false, _fmt, ##_args)
#define BRICK_INF(_fmt, _args...) _BRICK_MSG(SAY_INFO, false, _fmt, ##_args)
2011-03-22 14:36:26 +00:00
2010-07-23 11:55:18 +00:00
#ifdef BRICK_DEBUGGING
#define BRICK_DBG(_fmt, _args...) _BRICK_MSG(SAY_DEBUG, false, _fmt, ##_args)
2010-07-23 11:55:18 +00:00
#else
2011-07-20 13:11:44 +00:00
#define BRICK_DBG(_args...) /**/
2010-07-23 11:55:18 +00:00
#endif
2011-03-22 14:36:26 +00:00
#ifdef IO_DEBUGGING
#define BRICK_IO(_fmt, _args...) _BRICK_MSG(SAY_DEBUG, false, _fmt, ##_args)
2011-03-22 14:36:26 +00:00
#else
2011-07-20 13:11:44 +00:00
#define BRICK_IO(_args...) /*empty*/
2011-03-22 14:36:26 +00:00
#endif
#include "brick_checking.h"
2010-07-23 11:55:18 +00:00
/////////////////////////////////////////////////////////////////////////
2011-03-24 16:05:46 +00:00
// number management helpers
2010-07-23 11:55:18 +00:00
2011-03-24 16:05:46 +00:00
extern int get_nr(void);
extern void put_nr(int nr);
/////////////////////////////////////////////////////////////////////////
// definitions for generic objects with aspects
2010-07-23 11:55:18 +00:00
struct generic_object;
2010-07-23 11:55:18 +00:00
struct generic_aspect;
2012-01-30 11:54:27 +00:00
#define GENERIC_ASPECT_TYPE(OBJTYPE) \
const char *aspect_type_name; \
2010-07-30 05:46:22 +00:00
const struct generic_object_type *object_type; \
2010-08-08 09:03:42 +00:00
int aspect_size; \
2012-01-30 11:54:27 +00:00
int (*init_fn)(struct OBJTYPE##_aspect *ini); \
void (*exit_fn)(struct OBJTYPE##_aspect *ini); \
2010-07-23 11:55:18 +00:00
struct generic_aspect_type {
GENERIC_ASPECT_TYPE(generic);
};
2012-01-30 11:54:27 +00:00
#define GENERIC_OBJECT_TYPE(OBJTYPE) \
const char *object_type_name; \
2010-07-23 11:55:18 +00:00
int default_size; \
int object_type_nr; \
2012-01-30 11:54:27 +00:00
int (*init_fn)(struct OBJTYPE##_object *ini); \
void (*exit_fn)(struct OBJTYPE##_object *ini); \
2010-07-23 11:55:18 +00:00
struct generic_object_type {
GENERIC_OBJECT_TYPE(generic);
};
2012-01-30 11:54:27 +00:00
#define GENERIC_OBJECT_LAYOUT(OBJTYPE) \
int size_hint; \
2010-08-05 15:54:48 +00:00
atomic_t alloc_count; \
atomic_t aspect_count; \
2012-02-02 15:25:43 +00:00
atomic_t total_alloc_count; \
atomic_t total_aspect_count; \
2010-07-23 11:55:18 +00:00
struct generic_object_layout {
GENERIC_OBJECT_LAYOUT(generic);
};
2012-01-30 11:54:27 +00:00
#define GENERIC_OBJECT(OBJTYPE) \
const struct generic_object_type *object_type; \
2012-02-02 15:25:43 +00:00
struct generic_object_layout *object_layout; \
2012-01-30 11:54:27 +00:00
struct OBJTYPE##_aspect **aspects; \
int aspect_nr_max; \
int free_offset; \
int max_offset; \
2010-07-23 11:55:18 +00:00
struct generic_object {
GENERIC_OBJECT(generic);
};
2012-01-30 11:54:27 +00:00
#define GENERIC_ASPECT(OBJTYPE) \
struct OBJTYPE##_object *object; \
const struct generic_aspect_type *aspect_type; \
bool shortcut; \
2010-07-23 11:55:18 +00:00
struct generic_aspect {
GENERIC_ASPECT(generic);
};
/////////////////////////////////////////////////////////////////////////
// definitions for asynchronous callback objects
2012-01-30 11:54:27 +00:00
#define GENERIC_CALLBACK(OBJTYPE) \
void (*cb_fn)(struct OBJTYPE##_callback *cb); \
2010-08-08 14:02:54 +00:00
void *cb_private; \
int cb_error; \
struct generic_callback *cb_next; \
2010-08-08 14:02:54 +00:00
struct generic_callback {
GENERIC_CALLBACK(generic);
};
2012-01-30 11:54:27 +00:00
#define CALLBACK_OBJECT(OBJTYPE) \
GENERIC_OBJECT(OBJTYPE); \
struct generic_callback *object_cb; \
struct generic_callback _object_cb; \
struct callback_object {
CALLBACK_OBJECT(generic);
};
/* Initial setup of the callback chain
*/
2014-03-23 09:48:46 +00:00
#define _SETUP_CALLBACK(obj,fn,priv) \
(obj)->_object_cb.cb_fn = (fn); \
(obj)->_object_cb.cb_private = (priv); \
(obj)->_object_cb.cb_error = 0; \
(obj)->_object_cb.cb_next = NULL; \
(obj)->object_cb = &(obj)->_object_cb; \
2014-03-23 09:48:46 +00:00
#ifdef BRICK_DEBUGGING
#define SETUP_CALLBACK(obj,fn,priv) \
if (unlikely((obj)->_object_cb.cb_fn)) { \
BRICK_ERR("callback function %p is already installed (new=%p)\n", \
(obj)->_object_cb.cb_fn, (fn)); \
} \
_SETUP_CALLBACK(obj,fn,priv)
#else
#define SETUP_CALLBACK(obj,fn,priv) _SETUP_CALLBACK(obj,fn,priv)
#endif
/* Insert a new member into the callback chain
*/
2014-03-23 09:48:46 +00:00
#define _INSERT_CALLBACK(obj,new,fn,priv) \
if (likely(!(new)->cb_fn)) { \
(new)->cb_fn = (fn); \
(new)->cb_private = (priv); \
(new)->cb_error = 0; \
(new)->cb_next = (obj)->object_cb; \
(obj)->object_cb = (new); \
}
2014-03-23 09:48:46 +00:00
#ifdef BRICK_DEBUGGING
#define INSERT_CALLBACK(obj,new,fn,priv) \
if (unlikely(!(obj)->_object_cb.cb_fn)) { \
BRICK_ERR("initical callback function is missing\n"); \
} \
_INSERT_CALLBACK(obj,new,fn,priv) \
else { BRICK_ERR("new object %p is not pristine\n", (new)->cb_fn); }
#else
#define INSERT_CALLBACK(obj,new,fn,priv) _INSERT_CALLBACK(obj,new,fn,priv)
#endif
/* Call the first callback in the chain.
*/
#define SIMPLE_CALLBACK(obj,err) \
2014-03-23 09:48:46 +00:00
if (likely(obj)) { \
struct generic_callback *__cb = (obj)->object_cb; \
2014-03-23 09:48:46 +00:00
if (likely(__cb)) { \
__cb->cb_error = (err); \
__cb->cb_fn(__cb); \
2014-03-23 09:48:46 +00:00
} else { \
BRICK_ERR("callback object_cb pointer is NULL\n"); \
} \
2014-03-23 09:48:46 +00:00
} else { \
BRICK_ERR("callback obj pointer is NULL\n"); \
}
#define CHECKED_CALLBACK(obj,err,done) \
{ \
struct generic_callback *__cb; \
CHECK_PTR(obj, done); \
__cb = (obj)->object_cb; \
CHECK_PTR_NULL(__cb, done); \
__cb->cb_error = (err); \
__cb->cb_fn(__cb); \
}
/* An intermediate callback handler must call this
* to continue the callback chain.
*/
#define NEXT_CHECKED_CALLBACK(cb,done) \
{ \
struct generic_callback *__next_cb = (cb)->cb_next; \
CHECK_PTR_NULL(__next_cb, done); \
__next_cb->cb_error = (cb)->cb_error; \
__next_cb->cb_fn(__next_cb); \
}
2014-03-23 09:48:46 +00:00
/* The last callback handler in the chain should call this
* for checking whether the end of the chain has been reached
*/
#define LAST_CALLBACK(cb) \
{ \
struct generic_callback *__next_cb = (cb)->cb_next; \
if (unlikely(__next_cb)) { \
BRICK_ERR("end of callback chain %p has not been reached, rest = %p\n", (cb), __next_cb); \
} \
}
/* Query the callback status.
* This uses always the first member of the chain!
*/
#define CALLBACK_ERROR(obj) \
((obj)->object_cb ? (obj)->object_cb->cb_error : -EINVAL)
2010-07-23 11:55:18 +00:00
/////////////////////////////////////////////////////////////////////////
// definitions for generic bricks
struct generic_input;
struct generic_output;
struct generic_brick_ops;
struct generic_output_ops;
struct generic_brick_type;
2011-02-23 20:48:06 +00:00
struct generic_switch {
bool button; /* in: main switch (on/off) */
bool led_on; /* out: indicate regular operation */
bool led_off; /* out: indicate no activity of any kind */
bool force_off; /* in: make ready for destruction */
int io_timeout; /* in: report IO errors after timeout (seconds) */
int percent_done; /* out: generic progress indicator */
2011-02-23 20:48:06 +00:00
wait_queue_head_t event;
};
2012-01-30 11:54:27 +00:00
#define GENERIC_BRICK(BRITYPE) \
2011-02-23 20:48:06 +00:00
const char *brick_name; \
2012-01-30 11:54:27 +00:00
const struct BRITYPE##_brick_type *type; \
struct BRITYPE##_brick_ops *ops; \
2010-07-23 11:55:18 +00:00
int nr_inputs; \
int nr_outputs; \
int brick_index; /* globally unique */ \
2012-01-30 11:54:27 +00:00
struct BRITYPE##_input **inputs; \
struct BRITYPE##_output **outputs; \
2011-02-23 20:48:06 +00:00
struct generic_switch power; \
2012-01-30 11:54:27 +00:00
int (*free)(struct BRITYPE##_brick *del); \
2010-07-23 11:55:18 +00:00
struct list_head tmp_head; \
struct generic_brick {
GENERIC_BRICK(generic);
};
2012-01-30 11:54:27 +00:00
#define GENERIC_INPUT(BRITYPE) \
2011-02-23 20:48:06 +00:00
const char *input_name; \
2012-01-30 11:54:27 +00:00
struct BRITYPE##_brick *brick; \
const struct BRITYPE##_input_type *type; \
struct BRITYPE##_output *connect; \
2010-07-30 05:46:22 +00:00
struct list_head input_head; \
2010-07-23 11:55:18 +00:00
struct generic_input {
GENERIC_INPUT(generic);
};
2012-01-30 11:54:27 +00:00
#define GENERIC_OUTPUT(BRITYPE) \
2011-02-23 20:48:06 +00:00
const char *output_name; \
2012-01-30 11:54:27 +00:00
struct BRITYPE##_brick *brick; \
const struct BRITYPE##_output_type *type; \
struct BRITYPE##_output_ops *ops; \
2010-07-30 05:46:22 +00:00
struct list_head output_head; \
2010-07-23 11:55:18 +00:00
int nr_connected; \
struct generic_output {
GENERIC_OUTPUT(generic);
};
2010-07-30 05:46:22 +00:00
#define GENERIC_OUTPUT_CALL(OUTPUT,OP,ARGS...) \
2021-04-16 09:42:16 +00:00
({ \
mb(); \
2010-08-01 20:21:18 +00:00
(void)LOCK_CHECK(OP), \
2010-07-30 05:46:22 +00:00
(OUTPUT) && (OUTPUT)->ops->OP ? \
(OUTPUT)->ops->OP(OUTPUT, ##ARGS) : \
2021-04-16 09:42:16 +00:00
-ENOTCONN; \
})
2010-07-30 05:46:22 +00:00
#define GENERIC_INPUT_CALL(INPUT,OP,ARGS...) \
2021-04-16 09:42:16 +00:00
({ \
mb(); \
2010-08-01 20:21:18 +00:00
(void)LOCK_CHECK(OP), \
2010-07-30 05:46:22 +00:00
(INPUT) && (INPUT)->connect ? \
GENERIC_OUTPUT_CALL((INPUT)->connect, OP, ##ARGS) : \
2021-04-16 09:42:16 +00:00
-ENOTCONN; \
})
2010-07-23 11:55:18 +00:00
2012-01-30 11:54:27 +00:00
#define GENERIC_BRICK_OPS(BRITYPE) \
int (*brick_switch)(struct BRITYPE##_brick *brick); \
2010-07-23 11:55:18 +00:00
struct generic_brick_ops {
GENERIC_BRICK_OPS(generic);
};
2012-01-30 11:54:27 +00:00
#define GENERIC_OUTPUT_OPS(BRITYPE) \
/*int (*output_start)(struct BRITYPE##_output *output);*/ \
/*int (*output_stop)(struct BRITYPE##_output *output);*/ \
2010-07-23 11:55:18 +00:00
struct generic_output_ops {
GENERIC_OUTPUT_OPS(generic)
};
// although possible, *_type should never be extended
2012-01-30 11:54:27 +00:00
#define GENERIC_BRICK_TYPE(BRITYPE) \
2011-02-23 20:48:06 +00:00
const char *type_name; \
2010-07-23 11:55:18 +00:00
int brick_size; \
int max_inputs; \
int max_outputs; \
2012-01-30 11:54:27 +00:00
const struct BRITYPE##_input_type **default_input_types; \
2011-02-23 20:48:06 +00:00
const char **default_input_names; \
2012-01-30 11:54:27 +00:00
const struct BRITYPE##_output_type **default_output_types; \
2011-02-23 20:48:06 +00:00
const char **default_output_names; \
2012-01-30 11:54:27 +00:00
struct BRITYPE##_brick_ops *master_ops; \
const struct generic_aspect_type **aspect_types; \
2012-01-30 11:54:27 +00:00
const struct BRITYPE##_input_types **default_type; \
int (*brick_construct)(struct BRITYPE##_brick *brick); \
int (*brick_destruct)(struct BRITYPE##_brick *brick); \
2010-07-23 11:55:18 +00:00
struct generic_brick_type {
GENERIC_BRICK_TYPE(generic);
};
2012-01-30 11:54:27 +00:00
#define GENERIC_INPUT_TYPE(BRITYPE) \
2010-07-23 11:55:18 +00:00
char *type_name; \
int input_size; \
2012-01-30 11:54:27 +00:00
int (*input_construct)(struct BRITYPE##_input *input); \
int (*input_destruct)(struct BRITYPE##_input *input); \
2010-07-23 11:55:18 +00:00
struct generic_input_type {
GENERIC_INPUT_TYPE(generic);
};
2012-01-30 11:54:27 +00:00
#define GENERIC_OUTPUT_TYPE(BRITYPE) \
2010-07-23 11:55:18 +00:00
char *type_name; \
int output_size; \
2012-01-30 11:54:27 +00:00
struct BRITYPE##_output_ops *master_ops; \
int (*output_construct)(struct BRITYPE##_output *output); \
int (*output_destruct)(struct BRITYPE##_output *output); \
2010-07-23 11:55:18 +00:00
struct generic_output_type {
GENERIC_OUTPUT_TYPE(generic);
};
int generic_register_brick_type(const struct generic_brick_type *new_type);
int generic_unregister_brick_type(const struct generic_brick_type *old_type);
2011-04-08 09:52:46 +00:00
INLINE void _generic_output_init(struct generic_brick *brick, const struct generic_output_type *type, struct generic_output *output, const char *output_name)
2010-08-10 17:39:30 +00:00
{
output->output_name = output_name;
output->brick = brick;
output->type = type;
output->ops = type->master_ops;
output->nr_connected = 0;
2011-02-27 14:17:58 +00:00
INIT_LIST_HEAD(&output->output_head);
2010-08-10 17:39:30 +00:00
}
2011-04-08 09:52:46 +00:00
INLINE void _generic_output_exit(struct generic_output *output)
2011-03-24 16:05:46 +00:00
{
list_del_init(&output->output_head);
output->output_name = NULL;
output->brick = NULL;
output->type = NULL;
output->ops = NULL;
output->nr_connected = 0;
}
2010-07-23 11:55:18 +00:00
#ifdef _STRATEGY // call this only in strategy bricks, never in ordinary bricks
// you need this only if you circumvent generic_brick_init_full()
2011-04-08 09:52:46 +00:00
INLINE int generic_brick_init(const struct generic_brick_type *type, struct generic_brick *brick, const char *brick_name)
2010-07-23 11:55:18 +00:00
{
brick->brick_index = get_nr();
2010-07-23 11:55:18 +00:00
brick->brick_name = brick_name;
brick->type = type;
brick->ops = type->master_ops;
brick->nr_inputs = 0;
brick->nr_outputs = 0;
2011-02-23 20:48:06 +00:00
brick->power.led_off = true;
init_waitqueue_head(&brick->power.event);
2011-03-24 16:05:46 +00:00
INIT_LIST_HEAD(&brick->tmp_head);
2010-07-23 11:55:18 +00:00
return 0;
}
2011-04-08 09:52:46 +00:00
INLINE void generic_brick_exit(struct generic_brick *brick)
2011-03-24 16:05:46 +00:00
{
list_del_init(&brick->tmp_head);
brick->brick_name = NULL;
brick->type = NULL;
brick->ops = NULL;
brick->nr_inputs = 0;
brick->nr_outputs = 0;
put_nr(brick->brick_index);
2011-03-24 16:05:46 +00:00
}
2011-04-08 09:52:46 +00:00
INLINE int generic_input_init(struct generic_brick *brick, int index, const struct generic_input_type *type, struct generic_input *input, const char *input_name)
2010-07-23 11:55:18 +00:00
{
if (index < 0 || index >= brick->type->max_inputs)
2011-03-01 18:00:14 +00:00
return -EINVAL;
2010-07-23 11:55:18 +00:00
if (brick->inputs[index])
return -EEXIST;
input->input_name = input_name;
input->brick = brick;
input->type = type;
input->connect = NULL;
2011-02-27 14:17:58 +00:00
INIT_LIST_HEAD(&input->input_head);
2010-07-23 11:55:18 +00:00
brick->inputs[index] = input;
brick->nr_inputs++;
return 0;
}
2011-04-08 09:52:46 +00:00
INLINE void generic_input_exit(struct generic_input *input)
2011-03-24 16:05:46 +00:00
{
list_del_init(&input->input_head);
input->input_name = NULL;
input->brick = NULL;
input->type = NULL;
input->connect = NULL;
}
2011-04-08 09:52:46 +00:00
INLINE int generic_output_init(struct generic_brick *brick, int index, const struct generic_output_type *type, struct generic_output *output, const char *output_name)
2010-07-23 11:55:18 +00:00
{
if (index < 0 || index >= brick->type->max_outputs)
return -ENOMEM;
if (brick->outputs[index])
return -EEXIST;
2010-08-10 17:39:30 +00:00
_generic_output_init(brick, type, output, output_name);
2010-07-23 11:55:18 +00:00
brick->outputs[index] = output;
brick->nr_outputs++;
return 0;
}
2011-04-08 09:52:46 +00:00
INLINE int generic_size(const struct generic_brick_type *brick_type)
2010-07-23 11:55:18 +00:00
{
int size = brick_type->brick_size;
int i;
size += brick_type->max_inputs * sizeof(void*);
for (i = 0; i < brick_type->max_inputs; i++) {
size += brick_type->default_input_types[i]->input_size;
}
size += brick_type->max_outputs * sizeof(void*);
for (i = 0; i < brick_type->max_outputs; i++) {
size += brick_type->default_output_types[i]->output_size;
}
return size;
}
/* If possible, use this instead of generic_*_init().
* input_types and output_types may be NULL => use default_*_types
*/
int generic_brick_init_full(
void *data,
int size,
const struct generic_brick_type *brick_type,
const struct generic_input_type **input_types,
const struct generic_output_type **output_types,
2011-02-23 20:48:06 +00:00
const char **names);
2010-07-23 11:55:18 +00:00
int generic_brick_exit_full(
struct generic_brick *brick);
2011-04-08 09:52:46 +00:00
INLINE int generic_connect(struct generic_input *input, struct generic_output *output)
2010-07-23 11:55:18 +00:00
{
BRICK_DBG("generic_connect(input=%p, output=%p)\n", input, output);
2011-03-01 18:00:14 +00:00
if (unlikely(!input || !output))
2010-07-23 11:55:18 +00:00
return -EINVAL;
2011-03-01 18:00:14 +00:00
if (unlikely(input->connect))
2010-07-23 11:55:18 +00:00
return -EEXIST;
2011-03-23 17:58:02 +00:00
if (unlikely(!list_empty(&input->input_head)))
return -EINVAL;
2011-03-01 18:00:14 +00:00
// helps only against the most common errors
if (unlikely(input->brick == output->brick))
return -EDEADLK;
2011-03-23 17:58:02 +00:00
2010-07-23 11:55:18 +00:00
input->connect = output;
2011-03-20 17:38:08 +00:00
output->nr_connected++;
2011-03-23 17:58:02 +00:00
list_add(&input->input_head, &output->output_head);
BRICK_DBG("now nr_connected=%d\n", output->nr_connected);
2010-07-23 11:55:18 +00:00
return 0;
}
2011-04-08 09:52:46 +00:00
INLINE int generic_disconnect(struct generic_input *input)
2010-07-23 11:55:18 +00:00
{
2011-08-25 10:16:32 +00:00
struct generic_output *connect;
2010-07-23 11:55:18 +00:00
BRICK_DBG("generic_disconnect(input=%p)\n", input);
if (!input)
return -EINVAL;
2011-08-25 10:16:32 +00:00
connect = input->connect;
if (connect) {
connect->nr_connected--;
BRICK_DBG("now nr_connected=%d\n", connect->nr_connected);
2010-07-23 11:55:18 +00:00
input->connect = NULL;
2011-02-27 14:17:58 +00:00
list_del_init(&input->input_head);
2010-07-23 11:55:18 +00:00
}
return 0;
}
#endif // _STRATEGY
// simple wrappers for type safety
2012-01-30 11:54:27 +00:00
#define DECLARE_BRICK_FUNCTIONS(BRITYPE) \
static inline int BRITYPE##_register_brick_type(void) \
2010-07-23 11:55:18 +00:00
{ \
2012-01-30 11:54:27 +00:00
extern const struct BRITYPE##_brick_type BRITYPE##_brick_type; \
extern int BRITYPE##_brick_nr; \
if (BRITYPE##_brick_nr >= 0) { \
BRICK_ERR("brick type " #BRITYPE " is already registered.\n"); \
2010-07-23 11:55:18 +00:00
return -EEXIST; \
} \
2012-01-30 11:54:27 +00:00
BRITYPE##_brick_nr = generic_register_brick_type((const struct generic_brick_type*)&BRITYPE##_brick_type); \
return BRITYPE##_brick_nr < 0 ? BRITYPE##_brick_nr : 0; \
2010-07-23 11:55:18 +00:00
} \
\
2012-01-30 11:54:27 +00:00
static inline int BRITYPE##_unregister_brick_type(void) \
2010-07-23 11:55:18 +00:00
{ \
2012-01-30 11:54:27 +00:00
extern const struct BRITYPE##_brick_type BRITYPE##_brick_type; \
return generic_unregister_brick_type((const struct generic_brick_type*)&BRITYPE##_brick_type); \
2010-07-23 11:55:18 +00:00
} \
\
2012-01-30 11:54:27 +00:00
extern const struct BRITYPE##_brick_type BRITYPE##_brick_type; \
extern const struct BRITYPE##_input_type BRITYPE##_input_type; \
extern const struct BRITYPE##_output_type BRITYPE##_output_type; \
2010-07-23 11:55:18 +00:00
\
2012-01-30 11:54:27 +00:00
INLINE void _##BRITYPE##_output_init(struct BRITYPE##_brick *brick, struct BRITYPE##_output *output, char *output_name) \
2010-08-10 17:39:30 +00:00
{ \
_generic_output_init( \
(struct generic_brick*)brick, \
2012-01-30 11:54:27 +00:00
(const struct generic_output_type*)&BRITYPE##_output_type, \
2010-08-10 17:39:30 +00:00
(struct generic_output*)output, \
output_name); \
} \
2010-07-23 11:55:18 +00:00
2010-07-30 05:46:22 +00:00
///////////////////////////////////////////////////////////////////////
// default operations on objects / aspects
extern struct generic_object *generic_alloc(struct generic_brick *brick, struct generic_object_layout *object_layout, const struct generic_object_type *object_type);
extern void generic_free(struct generic_object *object);
extern struct generic_aspect *generic_get_aspect(struct generic_brick *brick, struct generic_object *obj);
2010-07-30 05:46:22 +00:00
2012-01-30 11:54:27 +00:00
#define DECLARE_ASPECT_FUNCTIONS(BRITYPE,OBJTYPE) \
2010-07-30 05:46:22 +00:00
\
2012-02-02 15:25:43 +00:00
INLINE struct OBJTYPE##_object *BRITYPE##_alloc_##OBJTYPE(struct BRITYPE##_brick *brick) \
2010-08-01 20:21:18 +00:00
{ \
2012-02-02 15:25:43 +00:00
return (void*)generic_alloc((struct generic_brick*)brick, &brick->OBJTYPE##_object_layout, &OBJTYPE##_type); \
2010-08-04 17:32:04 +00:00
} \
\
2012-01-30 11:54:27 +00:00
INLINE void BRITYPE##_free_##OBJTYPE(struct OBJTYPE##_object *object) \
2010-08-04 17:32:04 +00:00
{ \
generic_free((struct generic_object*)object); \
2010-08-01 20:21:18 +00:00
} \
2010-08-02 16:31:10 +00:00
\
2012-01-30 11:54:27 +00:00
INLINE struct BRITYPE##_##OBJTYPE##_aspect *BRITYPE##_##OBJTYPE##_get_aspect(struct BRITYPE##_brick *brick, struct OBJTYPE##_object *obj) \
2010-08-02 16:31:10 +00:00
{ \
return (void*)generic_get_aspect((struct generic_brick*)brick, (struct generic_object*)obj); \
2010-08-02 16:31:10 +00:00
} \
\
2010-08-01 20:21:18 +00:00
2010-07-30 05:46:22 +00:00
///////////////////////////////////////////////////////////////////////
2011-02-23 20:48:06 +00:00
// some general helpers
2011-02-28 18:00:32 +00:00
/* Generic interface to simple brick status changes.
2011-02-27 14:17:58 +00:00
*/
extern void set_button(struct generic_switch *sw, bool val, bool force);
2011-02-23 20:48:06 +00:00
extern void set_led_on(struct generic_switch *sw, bool val);
extern void set_led_off(struct generic_switch *sw, bool val);
2011-03-01 09:34:36 +00:00
/*
* "Forced switch off" means that it cannot be switched on again.
*/
extern void set_button_wait(struct generic_brick *brick, bool val, bool force, int timeout);
2011-02-23 20:48:06 +00:00
2011-02-27 14:17:58 +00:00
/* Operations on networks of bricks (wiring graphs).
*
* Switch on => first switch on all predecessors in the wiring graph
* Switch off => first switch off all successors in the wiring graph
*
* Operations on brick networks by multiple threads in parallel are dangerous,
* because the buttons may start flipping.
* There is one exception: when @force is set, only the direction to
* "off" remains possible. This is useful for emergency shutdowns.
*/
2011-02-28 18:00:32 +00:00
typedef enum {
// only one brick instance
BR_ON_ONE, // switch on one brick instance
BR_OFF_ONE, // just switch off (may be switched on again)
BR_KILL_ONE, // forced switch off => may be never switched on again
BR_FREE_ONE, // forced switch off + deallocation (when possible)
// dito, but operating on the whole graph
BR_ON_ALL,
BR_OFF_ALL,
BR_KILL_ALL,
BR_FREE_ALL,
} brick_switch_t;
2011-08-25 10:16:32 +00:00
/////////////////////////////////////////////////////////////////////////
// threads
/* Please do not directly use kthreads any more in future.
* Use these thin abstractions instead.
*/
#define brick_thread_t struct task_struct
#define brick_thread_create(_thread_fn, _data, _fmt, _args...) \
({ \
2019-11-22 09:00:15 +00:00
brick_thread_t *_thr = NULL; \
int _max_retry = 3; \
\
2019-11-22 09:00:15 +00:00
while (_max_retry-- > 0) { \
int _err; \
\
flush_signals(current); \
_thr = kthread_create(_thread_fn, _data, _fmt, ##_args); \
if (likely(!IS_ERR(_thr))) \
break; \
_err = PTR_ERR(_thr); \
if (_err == -EAGAIN || _err == -EINTR) \
continue; \
BRICK_ERR("cannot create thread '%s', status = %d\n", _fmt, _err); \
_thr = NULL; \
2019-11-22 09:00:15 +00:00
break; \
} \
if (_thr) { \
struct say_channel *ch = get_binding(current); \
if (ch) \
bind_to_channel(ch, _thr); \
get_task_struct(_thr); \
wake_up_process(_thr); \
} \
_thr; \
})
#define brick_thread_stop(_thread) \
do { \
struct task_struct *__thread__ = (_thread); \
\
if (likely(__thread__)) { \
BRICK_INF("stopping thread '%s'\n", __thread__->comm); \
kthread_stop(__thread__); \
BRICK_INF("thread '%s' finished.\n", __thread__->comm); \
remove_binding(__thread__); \
put_task_struct(__thread__); \
(_thread) = NULL; \
} \
} while (0)
2012-12-14 11:44:54 +00:00
#define brick_thread_should_stop() \
({ \
2017-05-22 09:23:39 +00:00
flush_signals(current); \
2012-12-14 11:44:54 +00:00
brick_yield(); \
kthread_should_stop(); \
})
/////////////////////////////////////////////////////////////////////////
2011-08-25 10:16:32 +00:00
// init
extern int init_brick(void);
extern void exit_brick(void);
2010-07-30 11:50:20 +00:00
#endif