@@ -26,6 +26,7 @@ static std::thread *stream_thread = nullptr;
2626static std::thread *event_thread = nullptr ;
2727static std::atomic<bool > stream_thread_started = false ;
2828static std::atomic<bool > event_thread_started = false ;
29+ static std::atomic<bool > runtime_stop_requested = false ;
2930
3031std::atomic<stream_execution_context_t *> current_context = nullptr ;
3132
@@ -103,6 +104,10 @@ static void wait_stream_resume(stream_execution_context_t *context)
103104 continue ;
104105 }
105106
107+ if (runtime_stop_requested.load ()) {
108+ return ;
109+ }
110+
106111 context = current_context.load ();
107112 context->reset_fifos (1 );
108113 if (context->resume_all_nodes ) {
@@ -145,6 +150,9 @@ static void pause_stream_thread_on_error(stream_execution_context_t *context, cg
145150
146151 wait_event_thread_paused ();
147152 report_runtime_error (kStreamThread , status, CG_UNIDENTIFIED_NODE , 0 );
153+ if (runtime_stop_requested.load ()) {
154+ return ;
155+ }
148156 cg_streamReplyEvent.post (STREAM_PAUSED_EVENT );
149157 wait_stream_resume (context);
150158}
@@ -160,6 +168,9 @@ static void pause_stream_thread_on_stop_graph(stream_execution_context_t *contex
160168
161169 wait_event_thread_paused ();
162170 report_stop_graph ();
171+ if (runtime_stop_requested.load ()) {
172+ return ;
173+ }
163174 cg_streamReplyEvent.post (STREAM_PAUSED_EVENT );
164175 wait_stream_resume (context);
165176}
@@ -204,6 +215,9 @@ static void event_thread_function()
204215 report_runtime_error (kEventThread , event_error,
205216 event_error_node, event_error_info);
206217 }
218+ if (runtime_stop_requested.load ()) {
219+ return ;
220+ }
207221 cg_streamReplyEvent.post (EVENT_PAUSED_EVENT );
208222 wait_event_resume ();
209223 }
@@ -225,11 +239,17 @@ static void stream_thread_function()
225239 if (is_runtime_scheduler_error (error)) {
226240 CMSISSTREAM_LOG_ERR (" Scheduler error %d\n " , error);
227241 pause_stream_thread_on_error (context, static_cast <cg_status>(error));
242+ if (runtime_stop_requested.load ()) {
243+ break ;
244+ }
228245 continue ;
229246 }
230247 if ((context->scheduler_length > 0 ) && (error == CG_STOP_SCHEDULER )) {
231248 CMSISSTREAM_LOG_DBG (" Scheduler requested stop graph\n " );
232249 pause_stream_thread_on_stop_graph (context);
250+ if (runtime_stop_requested.load ()) {
251+ break ;
252+ }
233253 continue ;
234254 }
235255 if ((error == CG_PAUSED_SCHEDULER ) ||
@@ -242,6 +262,9 @@ static void stream_thread_function()
242262 }
243263
244264 wait_stream_resume (context);
265+ if (runtime_stop_requested.load ()) {
266+ break ;
267+ }
245268 } else {
246269 done = true ;
247270 }
@@ -316,6 +339,7 @@ bool stream_start_threads(stream_execution_context_t *context)
316339 }
317340
318341 set_current_context (context);
342+ runtime_stop_requested.store (false );
319343
320344 try {
321345 event_thread = new std::thread (event_thread_function);
@@ -342,20 +366,71 @@ bool stream_start_threads(stream_execution_context_t *context)
342366 return true ;
343367}
344368
345- void stream_wait_for_threads_end ()
369+ static void stop_thread (std::thread *&thread, std::atomic<bool > &started,
370+ bool callerIsRuntimeThread)
346371{
347- if (stream_thread_started.load () && (stream_thread != nullptr ) && stream_thread->joinable ()) {
348- stream_thread->join ();
349- stream_thread_started.store (false );
350- delete stream_thread;
351- stream_thread = nullptr ;
372+ if (!started.load () || (thread == nullptr )) {
373+ return ;
352374 }
353- if (event_thread_started.load () && (event_thread != nullptr ) && event_thread->joinable ()) {
354- event_thread->join ();
355- event_thread_started.store (false );
356- delete event_thread;
357- event_thread = nullptr ;
375+
376+ if (thread->joinable ()) {
377+ if (thread->get_id () == std::this_thread::get_id ()) {
378+ (void )callerIsRuntimeThread;
379+ thread->detach ();
380+ } else {
381+ // Always wait for peer runtime threads. Freeing graph resources
382+ // while a peer thread may still execute them is not safe.
383+ thread->join ();
384+ }
358385 }
386+
387+ started.store (false );
388+ delete thread;
389+ thread = nullptr ;
390+ }
391+
392+ static void wait_thread (std::thread *&thread, std::atomic<bool > &started)
393+ {
394+ if (!started.load () || (thread == nullptr )) {
395+ return ;
396+ }
397+
398+ if (thread->joinable ()) {
399+ if (thread->get_id () == std::this_thread::get_id ()) {
400+ thread->detach ();
401+ } else {
402+ thread->join ();
403+ }
404+ }
405+
406+ started.store (false );
407+ delete thread;
408+ thread = nullptr ;
409+ }
410+
411+ void stream_stop_threads (bool callerIsRuntimeThread)
412+ {
413+ runtime_stop_requested.store (true );
414+
415+ stream_execution_context_t *context = current_context.load ();
416+ if ((context != nullptr ) && (context->evtQueue != nullptr )) {
417+ context->evtQueue ->end ();
418+ }
419+
420+ cg_streamEvent.post (STREAM_DONE_EVENT | STREAM_RESUME_EVENT | EVENT_RESUME_EVENT );
421+ cg_streamReplyEvent.post (STREAM_PAUSED_EVENT | STREAM_RESUMED_EVENT |
422+ EVENT_PAUSED_EVENT | EVENT_RESUMED_EVENT );
423+
424+ stop_thread (event_thread, event_thread_started, callerIsRuntimeThread);
425+ stop_thread (stream_thread, stream_thread_started, callerIsRuntimeThread);
426+ set_current_context (nullptr );
427+ }
428+
429+ void stream_wait_for_threads_end ()
430+ {
431+ wait_thread (stream_thread, stream_thread_started);
432+ wait_thread (event_thread, event_thread_started);
433+ set_current_context (nullptr );
359434}
360435
361436void stream_free_memory ()
0 commit comments