Profiling..entry for a function in pthread_create

Hello,

i am try to write a profiler for a multithreaded applciation. When i creat e a thread for "function f2()" the profiling information for this function does not get captured in the struct profileManager. i;e i get the exit information for "function f2()" in that thread, but the entry information does not get captured. Is it because the profiling function "__cyg_profile_func_enter" does not get inserted fot that thread? Do i have to use pthread_once_t to initialize so that its entry gets profiled??

Thanks,
Vikky.

////**** This is my instrument.c file ****/////
static FILE *fp;

struct profileManager{
pid_t pth;
pthread_t th;
char Ch;
int addr;
struct timeval tp;
}pM[1000];

static int cnt=0;

void __cyg_profile_func_enter( void *this, void callsite ) {
pthread_mutex_lock(&Lock);
pM[cnt].pth=getpid();
pM[cnt].th=pthread_self();
pM[cnt].Ch='E';
pM[cnt].addr=(int
)this;
gettimeofday(&pM[cnt].tp,NULL);
cnt++;
pthread_mutex_unlock(&Lock);
}

void __cyg_profile_func_exit( void *this, void callsite ) {
pthread_mutex_lock(&Lock);
pM[cnt].pth=getpid();
pM[cnt].th=pthread_self();
pM[cnt].Ch='X';
pM[cnt].addr=(int
)this;
gettimeofday(&pM[cnt].tp,NULL);
cnt++;
pthread_mutex_unlock(&Lock);
}

////***** my sample code test.c ****/////
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

int f1(int i){
sleep(1);
if(i==1)
return 0;
f1(i-1);
}

void f3(){
f1(5);
}

void* f2(void* arg){
f3();
}

void f4(){
sleep(1);
}

int main(){
int i;
pthread_t th;
int code;

code = pthread_create(&th,NULL,f2,NULL); ///Create Thread for F2
if(code==0)
printf("Thread created %d\n",th);
printf("Hello World\n");
(void)f2(NULL);
for(i=0;i<5;i++)
f4();
sleep(10);
return 0;
}

Can I make a suggestion? Try using monitor(), or profil(). You can force monitoring on a given function. See man monitor.

Even better use the profiler on your system, unless this is homework.

Hi jim,

Thanks a lot for ur reply....

I have tried using gprof, FncCheck, SunWorkShop Pro, gprof does not give results thread wise, SunWorkShop is an excellent profiling tool, but since it is avaiable for Solaris platform i am try to find tool that can be used on other m/s also.
i had downloaded the code for profiling pv_trace (Author:= M. Tim Jones), and added modifications for multithreading and shared libraries.

i have made few modifications to the instrument.c code,
eg: As shown below.....
what i wanted is to profile for speicific functions, so what did is specify those functions as an environment variable and had them exported, in the instrument.c i read for that environment variable and populated list of functon entries in a hash table.
Now the problem is for functions calls from shared libraries. The ( *this ) parameter of "__cyg_profile_func_enter" points to some different addr.
eg:
my shared lbrary libMyThread.so on doing an "nm" gives
Addr mangled name demangled name
0x000010cc T EntryPoint__8MyThreadPv MyThread::EntryPoint(void *)

but on call to "MyThread::EntryPoint" the addr is "0xff3510cc"
This is because the linker is resolves entries to such functions at run time, i tried to use dlopen, dlsym functions but how to i get information of mangled functions corresponding to such address (in this case 0xff3510cc),

Also, when casting (*this) as int is gives a negative value(in this case 0xff3510cc). plz help...

Desc.:
checkProfileFlag() := This function tell whether to profile for all functions or
user specified functions.

DEBUG:= Macro for outputting debuggng info.
hx_search():= This is a function form "hash.c" which looks whether the
function needs to be proifiled or not.(Only useful when
functions are exported as env. variables.)

void __cyg_profile_func_enter( void *this, void *callsite )
{

if(DEBUG)
printf("E%p, %d,\n",(int*)this,abs((int*)this));

if(!checkProfileFlag()) {
if(hx_search((int *)this)){
if(DEBUG) {
printf("Profiling for %d, %p,\n",(int )this,(int )this);
printf("E%d,J%d\n",pthread_self(),pM[pthread_self()].size);
}
pM[pthread_self()].pth=getpid();
pM[pthread_self()].th=pthread_self();
pM[pthread_self()].fnc[pM[pthread_self()].size].addr=(int
)this;
pM[pthread_self()].fnc[pM[pthread_self()].size].Ch='E';
gettimeofday(&pM[pthread_self()].fnc[pM[pthread_self()].size].tp,NULL);
pM[pthread_self()].size++;
}
} else {
pM[pthread_self()].pth=getpid();
pM[pthread_self()].th=pthread_self();
pM[pthread_self()].fnc[pM[pthread_self()].size].addr=(int
)this;
pM[pthread_self()].fnc[pM[pthread_self()].size].Ch='E';
gettimeofday(&pM[pthread_self()].fnc[pM[pthread_self()].size].tp,NULL);
pM[pthread_self()].size++;
}

}