--- /dev/null
+/*
+ * faultd
+ *
+ * Copyright © 2017 Samsung Electronics
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+
+#include "module.h"
+#include "log.h"
+#include "common.h"
+
+static struct list_head modules[FAULTD_MODULE_TYPE_MAX];
+
+static void init_heads(void)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(modules); ++i)
+ INIT_LIST_HEAD(modules + i);
+}
+
+int faultd_module_register(struct faultd_module *module)
+{
+ if (!module->name || !module->init) {
+ log_error("Missing module name or init()");
+ return -EINVAL;
+ }
+
+ if (!modules[0].next)
+ init_heads();
+
+ list_add_tail(&module->node, modules + module->type);
+
+ return 0;
+}
+
+void faultd_module_unregister(struct faultd_module *module)
+{
+ list_del(&module->node);
+}
+
+int faultd_modules_init(sd_event *event_loop)
+{
+ struct faultd_module *module, *module_to_clean;
+ int i;
+ int ret = 0;
+
+ if (!modules[0].next)
+ init_heads();
+
+ for (i = 0; i < (int)(ARRAY_SIZE(modules)); ++i) {
+ log_debug("Initializing modules category %d", i);
+ list_for_each_entry(module, modules + i, node) {
+ log_debug("Initializing %s module", module->name);
+
+ ret = module->init(module, event_loop);
+ if (ret)
+ goto err_cleanup;
+ }
+ }
+
+ return 0;
+
+err_cleanup:
+ for (; i >= 0; --i) {
+ log_debug("Cleaning up modules category %d", i);
+ /* From first element of the list... */
+ for (module_to_clean = list_first_entry(modules + i,
+ struct faultd_module,
+ node);
+ /* iterate as long as modules has been initialized */
+ module_to_clean != module &&
+ &module_to_clean->node != (modules + i);
+ /* move to next one */
+ module_to_clean = list_next_entry(module_to_clean, node)) {
+ log_debug("Cleaning up %s module",
+ module_to_clean->name);
+ module_to_clean->cleanup(module_to_clean);
+ }
+ }
+
+ return ret;
+}
+
+void faultd_modules_cleanup()
+{
+ struct faultd_module *module;
+ int i;
+
+ for (i = FAULTD_MODULE_TYPE_MAX - 1; i >= 0; --i) {
+ log_debug("Cleaning up modules category %d", i);
+ list_for_each_entry(module, modules + i, node) {
+ log_debug("Cleaning up %s module", module->name);
+
+ module->cleanup(module);
+ }
+ }
+}
--- /dev/null
+/*
+ * faultd
+ *
+ * Copyright © 2017 Samsung Electronics
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FAULTD_MODULE_H
+#define FAULTD_MODULE_H
+
+#include <time.h>
+#include <systemd/sd-event.h>
+
+#include "list.h"
+#include "common.h"
+
+/* Order in this enum is also order of initialization */
+enum faultd_module_type {
+ FAULTD_MODULE_TYPE_MIN = 0,
+ FAULTD_MODULE_TYPE_UNCATEGORIZED = FAULTD_MODULE_TYPE_MIN,
+ FAULTD_MODULE_TYPE_CORE,
+ FAULTD_MODULE_TYPE_EVENT,
+ FAULTD_MODULE_TYPE_ACTION_EXECUTOR,
+ FAULTD_MODULE_TYPE_DECISION_MAKER,
+ FAULTD_MODULE_TYPE_LISTENER,
+ FAULTD_MODULE_TYPE_MAX,
+};
+
+struct faultd_module {
+ char *name;
+ enum faultd_module_type type;
+
+ int (*init)(struct faultd_module *, sd_event *event_loop);
+ void (*cleanup)(struct faultd_module *);
+
+ struct list_head node;
+};
+
+int faultd_module_register(struct faultd_module *module);
+void faultd_module_unregister(struct faultd_module *module);
+
+int faultd_modules_init(sd_event *event_loop);
+void faultd_modules_cleanup(void);
+
+#ifndef __CONSTRUCTOR__
+#define __CONSTRUCTOR__ __attribute__((constructor))
+#endif
+
+#ifndef __DESTRUCTOR__
+#define __DESTRUCTOR__ __attribute__((destructor))
+#endif
+
+#define FAULTD_MODULE_REGISTER(module) \
+ static void __CONSTRUCTOR__ module_init(void) \
+ { \
+ faultd_module_register(module); \
+ } \
+ static void __DESTRUCTOR__ module_cleanup(void) \
+ { \
+ faultd_module_unregister(module); \
+ }
+
+#endif /* FAULTD_MODULE_H */