perf tool: Refactor comm/tgid lookup
PATCH v2 1/2 perf tool: Refactor comm/tgid lookup
Rather than parsing /proc/pid/status file one line at a time, read it into a buffer in one shot and search for all strings in one pass.
tgid conversion also simplified -- removing the isspace walk. As noted by Arnaldo those are not needed for atoi == strtol calls.
---
v2:
- removed the isspace checks on tgid string
tools/perf/util/event.c | 72 ++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 28 deletions(-)
tools/perf/util/event.c +44 -28
@@ -49,48 +49,64 @@ static struct perf_sample synth_sample = { .period = 1, }; +/* +* Assumes that the first 4095 bytes of /proc/pid/stat contains +* the comm and tgid. +*/ static pid_t perf_event__get_comm_tgid (pid_t pid,char *comm,size_t len) {char filename[PATH_MAX ]; -char bf[BUFSIZ ]; -FILE *fp; -size_t size =0 ; +char bf[4096 ]; +int fd; +size_t size =0 , n;pid_t tgid =-1 ; +char *nl, *name, *tgids;snprintf (filename,sizeof (filename),"/proc/%d/status" , pid); - fp =fopen (filename,"r" ); -if (fp ==NULL ) { + fd =open (filename,O_RDONLY ); +if (fd <0 ) {pr_debug ("couldn't open %s\n" , filename);return 0 ; } -while (!comm[0 ] || (tgid <0 )) { -if (fgets (bf,sizeof (bf), fp) ==NULL ) { -pr_warning ("couldn't get COMM and pgid, malformed %s\n" , - filename); -break ; - } + n =read (fd, bf,sizeof (bf) -1 ); +close (fd); +if (n <=0 ) { +pr_warning ("Couldn't get COMM and tgid for pid %d\n" , + pid); +return -1 ; + } + bf[n] ='\0' ; -if (memcmp (bf,"Name:" ,5 ) ==0 ) { -char *name = bf +5 ; -while (*name &&isspace (*name)) - ++name; - size =strlen (name) -1 ; -if (size >= len) - size = len -1 ; -memcpy (comm, name, size); - comm[size] ='\0' ; - - }else if (memcmp (bf,"Tgid:" ,5 ) ==0 ) { -char *tgids = bf +5 ; -while (*tgids &&isspace (*tgids)) - ++tgids; - tgid =atoi (tgids); - } + name =strstr (bf,"Name:" ); + tgids =strstr (bf,"Tgid:" ); + +if (name) { + name +=5 ;/* strlen("Name:") */ + +while (*name &&isspace (*name)) + ++name; + + nl =strchr (name,'\n' ); +if (nl) + *nl ='\0' ; + + size =strlen (name); +if (size >= len) + size = len -1 ; +memcpy (comm, name, size); + comm[size] ='\0' ; + }else { +pr_debug ("Name: string not found for pid %d\n" , pid); } -fclose (fp); +if (tgids) { + tgids +=5 ;/* strlen("Tgid:") */ + tgid =atoi (tgids); + }else { +pr_debug ("Tgid: string not found for pid %d\n" , pid); + }return tgid; }
Signature · 1 line
2.2.1
PATCH v3 2/2 perf tool: Fix ppid for synthesized fork events
363b785f38 added synthesized fork events and set a thread's parent id to itself. Since we are already processing /proc/<pid>/status the ppid can be determined properly. Make it so.
---
v3
- removed isspace and newline checks; added brackets per Arnaldo's comments
v2:
- removed changes to function signature for perf_event__synthesize_comm as noted by Jiri
tools/perf/util/event.c | 83 +++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 33 deletions(-)
tools/perf/util/event.c +50 -33
@@ -51,29 +51,32 @@ static struct perf_sample synth_sample = {/* * Assumes that the first 4095 bytes of /proc/pid/stat contains -* the comm and tgid. +* the comm, tgid and ppid. */ -static pid_t perf_event__get_comm_tgid (pid_t pid,char *comm,size_t len) +static int perf_event__get_comm_ids (pid_t pid,char *comm,size_t len, +pid_t *tgid,pid_t *ppid) {char filename[PATH_MAX ];char bf[4096 ];int fd;size_t size =0 , n; -pid_t tgid =-1 ; -char *nl, *name, *tgids; +char *nl, *name, *tgids, *ppids; + + *tgid =-1 ; + *ppid =-1 ;snprintf (filename,sizeof (filename),"/proc/%d/status" , pid); fd =open (filename,O_RDONLY );if (fd <0 ) {pr_debug ("couldn't open %s\n" , filename); -return 0 ; +return -1 ; } n =read (fd, bf,sizeof (bf) -1 );close (fd);if (n <=0 ) { -pr_warning ("Couldn't get COMM and tgid for pid %d\n" , +pr_warning ("Couldn't get COMM, tigd and ppid for pid %d\n" , pid);return -1 ; }
@@ -81,6 +84,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) name =strstr (bf,"Name:" ); tgids =strstr (bf,"Tgid:" ); + ppids =strstr (bf,"PPid:" );if (name) { name +=5 ;/* strlen("Name:") */
@@ -103,32 +107,45 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)if (tgids) { tgids +=5 ;/* strlen("Tgid:") */ - tgid =atoi (tgids); + *tgid =atoi (tgids); }else {pr_debug ("Tgid: string not found for pid %d\n" , pid); } -return tgid; +if (ppids) { + ppids +=5 ;/* strlen("PPid:") */ + *ppid =atoi (ppids); + }else { +pr_debug ("PPid: string not found for pid %d\n" , pid); + } + +return 0 ; } -static pid_t perf_event__prepare_comm (union perf_event *event,pid_t pid, -struct machine *machine) +static int perf_event__prepare_comm (union perf_event *event,pid_t pid, +struct machine *machine, +pid_t *tgid,pid_t *ppid) {size_t size; -pid_t tgid; + + *ppid =-1 ;memset (&event->comm,0 ,sizeof (event->comm)); -if (machine__is_host (machine)) - tgid =perf_event__get_comm_tgid (pid, event->comm.comm, -sizeof (event->comm.comm)); -else - tgid = machine->pid; +if (machine__is_host (machine)) { +if (perf_event__get_comm_ids (pid, event->comm.comm, +sizeof (event->comm.comm), + tgid, ppid) !=0 ) { +return -1 ; + } + }else { + *tgid = machine->pid; + } -if (tgid <0 ) - goto out; +if (*tgid <0 ) +return -1 ; - event->comm.pid = tgid; + event->comm.pid = *tgid; event->comm.header.type =PERF_RECORD_COMM ; size =strlen (event->comm.comm) +1 ;
@@ -138,8 +155,8 @@ static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, (sizeof (event->comm.comm) - size) + machine->id_hdr_size); event->comm.tid = pid; -out: -return tgid; + +return 0 ; } static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
@@ -147,27 +164,27 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,perf_event__handler_t process, struct machine *machine) { - pid_t tgid = perf_event__prepare_comm(event, pid, machine); + pid_t tgid, ppid; -if (tgid ==-1 ) - goto out; +if (perf_event__prepare_comm (event, pid, machine, &tgid, &ppid) !=0 ) +return -1 ;if (process (tool, event, &synth_sample, machine) !=0 )return -1 ; -out:return tgid; }static int perf_event__synthesize_fork (struct perf_tool *tool, -union perf_event *event,pid_t pid, -pid_t tgid,perf_event__handler_t process, +union perf_event *event, +pid_t pid,pid_t tgid,pid_t ppid, +perf_event__handler_t process,struct machine *machine) {memset (&event->fork,0 ,sizeof (event->fork) + machine->id_hdr_size); - event->fork.ppid = tgid; - event->fork.ptid = tgid; + event->fork.ppid = ppid; + event->fork.ptid = ppid; event->fork.pid = tgid; event->fork.tid = pid; event->fork.header.type =PERF_RECORD_FORK ;
@@ -359,7 +376,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,char filename[PATH_MAX ];DIR *tasks;struct dirent dirent, *next; -pid_t tgid; +pid_t tgid, ppid;/* special case: only send one comm event using passed in pid */ if (!full) {
@@ -394,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event,if (*end)continue ; - tgid =perf_event__prepare_comm (comm_event, _pid, machine); -if (tgid ==-1 ) +if (perf_event__prepare_comm (comm_event, _pid, machine, + &tgid, &ppid) !=0 )return -1 ;if (perf_event__synthesize_fork (tool, fork_event, _pid, tgid, - process, machine) <0 ) + ppid, process, machine) <0 )return -1 ;/* * Send the prepared comm event
Signature · 1 line
2.2.1
Re: [PATCH v3 2/2] perf tool: Fix ppid for synthesized fork events
Quoted 42 lines · David Ahern
363b785f38added synthesized fork events and set a thread's parent id to itself. Since we are already processing /proc/<pid>/status the ppid can be determined properly. Make it so.Signed-off-by David Ahern <[email protected]>Cc Don Zickus <[email protected]>Cc Joe Mario <[email protected]>Cc Jiri Olsa <[email protected]>---
v3
- removed isspace and newline checks; added brackets per Arnaldo's commentsv2:
- removed changes to function signature forperf_event__synthesize_commas noted by Jiritools/perf/util/event.c | 83 +++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 33 deletions(-)tools/perf/util/event.c +5
-4@@ -51,29 +51,32 @@ static struct perf_sample synth_sample = {/* * Assumes that the first 4095 bytes of /proc/pid/stat contains -* the comm and tgid. +* the comm, tgid and ppid. */ -static pid_t perf_event__get_comm_tgid (pid_t pid,char *comm,size_t len) +static int perf_event__get_comm_ids (pid_t pid,char *comm,size_t len, +pid_t *tgid,pid_t *ppid) {char filename[PATH_MAX ];char bf[4096 ];int fd;size_t size =0 , n; -pid_t tgid =-1 ; -char *nl, *name, *tgids; +char *nl, *name, *tgids, *ppids; +
tools/perf/util/event.c static struct perf_sample synth_sample = { · line 73
Quoted 10 lines
tools/perf/util/event.c +3
-1+ *tgid =-1 ; + *ppid =-1 ;snprintf (filename,sizeof (filename),"/proc/%d/status" , pid); fd =open (filename,O_RDONLY );if (fd <0 ) {pr_debug ("couldn't open %s\n" , filename); -return 0 ; +return -1 ;
hum, missed this one in previous version.. why did not we fail before?
jirka
Re: [PATCH v3 2/2] perf tool: Fix ppid for synthesized fork events
Quoted 48 lines · Jiri Olsa
Quoted 47 lines · David Ahern
363b785f38added synthesized fork events and set a thread's parent id to itself. Since we are already processing /proc/<pid>/status the ppid can be determined properly. Make it so.Signed-off-by David Ahern <[email protected]>Cc Don Zickus <[email protected]>Cc Joe Mario <[email protected]>Cc Jiri Olsa <[email protected]>---
v3
- removed isspace and newline checks; added brackets per Arnaldo's commentsv2:
- removed changes to function signature forperf_event__synthesize_commas noted by Jiritools/perf/util/event.c | 83 +++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 33 deletions(-)tools/perf/util/event.c +7
-4@@ -51,29 +51,32 @@ static struct perf_sample synth_sample = {/* * Assumes that the first 4095 bytes of /proc/pid/stat contains -* the comm and tgid. +* the comm, tgid and ppid. */ -static pid_t perf_event__get_comm_tgid (pid_t pid,char *comm,size_t len) +static int perf_event__get_comm_ids (pid_t pid,char *comm,size_t len, +pid_t *tgid,pid_t *ppid) {char filename[PATH_MAX ];char bf[4096 ];int fd;size_t size =0 , n; -pid_t tgid =-1 ; -char *nl, *name, *tgids; +char *nl, *name, *tgids, *ppids; + + *tgid =-1 ; + *ppid =-1 ;snprintf (filename,sizeof (filename),"/proc/%d/status" , pid);
Quoted 7 lines
tools/perf/util/event.c static struct perf_sample synth_sample = { · line 73
Quoted 5 lines
tools/perf/util/event.c +1
-1fd =open (filename,O_RDONLY );if (fd <0 ) {pr_debug ("couldn't open %s\n" , filename); -return 0 ; +return -1 ;hum, missed this one in previous version.. why did not we fail before?
sigh, it was the tgid before, now it's err.. ;-) ook
jirka
Re: [PATCH v3 2/2] perf tool: Fix ppid for synthesized fork events
In reply to David AhernQuoted 8 lines · David Ahern
363b785f38added synthesized fork events and set a thread's parent id to itself. Since we are already processing /proc/<pid>/status the ppid can be determined properly. Make it so.Signed-off-by David Ahern <[email protected]>Cc Don Zickus <[email protected]>Cc Joe Mario <[email protected]>Cc Jiri Olsa <[email protected]>
thanks,
jirka
Re: [PATCH v3 2/2] perf tool: Fix ppid for synthesized fork events
In reply to David AhernQuoted 3 lines · David Ahern
363b785f38added synthesized fork events and set a thread's parent id to itself. Since we are already processing /proc/<pid>/status the ppid can be determined properly. Make it so.
Quoted 201 lines
Signed-off-by David Ahern <[email protected]>Cc Don Zickus <[email protected]>Cc Joe Mario <[email protected]>Cc Jiri Olsa <[email protected]>---
v3
- removed isspace and newline checks; added brackets per Arnaldo's commentsv2:
- removed changes to function signature forperf_event__synthesize_commas noted by Jiritools/perf/util/event.c | 83 +++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 33 deletions(-)tools/perf/util/event.c +50
-33@@ -51,29 +51,32 @@ static struct perf_sample synth_sample = {/* * Assumes that the first 4095 bytes of /proc/pid/stat contains -* the comm and tgid. +* the comm, tgid and ppid. */ -static pid_t perf_event__get_comm_tgid (pid_t pid,char *comm,size_t len) +static int perf_event__get_comm_ids (pid_t pid,char *comm,size_t len, +pid_t *tgid,pid_t *ppid) {char filename[PATH_MAX ];char bf[4096 ];int fd;size_t size =0 , n; -pid_t tgid =-1 ; -char *nl, *name, *tgids; +char *nl, *name, *tgids, *ppids; + + *tgid =-1 ; + *ppid =-1 ;snprintf (filename,sizeof (filename),"/proc/%d/status" , pid); fd =open (filename,O_RDONLY );if (fd <0 ) {pr_debug ("couldn't open %s\n" , filename); -return 0 ; +return -1 ; } n =read (fd, bf,sizeof (bf) -1 );close (fd);if (n <=0 ) { -pr_warning ("Couldn't get COMM and tgid for pid %d\n" , +pr_warning ("Couldn't get COMM, tigd and ppid for pid %d\n" , pid);return -1 ; }@@ -81,6 +84,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) name =strstr (bf,"Name:" ); tgids =strstr (bf,"Tgid:" ); + ppids =strstr (bf,"PPid:" );if (name) { name +=5 ;/* strlen("Name:") */ @@ -103,32 +107,45 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)if (tgids) { tgids +=5 ;/* strlen("Tgid:") */ - tgid =atoi (tgids); + *tgid =atoi (tgids); }else {pr_debug ("Tgid: string not found for pid %d\n" , pid); } -return tgid; +if (ppids) { + ppids +=5 ;/* strlen("PPid:") */ + *ppid =atoi (ppids); + }else { +pr_debug ("PPid: string not found for pid %d\n" , pid); + } + +return 0 ; } -static pid_t perf_event__prepare_comm (union perf_event *event,pid_t pid, -struct machine *machine) +static int perf_event__prepare_comm (union perf_event *event,pid_t pid, +struct machine *machine, +pid_t *tgid,pid_t *ppid) {size_t size; -pid_t tgid; + + *ppid =-1 ;memset (&event->comm,0 ,sizeof (event->comm)); -if (machine__is_host (machine)) - tgid =perf_event__get_comm_tgid (pid, event->comm.comm, -sizeof (event->comm.comm)); -else - tgid = machine->pid; +if (machine__is_host (machine)) { +if (perf_event__get_comm_ids (pid, event->comm.comm, +sizeof (event->comm.comm), + tgid, ppid) !=0 ) { +return -1 ; + } + }else { + *tgid = machine->pid; + } -if (tgid <0 ) - goto out; +if (*tgid <0 ) +return -1 ; - event->comm.pid = tgid; + event->comm.pid = *tgid; event->comm.header.type =PERF_RECORD_COMM ; size =strlen (event->comm.comm) +1 ;@@ -138,8 +155,8 @@ static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, (sizeof (event->comm.comm) - size) + machine->id_hdr_size); event->comm.tid = pid; -out: -return tgid; + +return 0 ; } static pid_t perf_event__synthesize_comm(struct perf_tool *tool,@@ -147,27 +164,27 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,perf_event__handler_t process, struct machine *machine) { - pid_t tgid = perf_event__prepare_comm(event, pid, machine); + pid_t tgid, ppid; -if (tgid ==-1 ) - goto out; +if (perf_event__prepare_comm (event, pid, machine, &tgid, &ppid) !=0 ) +return -1 ;if (process (tool, event, &synth_sample, machine) !=0 )return -1 ; -out:return tgid; }static int perf_event__synthesize_fork (struct perf_tool *tool, -union perf_event *event,pid_t pid, -pid_t tgid,perf_event__handler_t process, +union perf_event *event, +pid_t pid,pid_t tgid,pid_t ppid, +perf_event__handler_t process,struct machine *machine) {memset (&event->fork,0 ,sizeof (event->fork) + machine->id_hdr_size); - event->fork.ppid = tgid; - event->fork.ptid = tgid; + event->fork.ppid = ppid; + event->fork.ptid = ppid; event->fork.pid = tgid; event->fork.tid = pid; event->fork.header.type =PERF_RECORD_FORK ;@@ -359,7 +376,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,char filename[PATH_MAX ];DIR *tasks;struct dirent dirent, *next; -pid_t tgid; +pid_t tgid, ppid;/* special case: only send one comm event using passed in pid */ if (!full) {@@ -394,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event,if (*end)continue ; - tgid =perf_event__prepare_comm (comm_event, _pid, machine); -if (tgid ==-1 ) +if (perf_event__prepare_comm (comm_event, _pid, machine, + &tgid, &ppid) !=0 )return -1 ;if (perf_event__synthesize_fork (tool, fork_event, _pid, tgid, - process, machine) <0 ) + ppid, process, machine) <0 )return -1 ;/* * Send the prepared comm event Signature · 1 line
2.2.1
tip-bot for David Ahern
merge bot[tip:perf/core] perf tools: Fix ppid for synthesized fork events
In reply to David Ahernperf tools: Fix ppid for synthesized fork events
Commit-ID: ca6c41c59b964d362823e80442e9e32c31106b29 Gitweb: http://git.kernel.org/tip/ca6c41c59b964d362823e80442e9e32c31106b29 Author: David Ahern <[email protected]> AuthorDate: Mon, 30 Mar 2015 14:35:58 -0600 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 31 Mar 2015 17:52:30 -0300
perf tools: Fix ppid for synthesized fork events
363b785f38 added synthesized fork events and set a thread's parent id to itself. Since we are already processing /proc/<pid>/status the ppid can be determined properly. Make it so.
--- tools/perf/util/event.c | 83 +++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 33 deletions(-)
tools/perf/util/event.c +50 -33
@@ -51,29 +51,32 @@ static struct perf_sample synth_sample = {/* * Assumes that the first 4095 bytes of /proc/pid/stat contains -* the comm and tgid. +* the comm, tgid and ppid. */ -static pid_t perf_event__get_comm_tgid (pid_t pid,char *comm,size_t len) +static int perf_event__get_comm_ids (pid_t pid,char *comm,size_t len, +pid_t *tgid,pid_t *ppid) {char filename[PATH_MAX ];char bf[4096 ];int fd;size_t size =0 , n; -pid_t tgid =-1 ; -char *nl, *name, *tgids; +char *nl, *name, *tgids, *ppids; + + *tgid =-1 ; + *ppid =-1 ;snprintf (filename,sizeof (filename),"/proc/%d/status" , pid); fd =open (filename,O_RDONLY );if (fd <0 ) {pr_debug ("couldn't open %s\n" , filename); -return 0 ; +return -1 ; } n =read (fd, bf,sizeof (bf) -1 );close (fd);if (n <=0 ) { -pr_warning ("Couldn't get COMM and tgid for pid %d\n" , +pr_warning ("Couldn't get COMM, tigd and ppid for pid %d\n" , pid);return -1 ; }
@@ -81,6 +84,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) name =strstr (bf,"Name:" ); tgids =strstr (bf,"Tgid:" ); + ppids =strstr (bf,"PPid:" );if (name) { name +=5 ;/* strlen("Name:") */
@@ -103,32 +107,45 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)if (tgids) { tgids +=5 ;/* strlen("Tgid:") */ - tgid =atoi (tgids); + *tgid =atoi (tgids); }else {pr_debug ("Tgid: string not found for pid %d\n" , pid); } -return tgid; +if (ppids) { + ppids +=5 ;/* strlen("PPid:") */ + *ppid =atoi (ppids); + }else { +pr_debug ("PPid: string not found for pid %d\n" , pid); + } + +return 0 ; } -static pid_t perf_event__prepare_comm (union perf_event *event,pid_t pid, -struct machine *machine) +static int perf_event__prepare_comm (union perf_event *event,pid_t pid, +struct machine *machine, +pid_t *tgid,pid_t *ppid) {size_t size; -pid_t tgid; + + *ppid =-1 ;memset (&event->comm,0 ,sizeof (event->comm)); -if (machine__is_host (machine)) - tgid =perf_event__get_comm_tgid (pid, event->comm.comm, -sizeof (event->comm.comm)); -else - tgid = machine->pid; +if (machine__is_host (machine)) { +if (perf_event__get_comm_ids (pid, event->comm.comm, +sizeof (event->comm.comm), + tgid, ppid) !=0 ) { +return -1 ; + } + }else { + *tgid = machine->pid; + } -if (tgid <0 ) - goto out; +if (*tgid <0 ) +return -1 ; - event->comm.pid = tgid; + event->comm.pid = *tgid; event->comm.header.type =PERF_RECORD_COMM ; size =strlen (event->comm.comm) +1 ;
@@ -138,8 +155,8 @@ static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid, (sizeof (event->comm.comm) - size) + machine->id_hdr_size); event->comm.tid = pid; -out: -return tgid; + +return 0 ; } static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
@@ -147,27 +164,27 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,perf_event__handler_t process, struct machine *machine) { - pid_t tgid = perf_event__prepare_comm(event, pid, machine); + pid_t tgid, ppid; -if (tgid ==-1 ) - goto out; +if (perf_event__prepare_comm (event, pid, machine, &tgid, &ppid) !=0 ) +return -1 ;if (process (tool, event, &synth_sample, machine) !=0 )return -1 ; -out:return tgid; }static int perf_event__synthesize_fork (struct perf_tool *tool, -union perf_event *event,pid_t pid, -pid_t tgid,perf_event__handler_t process, +union perf_event *event, +pid_t pid,pid_t tgid,pid_t ppid, +perf_event__handler_t process,struct machine *machine) {memset (&event->fork,0 ,sizeof (event->fork) + machine->id_hdr_size); - event->fork.ppid = tgid; - event->fork.ptid = tgid; + event->fork.ppid = ppid; + event->fork.ptid = ppid; event->fork.pid = tgid; event->fork.tid = pid; event->fork.header.type =PERF_RECORD_FORK ;
@@ -359,7 +376,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,char filename[PATH_MAX ];DIR *tasks;struct dirent dirent, *next; -pid_t tgid; +pid_t tgid, ppid;/* special case: only send one comm event using passed in pid */ if (!full) {
@@ -394,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event,if (*end)continue ; - tgid =perf_event__prepare_comm (comm_event, _pid, machine); -if (tgid ==-1 ) +if (perf_event__prepare_comm (comm_event, _pid, machine, + &tgid, &ppid) !=0 )return -1 ;if (perf_event__synthesize_fork (tool, fork_event, _pid, tgid, - process, machine) <0 ) + ppid, process, machine) <0 )return -1 ;/* * Send the prepared comm event
Quoted 10 lines · David Ahern
Rather than parsing
/proc/pid/statusfile one line at a time, read it into a buffer in one shot and search for all strings in one pass.tgid conversion also simplified -- removing the isspace walk. As noted by Arnaldo those are not needed for atoi == strtol calls.
Signed-off-by David Ahern <[email protected]>Cc Don Zickus <[email protected]>Cc Joe Mario <[email protected]>Cc Jiri Olsa <[email protected]>
thanks,
jirka
Em Tue, Mar 31, 2015 at 04:35:46PM +0200, Jiri Olsa escreveu:
Quoted 7 lines · David Ahern
Quoted 6 lines
Rather than parsing
/proc/pid/statusfile one line at a time, read it into a buffer in one shot and search for all strings in one pass.tgid conversion also simplified -- removing the isspace walk. As noted by Arnaldo those are not needed for atoi == strtol calls.
Quoted 6 lines
Quoted 4 lines
Signed-off-by David Ahern <[email protected]>Cc Don Zickus <[email protected]>Cc Joe Mario <[email protected]>Cc Jiri Olsa <[email protected]>Acked-by Jiri Olsa <[email protected]>
Thanks, applied both, with Jiri's acks.
- Arnaldo
Quoted 5 lines · David Ahern
Rather than parsing
/proc/pid/statusfile one line at a time, read it into a buffer in one shot and search for all strings in one pass.tgid conversion also simplified -- removing the isspace walk. As noted by Arnaldo those are not needed for atoi == strtol calls.
Seeing Jiri is happy now. :-)
Quoted 112 lines
Signed-off-by David Ahern <[email protected]>Cc Don Zickus <[email protected]>Cc Joe Mario <[email protected]>Cc Jiri Olsa <[email protected]>---
v2:
- removed the isspace checks on tgid stringtools/perf/util/event.c | 72 ++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 28 deletions(-)tools/perf/util/event.c +44
-28@@ -49,48 +49,64 @@ static struct perf_sample synth_sample = { .period = 1, }; +/* +* Assumes that the first 4095 bytes of /proc/pid/stat contains +* the comm and tgid. +*/ static pid_t perf_event__get_comm_tgid (pid_t pid,char *comm,size_t len) {char filename[PATH_MAX ]; -char bf[BUFSIZ ]; -FILE *fp; -size_t size =0 ; +char bf[4096 ]; +int fd; +size_t size =0 , n;pid_t tgid =-1 ; +char *nl, *name, *tgids;snprintf (filename,sizeof (filename),"/proc/%d/status" , pid); - fp =fopen (filename,"r" ); -if (fp ==NULL ) { + fd =open (filename,O_RDONLY ); +if (fd <0 ) {pr_debug ("couldn't open %s\n" , filename);return 0 ; } -while (!comm[0 ] || (tgid <0 )) { -if (fgets (bf,sizeof (bf), fp) ==NULL ) { -pr_warning ("couldn't get COMM and pgid, malformed %s\n" , - filename); -break ; - } + n =read (fd, bf,sizeof (bf) -1 ); +close (fd); +if (n <=0 ) { +pr_warning ("Couldn't get COMM and tgid for pid %d\n" , + pid); +return -1 ; + } + bf[n] ='\0' ; -if (memcmp (bf,"Name:" ,5 ) ==0 ) { -char *name = bf +5 ; -while (*name &&isspace (*name)) - ++name; - size =strlen (name) -1 ; -if (size >= len) - size = len -1 ; -memcpy (comm, name, size); - comm[size] ='\0' ; - - }else if (memcmp (bf,"Tgid:" ,5 ) ==0 ) { -char *tgids = bf +5 ; -while (*tgids &&isspace (*tgids)) - ++tgids; - tgid =atoi (tgids); - } + name =strstr (bf,"Name:" ); + tgids =strstr (bf,"Tgid:" ); + +if (name) { + name +=5 ;/* strlen("Name:") */ + +while (*name &&isspace (*name)) + ++name; + + nl =strchr (name,'\n' ); +if (nl) + *nl ='\0' ; + + size =strlen (name); +if (size >= len) + size = len -1 ; +memcpy (comm, name, size); + comm[size] ='\0' ; + }else { +pr_debug ("Name: string not found for pid %d\n" , pid); } -fclose (fp); +if (tgids) { + tgids +=5 ;/* strlen("Tgid:") */ + tgid =atoi (tgids); + }else { +pr_debug ("Tgid: string not found for pid %d\n" , pid); + }return tgid; }Signature · 1 line
2.2.1
tip-bot for David Ahern
merge bot[tip:perf/core] perf tools: Refactor comm/tgid lookup
In reply to David Ahernperf tools: Refactor comm/tgid lookup
Commit-ID: 5aa0b030e8d29d6719c144818814b519cfcb105c Gitweb: http://git.kernel.org/tip/5aa0b030e8d29d6719c144818814b519cfcb105c Author: David Ahern <[email protected]> AuthorDate: Mon, 30 Mar 2015 14:35:57 -0600 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 31 Mar 2015 17:52:30 -0300
perf tools: Refactor comm/tgid lookup
Rather than parsing /proc/pid/status file one line at a time, read it into a buffer in one shot and search for all strings in one pass.
tgid conversion also simplified -- removing the isspace walk. As noted by Arnaldo those are not needed for atoi == strtol calls.
--- tools/perf/util/event.c | 72 ++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 28 deletions(-)
tools/perf/util/event.c +44 -28
@@ -49,48 +49,64 @@ static struct perf_sample synth_sample = { .period = 1, }; +/* +* Assumes that the first 4095 bytes of /proc/pid/stat contains +* the comm and tgid. +*/ static pid_t perf_event__get_comm_tgid (pid_t pid,char *comm,size_t len) {char filename[PATH_MAX ]; -char bf[BUFSIZ ]; -FILE *fp; -size_t size =0 ; +char bf[4096 ]; +int fd; +size_t size =0 , n;pid_t tgid =-1 ; +char *nl, *name, *tgids;snprintf (filename,sizeof (filename),"/proc/%d/status" , pid); - fp =fopen (filename,"r" ); -if (fp ==NULL ) { + fd =open (filename,O_RDONLY ); +if (fd <0 ) {pr_debug ("couldn't open %s\n" , filename);return 0 ; } -while (!comm[0 ] || (tgid <0 )) { -if (fgets (bf,sizeof (bf), fp) ==NULL ) { -pr_warning ("couldn't get COMM and pgid, malformed %s\n" , - filename); -break ; - } + n =read (fd, bf,sizeof (bf) -1 ); +close (fd); +if (n <=0 ) { +pr_warning ("Couldn't get COMM and tgid for pid %d\n" , + pid); +return -1 ; + } + bf[n] ='\0' ; -if (memcmp (bf,"Name:" ,5 ) ==0 ) { -char *name = bf +5 ; -while (*name &&isspace (*name)) - ++name; - size =strlen (name) -1 ; -if (size >= len) - size = len -1 ; -memcpy (comm, name, size); - comm[size] ='\0' ; - - }else if (memcmp (bf,"Tgid:" ,5 ) ==0 ) { -char *tgids = bf +5 ; -while (*tgids &&isspace (*tgids)) - ++tgids; - tgid =atoi (tgids); - } + name =strstr (bf,"Name:" ); + tgids =strstr (bf,"Tgid:" ); + +if (name) { + name +=5 ;/* strlen("Name:") */ + +while (*name &&isspace (*name)) + ++name; + + nl =strchr (name,'\n' ); +if (nl) + *nl ='\0' ; + + size =strlen (name); +if (size >= len) + size = len -1 ; +memcpy (comm, name, size); + comm[size] ='\0' ; + }else { +pr_debug ("Name: string not found for pid %d\n" , pid); } -fclose (fp); +if (tgids) { + tgids +=5 ;/* strlen("Tgid:") */ + tgid =atoi (tgids); + }else { +pr_debug ("Tgid: string not found for pid %d\n" , pid); + }return tgid; }