| File: | /shared/playproj/i2c/src/dw/dw_recheck.c |
| Warning: | line 208, column 28 Access to field 'initial_ts_nanos' results in a dereference of a null pointer (loaded from variable 'rqe') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /** @file dw_recheck.c | |||
| 2 | * | |||
| 3 | * Process the queue of display references added in | |||
| 4 | * the main loop for which DDC communication was not | |||
| 5 | * immediately detected as enabled. | |||
| 6 | */ | |||
| 7 | ||||
| 8 | // Copyright (C) 2025-2026 Sanford Rockowitz <rockowitz@minsoft.com> | |||
| 9 | // SPDX-License-Identifier: GPL-2.0-or-later | |||
| 10 | ||||
| 11 | #include <glib-2.0/glib.h> | |||
| 12 | ||||
| 13 | #include "public/ddcutil_types.h" | |||
| 14 | ||||
| 15 | #include "util/timestamp.h" | |||
| 16 | #include "util/traced_function_stack.h" | |||
| 17 | ||||
| 18 | #include "base/core.h" | |||
| 19 | #include "base/displays.h" | |||
| 20 | #include "base/rtti.h" | |||
| 21 | #include "base/sleep.h" | |||
| 22 | ||||
| 23 | #include "ddc/ddc_displays.h" | |||
| 24 | #include "ddc/ddc_initial_checks.h" | |||
| 25 | ||||
| 26 | #include "dw_common.h" | |||
| 27 | #include "dw_dref.h" | |||
| 28 | #include "dw_status_events.h" | |||
| 29 | #include "dw_poll.h" // or process_event_mutex, todo: move | |||
| 30 | ||||
| 31 | #include "dw_recheck.h" | |||
| 32 | ||||
| 33 | static DDCA_Trace_Group TRACE_GROUP = DDCA_TRC_CONN; | |||
| 34 | ||||
| 35 | ||||
| 36 | #ifdef UNUSED | |||
| 37 | static int simple_ipow(int base, int exponent) { | |||
| 38 | assert(exponent >= 0)((exponent >= 0) ? (void) (0) : __assert_fail ("exponent >= 0" , "dw_recheck.c", 38, __extension__ __PRETTY_FUNCTION__)); | |||
| 39 | int result = 1; | |||
| 40 | for (int i = 0; i < exponent; i++) { | |||
| 41 | result = result * base; | |||
| 42 | } | |||
| 43 | return result; | |||
| 44 | } | |||
| 45 | #endif | |||
| 46 | ||||
| 47 | ||||
| 48 | static void emit_recheck_debug_msg( | |||
| 49 | bool_Bool debug, | |||
| 50 | DDCA_Syslog_Level syslog_level, | |||
| 51 | const char * format, ...) | |||
| 52 | { | |||
| 53 | va_list args; | |||
| 54 | va_start(args, format)__builtin_va_start(args, format); | |||
| 55 | char buffer[200]; | |||
| 56 | vsnprintf(buffer, 200, format, args); | |||
| 57 | va_end(args)__builtin_va_end(args); | |||
| 58 | ||||
| 59 | DBGTRC_NOPREFIX(debug, DDCA_TRC_NONE, "%s", buffer)dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 59, "dw_recheck.c", " " "%s", buffer); | |||
| 60 | SYSLOG2(syslog_level, "%s", buffer)do { if (test_emit_syslog(syslog_level)) { int syslog_priority = syslog_importance_from_ddcutil_syslog_level(syslog_level); if (syslog_priority >= 0) { char * body = g_strdup_printf ("%s", buffer); syslog(syslog_priority, "[%6jd]"" %s%s", (intmax_t ) tid(), body, (tag_output) ? " (P)" : "" ); free(body); } } } while(0); | |||
| 61 | } | |||
| 62 | ||||
| 63 | ||||
| 64 | typedef struct { | |||
| 65 | Display_Ref* dref; | |||
| 66 | uint64_t initial_ts_nanos; | |||
| 67 | int sleepctr; | |||
| 68 | } Recheck_Queue_Entry; | |||
| 69 | ||||
| 70 | ||||
| 71 | static void dw_free_recheck_queue_entry(Recheck_Queue_Entry * entry) { | |||
| 72 | free(entry); | |||
| 73 | } | |||
| 74 | ||||
| 75 | ||||
| 76 | GAsyncQueue * recheck_queue = NULL((void*)0); | |||
| 77 | // GMutex * recheck_queue_mutex = NULL; | |||
| 78 | ||||
| 79 | ||||
| 80 | static GAsyncQueue * | |||
| 81 | init_recheck_queue() { | |||
| 82 | recheck_queue = g_async_queue_new(); | |||
| 83 | return recheck_queue; | |||
| 84 | } | |||
| 85 | ||||
| 86 | ||||
| 87 | /** Adds a display reference to the recheck queue | |||
| 88 | * | |||
| 89 | * @param dref display reference | |||
| 90 | */ | |||
| 91 | void dw_put_recheck_queue(Display_Ref* dref) { | |||
| 92 | bool_Bool debug = false0; | |||
| 93 | DBGTRC_STARTING(debug, DDCA_TRC_CONN, "dref=%s", dref_reprx_t(dref))do { if (traced_function_stack_enabled) push_traced_function( __func__); dbgtrc( (debug) || trace_callstack_call_depth > 0 || is_traced_callstack_call(__func__) ? DDCA_TRC_ALL : (DDCA_TRC_CONN ), 0x08, __func__, 93, "dw_recheck.c", "Starting ""dref=%s", dref_reprx_t(dref)); } while(0); | |||
| 94 | ||||
| 95 | Recheck_Queue_Entry * entry = calloc(1, sizeof(Recheck_Queue_Entry)); | |||
| 96 | entry->dref = dref; | |||
| 97 | entry->initial_ts_nanos = cur_realtime_nanosec(); | |||
| 98 | entry->sleepctr = 0; | |||
| 99 | ||||
| 100 | // g_mutex_lock(recheck_queue_mutex); | |||
| 101 | g_async_queue_push(recheck_queue, entry); | |||
| 102 | // g_mutex_unlock(recheck_queue_mutex); | |||
| 103 | ||||
| 104 | DBGTRC_DONE(debug, DDCA_TRC_CONN, "")do { dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_CONN), 0x10, __func__, 104, "dw_recheck.c", "Done " ""); if (traced_function_stack_enabled) pop_traced_function(__func__ ); } while (0); | |||
| 105 | } | |||
| 106 | ||||
| 107 | ||||
| 108 | #ifdef NO | |||
| 109 | typedef struct { | |||
| 110 | GArray * deferred_event_queue; | |||
| 111 | GMutex * deferred_event_queue_mutex; | |||
| 112 | } Recheck_Displays_Data; | |||
| 113 | #endif | |||
| 114 | ||||
| 115 | STATICstatic Error_Info * | |||
| 116 | dw_recheck_dref(Display_Ref * dref) { | |||
| 117 | bool_Bool debug = false0; | |||
| 118 | DBGTRC_STARTING(debug, DDCA_TRC_NONE, "dref=%s", dref_reprx_t(dref))do { if (traced_function_stack_enabled) push_traced_function( __func__); dbgtrc( (debug) || trace_callstack_call_depth > 0 || is_traced_callstack_call(__func__) ? DDCA_TRC_ALL : (DDCA_TRC_NONE ), 0x08, __func__, 118, "dw_recheck.c", "Starting ""dref=%s" , dref_reprx_t(dref)); } while(0); | |||
| 119 | Error_Info * err = NULL((void*)0); | |||
| 120 | ||||
| 121 | DDCA_Status ddcrc = dref_lock(dref); | |||
| 122 | if (ddcrc != 0) { | |||
| 123 | err = ERRINFO_NEW(ddcrc, "dref_lock() failed for %s", dref_reprx_t(dref))errinfo_new(ddcrc, __func__, "dref_lock() failed for %s", dref_reprx_t (dref)); | |||
| 124 | SYSLOG2(DDCA_SYSLOG_ERROR, "dref_lock() failed for %s", dref_reprx_t(dref))do { if (test_emit_syslog(DDCA_SYSLOG_ERROR)) { int syslog_priority = syslog_importance_from_ddcutil_syslog_level(DDCA_SYSLOG_ERROR ); if (syslog_priority >= 0) { char * body = g_strdup_printf ("dref_lock() failed for %s", dref_reprx_t(dref)); syslog(syslog_priority , "[%6jd]"" %s%s", (intmax_t) tid(), body, (tag_output) ? " (P)" : "" ); free(body); } } } while(0); | |||
| 125 | } | |||
| 126 | else { | |||
| 127 | DBGTRC_NOPREFIX(debug, DDCA_TRC_NONE, "Obtained lock on %s:", dref_reprx_t(dref))dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 127, "dw_recheck.c", " " "Obtained lock on %s:", dref_reprx_t(dref)); | |||
| 128 | err = ddc_initial_checks_by_dref(dref, false0); | |||
| 129 | dref_unlock(dref); | |||
| 130 | DBGTRC_NOPREFIX(debug, DDCA_TRC_NONE, "Released lock on %s:", dref_reprx_t(dref))dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 130, "dw_recheck.c", " " "Released lock on %s:", dref_reprx_t(dref)); | |||
| 131 | } | |||
| 132 | ||||
| 133 | DBGTRC_RET_ERRINFO(debug, DDCA_TRC_NONE, err, "")do { dbgtrc_returning_errinfo( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x10, __func__, 133 , "dw_recheck.c", err, ""); if (traced_function_stack_enabled ) pop_traced_function(__func__); } while (0); | |||
| 134 | return err; | |||
| 135 | } | |||
| 136 | ||||
| 137 | ||||
| 138 | /** Function that executes in the recheck thread to check if DDC | |||
| 139 | * communication has become enabled for newly added display refs for which | |||
| 140 | * DDC communication was not initially detected as working. | |||
| 141 | * | |||
| 142 | * @param data pointer to a #Recheck_Displays_Data struct | |||
| 143 | * | |||
| 144 | * At increasing time intervals, each display ref is checked to see if DDC | |||
| 145 | * communication is working. If so, a #DDC_Display_Status event of type | |||
| 146 | * #DDCA_EVENT_DDC_ENABLED is emitted, and the display ref is removed from | |||
| 147 | * from the array. | |||
| 148 | * | |||
| 149 | * The time intervals are calculated as follows. The intervals are numbered | |||
| 150 | * from 0. The base interval is global variable #retry_thread_sleep_factor_millis. | |||
| 151 | * An adjustment factor is calculated as 2**i, where i is the interval number, | |||
| 152 | * i.e. 1, 2, 4, 8 etc. | |||
| 153 | * | |||
| 154 | * The thread terminates when either all display refs have been removed from | |||
| 155 | * the array because communication has succeeded, or because the maximum of | |||
| 156 | * sleep intervals have occurred, i.e. until a total of | |||
| 157 | * (1+2+4+8)*retry_thread_sleep_factor_millis milliseconds have been slept. | |||
| 158 | * | |||
| 159 | * On termination the **displays to recheck** array is freed. Note that the | |||
| 160 | * display references themselves are not; display references are persistent. | |||
| 161 | */ | |||
| 162 | gpointer dw_recheck_displays_func(gpointer data) { | |||
| 163 | bool_Bool debug = false0; | |||
| 164 | DBGTRC_STARTING(debug, TRACE_GROUP, "data=%p", data)do { if (traced_function_stack_enabled) push_traced_function( __func__); dbgtrc( (debug) || trace_callstack_call_depth > 0 || is_traced_callstack_call(__func__) ? DDCA_TRC_ALL : (TRACE_GROUP ), 0x08, __func__, 164, "dw_recheck.c", "Starting ""data=%p" , data); } while(0); | |||
| ||||
| 165 | Recheck_Displays_Data* rdd = (Recheck_Displays_Data *) data; | |||
| 166 | init_recheck_queue(); | |||
| 167 | // recheck_thread_active = true; | |||
| 168 | ||||
| 169 | // GPtrArray * displays_to_recheck = g_ptr_array_new(); | |||
| 170 | #ifdef DEBUG | |||
| 171 | for (int ndx = 0; ndx < displays_to_recheck->len; ndx++) { | |||
| 172 | Display_Ref * dref = g_ptr_array_index(displays_to_recheck, ndx)((displays_to_recheck)->pdata)[ndx]; | |||
| 173 | DBGMSG("dref=%s", dref_reprx_t(dref))dbgtrc(DDCA_TRC_ALL, 0x00, __func__, 173, "dw_recheck.c", "dref=%s" , dref_reprx_t(dref)); | |||
| 174 | } | |||
| 175 | #endif | |||
| 176 | ||||
| 177 | GQueue * to_check_again = g_queue_new(); | |||
| 178 | ||||
| 179 | int sleep_interval_millis = 200; // temp | |||
| 180 | int max_sleep_time_millis = 3000; | |||
| 181 | int pop_interval_millis = 100; | |||
| 182 | ||||
| 183 | while (!terminate_watch_thread) { | |||
| 184 | SLEEP_MILLIS_WITH_SYSLOG(sleep_interval_millis, "Recheck interval")do { loggable_sleep(sleep_interval_millis, SLEEP_OPT_NONE, DDCA_SYSLOG_NOTICE , __func__, 184, "dw_recheck.c", "Recheck interval"); } while (0); // move to end of loop | |||
| 185 | uint64_t cur_time_nanos = cur_realtime_nanosec(); | |||
| 186 | ||||
| 187 | Recheck_Queue_Entry* rqe = NULL((void*)0); | |||
| 188 | while (!rqe
| |||
| 189 | while (g_queue_get_length(to_check_again) > 0) { | |||
| 190 | rqe = g_queue_pop_head(to_check_again); | |||
| 191 | g_async_queue_push_front(recheck_queue, rqe); | |||
| 192 | } | |||
| 193 | uint64_t pop_interval_micros = MILLIS2MICROS(pop_interval_millis)(pop_interval_millis*(uint64_t)1000); | |||
| 194 | rqe = g_async_queue_timeout_pop(recheck_queue, pop_interval_micros); | |||
| 195 | if (terminate_watch_thread) { | |||
| 196 | if (rqe) { | |||
| 197 | dw_free_recheck_queue_entry(rqe); | |||
| 198 | rqe = NULL((void*)0); | |||
| 199 | } | |||
| 200 | } | |||
| 201 | } | |||
| 202 | if (terminate_watch_thread) { | |||
| 203 | DBGTRC_NOPREFIX(debug, DDCA_TRC_NONE, "terminating recheck thread execution")dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 203, "dw_recheck.c", " " "terminating recheck thread execution"); | |||
| 204 | break; | |||
| 205 | } | |||
| 206 | ||||
| 207 | // check if max recheck time has elapsed | |||
| 208 | if (cur_time_nanos > rqe->initial_ts_nanos + MILLIS2NANOS(max_sleep_time_millis)(max_sleep_time_millis*(uint64_t)1000000)) { | |||
| ||||
| 209 | emit_recheck_debug_msg(debug, DDCA_SYSLOG_NOTICE, | |||
| 210 | "ddc did not become enabled for %s after %d milliseconds", | |||
| 211 | dref_reprx_t(rqe->dref), max_sleep_time_millis); | |||
| 212 | dw_free_recheck_queue_entry(rqe); | |||
| 213 | continue; | |||
| 214 | } | |||
| 215 | ||||
| 216 | DBGTRC_NOPREFIX(debug, TRACE_GROUP, "Locking master_dw_mutex, thread_id = %d", TID())dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (TRACE_GROUP), 0x00, __func__, 216, "dw_recheck.c", " " "Locking master_dw_mutex, thread_id = %d", (intmax_t) tid()); | |||
| 217 | g_mutex_lock(&master_dw_mutex); | |||
| 218 | ||||
| 219 | Display_Ref * dref = rqe->dref; | |||
| 220 | // DBGMSG(" rechecking %s", dref_repr_t(dref)); | |||
| 221 | Error_Info * err = dw_recheck_dref(dref); // <=== | |||
| 222 | DBGTRC_NOPREFIX(false, DDCA_TRC_NONE, "after dw_recheck_dref(), dref->flags=%s",dbgtrc( (0) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 223, "dw_recheck.c", " " "after dw_recheck_dref(), dref->flags=%s", interpret_dref_flags_t (dref->flags)) | |||
| 223 | interpret_dref_flags_t(dref->flags))dbgtrc( (0) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 223, "dw_recheck.c", " " "after dw_recheck_dref(), dref->flags=%s", interpret_dref_flags_t (dref->flags)); | |||
| 224 | // dbgrpt_display_ref(dref,false,2); | |||
| 225 | if (!err) { | |||
| 226 | emit_recheck_debug_msg(debug, DDCA_SYSLOG_NOTICE, | |||
| 227 | "ddc became enabled for %s after %ld milliseconds", | |||
| 228 | dref_reprx_t(dref), NANOS2MILLIS(cur_realtime_nanosec() - rqe->initial_ts_nanos)(((cur_realtime_nanosec() - rqe->initial_ts_nanos)+500000) /1000000)); | |||
| 229 | dref->dispno = ++dispno_max; | |||
| 230 | ||||
| 231 | DBGTRC_NOPREFIX(false, DDCA_TRC_NONE, "locking process_event_mutex")dbgtrc( (0) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 231, "dw_recheck.c", " " "locking process_event_mutex"); | |||
| 232 | g_mutex_lock(&process_event_mutex); | |||
| 233 | dw_emit_or_queue_display_status_event( | |||
| 234 | DDCA_EVENT_DDC_ENABLED, | |||
| 235 | dref->drm_connector, | |||
| 236 | dref, | |||
| 237 | dref->io_path, | |||
| 238 | NULL((void*)0)); // deferred_event_queue); | |||
| 239 | g_mutex_unlock(&process_event_mutex); | |||
| 240 | DBGTRC_NOPREFIX(false, DDCA_TRC_NONE, "unlocked process_event_mutex")dbgtrc( (0) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 240, "dw_recheck.c", " " "unlocked process_event_mutex"); | |||
| 241 | dw_free_recheck_queue_entry(rqe); | |||
| 242 | } | |||
| 243 | else { | |||
| 244 | if (err->status_code == DDCRC_DISCONNECTED(-(3000 +29) )) { | |||
| 245 | emit_recheck_debug_msg(debug, DDCA_SYSLOG_NOTICE, | |||
| 246 | "Display %s no longer detected after %"PRIu64"l" "u"" milliseconds", | |||
| 247 | dref_reprx_t(dref), | |||
| 248 | NANOS2MILLIS(cur_time_nanos - rqe->initial_ts_nanos)(((cur_time_nanos - rqe->initial_ts_nanos)+500000)/1000000 )); | |||
| 249 | ||||
| 250 | dref->dispno = DISPNO_REMOVED-3; | |||
| 251 | dw_emit_or_queue_display_status_event( | |||
| 252 | DDCA_EVENT_DISPLAY_DISCONNECTED, | |||
| 253 | dref->drm_connector, | |||
| 254 | dref, | |||
| 255 | dref->io_path, | |||
| 256 | NULL((void*)0)); // rdd->deferred_event_queue); | |||
| 257 | dw_free_recheck_queue_entry(rqe); | |||
| 258 | } | |||
| 259 | else { | |||
| 260 | DBGTRC_NOPREFIX(debug, DDCA_TRC_NONE,dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 262, "dw_recheck.c", " " "ddc still not enabled for %s after %d milliseconds, retrying ..." , dref_reprx_t(rqe->dref), sleep_interval_millis) | |||
| 261 | "ddc still not enabled for %s after %d milliseconds, retrying ...",dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 262, "dw_recheck.c", " " "ddc still not enabled for %s after %d milliseconds, retrying ..." , dref_reprx_t(rqe->dref), sleep_interval_millis) | |||
| 262 | dref_reprx_t(rqe->dref), sleep_interval_millis)dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 262, "dw_recheck.c", " " "ddc still not enabled for %s after %d milliseconds, retrying ..." , dref_reprx_t(rqe->dref), sleep_interval_millis); | |||
| 263 | g_queue_push_head(to_check_again, rqe); | |||
| 264 | } | |||
| 265 | ERRINFO_FREE_WITH_REPORT(err, IS_DBGTRC(debug, DDCA_TRC_NONE) || is_report_ddc_errors_enabled() )if (err) errinfo_free_with_report(err, (( (debug) || is_tracing ((DDCA_TRC_NONE), "dw_recheck.c", __func__) ) || is_report_ddc_errors_enabled ()), __func__); | |||
| 266 | } | |||
| 267 | ||||
| 268 | DBGTRC_NOPREFIX(debug, TRACE_GROUP, "Unlocking master_dw_mutex, thread_id = %d", TID())dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (TRACE_GROUP), 0x00, __func__, 268, "dw_recheck.c", " " "Unlocking master_dw_mutex, thread_id = %d", (intmax_t) tid() ); | |||
| 269 | g_mutex_unlock(&master_dw_mutex); | |||
| 270 | } | |||
| 271 | ||||
| 272 | if (terminate_watch_thread) { | |||
| 273 | char * s = "recheck thread terminating because watch thread terminated"; | |||
| 274 | DBGTRC_NOPREFIX(debug, DDCA_TRC_NONE, "%s", s)dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (DDCA_TRC_NONE), 0x00, __func__, 274, "dw_recheck.c", " " "%s", s); | |||
| 275 | SYSLOG2(DDCA_SYSLOG_NOTICE, "%s", s)do { if (test_emit_syslog(DDCA_SYSLOG_NOTICE)) { int syslog_priority = syslog_importance_from_ddcutil_syslog_level(DDCA_SYSLOG_NOTICE ); if (syslog_priority >= 0) { char * body = g_strdup_printf ("%s", s); syslog(syslog_priority, "[%6jd]"" %s%s", (intmax_t ) tid(), body, (tag_output) ? " (P)" : "" ); free(body); } } } while(0); | |||
| 276 | ||||
| 277 | // free what's left on the queue | |||
| 278 | while (true1) { | |||
| 279 | Recheck_Queue_Entry * rqe = g_async_queue_timeout_pop(recheck_queue, 0); | |||
| 280 | if (!rqe) | |||
| 281 | break; | |||
| 282 | emit_recheck_debug_msg(debug, DDCA_SYSLOG_ERROR, | |||
| 283 | "Flushing request queue entry for %s ", | |||
| 284 | dref_reprx_t(rqe->dref)); | |||
| 285 | dw_free_recheck_queue_entry(rqe); | |||
| 286 | } | |||
| 287 | } | |||
| 288 | ||||
| 289 | g_queue_free(to_check_again); | |||
| 290 | dw_free_recheck_displays_data(rdd); // actually just a free() | |||
| 291 | DBGTRC_DONE(debug, TRACE_GROUP, "terminating recheck thread")do { dbgtrc( (debug) || trace_callstack_call_depth > 0 ? DDCA_TRC_ALL : (TRACE_GROUP), 0x10, __func__, 291, "dw_recheck.c", "Done " "terminating recheck thread"); if (traced_function_stack_enabled ) pop_traced_function(__func__); } while (0); | |||
| 292 | free_current_traced_function_stack(); | |||
| 293 | // recheck_thread_active = false; | |||
| 294 | g_thread_exit(NULL((void*)0)); | |||
| 295 | return NULL((void*)0); // no effect, but avoids compiler error | |||
| 296 | } | |||
| 297 | ||||
| 298 | ||||
| 299 | void init_dw_recheck() { | |||
| 300 | RTTI_ADD_FUNC(dw_recheck_dref)rtti_func_name_table_add(dw_recheck_dref, "dw_recheck_dref");; | |||
| 301 | RTTI_ADD_FUNC(dw_recheck_displays_func)rtti_func_name_table_add(dw_recheck_displays_func, "dw_recheck_displays_func" );; | |||
| 302 | } |