3030 * 2015-12-20 Support to attach to process by pid
3131 */
3232
33+ #define _GNU_SOURCE
34+
35+ #include <sched.h>
36+ #include <sys/resource.h>
3337#include <sys/types.h>
3438#include <sys/stat.h>
3539#include <fcntl.h>
3842#include <stdlib.h>
3943#include <stdint.h>
4044#include <wait.h>
41- #include <sys/resource.h>
4245#include <err.h>
4346#include <unistd.h>
4447#include <errno.h>
4548#include <stdio.h>
4649#include <semaphore.h>
4750#include <sys/ipc.h>
4851#include <sys/shm.h>
49- #include <sched.h>
5052#include <inttypes.h>
5153#include <pmc_user.h> /*For the data type */
5254#include <sys/time.h> /* For setitimer */
5759#define _GNU_SOURCE
5860#endif
5961
62+
63+
64+
6065#ifndef NO_CPU_BINDING
6166#define NO_CPU_BINDING 0xffffffff
6267#endif
@@ -91,7 +96,11 @@ struct options {
9196 int max_samples ;
9297 int max_ebs_samples ;
9398 int kernel_buffer_size ;
99+ #ifdef OLD_CPUMASK
94100 unsigned long cpumask ;
101+ #else
102+ cpu_set_t cpumask ;
103+ #endif
95104 int optind ;
96105 char * * argv ;
97106 unsigned long flags ;
@@ -174,6 +183,7 @@ static void init_posix_semaphore(sem_t** sem, int value)
174183}
175184#endif
176185
186+ #ifdef OLD_CPUMASK
177187/* Included due to an issue with header files in some Linux distributions */
178188extern int sched_setaffinity (pid_t pid , unsigned int len , unsigned long * mask );
179189
@@ -191,12 +201,41 @@ static unsigned long str_to_cpumask(const char* str)
191201 return 0x1 <<val ;
192202 }
193203}
204+ #endif
205+
206+ static void str_to_cpuset (const char * str ,cpu_set_t * cpu_set )
207+ {
208+ long int val = 0 ;
209+ unsigned long int uval ;
210+ int i ;
211+
212+ CPU_ZERO (cpu_set );
213+
214+ if (strncmp (str ,"0x" ,2 )== 0 ) {
215+ /* Remove the 0x preffix and convert to the mask directly */
216+ val = strtol (str + 2 ,NULL ,16 );
217+ uval = (unsigned long ) val ;
218+ for (i = 0 ; uval && i < sizeof (unsigned long )<<3 ; i ++ ) {
219+ if (uval & 1 <<i ) {
220+ uval &=~(1 <<i );
221+ CPU_SET (i ,cpu_set );
222+ }
223+ }
224+
225+ } else {
226+ /* Assume just a CPU number in decimal format */
227+ i = strtol (str ,NULL ,10 );
228+ CPU_SET (i ,cpu_set );
229+ }
230+ }
194231
232+
233+ #ifdef OLD_CPUMASK
195234/* Wrapper for sched_setaffinity */
196235static inline void bind_process_cpumask (int pid , unsigned long cpumask )
197236{
198237 if ((cpumask != NO_CPU_BINDING ) && sched_setaffinity (pid , sizeof (unsigned long ),& cpumask )!= 0 ) {
199- warnx ("Error when binding process to cpumask 0x%lu " ,cpumask );
238+ warnx ("Error when binding process to cpuset " ,cpumask );
200239 exit (1 );
201240 }
202241}
@@ -210,6 +249,32 @@ static int try_to_bind_process_cpumask(int pid, unsigned long cpumask)
210249 return 0 ;
211250}
212251
252+ #else
253+ static inline void bind_process_cpuset (int pid , cpu_set_t * cpu_set )
254+ {
255+ if (!cpu_set || CPU_COUNT (cpu_set )== 0 )
256+ return ;
257+
258+ if (sched_setaffinity (pid , CPU_ALLOC_SIZE (128 ),cpu_set )!= 0 ) {
259+ perror ("Error when binding process to cpuset\n" );
260+ exit (1 );
261+ }
262+ }
263+
264+
265+
266+ static int try_to_bind_process_cpuset (int pid , cpu_set_t * cpu_set )
267+ {
268+ if (!cpu_set || CPU_COUNT (cpu_set )== 0 )
269+ return 0 ;
270+
271+ if (sched_setaffinity (pid , sizeof (cpu_set_t ),cpu_set )!= 0 ) {
272+ warnx ("Cannot bind process to cpuset %p" ,cpu_set );
273+ return 1 ;
274+ }
275+ return 0 ;
276+ }
277+ #endif
213278
214279/*
215280 * When using vfork(), it is strongly advisable to use _exit() rather than exit()
@@ -503,8 +568,11 @@ static void monitoring_counters(struct options* opts,int optind,char** argv)
503568 exit (1 );
504569
505570 /* Bind first */
571+ #ifdef OLD_CPUMASK
506572 bind_process_cpumask (getpid (),opts -> cpumask );
507-
573+ #else
574+ bind_process_cpuset (getpid (),& opts -> cpumask );
575+ #endif
508576 /* Set up kernel buffer size */
509577 if (opts -> kernel_buffer_size != -1 && pmct_set_kernel_buffer_size (opts -> kernel_buffer_size ))
510578 pmctrack_exit (1 );
@@ -650,7 +718,11 @@ void monitoring_counters_syswide(struct options* opts,int optind,char** argv)
650718 exit (1 );
651719
652720 /* Bind first */
721+ #ifdef OLD_CPUMASK
653722 bind_process_cpumask (getpid (),opts -> cpumask );
723+ #else
724+ bind_process_cpuset (getpid (),& opts -> cpumask );
725+ #endif
654726
655727#ifndef USE_VFORK
656728 /* Notify the parent that the configuration is done */
@@ -769,7 +841,13 @@ static int populate_pid_set(pid_set_t* set,int pid)
769841 * Returns the number of pids that could not be attached
770842 * The PID of the master thread must be attached for this to succeed
771843 */
772- static int attach_pid_set (pid_set_t * set ,int pid , unsigned long cpumask )
844+ static int attach_pid_set (pid_set_t * set ,int pid ,
845+ #ifdef OLD_CPUMASK
846+ unsigned long cpumask
847+ #else
848+ cpu_set_t * cpumask
849+ #endif
850+ )
773851{
774852 int i = 0 ;
775853 int nr_attached = 0 ;
@@ -778,9 +856,11 @@ static int attach_pid_set(pid_set_t* set,int pid, unsigned long cpumask)
778856 warnx ("Can't attach to process with PID %d\n" ,pid );
779857 return -1 ;
780858 }
781-
859+ #ifdef OLD_CPUMASK
782860 try_to_bind_process_cpumask (pid ,cpumask );
783-
861+ #else
862+ try_to_bind_process_cpuset (pid ,cpumask );
863+ #endif
784864 nr_attached = 1 ;
785865
786866 for (i = 0 ; i < set -> nr_pids ; i ++ ) {
@@ -797,7 +877,11 @@ static int attach_pid_set(pid_set_t* set,int pid, unsigned long cpumask)
797877 } else {
798878 set -> pid_status [i ].attached = 1 ;
799879 nr_attached ++ ;
880+ #ifdef OLD_CPUMASK
800881 try_to_bind_process_cpumask (cur_pid ,cpumask );
882+ #else
883+ try_to_bind_process_cpuset (cur_pid ,cpumask );
884+ #endif
801885 }
802886 }
803887
@@ -907,7 +991,12 @@ static void monitoring_counters_attach(struct options* opts,int optind,char** ar
907991 /* Keep track of start time */
908992 gettimeofday (& start_time , NULL );
909993
910- if (attach_pid_set (set ,opts -> target_pid ,opts -> cpumask )< 0 ) {
994+ #ifdef OLD_CPUMASK
995+ if (attach_pid_set (set ,opts -> target_pid ,opts -> cpumask )< 0 )
996+ #else
997+ if (attach_pid_set (set ,opts -> target_pid ,& opts -> cpumask )< 0 )
998+ #endif
999+ {
9111000 exit_val = 1 ;
9121001 goto free_up_pid_set ;
9131002 }
@@ -1124,7 +1213,11 @@ void init_options( struct options* opts)
11241213 for (i = 0 ; i < MAX_COUNTER_CONFIGS ; ++ i )
11251214 opts -> user_cfg_str [i ]= NULL ;
11261215
1127- opts -> cpumask = NO_CPU_BINDING ;
1216+ #ifdef OLD_CPUMASK
1217+ opts -> cpumask = NO_CPU_BINDING ;
1218+ #else
1219+ CPU_ZERO (& opts -> cpumask );
1220+ #endif
11281221 opts -> max_samples = -1 ;
11291222 opts -> max_ebs_samples = -1 ;
11301223 opts -> flags = 0 ;
@@ -1305,10 +1398,11 @@ int main(int argc, char *argv[])
13051398 opts .msecs = (int )1000.0 * atof (optarg );
13061399 break ;
13071400 case 'b' :
1308- opts .cpumask = str_to_cpumask ( optarg );
1401+ str_to_cpuset ( optarg , & opts .cpumask );
13091402 break ;
13101403 case 'B' :
1311- bind_process_cpumask (getpid (),str_to_cpumask (optarg ));
1404+ str_to_cpuset (optarg ,& opts .cpumask );
1405+ bind_process_cpuset (getpid (),& opts .cpumask );
13121406 break ;
13131407 case 'n' :
13141408 opts .max_samples = atoi (optarg );
0 commit comments