echo "$BASHPID" > /tmp/sleeper_1.pid
echo "Sleeper 1, now sleeping."
- sleep 20m
+ sleep 1m
echo "Sleeper 1, done sleeping."
rm -f /tmp/sleeper_1.pid
echo "$BASHPID" > /tmp/sleeper_2.pid
echo "Sleeper 2, now sleeping."
- sleep 25m
+ sleep 2m
echo "Sleeper 2, done sleeping."
rm -f /tmp/sleeper_2.pid
echo "$BASHPID" > /tmp/sleeper_3.1.pid
echo "Sleeper 3.1, now sleeping."
- sleep 15
+ sleep 10
echo "Sleeper 3.1, done sleeping."
rm -f /tmp/sleeper_3.1.pid
#ifndef _di_controller_error_simplify_
f_status_t controller_error_simplify(const f_status_t status) {
- if (status == F_memory_not) {
- return F_status_set_error(F_memory);
- }
-
- if (status == F_file_open_max || status == F_space_not || status == F_busy) {
- return F_status_set_error(F_resource);
- }
-
- if (status == F_access_denied || status == F_filesystem_quota_block || status == F_prohibited || status == F_input_output) {
- return F_status_set_error(F_access);
- }
-
- if (status == F_complete_not_utf || status == F_complete_not_utf_block || status == F_complete_not_utf_eof || status == F_complete_not_utf_eol || status == F_complete_not_utf_eos || status == F_complete_not_utf_stop) {
- return F_status_set_error(F_encoding);
- }
-
- if (status == F_number || status == F_number_negative || status == F_number_positive || status == F_number_overflow) {
- return F_status_set_error(F_number);
- }
-
- if (status == F_parameter || status == F_found_not || status == F_interrupt || status == F_support_not || status == F_critical) {
- return F_status_set_error(status);
- }
-
- if (status == F_valid_not) {
- return F_status_set_error(F_valid_not);
+ switch (status) {
+ case F_memory_not:
+ return F_status_set_error(F_memory);
+
+ case F_file_open_max:
+ case F_space_not:
+ case F_busy:
+ return F_status_set_error(F_resource);
+
+ case F_access_denied:
+ case F_filesystem_quota_block:
+ case F_prohibited:
+ case F_input_output:
+ return F_status_set_error(F_access);
+
+ case F_complete_not_utf:
+ case F_complete_not_utf_block:
+ case F_complete_not_utf_eof:
+ case F_complete_not_utf_eol:
+ case F_complete_not_utf_eos:
+ case F_complete_not_utf_stop:
+ return F_status_set_error(F_encoding);
+
+ case F_number:
+ case F_number_negative:
+ case F_number_positive:
+ case F_number_overflow:
+ return F_status_set_error(F_number);
+
+ case F_parameter:
+ case F_found_not:
+ case F_interrupt:
+ case F_support_not:
+ case F_critical:
+ return F_status_set_error(status);
+
+ case F_valid_not:
+ return F_status_set_error(F_valid_not);
}
return F_status_set_error(F_failure);
memset(&main->process.control.server.address, 0, sizeof(f_socket_address_t));
{
- const uint8_t codes[] = {
+ const f_number_unsigned_t codes[] = {
controller_parameter_cgroup_e,
controller_parameter_pid_e,
controller_parameter_settings_e,
controller_long_socket_s,
};
+ const uint16_t flags[] = {
+ 0,
+ controller_main_flag_pid_e,
+ 0,
+ 0,
+ };
+
+ main->setting.state.status = F_okay;
+
for (index = 0; index < 4; ++index) {
if (main->program.parameters.array[codes[index]].result & f_console_result_found_e) {
main->setting.state.status = F_status_set_error(F_parameter);
fll_program_print_error_parameter_missing_value(&main->program.error, f_console_symbol_long_normal_s, strings[index]);
-
- return;
+ }
+ else if (main->program.parameters.array[codes[index]].result & f_console_result_value_e) {
+ if (flags[index]) main->setting.flag |= flags[index];
}
} // for
+
+ if (F_status_is_error(main->setting.state.status)) return;
}
// The first remaining argument represents the Entry name.
return;
}
+ {
+ const f_number_unsigned_t codes[] = {
+ controller_parameter_daemon_e,
+ controller_parameter_simulate_e,
+ controller_parameter_validate_e,
+ };
+
+ const uint16_t flags[] = {
+ controller_main_flag_daemon_e,
+ controller_main_flag_simulate_e,
+ controller_main_flag_validate_e,
+ };
+
+ for (index = 0; index < 3; ++index) {
+ if (main->program.parameters.array[codes[index]].result & f_console_result_value_e) main->setting.flag |= flags[index];
+ } // for
+ }
+
main->process.path_setting.used = 0;
if (main->program.parameters.array[controller_parameter_settings_e].locations.used) {
}
}
- if (main->program.parameters.array[controller_parameter_pid_e].result & f_console_result_value_e) {
- main->setting.flag |= controller_main_flag_pid_e;
- }
-
if (!main->process.path_pid.used && !(main->setting.flag & controller_main_flag_pid_e)) {
main->setting.state.status = f_string_dynamic_append(controller_default_path_pid_s, &main->process.path_pid);
else if (main->program.parameters.array[controller_parameter_uninterruptible_e].result & f_console_result_found_e) {
main->setting.flag &= ~controller_main_flag_interruptible_e;
}
-
- if (main->program.parameters.array[controller_parameter_daemon_e].result & f_console_result_found_e) {
- main->setting.flag |= controller_main_flag_daemon_e;
- }
-
- if (main->program.parameters.array[controller_parameter_simulate_e].result & f_console_result_found_e) {
- main->setting.flag |= controller_main_flag_simulate_e;
- }
-
- if (main->program.parameters.array[controller_parameter_validate_e].result & f_console_result_found_e) {
- main->setting.flag |= controller_main_flag_validate_e;
- }
}
#endif // _di_controller_setting_load_
#define controller_with_session_same_d 0x4
#endif // _di_controller_with_d_
+/**
+ * Controller lock defines.
+ *
+ * controller_lock_*_d:
+ * - mutex_max_retry: The maximum amount of times to retry the mutex lock before giving up.
+ */
+#ifndef _di_controller_lock_d_
+ #define controller_lock_mutex_max_retry_d 1000000
+#endif // _di_controller_lock_d_
+
+/**
+ * Flags associated with Controller locks.
+ *
+ * controller_lock_flag_*_d:
+ * - setup_not: No locks are initialized, so do not attempt to deallocate them.
+ */
+#ifndef _di_controller_lock_flag_d_
+ #define controller_lock_flag_setup_not_d 0x1
+#endif // _di_controller_lock_flag_d_
+
#ifdef __cplusplus
} // extern "C"
#endif
#ifndef _di_controller_lock_delete_
void controller_lock_delete(controller_lock_t * const lock) {
+ if (!lock || (lock->flag & controller_lock_flag_setup_not_d)) return;
+
f_thread_mutex_delete(&lock->alert);
f_thread_mutex_delete(&lock->cancel);
f_thread_mutex_delete(&lock->print);
f_thread_lock_delete(&lock->rule);
f_thread_condition_delete(&lock->alert_condition);
-
- memset(&lock->alert, 0, sizeof(f_thread_mutex_t));
- memset(&lock->cancel, 0, sizeof(f_thread_mutex_t));
- memset(&lock->print, 0, sizeof(f_thread_mutex_t));
-
- memset(&lock->instance, 0, sizeof(f_thread_lock_t));
- memset(&lock->rule, 0, sizeof(f_thread_lock_t));
-
- memset(&lock->alert_condition, 0, sizeof(f_thread_condition_t));
}
#endif // _di_controller_lock_delete_
* The Rule lock is intended to lock any activity on the rules structure.
*
* Properties:
+ * - flag: A set of flags associated with the locks.
* - alert: The alert mutex lock for waking up on alerts.
* - cancel: The cancel mutex lock for locking the cancel operation.
* - print: The print mutex lock.
*/
#ifndef _di_controller_lock_t_
typedef struct {
+ uint8_t flag;
+
f_thread_mutex_t alert;
f_thread_mutex_t cancel;
f_thread_mutex_t print;
} controller_lock_t;
#define controller_lock_t_initialize { \
+ 0, \
f_thread_mutex_t_initialize, \
f_thread_mutex_t_initialize, \
f_thread_mutex_t_initialize, \
*
* 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:
/**
* Convert the string from a string representation of an ID or a user name into the numeric representation of that ID or user name.
*
+ * @param cache
+ * The cache.
+ *
+ * Must not be NULL.
* @param buffer
- * A string containing user name or ID.
+ * A string containing group name or ID.
* @param range
* The range within the buffer specifically containing the name or ID.
- * @param cache
- * The cache.
* @param id
* The determined user ID.
*
+ * Must not be NULL.
+ *
* @return
* F_okay on success.
*
/**
* Convert the string from a string representation of an ID or a group name into the numeric representation of that ID or group name.
*
+ * @param cache
+ * The cache.
+ *
+ * Must not be NULL.
* @param buffer
* A string containing group name or ID.
* @param range
* The range within the buffer specifically containing the name or ID.
- * @param cache
- * The cache.
* @param id
- * The determined group ID.
+ * The determined user ID.
+ *
+ * Must not be NULL.
*
* @return
* F_okay on success.
#endif
#ifndef _di_controller_entry_read_
- f_status_t controller_entry_read(controller_t * const main, controller_entry_t * const entry) {
+ f_status_t controller_entry_read(controller_t * const main, const uint8_t is_entry) {
if (!main) return F_status_set_error(F_parameter);
- controller_interrupt_t custom = macro_controller_interrupt_t_initialize_1(entry->flag & controller_entry_flag_is_e, main);
+ controller_entry_t * const entry = is_entry ? &main->process.entry : &main->process.exit;
+
+ controller_interrupt_t custom = macro_controller_interrupt_t_initialize_1(is_entry, main);
f_state_t state = macro_f_state_t_initialize_1(controller_allocation_large_d, controller_allocation_small_d, F_okay, 0, 0, 0, &controller_thread_signal_state_fss, 0, 0, 0);
f_number_unsigned_t i = 0;
main->thread.cache.action.name_item.used = 0;
if (F_status_is_error_not(state.status)) {
- if (entry->flag & controller_entry_flag_is_e) {
+ if (is_entry) {
state.status = controller_file_load(main, F_true, controller_entries_s, main->process.name_entry, controller_entry_s);
}
else {
state.status = controller_file_load(main, F_false, controller_exits_s, main->process.name_entry, controller_exit_s);
- if (state.status == F_file_found_not) return F_file_found_not;
+
+ // Immediately return on error whole loading the Exit.
+ if (state.status == F_file_found_not) {
+ entry->status = controller_status_simplify_error(F_file_found_not);
+
+ return F_status_set_error(F_file_found_not);
+ }
}
}
f_fss_apply_delimit(main->thread.cache.delimits, &main->thread.cache.buffer_file, &state);
if (F_status_is_error(state.status)) {
- controller_print_error_entry(&main->program.error, entry->flag & controller_entry_flag_is_e, F_status_set_fine(state.status), macro_controller_f(f_fss_apply_delimit), F_true);
+ controller_print_error_entry(&main->program.error, is_entry, F_status_set_fine(state.status), macro_controller_f(f_fss_apply_delimit), F_true);
}
}
}
else {
- controller_print_error_file_status(&main->program.error, macro_controller_f(controller_file_load), (entry->flag & controller_entry_flag_is_e) ? controller_entry_s : controller_exit_s, f_file_operation_read_s, fll_error_file_type_file_e, F_status_set_fine(state.status));
+ controller_print_error_file_status(&main->program.error, macro_controller_f(controller_file_load), is_entry ? controller_entry_s : controller_exit_s, f_file_operation_read_s, fll_error_file_type_file_e, F_status_set_fine(state.status));
}
}
state.status = f_memory_array_increase_by(main->thread.cache.object_items.used, sizeof(f_range_t), (void **) &main->thread.cache.object_items.array, &main->thread.cache.object_items.used, &main->thread.cache.object_items.size);
if (F_status_is_error(state.status)) {
- controller_print_error_entry(&main->program.error, entry->flag & controller_entry_flag_is_e, F_status_set_fine(state.status), macro_controller_f(f_memory_array_increase_by), F_true);
+ controller_print_error_entry(&main->program.error, is_entry, F_status_set_fine(state.status), macro_controller_f(f_memory_array_increase_by), F_true);
}
else {
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(entry->flag & controller_entry_flag_is_e, &main->thread); ++i) {
+ for (i = 0; i < main->thread.cache.object_items.used && controller_thread_is_enabled(&main->thread, is_entry); ++i) {
code &= ~0x2;
at = 0;
state.status = f_memory_array_increase(controller_allocation_small_d, sizeof(controller_entry_item_t), (void **) &entry->items.array, &entry->items.used, &entry->items.size);
if (F_status_is_error(state.status)) {
- controller_print_error_entry(&main->program.error, entry->flag & controller_entry_flag_is_e, F_status_set_fine(state.status), macro_controller_f(f_memory_array_increase), F_true);
+ controller_print_error_entry(&main->program.error, is_entry, F_status_set_fine(state.status), macro_controller_f(f_memory_array_increase), F_true);
break;
}
state.status = f_string_dynamic_partial_append(main->thread.cache.buffer_file, main->thread.cache.object_items.array[i], &main->thread.cache.action.name_item);
if (F_status_is_error(state.status)) {
- controller_print_error_entry(&main->program.error, entry->flag & controller_entry_flag_is_e, F_status_set_fine(state.status), macro_controller_f(f_string_dynamic_partial_append), F_true);
+ controller_print_error_entry(&main->program.error, is_entry, F_status_set_fine(state.status), macro_controller_f(f_string_dynamic_partial_append), F_true);
break;
}
f_fss_count_lines(main->thread.cache.buffer_file, main->thread.cache.object_items.array[i].start, &main->thread.cache.action.line_item, &state);
if (F_status_is_error(state.status)) {
- controller_print_error_entry(&main->program.error, entry->flag & controller_entry_flag_is_e, F_status_set_fine(state.status), macro_controller_f(f_fss_count_lines), F_true);
+ controller_print_error_entry(&main->program.error, is_entry, F_status_set_fine(state.status), macro_controller_f(f_fss_count_lines), F_true);
break;
}
for (j = (code & 0x1) ? 1 : 0; j < entry->items.used; ++j) {
if (f_compare_dynamic(entry->items.array[j].name, main->thread.cache.action.name_item) == F_equal_to) {
- controller_print_warning_entry_item_duplicate_ignore(&main->program.warning, &main->thread.cache, entry->flag & controller_entry_flag_is_e, main->thread.cache.action.name_item);
+ controller_print_warning_entry_item_duplicate_ignore(&main->program.warning, &main->thread.cache, is_entry, main->thread.cache.action.name_item);
code |= 0x2;
}
}
else if (f_compare_dynamic(controller_settings_s, main->thread.cache.action.name_item) == F_equal_to) {
- state.status = controller_entry_setting_read(main, entry->flag & controller_entry_flag_is_e, *range);
+ state.status = controller_entry_setting_read(main, is_entry, *range);
continue;
}
if (F_status_set_fine(state.status) != F_interrupt) {
controller_lock_print(main->program.error.to, &main->thread);
- controller_print_error_entry_cache(&main->program.error, &main->thread.cache.action, entry->flag & controller_entry_flag_is_e);
+ controller_print_error_entry_cache(&main->program.error, &main->thread.cache.action, is_entry);
controller_unlock_print_flush(main->program.error.to, &main->thread);
}
}
} // for
- if (entry->flag & controller_entry_flag_is_e && F_status_set_fine(state.status) == F_interrupt) return state.status;
+ if (is_entry && F_status_set_fine(state.status) == F_interrupt) {
+ entry->status = controller_status_simplify_error(F_status_set_fine(state.status));
+
+ return state.status;
+ }
if (F_status_is_error_not(state.status)) {
if (!(code & 0x1)) {
state.status = F_status_set_error(F_found_not);
- controller_print_message_entry_item_required(&main->program.error, entry->flag & controller_entry_flag_is_e, main->thread.cache.action.name_item, "is not found");
+ controller_print_message_entry_item_required(&main->program.error, is_entry, main->thread.cache.action.name_item, "is not found");
}
main->thread.cache.action.name_action.used = 0;
if (F_status_is_error_not(state.status)) {
controller_entry_action_t *action = 0;
-
f_number_unsigned_t k = 0;
// 0x1 = missing or not, 0x2 = one or more missing.
for (j = 0; j < entry->items.array[i].actions.used; ++j) {
- if (!controller_thread_is_enabled(entry->flag & controller_entry_flag_is_e, &main->thread)) {
+ if (!controller_thread_is_enabled(&main->thread, is_entry)) {
+ entry->status = controller_status_simplify_error(F_interrupt);
+
return F_status_set_error(F_interrupt);
}
break;
}
- controller_print_message_entry_item_required(&main->program.error, entry->flag & controller_entry_flag_is_e, main->thread.cache.action.name_item, "does not exist");
+ controller_print_message_entry_item_required(&main->program.error, is_entry, main->thread.cache.action.name_item, "does not exist");
action->number = 0;
action->status = controller_status_simplify_error(F_found_not);
entry->status = controller_status_simplify_error(F_status_set_fine(state.status));
if (F_status_set_fine(state.status) != F_interrupt) {
- controller_print_error_entry_cache(&main->program.error, &main->thread.cache.action, entry->flag & controller_entry_flag_is_e);
+ controller_print_error_entry_cache(&main->program.error, &main->thread.cache.action, is_entry);
}
}
else {
* @param main
* The main program data.
*
- * Must not be NULL.
- * @param entry
- * The Entry data.
+ * This alters either main.process.entry.state or main.process.exit.state.
*
* Must not be NULL.
+ * @param is_entry
+ * If TRUE, then this operates as an Entry.
+ * If FALSE, then this operates as an Exit.
*
* @return
* F_okay on success.
* @see fll_fss_basic_list_read()
*/
#ifndef _di_controller_entry_read_
- extern f_status_t controller_entry_read(controller_t * const main, controller_entry_t * const entry);
+ extern f_status_t controller_entry_read(controller_t * const main, const uint8_t is_entry);
#endif // _di_controller_entry_read_
#ifdef __cplusplus
return status;
}
- while (controller_thread_is_enabled(is_entry, &main->thread)) {
+ while (controller_thread_is_enabled(&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(is_entry, &main->thread); ++cache->ats.array[at_j]) {
+ for (; cache->ats.array[at_j] < actions->used && controller_thread_is_enabled(&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;
error_has = F_false;
// "main" is not allowed to be used for an "item" and "setting" is not an executable "item".
- if (f_compare_dynamic(controller_main_s, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) {
- continue;
- }
- else if (f_compare_dynamic(controller_settings_s, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) {
- continue;
- }
+ if (f_compare_dynamic(controller_main_s, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) continue;
+ 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(is_entry, &main->thread); ++i) {
+ for (i = 1; i < entry->items.used && controller_thread_is_enabled(&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(is_entry, &main->thread)) return F_status_set_error(F_interrupt);
+ if (!controller_thread_is_enabled(&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) {
#endif
#ifndef _di_controller_entry_process_
- f_status_t controller_entry_process(controller_t * const main, const uint8_t failsafe, const uint8_t is_entry) {
+ f_status_t controller_entry_process(controller_t * const main, const uint8_t is_entry, const uint8_t failsafe) {
f_status_t status = F_okay;
f_status_t status_lock = F_okay;
if (F_status_is_error(status)) return status;
}
- while (controller_thread_is_enabled(is_entry, &main->thread)) {
+ while (controller_thread_is_enabled(&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(is_entry, &main->thread); ++cache->ats.array[at_j]) {
+ for (; cache->ats.array[at_j] < entry_actions->used && controller_thread_is_enabled(&main->thread, is_entry); ++cache->ats.array[at_j]) {
entry_action = &entry_actions->array[cache->ats.array[at_j]];
controller_print_message_entry_item_rule(&main->program.message, entry, entry_action, is_entry, alias_rule);
}
- if (!controller_thread_is_enabled(is_entry, &main->thread)) break;
+ if (!controller_thread_is_enabled(&main->thread, is_entry)) break;
// The Rule is not yet loaded, ensure that it is loaded.
if (status != F_true) {
break;
}
- if (F_status_set_fine(status) == F_interrupt || !controller_thread_is_enabled(is_entry, &main->thread)) {
+ if (F_status_set_fine(status) == F_interrupt || !controller_thread_is_enabled(&main->thread, is_entry)) {
f_thread_unlock(&main->thread.lock.rule);
break;
}
} // while
- if (!controller_thread_is_enabled(is_entry, &main->thread)) return F_status_set_error(F_interrupt);
+ if (!controller_thread_is_enabled(&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;
* The main program data.
*
* Must not be NULL.
- * @param failsafe
- * If TRUE, operate in failsafe mode (starts at designated failsafe Item).
- * If FALSE, operate in normal mode (starts at "main" Item).
* @param is_entry
* If TRUE, then this operates as an Entry.
* If FALSE, then this operates as an Exit.
+ * @param failsafe
+ * If TRUE, operate in failsafe mode (starts at designated failsafe Item).
+ * If FALSE, operate in normal mode (starts at "main" Item).
*
* @return
* F_okay on success.
* @see controller_perform_ready()
*/
#ifndef _di_controller_entry_process_
- extern f_status_t controller_entry_process(controller_t * const main, const uint8_t failsafe, const uint8_t is_entry);
+ extern f_status_t controller_entry_process(controller_t * const main, const uint8_t is_entry, const uint8_t failsafe);
#endif // _di_controller_entry_process_
#ifdef __cplusplus
if (!lock) return F_status_set_error(F_parameter);
f_status_t status = f_thread_mutex_create(0, &lock->alert);
+ if (F_status_is_error(status)) return status;
- if (F_status_is_error_not(status)) {
- status = f_thread_mutex_create(0, &lock->cancel);
- }
+ status = f_thread_mutex_create(0, &lock->cancel);
+
+ if (F_status_is_error(status)) {
+ f_thread_mutex_delete(&lock->alert);
- if (F_status_is_error_not(status)) {
- status = f_thread_mutex_create(0, &lock->print);
+ return status;
}
- if (F_status_is_error_not(status)) {
- status = f_thread_lock_create(0, &lock->instance);
+ status = f_thread_mutex_create(0, &lock->print);
+
+ if (F_status_is_error(status)) {
+ f_thread_mutex_delete(&lock->alert);
+ f_thread_mutex_delete(&lock->cancel);
+
+ return status;
}
- 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(status)) {
+ f_thread_mutex_delete(&lock->alert);
+ f_thread_mutex_delete(&lock->cancel);
+ f_thread_mutex_delete(&lock->print);
+
+ return status;
}
- if (F_status_is_error_not(status)) {
- status = f_thread_mutex_create(0, &lock->alert);
+ status = f_thread_lock_create(0, &lock->rule);
+
+ if (F_status_is_error(status)) {
+ f_thread_mutex_delete(&lock->alert);
+ f_thread_mutex_delete(&lock->cancel);
+ f_thread_mutex_delete(&lock->print);
+ f_thread_lock_delete(&lock->instance);
+
+ return status;
}
- if (F_status_is_error_not(status)) {
- status = f_thread_condition_create(0, &lock->alert_condition);
+
+ status = f_thread_condition_create(0, &lock->alert_condition);
+
+ if (F_status_is_error(status)) {
+ f_thread_mutex_delete(&lock->alert);
+ f_thread_mutex_delete(&lock->cancel);
+ f_thread_mutex_delete(&lock->print);
+ f_thread_lock_delete(&lock->instance);
+ f_thread_lock_delete(&lock->rule);
+
+ return status;
}
- return F_status_is_error(status) ? status : F_okay;
+ lock->flag &= ~controller_lock_flag_setup_not_d;
+
+ return F_okay;
}
#endif // _di_controller_lock_create_
status = f_thread_lock_read_timed(&time, lock);
if (status == F_time) {
- if (check && !controller_thread_is_enabled(is_normal, thread)) return F_status_set_error(F_interrupt);
+ if (check && !controller_thread_is_enabled(thread, is_normal)) return F_status_set_error(F_interrupt);
}
else {
break;
status = f_thread_lock_write_timed(&time, lock);
if (status == F_time) {
- if (check && !controller_thread_is_enabled(is_normal, thread)) return F_status_set_error(F_interrupt);
+ if (check && !controller_thread_is_enabled(thread, is_normal)) return F_status_set_error(F_interrupt);
}
else {
break;
return;
}
- if (F_status_is_error_not(status) && status != F_failure && !(main->setting.flag & controller_main_flag_validate_e) && controller_thread_is_enabled(F_true, &main->thread)) {
+ if (F_status_is_error_not(status) && status != F_failure && !(main->setting.flag & controller_main_flag_validate_e) && controller_thread_is_enabled(&main->thread, F_true)) {
if (main->process.mode == controller_process_mode_service_e) {
controller_thread_join(&main->thread.id_signal);
}
if (F_status_is_error(status)) {
if (F_status_set_fine(status) == F_lock) {
- if (!controller_thread_is_enabled_instance_type(instance->type, &main->thread)) return F_status_set_error(F_interrupt);
+ if (!controller_thread_is_enabled_instance_type(&main->thread, instance->type)) return F_status_set_error(F_interrupt);
}
controller_print_error_rule_item_rule_not_loaded(&main->program.error, &instance->cache.action, dynamics[i]->array[j]);
if (!main || !cache) return F_status_set_error(F_parameter);
- if (!controller_thread_is_enabled_instance_type(type, &main->thread)) {
+ if (!controller_thread_is_enabled_instance_type(&main->thread, type)) {
return F_status_set_error(F_interrupt);
}
}
}
else {
- status = controller_rule_instance_perform(options_force, instance);
+ status = controller_rule_instance_perform(instance, options_force);
if (status == F_child || F_status_set_fine(status) == F_interrupt) {
f_thread_unlock(&instance->active);
#endif // _di_controller_rule_instance_begin_
#ifndef _di_controller_rule_instance_perform_
- f_status_t controller_rule_instance_perform(const uint8_t options_force, controller_instance_t * const instance) {
+ f_status_t controller_rule_instance_perform(controller_instance_t * const instance, const uint8_t options_force) {
if (!instance || !instance->main) return F_status_set_error(F_parameter);
* This does all the preparation work that needs to be synchronously performed within the same thread.
* This will copy the Rule by the alias to the instance structure.
*
+ * @param instance
+ * The instance data.
+ *
+ * Must not be NULL.
* @param options_force
* Force the given instance options, only supporting a subset of instance options.
*
* If controller_instance_option_asynchronous_e, then asynchronously execute.
* If not controller_instance_option_asynchronous_e, then synchronously execute.
- * @param instance
- * The instance data.
- *
- * Must not be NULL.
*
* @return
* F_okay on success.
* @see controller_rule_instance_begin()
*/
#ifndef _di_controller_rule_instance_perform_
- extern f_status_t controller_rule_instance_perform(const uint8_t options_force, controller_instance_t * const instance);
+ extern f_status_t controller_rule_instance_perform(controller_instance_t * const instance, const uint8_t options_force);
#endif // _di_controller_rule_instance_perform_
#ifdef __cplusplus
for (i = 0; i < instance_total; ++i) {
- if (!controller_thread_is_enabled(is_normal, &main->thread)) break;
+ if (!controller_thread_is_enabled(&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);
return status_lock;
}
- if (!controller_thread_is_enabled(is_normal, &main->thread)) return F_status_set_error(F_interrupt);
+ if (!controller_thread_is_enabled(&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;
if (main->thread.enabled != controller_thread_enabled_e) return 0;
- const f_time_spec_t delay = {
- .tv_sec = (main->setting.flag & controller_main_flag_simulate_e)
+ const f_time_spec_t delay = macro_f_time_spec_t_initialize_1(
+ (main->setting.flag & controller_main_flag_simulate_e)
? controller_thread_cleanup_interval_short_d
: controller_thread_cleanup_interval_long_d,
- .tv_nsec = 0,
- };
-
- f_status_t status = F_okay;
+ 0
+ );
while (main->thread.enabled == controller_thread_enabled_e) {
if (main->thread.enabled != controller_thread_enabled_e) break;
if (f_thread_lock_write_try(&main->thread.lock.instance) == F_okay) {
+ f_status_t status = F_okay;
controller_instance_t *instance = 0;
f_number_unsigned_t i = 0;
controller_t * const main = (controller_t *) argument;
- if (!controller_thread_is_enabled(F_true, &main->thread)) return 0;
+ if (!controller_thread_is_enabled(&main->thread, F_true)) return 0;
f_status_t * const status = &main->thread.status;
- *status = controller_entry_read(main, &main->process.entry);
+ *status = controller_entry_read(main, F_true);
if (F_status_set_fine(*status) == F_interrupt) {
main->process.ready = controller_process_ready_abort_e;
controller_print_error_file_pid_exists(&main->program.error, &main->thread, main->process.path_pid);
}
else {
- *status = controller_entry_process(main, F_false, F_true);
+ *status = controller_entry_process(main, F_true, F_false);
if (F_status_is_error(*status)) {
main->process.ready = controller_process_ready_fail_e;
}
}
- if (F_status_is_error_not(*status) && *status != F_child && main->program.parameters.array[controller_parameter_validate_e].result == f_console_result_none_e && main->process.mode == controller_process_mode_helper_e) {
- f_time_spec_t time;
- time.tv_sec = controller_thread_timeout_exit_helper_seconds_d;
- time.tv_nsec = controller_thread_timeout_exit_helper_nanoseconds_d;
+ if (F_status_is_error_not(*status) && *status != F_child && !(main->setting.flag & controller_main_flag_validate_e) && main->process.mode == controller_process_mode_helper_e) {
+ const f_time_spec_t time = macro_f_time_spec_t_initialize_1(controller_thread_timeout_exit_helper_seconds_d, controller_thread_timeout_exit_helper_nanoseconds_d);
- nanosleep(&time, 0);
+ f_time_sleep_spec(time, 0);
controller_thread_instance_cancel(main, F_true, controller_thread_cancel_exit_e);
}
controller_t * const main = (controller_t *) argument;
f_status_t * const status = &main->thread.status;
- *status = controller_entry_read(main, &main->process.exit);
+ *status = controller_entry_read(main, F_false);
if (F_status_set_fine(*status) == F_interrupt) {
main->process.ready = controller_process_ready_abort_e;
}
}
- const f_status_t status_failsafe = controller_entry_process(main, F_true, F_false);
+ const f_status_t status_failsafe = controller_entry_process(main, F_false, F_true);
if (F_status_is_error(status_failsafe)) {
*status = F_status_set_error(F_failure);
#endif
#ifndef _di_controller_thread_instance_
- void controller_thread_instance(const uint8_t is_normal, controller_instance_t * const instance) {
+ void controller_thread_instance(controller_instance_t * const instance, const uint8_t is_normal) {
if (!instance || !instance->main) return;
- if (!controller_thread_is_enabled(is_normal, &instance->main->thread)) return;
+ if (!controller_thread_is_enabled(&instance->main->thread, is_normal)) return;
- const f_status_t status = controller_rule_instance_perform(controller_instance_option_asynchronous_e, instance);
+ const f_status_t status = controller_rule_instance_perform(instance, controller_instance_option_asynchronous_e);
// A forked child Instance should de-allocate memory on exit.
// It seems that this function doesn't return to the calling thread for a forked child Instance, even with the "return 0;" below.
f_thread_mutex_lock(&main->thread.lock.cancel);
// Only cancel when enabled.
- if (!controller_thread_is_enabled(is_normal, &main->thread)) {
+ if (!controller_thread_is_enabled(&main->thread, is_normal)) {
f_thread_mutex_unlock(&main->thread.lock.cancel);
return;
controller_instance_t *instance = 0;
f_time_spec_t time = f_time_spec_t_initialize;
- f_status_t status = F_okay;
f_number_unsigned_t i = 0;
f_number_unsigned_t j = 0;
pid_t pid = 0;
} // for
}
- // Use the alert lock to toggle enabled (using it as if it is a write like and a signal lock).
- status = f_thread_mutex_lock(&main->thread.lock.alert);
+ f_status_t status = F_okay;
- if (F_status_is_error(status)) {
- main->thread.enabled = controller_thread_enabled_not_e;
- }
- else {
+ 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
+
+ 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;
}
f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
- controller_thread_instance(F_true, (controller_instance_t * const) argument);
+ controller_thread_instance((controller_instance_t * const) argument, F_true);
return 0;
}
f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
- controller_thread_instance(F_false, (controller_instance_t * const) argument);
+ controller_thread_instance((controller_instance_t * const) argument, F_false);
return 0;
}
/**
* Asynchronously execute a Rule process.
*
- * @param is_normal
- * If F_true, then process as if this operates during a normal operation (Entry and Control).
- * If F_false, then process as if this operates during an Exit operation.
* @param instance
* The instance data.
*
* Must not be NULL.
+ * @param is_normal
+ * If F_true, then process as if this operates during a normal operation (Entry and Control).
+ * If F_false, then process as if this operates during an Exit operation.
*
* @see controller_rule_instance_perform()
*/
#ifndef _di_controller_thread_instance_
- extern void controller_thread_instance(const uint8_t is_normal, controller_instance_t * const instance);
+ extern void controller_thread_instance(controller_instance_t * const instance, const uint8_t is_normal);
#endif // _di_controller_thread_instance_
/**
#endif
#ifndef _di_controller_thread_is_enabled_
- f_status_t controller_thread_is_enabled(const uint8_t is_normal, controller_thread_t * const thread) {
+ f_status_t controller_thread_is_enabled(controller_thread_t * const thread, const uint8_t is_normal) {
if (!thread) return F_false;
- return is_normal ? thread->enabled == controller_thread_enabled_e : thread->enabled;
+ const uint8_t enabled = thread->enabled;
+
+ return is_normal ? enabled == controller_thread_enabled_e : enabled;
}
#endif // _di_controller_thread_is_enabled_
if (!instance) return F_false;
- return controller_thread_is_enabled_instance_type(instance->type, &instance->main->thread);
+ return controller_thread_is_enabled_instance_type(&instance->main->thread, instance->type);
}
#endif // _di_controller_thread_is_enabled_instance_
#ifndef _di_controller_thread_is_enabled_instance_type_
- f_status_t controller_thread_is_enabled_instance_type(const uint8_t type, controller_thread_t * const thread) {
+ f_status_t controller_thread_is_enabled_instance_type(controller_thread_t * const thread, const uint8_t type) {
- return controller_thread_is_enabled(type != controller_instance_type_exit_e, thread);
+ return controller_thread_is_enabled(thread, type != controller_instance_type_exit_e);
}
#endif // _di_controller_thread_is_enabled_instance_type_
/**
* Check to see if thread is enabled for the normal operations like Entry and Control or for Exit operations.
*
- * @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.
* @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(const uint8_t is_normal, controller_thread_t * const thread);
+ 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 type.
*
- * @param type
- * The instance type to use when checking if thread is enabled.
* @param thread
* The thread data.
*
* Must not be NULL.
+ * @param type
+ * The instance type to use when checking if thread is enabled.
*
* @return
* Success from controller_thread_is_enabled().
* @see controller_thread_is_enabled()
*/
#ifndef _di_controller_thread_is_enabled_instance_type_
- extern f_status_t controller_thread_is_enabled_instance_type(const uint8_t type, controller_thread_t * const thread);
+ extern f_status_t controller_thread_is_enabled_instance_type(controller_thread_t * const thread, const uint8_t type);
#endif // _di_controller_thread_is_enabled_instance_type_
#ifdef __cplusplus
controller_t * const main = (controller_t *) argument;
- if (!controller_thread_is_enabled(F_true, &main->thread)) return 0;
+ if (!controller_thread_is_enabled(&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(is_normal, &main->thread)) return;
+ if (!controller_thread_is_enabled(&main->thread, is_normal)) return;
if (!(main->setting.flag & controller_main_flag_interruptible_e)) return;
siginfo_t information;
f_time_spec_t time = f_time_spec_t_initialize;
- while (controller_thread_is_enabled(is_normal, &main->thread)) {
+ while (controller_thread_is_enabled(&main->thread, is_normal)) {
memset((void *) &information, 0, sizeof(siginfo_t));
if (!interrupt->main) return;
- if (!controller_thread_is_enabled(interrupt->is_normal, &interrupt->main->thread)) {
+ if (!controller_thread_is_enabled(&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->is_normal, &interrupt->main->thread)) {
+ if (!controller_thread_is_enabled(&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);
}