(Si prega di notare che nei commenti sopra, l'OP ha menzionato lo "stack" di cui stiamo parlando non è lo stack delle chiamate, è uno stack dedicato separato per lo scopo del monitoraggio delle chiamate)
Abbiamo già trattato il concetto di Thread Local Storage (TLS) nei commenti sopra. Se è disponibile e vuoi usarlo, ottimo.
Un altro approccio è leggermente più "roll your own", ma l'ho usato con successo. Per ora, presumo che stiamo parlando solo del tracciamento delle chiamate delle funzioni a livello di attività, sebbene questo metodo possa essere esteso anche agli ISR.
La maggior parte delle RTOS offre l'opportunità di eseguire funzioni di callout definite dall'utente, o "hook", in punti specifici, come entrare in & uscita da ISR, cambio di contesto in entrata e in uscita da un'attività, tick del timer, ecc. Ad esempio, FreeRTOS fornisce un ampio set di [Trace Macros] ( link ) che ti consente di utilizzare lo strumento & traccia il tuo codice (vedi traceTASK_SUSPEND(xTask)
e traceTASK_RESUME(xTask)
, ad esempio.)
Manteniamo questo semplice. Odio i globals, sono un bug di origine, interrompono l'incapsulamento, ecc. Detto questo, potresti avere una variabile globale:
FUNC_CALL_STK *stack_ptr;
o qualsiasi altra cosa. Ogni volta che si passa a un'attività (utilizzando la funzione di hook incorporato di RTOS), "stack_ptr" viene impostato sulla posizione "stack di traccia" dell'attività corrente. Ogni volta che si esce dall'attività (di nuovo, tramite hook RTOS), si memorizza stack_ptr nel puntatore dello stack privato dell'attività. Ogni attività ha il proprio stack di tracciamento privato & puntatore nella posizione corrente.
Un'altra alternativa, che evita di utilizzare le funzioni di hook fornite dal sistema operativo (io tendo a favorire questo approccio):
Ogni attività avrebbe ancora il suo stack di tracciamento e amp; puntatore, ma questo potrebbe essere implementato come una tabella di ricerca di "puntatori dello stack" (forse indicizzati dall'ID dell'attività o da qualsiasi altra cosa), e basta usare quelli direttamente dal contesto dell'attività per spingere & pop. Stack di tracciamento di ogni attività & il puntatore dello stack verrebbe inizializzato all'avvio dell'attività, prima di entrare nel "ciclo infinito" dell'attività. Ad esempio, la tua funzione START farebbe qualcosa del tipo:
PushCurrentFuncIdentifier(FuncId, GetCurrentTaskID());
GetCurrentTaskID()
è un'API del sistema operativo che restituirebbe un numero intero che identifica in modo univoco l'attività attualmente in esecuzione (ogni RTOS ha una tale API). Non importa se / quando si verifica un cambio di contesto, questo dovrebbe essere thread-safe.
BTW, usando la tua classe C ++, CTOR potrebbe salvare l'ID Task (TID) come membro privato, e quindi il DTOR potrebbe usare il TID memorizzato nella cache invece di dover chiamare di nuovo l'API RTOS.