build_sources_library print/message.c print/message/entry.c print/message/entry/action.c print/message/entry/item.c
build_sources_library print/warning/entry/action.c print/warning/entry/item.c print/warning/entry/setting.c print/warning/rule/action.c print/warning/rule/item.c print/warning/rule/setting.c
build_sources_library signal.c status.c time.c
-build_sources_library thread.c thread/cleanup.c thread/control.c thread/entry.c thread/instance.c thread/is.c thread/rule.c thread/signal.c
+build_sources_library thread.c thread/cleanup.c thread/control.c thread/enable.c thread/entry.c thread/instance.c thread/is.c thread/rule.c thread/signal.c
build_sources_library validate.c
build_sources_headers common.h controller.h common/define.h common/enumeration.h common/print.h common/string.h common/thread.h common/type.h
build_sources_headers print/message.h print/message/entry.h print/message/entry/action.h print/message/entry/item.h
build_sources_headers print/warning/entry/action.h print/warning/entry/item.h print/warning/entry/setting.h print/warning/rule/action.h print/warning/rule/item.h print/warning/rule/setting.h
build_sources_headers signal.h status.h time.h
-build_sources_headers thread.h thread/cleanup.h thread/control.h thread/entry.h thread/instance.h thread/is.h thread/rule.h thread/signal.h
+build_sources_headers thread.h thread/cleanup.h thread/control.h thread/enable.h thread/entry.h thread/instance.h thread/is.h thread/rule.h thread/signal.h
build_sources_headers validate.h
build_sources_documentation man
build_sources_program program/controller/main/print/message.c program/controller/main/print/message/entry.c program/controller/main/print/message/entry/action.c program/controller/main/print/message/entry/item.c
build_sources_program program/controller/main/print/warning/entry/action.c program/controller/main/print/warning/entry/item.c program/controller/main/print/warning/entry/setting.c program/controller/main/print/warning/rule/action.c program/controller/main/print/warning/rule/item.c program/controller/main/print/warning/rule/setting.c
build_sources_program program/controller/main/signal.c program/controller/main/status.c program/controller/main/time.c
-build_sources_program program/controller/main/thread.c program/controller/main/thread/cleanup.c program/controller/main/thread/control.c program/controller/main/thread/entry.c program/controller/main/thread/instance.c program/controller/main/thread/is.c program/controller/main/thread/rule.c program/controller/main/thread/signal.c
+build_sources_program program/controller/main/thread.c program/controller/main/thread/cleanup.c program/controller/main/thread/control.c program/controller/main/thread/enable.c program/controller/main/thread/entry.c program/controller/main/thread/instance.c program/controller/main/thread/is.c program/controller/main/thread/rule.c program/controller/main/thread/signal.c
build_sources_program program/controller/main/validate.c
build_sources_program program/controller/controller/config.c program/controller/controller/main.c program/controller/controller/controller.c program/controller/controller/string.c
build_sources_program program/controller/main/print/message.c program/controller/main/print/message/entry.c program/controller/main/print/message/entry/action.c program/controller/main/print/message/entry/item.c
build_sources_program program/controller/main/print/warning/entry/action.c program/controller/main/print/warning/entry/item.c program/controller/main/print/warning/entry/setting.c program/controller/main/print/warning/rule/action.c program/controller/main/print/warning/rule/item.c program/controller/main/print/warning/rule/setting.c
build_sources_program program/controller/main/signal.c program/controller/main/status.c program/controller/main/time.c
-build_sources_program program/controller/main/thread.c program/controller/main/thread/cleanup.c program/controller/main/thread/control.c program/controller/main/thread/entry.c program/controller/main/thread/instance.c program/controller/main/thread/is.c program/controller/main/thread/rule.c program/controller/main/thread/signal.c
+build_sources_program program/controller/main/thread.c program/controller/main/thread/cleanup.c program/controller/main/thread/control.c program/controller/main/thread/enable.c program/controller/main/thread/entry.c program/controller/main/thread/instance.c program/controller/main/thread/is.c program/controller/main/thread/rule.c program/controller/main/thread/signal.c
build_sources_program program/controller/main/validate.c
build_sources_program program/controller/init/config.c program/controller/init/main.c program/controller/init/init.c program/controller/init/print.c program/controller/init/signal.c program/controller/init/string.c
void controller_init_signal_thread(controller_t * const main, const uint8_t is_normal) {
if (!main) return;
- if (!controller_thread_is_enabled(&main->thread, is_normal)) return;
+ if (!controller_thread_enable_is(&main->thread, is_normal)) return;
if (!(main->setting.flag & controller_main_flag_interruptible_d)) return;
siginfo_t information;
f_time_spec_t time = f_time_spec_t_initialize;
- while (controller_thread_is_enabled(&main->thread, is_normal)) {
+ while (controller_thread_enable_is(&main->thread, is_normal)) {
memset((void *) &information, 0, sizeof(siginfo_t));
// Send F_signal_reserved_35 to cleanup process to reap child processes.
if (information.si_signo == F_signal_child || information.si_signo == F_signal_reserved_35) {
- controller_lock_signal(&main->thread.lock.reap_condition, &main->thread.lock.reap);
+ f_thread_condition_signal_all(&main->thread.lock.reap_condition);
continue;
}
if (information.si_signo == F_signal_interrupt || information.si_signo == F_signal_abort || information.si_signo == F_signal_quit || information.si_signo == F_signal_termination) {
main->thread.signal = information.si_signo;
- controller_lock_signal(&main->thread.lock.reap_condition, &main->thread.lock.reap);
+ f_thread_condition_signal_all(&main->thread.lock.reap_condition);
controller_thread_instance_cancel(main, is_normal, controller_thread_cancel_signal_e);
break;
/**
* States for the thread, designating how to stop the process.
*
- * controller_thread_*_e:
- * - enabled_not: The controller is no longer enabled, shut down and abort all work.
+ * controller_thread_enable_*_e:
+ * - enabled_none: The enable state is not set or unknown (may be returned to designate failure to read enable state).
+ * - enabled_not: The controller is no longer enabled, shut down and abort all work (this is expected to be smaller than all enabled modes other than "none".
* - enabled: The controller is operating normally.
* - enabled_execute: The controller is executing another process, all running operations must terminate.
* - enabled_exit: The controller is shutting down, only process Exit rules.
* - enabled_exit_ready: The controller is shutting down, only process Exit rules, and now ready to send termination signals.
*/
enum {
- controller_thread_enabled_not_e = 0,
- controller_thread_enabled_e,
- controller_thread_enabled_execute_e,
- controller_thread_enabled_exit_e,
- controller_thread_enabled_exit_execute_e,
- controller_thread_enabled_exit_ready_e,
+ controller_thread_enable_none_e = 0,
+ controller_thread_enable_not_e,
+ controller_thread_enable_e,
+ controller_thread_enable_execute_e,
+ controller_thread_enable_exit_e,
+ controller_thread_enable_exit_execute_e,
+ controller_thread_enable_exit_ready_e,
}; // enum
/**
f_thread_mutex_delete(&lock->print);
f_thread_mutex_delete(&lock->reap);
+ f_thread_lock_delete(&lock->enable);
f_thread_lock_delete(&lock->instance);
f_thread_lock_delete(&lock->rule);
*
* The alert lock is intended for a generic waiting on alerts operations.
* The cancel lock is intended for preventing double cancellation calls (which can happen due to interrupts).
+ * The enable lock is intended for a handling checks to the enable state.
* The print lock is intended to lock any activity printing to stdout/stderr.
* The instance lock is intended to lock any activity on the instance structure.
- * The Rule lock is intended to lock any activity on the rules structure.
+ * The rule lock is intended to lock any activity on the rules structure.
*
* Properties:
* - flag: A set of flags associated with the locks.
* - cancel: The cancel mutex lock for locking the cancel operation.
* - print: The print mutex lock.
* - reap: The reap_condition mutex lock.
+ * - enable: The enable r/w lock.
* - instance: The instance r/w lock.
- * - rule: The Rule r/w lock.
+ * - rule: The rule r/w lock.
* - alert_condition: The condition used to trigger alerts.
* - reap_condition: The condition used to trigger zombie reaping.
*/
f_thread_mutex_t print;
f_thread_mutex_t reap;
+ f_thread_lock_t enable;
f_thread_lock_t instance;
f_thread_lock_t rule;
f_thread_mutex_t_initialize, \
f_thread_lock_t_initialize, \
f_thread_lock_t_initialize, \
+ f_thread_lock_t_initialize, \
f_thread_condition_t_initialize, \
f_thread_condition_t_initialize, \
}
*
* This is essentially data shared globally between threads, about threads.
*
- * The "enabled" and "signal" utilize the lock: lock.process.
- *
- * The lock.alert must be used when writing to any of:
- * - enabled.
- *
* The typedef for this is located in the defs.h header.
*
* Properties:
- * - enabled: F_true when threads are active, FALSE when inactive and the program is essentially shutting down, no new threads should be started when F_false.
- * - signal: The code of any signal received.
- * - status: A status used by the main entry/rule processing thread for synchronous operations.
+ * - enable: F_true when threads are active, FALSE when inactive and the program is essentially shutting down, no new threads should be started when F_false.
+ * - signal: The code of any signal received.
+ * - status: A status used by the main entry/rule processing thread for synchronous operations.
*
* - id_cleanup: The thread ID representing the Cleanup Process.
* - id_control: The thread ID representing the Control Process.
*/
#ifndef _di_controller_thread_t_
struct controller_thread_t_ {
- uint8_t enabled;
+ uint8_t enable;
int signal;
f_status_t status;
};
#define controller_thread_t_initialize { \
- controller_thread_enabled_e, \
+ controller_thread_enable_e, \
0, \
F_none, \
f_thread_id_t_initialize, \
#include <program/controller/main/time.h>
#include <program/controller/main/thread/cleanup.h>
#include <program/controller/main/thread/control.h>
+#include <program/controller/main/thread/enable.h>
#include <program/controller/main/thread/entry.h>
#include <program/controller/main/thread/is.h>
#include <program/controller/main/thread/instance.h>
f_number_unsigned_t at = 0;
f_number_unsigned_t j = 0;
- for (i = 0; i < main->thread.cache.object_items.used && controller_thread_is_enabled(&main->thread, is_entry); ++i) {
+ for (i = 0; i < main->thread.cache.object_items.used && controller_thread_enable_is(&main->thread, is_entry); ++i) {
code &= ~0x2;
at = 0;
for (j = 0; j < entry->items.array[i].actions.used; ++j) {
- if (!controller_thread_is_enabled(&main->thread, is_entry)) {
+ if (!controller_thread_enable_is(&main->thread, is_entry)) {
entry->status = controller_status_simplify_error(F_interrupt);
return F_status_set_error(F_interrupt);
return status;
}
- while (controller_thread_is_enabled(&main->thread, is_entry)) {
+ while (controller_thread_enable_is(&main->thread, is_entry)) {
actions = &entry->items.array[cache->ats.array[at_i]].actions;
- for (; cache->ats.array[at_j] < actions->used && controller_thread_is_enabled(&main->thread, is_entry); ++cache->ats.array[at_j]) {
+ for (; cache->ats.array[at_j] < actions->used && controller_thread_enable_is(&main->thread, is_entry); ++cache->ats.array[at_j]) {
cache->action.line_action = actions->array[cache->ats.array[at_j]].line;
cache->action.name_action.used = 0;
else if (f_compare_dynamic(controller_settings_s, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) continue;
// Walk though each items and check to see if the item actually exists.
- for (i = 1; i < entry->items.used && controller_thread_is_enabled(&main->thread, is_entry); ++i) {
+ for (i = 1; i < entry->items.used && controller_thread_enable_is(&main->thread, is_entry); ++i) {
if (f_compare_dynamic(entry->items.array[i].name, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) {
}
} // while
- if (!controller_thread_is_enabled(&main->thread, is_entry)) return F_status_set_error(F_interrupt);
+ if (!controller_thread_enable_is(&main->thread, is_entry)) return F_status_set_error(F_interrupt);
// If ready is not found in the entry, then default to always ready.
if (main->process.ready == controller_process_ready_no_e) {
uint8_t options_force = 0;
uint8_t options_instance = 0;
- controller_entry_t * const entry = is_entry ? &main->process.entry : &main->process.exit;
controller_cache_t * const cache = &main->thread.cache;
+ controller_entry_t * const entry = is_entry ? &main->process.entry : &main->process.exit;
controller_entry_action_t *entry_action = 0;
controller_entry_actions_t *entry_actions = 0;
if (F_status_is_error(status)) return status;
}
- while (controller_thread_is_enabled(&main->thread, is_entry)) {
+ while (controller_thread_enable_is(&main->thread, is_entry)) {
entry_actions = &entry->items.array[cache->ats.array[at_i]].actions;
- for (; cache->ats.array[at_j] < entry_actions->used && controller_thread_is_enabled(&main->thread, is_entry); ++cache->ats.array[at_j]) {
+ for (; cache->ats.array[at_j] < entry_actions->used && controller_thread_enable_is(&main->thread, is_entry); ++cache->ats.array[at_j]) {
entry_action = &entry_actions->array[cache->ats.array[at_j]];
else if (entry_action->type == controller_entry_action_type_consider_e || controller_entry_action_type_is_rule(entry_action->type)) {
status_lock = controller_lock_write(is_entry, F_true, &main->thread, &main->thread.lock.rule);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_false);
break;
status_lock = controller_lock_read(is_entry, F_true, &main->thread, &main->thread.lock.rule);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_true);
break;
controller_print_message_entry_item_rule(&main->program.message, entry, entry_action, is_entry, alias_rule);
}
- if (!controller_thread_is_enabled(&main->thread, is_entry)) break;
+ if (!controller_thread_enable_is(&main->thread, is_entry)) break;
// The Rule is not yet loaded, ensure that it is loaded.
if (status != F_true) {
status_lock = controller_lock_write(is_entry, F_true, &main->thread, &main->thread.lock.rule);
- if (F_status_is_fine(status_lock)) {
+ if (status_lock == F_okay) {
status = controller_rule_read(main, cache, is_entry, alias_rule, entry, &main->process.rules.array[main->process.rules.used]);
}
cache->action.line_action = cache_line_action;
cache->action.line_item = cache_line_item;
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_false);
break;
}
- if (F_status_set_fine(status) == F_interrupt || !controller_thread_is_enabled(&main->thread, is_entry)) {
+ if (F_status_set_fine(status) == F_interrupt || !controller_thread_enable_is(&main->thread, is_entry)) {
f_thread_unlock(&main->thread.lock.rule);
break;
}
} // while
- if (!controller_thread_is_enabled(&main->thread, is_entry)) return F_status_set_error(F_interrupt);
+ if (!controller_thread_enable_is(&main->thread, is_entry)) return F_status_set_error(F_interrupt);
if (status == F_child) return status;
- if (F_status_is_error(status_lock)) return status_lock;
+ if (status_lock != F_okay) return status_lock;
// Check to see if any required processes failed, but do not do this if already operating in failsafe.
if (F_status_is_error_not(status) && !failsafe && !(main->setting.flag & controller_main_flag_validate_d) && main->process.mode != controller_process_mode_helper_e) {
}
#endif // _di_controller_instance_find_
-#ifndef _di_controller_instance_signal_wait_
- f_status_t controller_instance_signal_wait(controller_instance_t * const instance) {
-
- if (!instance) return F_status_set_error(F_parameter);
-
- const f_status_t status = controller_lock_mutex(instance->type != controller_instance_type_exit_e, F_true, &instance->main->thread, &instance->wait);
-
- if (status == F_okay) {
- f_thread_condition_signal_all(&instance->wait_condition);
- f_thread_mutex_unlock(&instance->wait);
- }
-
- return F_okay;
- }
-#endif // _di_controller_instance_signal_wait_
-
#ifdef __cplusplus
} // extern "C"
#endif
f_status_t controller_instance_find(const f_number_unsigned_t action, const f_string_static_t alias, const controller_instances_t instances, f_number_unsigned_t * const at);
#endif // _di_controller_instance_find_
-/**
- * Send a signal to the wait condition.
- *
- * Used to inform all things waiting on a specific instance that the specific instance has finished running.
- *
- * @param instance
- * The Controller Instance.
- *
- * Must not be NULL.
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * Errors (with error bit) from: controller_lock_mutex().
- *
- * @see controller_lock_mutex()
- */
-#ifndef _di_controller_instance_signal_wait_
- extern f_status_t controller_instance_signal_wait(controller_instance_t * const instance);
-#endif // _di_controller_instance_signal_wait_
-
#ifdef __cplusplus
} // extern "C"
#endif
status = controller_lock_write(is_normal, F_true, &main->thread, &main->thread.lock.instance);
- if (F_status_is_error(status)) {
+ if (status != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status), F_false);
}
else {
controller_instance_t * const instance = F_status_is_error_not(status) ? main->thread.instances.array[main->thread.instances.used] : 0;
- if (F_status_is_error_not(status)) {
+ if (status == F_okay) {
status = controller_lock_write(is_normal, F_true, &main->thread, &instance->lock);
}
status = f_thread_mutex_create(0, &lock->reap);
if (F_status_is_error_not(status)) {
- status = f_thread_lock_create(0, &lock->instance);
+ status = f_thread_lock_create(0, &lock->enable);
if (F_status_is_error_not(status)) {
- status = f_thread_lock_create(0, &lock->rule);
+ status = f_thread_lock_create(0, &lock->instance);
if (F_status_is_error_not(status)) {
- status = f_thread_condition_create(0, &lock->alert_condition);
+ status = f_thread_lock_create(0, &lock->rule);
if (F_status_is_error_not(status)) {
- status = f_thread_condition_create(0, &lock->reap_condition);
+ status = f_thread_condition_create(0, &lock->alert_condition);
+
+ if (F_status_is_error_not(status)) {
+ status = f_thread_condition_create(0, &lock->reap_condition);
+
+ if (F_status_is_error(status)) {
+ f_thread_condition_delete(&lock->alert_condition);
+ }
+ }
if (F_status_is_error(status)) {
- f_thread_condition_delete(&lock->alert_condition);
+ f_thread_lock_delete(&lock->rule);
}
}
if (F_status_is_error(status)) {
- f_thread_lock_delete(&lock->rule);
+ f_thread_lock_delete(&lock->instance);
}
}
if (F_status_is_error(status)) {
- f_thread_lock_delete(&lock->instance);
+ f_thread_lock_delete(&lock->enable);
}
}
status = f_thread_mutex_lock_timed(&time, mutex);
if (status == F_time) {
- if (check && !controller_thread_is_enabled(thread, is_normal)) return F_status_set_error(F_interrupt);
+ if (check && !controller_thread_enable_is(thread, is_normal)) return F_status_set_error(F_interrupt);
}
- else {
+ else if (status == F_okay) {
break;
}
} // for
- return status;
+ return F_okay;
}
#endif // _di_controller_lock_mutex_
status = f_thread_lock_read_timed(&time, lock);
if (status == F_time) {
- if (check && !controller_thread_is_enabled(thread, is_normal)) return F_status_set_error(F_interrupt);
+ if (check && !controller_thread_enable_is(thread, is_normal)) return F_status_set_error(F_interrupt);
}
- else {
+ else if (status == F_okay) {
break;
}
} // for
- return status;
+ return F_okay;
}
#endif // _di_controller_lock_read_
}
#endif // _di_controller_lock_read_instance_
-#ifndef _di_controller_lock_signal_
- f_status_t controller_lock_signal(f_thread_condition_t * const condition, f_thread_mutex_t * const mutex) {
-
- if (!condition || !mutex) return F_status_set_error(F_parameter);
-
- const f_status_t status = f_thread_mutex_lock(mutex);
-
- if (status == F_okay) {
- f_thread_condition_signal_all(condition);
- f_thread_mutex_unlock(mutex);
- }
-
- return F_okay;
- }
-#endif // _di_controller_lock_signal_
-
#ifndef _di_controller_lock_write_
f_status_t controller_lock_write(const uint8_t is_normal, const uint8_t check, controller_thread_t * const thread, f_thread_lock_t * const lock) {
status = f_thread_lock_write_timed(&time, lock);
if (status == F_time) {
- if (check && !controller_thread_is_enabled(thread, is_normal)) return F_status_set_error(F_interrupt);
+ if (check && !controller_thread_enable_is(thread, is_normal)) return F_status_set_error(F_interrupt);
}
- else {
+ else if (status == F_okay) {
break;
}
} // for
- return status;
+ return F_okay;
}
#endif // _di_controller_lock_write_
#endif // _di_controller_lock_read_instance_
/**
- * Send a signal to the given condition.
- *
- * @param condition
- * The condition to send the signal too.
- *
- * Must not be NULL.
- *
- * @param mutex
- * The mutex lock associated with the condition.
- *
- * Must not be NULL.
- *
- * @return
- * F_okay on success.
- *
- * F_parameter (with error bit) if a parameter is invalid.
- *
- * Errors (with error bit) from: controller_lock_mutex().
- *
- * @see controller_lock_mutex()
- */
-#ifndef _di_controller_lock_signal_
- extern f_status_t controller_lock_signal(f_thread_condition_t * const condition, f_thread_mutex_t * const mutex);
-#endif // _di_controller_lock_signal_
-
-/**
* Wait to get a write lock.
*
* Given a r/w lock, periodically check to see if main thread is disabled while waiting.
}
// Only make the Rule and control threads available once any/all pre-processing is complete.
- if (F_status_is_error_not(status) && status != F_failure && status != F_child && main->thread.enabled == controller_thread_enabled_e) {
+ if (F_status_is_error_not(status) && status != F_failure && status != F_child && controller_thread_enable_get(&main->thread) == controller_thread_enable_e) {
if (!(main->setting.flag & controller_main_flag_validate_d)) {
// Wait for the Entry thread to complete before starting the Rule thread.
controller_thread_join(&main->thread.id_rule);
- if (main->thread.enabled && main->process.mode == controller_process_mode_service_e) {
+ if (controller_thread_enable_get(&main->thread) > controller_thread_enable_not_e && main->process.mode == controller_process_mode_service_e) {
status = f_thread_create(0, &main->thread.id_rule, &controller_thread_rule, (void *) main);
if (F_status_is_error(status)) {
return;
}
- if (F_status_is_error_not(status) && status != F_failure && !(main->setting.flag & controller_main_flag_validate_d) && controller_thread_is_enabled(&main->thread, F_true)) {
+ if (F_status_is_error_not(status) && status != F_failure && !(main->setting.flag & controller_main_flag_validate_d) && controller_thread_enable_is(&main->thread, F_true)) {
if (main->process.mode == controller_process_mode_service_e) {
controller_thread_join(&main->thread.id_signal);
}
if (F_status_set_fine(status) == F_lock_read) {
status = controller_lock_read(instance->type != controller_instance_type_exit_e, F_false, &main->thread, &instance->lock);
- if (F_status_is_error(status)) return F_status_set_error(F_lock_read);
+ if (status != F_okay) return F_status_set_error(F_lock_read);
status = F_status_set_error(F_lock);
}
if (!instance || !instance->main) return F_status_set_error(F_parameter);
- f_status_t status = F_okay;
-
controller_t * const main = instance->main;
-
+ f_status_t status = F_okay;
f_execute_result_t result = f_execute_result_t_initialize;
+ // @fixme Lock the instance.childs.used with write access. (active should already have a read lock)
+ //status = controller_lock_write(instance->type != controller_instance_type_exit_e, F_false, &main->thread, &instance->lock);
+ //if (status != F_okay) return F_status_set_error(F_lock_read);
+
status = f_memory_array_increase(controller_allocation_small_d, sizeof(pid_t), (void **) &instance->childs.array, &instance->childs.used, &instance->childs.size);
if (F_status_is_error(status)) {
return status;
}
- pid_t * const process_child_id = controller_rule_execute_next_child(instance);
+ pid_t * const process_child_id = controller_rule_execute_next_child(instance); // @fixme should be included in write lock.
if (options & controller_instance_option_simulate_e) {
controller_print_entry_output_execute_simulate(&main->program.output, instance, program, arguments);
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_false);
status_lock = controller_lock_read(instance->type != controller_instance_type_exit_e, F_false, &instance->main->thread, &instance->lock);
- if (F_status_is_error(status_lock)) return F_status_set_error(F_lock_read);
+ if (status_lock != F_okay) return F_status_set_error(F_lock_read);
return F_status_set_error(F_lock);
}
status_lock = controller_lock_read_instance(instance, &instance->lock);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
// Try again, after the first interrupt.
if (F_status_set_fine(status_lock) == F_interrupt) {
status_lock = controller_lock_read(instance->type != controller_instance_type_exit_e, F_false, &instance->main->thread, &instance->lock);
}
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_true);
return F_status_set_error(F_lock_read);
if (!execute_set || !instance || !instance->main) return F_status_set_error(F_parameter);
- f_status_t status = F_okay;
controller_t * const main = instance->main;
+ f_status_t status = F_okay;
f_execute_result_t result = f_execute_result_t_initialize;
+ // @fixme Lock the instance.childs.used with write access. (active should already have a read lock)
+ //status = controller_lock_write(instance->type != controller_instance_type_exit_e, F_false, &main->thread, &instance->lock);
+ //if (status != F_okay) return F_status_set_error(F_lock_read);
+
status = f_memory_array_increase(controller_allocation_small_d, sizeof(pid_t), (void **) &instance->childs.array, &instance->childs.used, &instance->childs.size);
if (F_status_is_error_not(status)) {
return status;
}
- pid_t * const process_child_id = controller_rule_execute_next_child(instance);
+ pid_t * const process_child_id = controller_rule_execute_next_child(instance); // @fixme should be included in write lock.
f_string_dynamic_t * const process_child_pid_file = controller_rule_execute_next_pid_path(instance);
status = f_file_exists(pid_file, F_true);
f_status_t status_lock = controller_lock_write_instance(instance, &instance->lock);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_false);
status_lock = controller_lock_read(instance->type != controller_instance_type_exit_e, F_false, &instance->main->thread, &instance->lock);
- if (F_status_is_error(status_lock)) return F_status_set_error(F_lock_read);
+ if (status_lock != F_okay) return F_status_set_error(F_lock_read);
return F_status_set_error(F_lock);
}
status_lock = controller_lock_write_instance(instance, &instance->lock);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_false);
status_lock = controller_lock_read(instance->type != controller_instance_type_exit_e, F_false, &instance->main->thread, &instance->lock);
- if (F_status_is_error(status_lock)) return F_status_set_error(F_lock_read);
+ if (status_lock != F_okay) return F_status_set_error(F_lock_read);
return F_status_set_error(F_lock);
}
status_lock = controller_lock_read_instance(instance, &main->thread.lock.instance);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_true);
}
else {
// Find at least one of the requested Action when the Rule is required.
if (instance->options & controller_instance_option_require_e) {
- bool missing = F_true;
+ uint8_t missing = F_true;
f_number_unsigned_t j = 0;
for (i = 0; i < instance->rule.items.used; ++i) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_false);
status_lock = controller_lock_read(instance->type != controller_instance_type_exit_e, F_false, &main->thread, &instance->lock);
- if (F_status_is_error(status_lock)) return F_status_set_error(F_lock_read);
+ if (status_lock != F_okay) return F_status_set_error(F_lock_read);
return F_status_set_error(F_lock);
}
f_thread_unlock(&instance->lock);
status_lock = controller_lock_read(instance->type != controller_instance_type_exit_e, F_false, &main->thread, &instance->lock);
- if (F_status_is_error(status_lock)) return F_status_set_error(F_lock_read);
+ if (status_lock != F_okay) return F_status_set_error(F_lock_read);
return F_status_set_error(F_lock);
}
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_true);
status_lock = controller_lock_read(instance->type != controller_instance_type_exit_e, F_false, &main->thread, &instance->lock);
- if (F_status_is_error(status_lock)) return F_status_set_error(F_lock_read);
+ if (status_lock != F_okay) return F_status_set_error(F_lock_read);
return F_status_set_error(F_lock);
}
f_status_t status = controller_lock_read(type != controller_instance_type_exit_e, F_true, &main->thread, &main->thread.lock.instance);
- if (F_status_is_error(status)) {
+ if (status != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status), F_true);
return status;
status = controller_lock_read(type != controller_instance_type_exit_e, F_true, &main->thread, &instance->active);
- if (F_status_is_error(status)) {
+ if (status != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status), F_true);
controller_print_error_rule_item(&main->program.error, &cache->action, F_false, F_status_set_fine(status));
// The thread is done, so close the thread.
if (instance->state == controller_instance_state_done_e) {
controller_thread_join(&instance->id_thread);
- controller_instance_signal_wait(instance);
+ f_thread_condition_signal_all(&instance->wait_condition);
}
instance->id = at;
instance->state = controller_instance_state_idle_e;
}
- controller_instance_signal_wait(instance);
+ f_thread_condition_signal_all(&instance->wait_condition);
f_thread_unlock(&instance->lock);
}
f_status_t status_lock = F_okay;
// The instance and active locks shall be held for the duration of this instanceing (aside from switching between read to/from write).
- if (options_force & controller_instance_option_asynchronous_e) {
+ if (options_force & controller_instance_option_asynchronous_e) { // @fixme are all of these async "active" locks save/valid?
status_lock = controller_lock_read_instance(instance, &instance->active);
if (F_status_is_error(status_lock)) {
instance->state = (options_force & controller_instance_option_asynchronous_e) ? controller_instance_state_done_e : controller_instance_state_idle_e;
instance->stack.used = used_original_stack;
- controller_instance_signal_wait(instance);
+ f_thread_condition_signal_all(&instance->wait_condition);
f_thread_unlock(&instance->lock);
private_controller_rule_instance_perform_unlock_active(instance, options_force);
f_status_t status_lock = controller_lock_read(is_normal, F_false, &main->thread, &main->thread.lock.instance);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_true);
return status_lock;
for (i = 0; i < instance_total; ++i) {
- if (!controller_thread_is_enabled(&main->thread, is_normal)) break;
+ if (!controller_thread_enable_is(&main->thread, is_normal)) break;
// Re-establish instance read lock to wait for or protect from the cleanup thread while checking the read instance.
status_lock = controller_lock_read(is_normal, F_true, &main->thread, &main->thread.lock.instance);
- if (F_status_is_error(status_lock)) break;
+ if (status_lock != F_okay) break;
if (!instance_list[i]) {
f_thread_unlock(&main->thread.lock.instance);
status_lock = controller_lock_read(is_normal, F_true, &main->thread, &instance_list[i]->active);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
f_thread_unlock(&main->thread.lock.instance);
break;
status_lock = controller_lock_read(is_normal, F_true, &main->thread, &instance_list[i]->lock);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
f_thread_unlock(&instance_list[i]->active);
break;
status_lock = controller_lock_write(is_normal, F_true, &main->thread, &instance_list[i]->lock);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
controller_print_error_lock_critical(&main->program.error, F_status_set_fine(status_lock), F_false);
f_thread_unlock(&instance_list[i]->active);
instance_list[i]->state = controller_instance_state_idle_e;
f_thread_unlock(&instance_list[i]->active);
- controller_instance_signal_wait(instance_list[i]);
+ f_thread_condition_signal_all(&instance_list[i]->wait_condition);
}
status_lock = controller_lock_read(is_normal, F_true, &main->thread, &instance_list[i]->active);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
f_thread_unlock(&instance_list[i]->lock);
break;
f_thread_unlock(&instance_list[i]->lock);
status_lock = controller_lock_read(is_normal, F_true, &main->thread, &instance_list[i]->lock);
- if (F_status_is_error(status_lock)) break;
+ if (status_lock != F_okay) break;
}
if (instance_list[i]->options & controller_instance_option_require_e) {
status_lock = controller_lock_read(is_normal, F_true, &main->thread, &instance_list[i]->lock);
- if (F_status_is_error(status_lock)) {
+ if (status_lock != F_okay) {
f_thread_unlock(&instance_list[i]->active);
break;
return status_lock;
}
- if (!controller_thread_is_enabled(&main->thread, is_normal)) return F_status_set_error(F_interrupt);
+ if (!controller_thread_enable_is(&main->thread, is_normal)) return F_status_set_error(F_interrupt);
if (F_status_set_fine(status) == F_require) return status;
if (required_not_run) return F_require;
f_time_spec_t delay = f_time_spec_t_initialize;
siginfo_t signal_data;
uint8_t reap_count = 0;
+ uint8_t enable = controller_thread_enable_none_e;
f_status_t status = F_okay;
- while (main->thread.enabled == controller_thread_enabled_e) {
+ while (controller_thread_enable_get(&main->thread) == controller_thread_enable_e) {
controller_time_now(
main->setting.flag & controller_main_flag_simulate_d
} while (F_false);
}
- if (main->thread.enabled != controller_thread_enabled_e) {
- if (main->thread.enabled == controller_thread_enabled_exit_e) continue;
+ enable = controller_thread_enable_get(&main->thread);
+
+ if (enable != controller_thread_enable_e) {
+ if (enable == controller_thread_enable_exit_e) continue;
break;
}
f_number_unsigned_t i = 0;
- for (status = F_okay; i < main->thread.instances.size && main->thread.enabled == controller_thread_enabled_e; ++i) {
+ for (status = F_okay; i < main->thread.instances.used && controller_thread_enable_get(&main->thread) == controller_thread_enable_e; ++i) {
if (!main->thread.instances.array[i]) continue;
- if (i >= main->thread.instances.used) {
- status = controller_instance_initialize(&main->thread.instances.array[i]);
- }
-
instance = main->thread.instances.array[i];
+ {
+ f_time_spec_t time;
+
+ do {
+ if (controller_thread_enable_get(&main->thread) != controller_thread_enable_e) {
+ status = F_enable_not;
+
+ break;
+ }
+
+ memset((void *) &time, 0, sizeof(struct timespec));
+
+ controller_time_now(controller_thread_timeout_cancel_seconds_d, controller_thread_timeout_cancel_nanoseconds_d, &time);
+
+ status = f_thread_mutex_lock_timed(&time, &main->thread.lock.cancel);
+ if (F_status_is_error(status)) break;
+
+ } while (status != F_okay);
+
+ if (status == F_enable_not) break;
+ if (F_status_is_error(status)) continue;
+ }
+
// If "active" has a read or write lock, then do not attempt to clean it.
- if (f_thread_lock_write_try(&instance->active) != F_okay) continue;
+ if (f_thread_lock_write_try(&instance->active) != F_okay) {
+ f_thread_mutex_unlock(&main->thread.lock.cancel);
+
+ continue;
+ }
// If "lock" has a read or write lock, then do not attempt to clean it.
if (f_thread_lock_write_try(&instance->lock) != F_okay) {
f_thread_unlock(&instance->active);
+ f_thread_mutex_unlock(&main->thread.lock.cancel);
continue;
}
// If instance is active or busy, then do not attempt to clean it.
- if (instance->state == controller_instance_state_active_e || instance->state == controller_instance_state_busy_e || main->thread.enabled != controller_thread_enabled_e) {
+ if (instance->state == controller_instance_state_active_e || instance->state == controller_instance_state_busy_e || controller_thread_enable_get(&main->thread) != controller_thread_enable_e) {
f_thread_unlock(&instance->lock);
f_thread_unlock(&instance->active);
+ f_thread_mutex_unlock(&main->thread.lock.cancel);
- if (main->thread.enabled == controller_thread_enabled_e) continue;
+ if (controller_thread_enable_get(&main->thread) == controller_thread_enable_e) continue;
break;
}
if (instance->path_pids.used) {
f_number_unsigned_t j = 0;
- for (; j < instance->path_pids.used && main->thread.enabled == controller_thread_enabled_e; ++j) {
+ for (; j < instance->path_pids.used && controller_thread_enable_get(&main->thread) == controller_thread_enable_e; ++j) {
if (instance->path_pids.array[j].used && f_file_exists(instance->path_pids.array[j], F_true) == F_true) {
break;
}
} // for
- if (j < instance->path_pids.used || main->thread.enabled != controller_thread_enabled_e) {
+ if (j < instance->path_pids.used || controller_thread_enable_get(&main->thread) != controller_thread_enable_e) {
f_thread_unlock(&instance->lock);
f_thread_unlock(&instance->active);
+ f_thread_mutex_unlock(&main->thread.lock.cancel);
- if (main->thread.enabled == controller_thread_enabled_e) continue;
+ if (controller_thread_enable_get(&main->thread) == controller_thread_enable_e) continue;
break;
}
instance->state = controller_instance_state_idle_e;
instance->id_thread = 0;
- controller_instance_signal_wait(instance);
+ f_thread_condition_signal_all(&instance->wait_condition);
}
else {
f_thread_unlock(&instance->lock);
f_thread_unlock(&instance->active);
+ f_thread_mutex_unlock(&main->thread.lock.cancel);
continue;
}
// Shrink the childs array.
if (instance->childs.used) {
- for (; instance->childs.used && main->thread.enabled == controller_thread_enabled_e; --instance->childs.used) {
+ for (; instance->childs.used && controller_thread_enable_get(&main->thread) == controller_thread_enable_e; --instance->childs.used) {
if (instance->childs.array[instance->childs.used]) break;
} // for
- if (main->thread.enabled != controller_thread_enabled_e) {
+ if (controller_thread_enable_get(&main->thread) != controller_thread_enable_e) {
f_thread_unlock(&instance->lock);
f_thread_unlock(&instance->active);
f_thread_unlock(&instance->lock);
f_thread_unlock(&instance->active);
+ f_thread_mutex_unlock(&main->thread.lock.cancel);
} // for
f_thread_unlock(&main->thread.lock.instance);
controller_t * const main = (controller_t *) argument;
- if (main->thread.enabled != controller_thread_enabled_e) return 0;
+ if (controller_thread_enable_get(&main->thread) != controller_thread_enable_e) return 0;
f_status_t status = F_okay;
--- /dev/null
+#include "../controller.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_controller_thread_enable_get_
+ uint8_t controller_thread_enable_get(controller_thread_t * const thread) {
+
+ if (!thread) return controller_thread_enable_none_e;
+
+ if (f_thread_lock_read_try(&thread->lock.enable) != F_okay) {
+ for (f_time_spec_t time; ; ) {
+
+ memset(&time, 0, sizeof(f_time_spec_t));
+
+ controller_time_now(controller_thread_timeout_lock_read_seconds_d, controller_thread_timeout_lock_read_nanoseconds_d, &time);
+ if (f_thread_lock_read_timed(&time, &thread->lock.enable) == F_okay) break;
+ } // for
+ }
+
+ const uint8_t enable = thread->enable;
+
+ f_thread_unlock(&thread->lock.enable);
+
+ return enable;
+ }
+#endif // _di_controller_thread_enable_get_
+
+#ifndef _di_controller_thread_enable_is_
+ f_status_t controller_thread_enable_is(controller_thread_t * const thread, const uint8_t is_normal) {
+
+ if (!thread) return F_false;
+
+ const uint8_t enable = controller_thread_enable_get(thread);
+
+ return is_normal ? enable == controller_thread_enable_e : enable;
+ }
+#endif // _di_controller_thread_enable_is_
+
+#ifndef _di_controller_thread_enable_set_
+ f_status_t controller_thread_enable_set(controller_thread_t * const thread, const uint8_t value) {
+
+ if (!thread) return F_status_set_error(F_parameter);
+
+ if (f_thread_lock_write_try(&thread->lock.enable) != F_okay) {
+ for (f_time_spec_t time; ; ) {
+
+ memset(&time, 0, sizeof(f_time_spec_t));
+
+ controller_time_now(controller_thread_timeout_lock_write_seconds_d, controller_thread_timeout_lock_write_nanoseconds_d, &time);
+ if (f_thread_lock_write_timed(&time, &thread->lock.enable) == F_okay) break;
+ } // for
+ }
+
+ thread->enable = value;
+
+ f_thread_unlock(&thread->lock.enable);
+
+ return F_okay;
+ }
+#endif // _di_controller_thread_enable_set_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 3
+ *
+ * Project: Controller
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides the thread "enable" functionality.
+ *
+ * This is auto-included and should not need to be explicitly included.
+ */
+#ifndef _controller_main_thread_enable_h
+#define _controller_main_thread_enable_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the enable state of the system in a thread-safe manner.
+ *
+ * This infinitely tries to obtain the read lock.
+ *
+ * Locks used on run:
+ * - main.thread.lock.enable (read lock).
+ *
+ * Locks held on exit:
+ * - None.
+ *
+ * @param thread
+ * The thread data.
+ *
+ * Must not be NULL.
+ *
+ * @return
+ * The enable status on success.
+ *
+ * controller_thread_enable_none_e on any error.
+ *
+ * @see controller_time_now()
+ *
+ * @see f_thread_lock_read_timed()
+ * @see f_thread_lock_read_try()
+ * @see f_thread_unlock()
+ */
+#ifndef _di_controller_thread_enable_get_
+ extern uint8_t controller_thread_enable_get(controller_thread_t * const thread);
+#endif // _di_controller_thread_enable_get_
+
+/**
+ * Check to see if thread is enabled for the normal operations like Entry and Control or for Exit operations in a thread-safe manner.
+ *
+ * @param thread
+ * The thread data.
+ *
+ * Must not be NULL.
+ * @param is_normal
+ * If TRUE, then instance as if this operates during a normal operation (Entry and Control).
+ * If FALSE, then instance as if this operates during an Exit operation.
+ *
+ * @return
+ * F_true when enabled.
+ * F_false when disabled.
+ *
+ * @see controller_thread_enable_get()
+ */
+#ifndef _di_controller_thread_enable_is_
+ extern f_status_t controller_thread_enable_is(controller_thread_t * const thread, const uint8_t is_normal);
+#endif // _di_controller_thread_enable_is_
+
+/**
+ * Set the enable state of the system in a thread-safe manner.
+ *
+ * This infinitely tries to obtain the write lock.
+ *
+ * Locks used on run:
+ * - main.thread.lock.enable (write lock).
+ *
+ * Locks held on exit:
+ * - None.
+ *
+ * @param thread
+ * The thread data.
+ *
+ * Must not be NULL.
+ * @param value
+ * The new value to assign to the thread enable.
+ *
+ * @return
+ * F_okay on success.
+ *
+ * F_parameter (with error bit) if a parmeter is invalid.
+ *
+ * @see f_thread_lock_write_timed()
+ * @see f_thread_lock_write_try()
+ * @see f_thread_unlock()
+ */
+#ifndef _di_controller_thread_enable_set_
+ extern f_status_t controller_thread_enable_set(controller_thread_t * const thread, const uint8_t value);
+#endif // _di_controller_thread_enable_set_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _controller_main_thread_enable_h
controller_t * const main = (controller_t *) argument;
- if (!controller_thread_is_enabled(&main->thread, F_true)) return 0;
+ if (!controller_thread_enable_is(&main->thread, F_true)) return 0;
f_status_t * const status = &main->thread.status;
main->process.ready = controller_process_ready_fail_e;
if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && (main->process.flag & controller_process_flag_failsafe_e)) {
- const uint8_t original_enabled = main->thread.enabled;
+ const uint8_t original_enabled = controller_thread_enable_get(&main->thread);
- // Restore operating mode so that the failsafe can execute.
- *status = f_thread_mutex_lock(&main->thread.lock.alert);
-
- if (F_status_is_error_not(*status)) {
- main->thread.enabled = controller_thread_enabled_e;
-
- f_thread_mutex_unlock(&main->thread.lock.alert);
- }
+ controller_thread_enable_set(&main->thread, controller_thread_enable_e);
// Restart the signal main->thread to allow for signals while operating the failsafe Items.
if (!main->thread.id_signal) {
controller_print_error_failsafe_item(&main->program.error, &main->thread, main->process.entry.items.array[main->process.failsafe_item_id].name);
}
else {
-
- // Restore operating mode to value prior to failsafe mode.
- *status = f_thread_mutex_lock(&main->thread.lock.alert);
-
- if (F_status_is_error_not(*status)) {
- main->thread.enabled = original_enabled;
-
- f_thread_mutex_unlock(&main->thread.lock.alert);
- }
+ controller_thread_enable_set(&main->thread, original_enabled);
*status = F_failure;
}
// According to the manpages, pthread_exit() calls exit(0), which the value of main->program.child should be returned instead.
if (main->program.child) exit(main->program.child);
} else {
- controller_lock_signal(&main->thread.lock.alert_condition, &main->thread.lock.alert);
+ f_thread_condition_signal_all(&main->thread.lock.alert_condition);
}
return 0;
if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && (main->process.flag & controller_process_flag_failsafe_e)) {
- const uint8_t original_enabled = main->thread.enabled;
+ const uint8_t original_enabled = controller_thread_enable_get(&main->thread);
// Restore operating mode so that the failsafe can execute.
if (F_status_set_fine(*status) == F_execute) {
- *status = f_thread_mutex_lock(&main->thread.lock.alert);
-
- if (F_status_is_error_not(*status)) {
- main->thread.enabled = controller_thread_enabled_exit_e;
-
- f_thread_mutex_unlock(&main->thread.lock.alert);
- }
+ controller_thread_enable_set(&main->thread, controller_thread_enable_exit_e);
// Restart the signal thread to allow for signals while operating the failsafe Items.
if (!main->thread.id_signal) {
controller_print_error_failsafe_item(&main->program.error, &main->thread, main->process.entry.items.array[main->process.failsafe_item_id].name);
}
else {
-
- // Restore operating mode to value prior to failsafe mode.
- *status = f_thread_mutex_lock(&main->thread.lock.alert);
-
- if (F_status_is_error_not(*status)) {
- main->thread.enabled = original_enabled;
-
- f_thread_mutex_unlock(&main->thread.lock.alert);
- }
+ controller_thread_enable_set(&main->thread, original_enabled);
*status = F_failure;
}
controller_delete(main);
}
else {
- controller_thread_instance_force_set_disable(main);
- controller_lock_signal(&main->thread.lock.alert_condition, &main->thread.lock.alert);
+ controller_thread_enable_set(&main->thread, controller_thread_enable_not_e);
+
+ f_thread_condition_signal_all(&main->thread.lock.alert_condition);
}
return 0;
void controller_thread_instance(controller_instance_t * const instance, const uint8_t is_normal) {
if (!instance || !instance->main) return;
- if (!controller_thread_is_enabled(&instance->main->thread, is_normal)) return;
+ if (!controller_thread_enable_is(&instance->main->thread, is_normal)) return;
const f_status_t status = controller_rule_instance_perform(instance, controller_instance_option_asynchronous_e);
f_time_spec_t time;
do {
- if (!controller_thread_is_enabled(&main->thread, is_normal)) return;
+ if (!controller_thread_enable_is(&main->thread, is_normal)) return;
memset((void *) &time, 0, sizeof(struct timespec));
status = f_thread_mutex_lock_timed(&time, &main->thread.lock.cancel);
if (F_status_is_error(status)) return;
- } while (status == F_time);
+ } while (status != F_okay);
status = F_okay;
}
// Only cancel when enabled.
- if (!controller_thread_is_enabled(&main->thread, is_normal)) {
+ if (!controller_thread_enable_is(&main->thread, is_normal)) {
f_thread_mutex_unlock(&main->thread.lock.cancel);
return;
} // for
}
- for (f_number_unsigned_t i = 0; i < controller_lock_mutex_max_retry_d; ++i) {
-
- status = f_thread_mutex_lock(&main->thread.lock.alert);
-
- if (F_status_is_error_not(status) || F_status_set_fine(status) == F_parameter || F_status_set_fine(status) == F_deadlock) break;
- } // for
+ {
+ uint8_t enable = controller_thread_enable_exit_e;
- if (F_status_is_error_not(status) && F_status_set_fine(status) != F_parameter && F_status_set_fine(status) != F_deadlock) {
if (by == controller_thread_cancel_execute_e) {
- main->thread.enabled = controller_thread_enabled_execute_e;
+ enable = controller_thread_enable_execute_e;
}
else if (by == controller_thread_cancel_exit_e) {
- main->thread.enabled = controller_thread_enabled_not_e;
+ enable = controller_thread_enable_not_e;
}
else if (by == controller_thread_cancel_exit_execute_e) {
- main->thread.enabled = controller_thread_enabled_exit_execute_e;
- }
- else {
- main->thread.enabled = controller_thread_enabled_exit_e;
+ enable = controller_thread_enable_exit_execute_e;
}
- f_thread_mutex_unlock(&main->thread.lock.alert);
+ controller_thread_enable_set(&main->thread, enable);
}
if (main->thread.id_cleanup) {
instance = main->thread.instances.array[i];
// Do not cancel Exit Instances, when not performing "execute" during exit.
- if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) {
+ if (instance->type == controller_instance_type_exit_e && controller_thread_enable_get(&main->thread) != controller_thread_enable_exit_execute_e) {
continue;
}
instance = main->thread.instances.array[i];
// Do not wait for Instances, when not performing "execute" during exit.
- if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) {
+ if (instance->type == controller_instance_type_exit_e && controller_thread_enable_get(&main->thread) != controller_thread_enable_exit_execute_e) {
continue;
}
instance = main->thread.instances.array[i];
// Do not kill Exit Instances, when not performing "execute" during exit.
- if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) continue;
+ if (instance->type == controller_instance_type_exit_e && controller_thread_enable_get(&main->thread) != controller_thread_enable_exit_execute_e) continue;
if (instance->id_thread) {
if (instance->childs.used) {
for (j = 0; j < instance->childs.size; ++j) {
// Do not kill Exit processes, when not performing "execute" during exit.
- if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) continue;
+ if (instance->type == controller_instance_type_exit_e && controller_thread_enable_get(&main->thread) != controller_thread_enable_exit_execute_e) continue;
if (instance->childs.array[j]) {
for (j = 0; j < instance->path_pids.used; ++j) {
// Do not kill Exit processes, when not performing "execute" during exit.
- if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) continue;
+ if (instance->type == controller_instance_type_exit_e && controller_thread_enable_get(&main->thread) != controller_thread_enable_exit_execute_e) continue;
if (f_file_exists(instance->path_pids.array[j], F_true) == F_true) {
status = controller_file_pid_read(instance->path_pids.array[j], &pid);
while (instance->childs.used) {
// Do not shrink below an Exit Instances, when not performing "execute" during exit.
- if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) break;
+ if (instance->type == controller_instance_type_exit_e && controller_thread_enable_get(&main->thread) != controller_thread_enable_exit_execute_e) break;
if (instance->childs.array[j] > 0) break;
--instance->childs.used;
while (instance->path_pids.used) {
// Do not shrink below an Exit Instances, when not performing "execute" during exit.
- if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) break;
+ if (instance->type == controller_instance_type_exit_e && controller_thread_enable_get(&main->thread) != controller_thread_enable_exit_execute_e) break;
if (instance->path_pids.array[j].used) break;
--instance->path_pids.used;
#ifndef _di_controller_thread_instance_exit_
void controller_thread_instance_exit(controller_t * const main) {
- if (!main || main->thread.enabled != controller_thread_enabled_exit_e) return;
+ if (!main || controller_thread_enable_get(&main->thread) != controller_thread_enable_exit_e) return;
if (main->process.ready == controller_process_ready_done_e) {
controller_print_error_status(&main->program.error, macro_controller_f(f_thread_create), F_status_set_fine(status));
}
- controller_thread_instance_force_set_disable(main);
+ controller_thread_enable_set(&main->thread, controller_thread_enable_not_e);
}
else {
f_time_spec_t time = f_time_spec_t_initialize;
f_thread_mutex_unlock(&main->thread.lock.alert);
- } while (F_status_is_error_not(status) && main->thread.enabled == controller_thread_enabled_exit_e);
+ } while (F_status_is_error_not(status) && controller_thread_enable_get(&main->thread) == controller_thread_enable_exit_e);
- if (F_status_is_error(status)) controller_thread_instance_force_set_disable(main);
+ if (F_status_is_error(status)) controller_thread_enable_set(&main->thread, controller_thread_enable_not_e);
}
// The sigtimedwait() function that is run inside of signal must be interrupted directly via f_thread_signal_write().
controller_thread_instance_cancel(main, F_false, controller_thread_cancel_exit_e);
}
else {
- controller_thread_instance_force_set_disable(main);
+ controller_thread_enable_set(&main->thread, controller_thread_enable_not_e);
}
}
#endif // _di_controller_thread_instance_exit_
-#ifndef _di_controller_thread_instance_force_set_disable_
- void controller_thread_instance_force_set_disable(controller_t * const main) {
-
- if (!main) return;
-
- if (F_status_is_error_not(f_thread_mutex_lock(&main->thread.lock.alert))) {
- main->thread.enabled = controller_thread_enabled_not_e;
-
- f_thread_mutex_unlock(&main->thread.lock.alert);
-
- return;
- }
-
- f_time_spec_t time;
-
- for (uint8_t i = 0; i < controller_thread_exit_disable_force_times; ++i) {
-
- memset((void *) &time, 0, sizeof(struct timespec));
-
- controller_time_now(controller_thread_timeout_exit_disable_force_seconds_d, controller_thread_timeout_exit_disable_force_nanoseconds_d, &time);
-
- if (F_status_is_error_not(f_thread_mutex_lock_timed(&time, &main->thread.lock.alert))) {
- main->thread.enabled = controller_thread_enabled_not_e;
-
- f_thread_mutex_unlock(&main->thread.lock.alert);
-
- return;
- }
- } // for
-
- // Forcibly set disable regardless of the risk.
- main->thread.enabled = controller_thread_enabled_not_e;
- }
-#endif // _di_controller_thread_instance_force_set_disable_
-
#ifndef _di_controller_thread_instance_normal_
void * controller_thread_instance_normal(void * const argument) {
#endif // _di_controller_thread_instance_exit_
/**
- * Set the execution state to disabled during exiting and force the case if need be.
- *
- * The program must exit during the Exit process.
- * The state must be properly set.
- * Perform a limited number of attempts to set the state to exiting.
- * Should this fail, then force the case regardless of the risk.
- *
- * @param main
- * The main program data.
- *
- * Must not be NULL.
- *
- * This does not alter main.setting.state.status.
- *
- * The main.thread.lock.alert lock will be set and then unset if possible.
- * The main.thread.enabled will be updated and set to controller_thread_enabled_not_e.
- */
-#ifndef _di_controller_thread_instance_force_set_disable_
- extern void controller_thread_instance_force_set_disable(controller_t * const main);
-#endif // _di_controller_thread_instance_force_set_disable_
-
-/**
* Asynchronously execute a Rule process during normal operations.
*
* @param argument
extern "C" {
#endif
-#ifndef _di_controller_thread_is_enabled_
- f_status_t controller_thread_is_enabled(controller_thread_t * const thread, const uint8_t is_normal) {
-
- if (!thread) return F_false;
-
- const uint8_t enabled = thread->enabled;
-
- return is_normal ? enabled == controller_thread_enabled_e : enabled;
- }
-#endif // _di_controller_thread_is_enabled_
-
#ifndef _di_controller_thread_is_enabled_instance_
f_status_t controller_thread_is_enabled_instance(controller_instance_t * const instance) {
#ifndef _di_controller_thread_is_enabled_instance_type_
f_status_t controller_thread_is_enabled_instance_type(controller_thread_t * const thread, const uint8_t type) {
- return controller_thread_is_enabled(thread, type != controller_instance_type_exit_e);
+ return controller_thread_enable_is(thread, type != controller_instance_type_exit_e);
}
#endif // _di_controller_thread_is_enabled_instance_type_
#endif
/**
- * Check to see if thread is enabled for the normal operations like Entry and Control or for Exit operations.
- *
- * @param thread
- * The thread data.
- *
- * Must not be NULL.
- * @param is_normal
- * If TRUE, then instance as if this operates during a normal operation (Entry and Control).
- * If FALSE, then instance as if this operates during an Exit operation.
- *
- * @return
- * F_true when enabled.
- * F_false when disabled.
- */
-#ifndef _di_controller_thread_is_enabled_
- extern f_status_t controller_thread_is_enabled(controller_thread_t * const thread, const uint8_t is_normal);
-#endif // _di_controller_thread_is_enabled_
-
-/**
* Check to see if thread is enabled for the normal operations like Entry and Control or for Exit operations for some instance.
*
* @param instance
* The instance type to use when checking if thread is enabled.
*
* @return
- * Success from controller_thread_is_enabled().
+ * Success from controller_thread_enable_is().
*
- * @see controller_thread_is_enabled()
+ * @see controller_thread_enable_is()
*/
#ifndef _di_controller_thread_is_enabled_instance_type_
extern f_status_t controller_thread_is_enabled_instance_type(controller_thread_t * const thread, const uint8_t type);
controller_t * const main = (controller_t *) argument;
- if (!controller_thread_is_enabled(&main->thread, F_true)) return 0;
+ if (!controller_thread_enable_is(&main->thread, F_true)) return 0;
return 0;
}
void controller_thread_signal(controller_t * const main, const uint8_t is_normal) {
if (!main) return;
- if (!controller_thread_is_enabled(&main->thread, is_normal)) return;
+ if (!controller_thread_enable_is(&main->thread, is_normal)) return;
if (!(main->setting.flag & controller_main_flag_interruptible_d)) return;
siginfo_t information;
f_time_spec_t time = f_time_spec_t_initialize;
- while (controller_thread_is_enabled(&main->thread, is_normal)) {
+ while (controller_thread_enable_is(&main->thread, is_normal)) {
memset((void *) &information, 0, sizeof(siginfo_t));
// Send F_signal_reserved_35 to cleanup process to reap child processes.
if (information.si_signo == F_signal_child || information.si_signo == F_signal_reserved_35) {
- controller_lock_signal(&main->thread.lock.reap_condition, &main->thread.lock.reap);
+ f_thread_condition_signal_all(&main->thread.lock.reap_condition);
continue;
}
if (information.si_signo == F_signal_interrupt || information.si_signo == F_signal_abort || information.si_signo == F_signal_quit || information.si_signo == F_signal_termination) {
main->thread.signal = information.si_signo;
- controller_lock_signal(&main->thread.lock.reap_condition, &main->thread.lock.reap);
+ f_thread_condition_signal_all(&main->thread.lock.reap_condition);
controller_thread_instance_cancel(main, is_normal, controller_thread_cancel_signal_e);
break;
if (!interrupt->main) return;
- if (!controller_thread_is_enabled(&interrupt->main->thread, interrupt->is_normal)) {
+ if (!controller_thread_enable_is(&interrupt->main->thread, interrupt->is_normal)) {
interrupt->main->program.signal_received = F_signal_abort;
interrupt->main->setting.state.status = F_status_set_error(F_interrupt);
}
if (!interrupt->main) return;
- if (!controller_thread_is_enabled(&interrupt->main->thread, interrupt->is_normal)) {
+ if (!controller_thread_enable_is(&interrupt->main->thread, interrupt->is_normal)) {
interrupt->main->program.signal_received = F_signal_abort;
interrupt->main->setting.state.status = F_status_set_error(F_interrupt);
}