
I use -finstrument-functions to generated enter and exit information of my each function call and use dot to draw it just like above. However, I found one problem, in my main function, I create two threads, one called driver_TASL, another is keyBoard_TASK. but in my generated picture, It seems like my keyBoard_TASK was called by driver_TASK. It should be like these two TASK called by main
Remark: I can NOT upload picture, so I describe it below:
after I generate function call, it should be like:
maincalldriver_TASKmaincallkeyBoard_TASK
however, it becomes
maincalldriver_TASKdriver_TASKcallkeyboard_TASK
Why the keyBoard_TASK was called by driver_TASK? It should be called by main I think
In my source code, I wrote them like (I deleted some print functions in code):
int main(/*@ unused @*/int argc, /*@ unused @*/char *argv[]) //comment for lint
{
int res;
pthread_t driver_thread, keyBoard_thread;
void *thread_result;
res = pthread_create(&driver_thread, NULL, driver_TASK, (void *)&_gDriverStatus);
if(res != 0)
{
perror("Thread Creation Failed");
exit(EXIT_FAILURE);
}
sleep(1);
res = pthread_create(&keyBoard_thread, NULL, keyBoard_TASK, (void *)&_gKeyStatus);
if(res != 0)
{
perror("Thread Creation Failed");
exit(EXIT_FAILURE);
}
res = pthread_join(driver_thread, &thread_result);
if(res != 0)
{
perror("Thread Join Failed");
exit(EXIT_FAILURE);
}
res = pthread_join(keyBoard_thread, &thread_result);
if(res != 0)
{
perror("Thread Join Failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
I also attached my automatically dot file, the function call flow chart is automatically generated by pvtace
digraph DEMO {
main [shape=rectangle]
driver_TASK [shape=rectangle]
DDI_DRIVER_Probe [shape=rectangle]
_Driver_Clear [shape=ellipse]
_Driver [shape=ellipse]
DRIVER_Probe_Demo [shape=ellipse]
DDI_DRIVER_Init [shape=rectangle]
DRIVER_Init_Demo [shape=rectangle]
_DRIVER_Init_Demo [shape=ellipse]
DDI_DRIVER_Running [shape=rectangle]
DRIVER_Running_Demo [shape=rectangle]
_DRIVER_Running_Demo [shape=ellipse]
keyBoard_TASK [shape=rectangle]
main -> DBG_PrintColor [label="2 calls" fontsize="10"]
main -> driver_TASK [label="1 calls" fontsize="10"] //this is correct
driver_TASK -> DBG_PrintColor [label="6 calls" fontsize="10"]
driver_TASK -> DDI_DRIVER_Probe [label="1 calls" fontsize="10"]
driver_TASK -> DDI_DRIVER_Init [label="1 calls" fontsize="10"]
driver_TASK -> DDI_DRIVER_Running [label="1 calls" fontsize="10"]
driver_TASK -> keyBoard_TASK [label="1 calls" fontsize="10"] //this is not correct
DDI_DRIVER_Probe -> _Driver_Clear [label="1 calls" fontsize="10"]
DDI_DRIVER_Probe -> _Driver [label="1 calls" fontsize="10"]
DDI_DRIVER_Probe -> DRIVER_Probe_Demo [label="1 calls" fontsize="10"]
DDI_DRIVER_Init -> _Driver [label="1 calls" fontsize="10"]
DDI_DRIVER_Init -> DRIVER_Init_Demo [label="1 calls" fontsize="10"]
DRIVER_Init_Demo -> _DRIVER_Init_Demo [label="1 calls" fontsize="10"]
DDI_DRIVER_Running -> _Driver [label="1 calls" fontsize="10"]
DDI_DRIVER_Running -> DRIVER_Running_Demo [label="1 calls" fontsize="10"]
DRIVER_Running_Demo -> _DRIVER_Running_Demo [label="1 calls" fontsize="10"]
keyBoard_TASK -> DBG_PrintColor [label="6 calls" fontsize="10"]
}
I assume that you are using the ‘instrumental’ library for collecting the call graph information (if not, you should indicate what you are using and/or what you do do in the
__cyg_profile_func_enter()and__cyg_profile_func_exit()routines).Looking at the implementation (available at http://www.suse.de/~krahmer/instrumental/), it’s clear that the call graph information is not collected in a thread safe manner. Each function called is simply recorded in the log file as it’s called, and the depth of the call graph is kept in a global variable (actually a static variable). Information about the call chain is also kept in a global array.
So what’s happening is that something along the following line of events occurs:
The fact that these events happen to occur in this order, without intervening
__cyg_profile_func_exit()events means that the instrumental library records things as if:When there really should be separate call graphs for each thread (which would require thread awareness in the instrumentation). To fix the problem, you’ll need to do one of the following: