PAPI  5.3.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
multiattach.c
Go to the documentation of this file.
1 /* This file performs the following test: start, stop and timer functionality for
2  multiple attached processes.
3 
4  - It attempts to use the following two counters. It may use less depending on
5  hardware counter resource limitations. These are counted in the default counting
6  domain and default granularity, depending on the platform. Usually this is
7  the user domain (PAPI_DOM_USER) and thread context (PAPI_GRN_THR).
8  + PAPI_FP_INS
9  + PAPI_TOT_CYC
10  - Get us.
11  - Start counters
12  - Do flops
13  - Stop and read counters
14  - Get us.
15 */
16 
17 #include "papi_test.h"
18 #include <sys/ptrace.h>
19 #include <inttypes.h>
20 
21 #ifdef _AIX
22 #define _LINUX_SOURCE_COMPAT
23 #endif
24 
25 #if defined(__FreeBSD__)
26 # define PTRACE_ATTACH PT_ATTACH
27 # define PTRACE_CONT PT_CONTINUE
28 #endif
29 
30 int
32 {
33  kill( getpid( ), SIGSTOP );
34  do_flops( NUM_FLOPS * num );
35  kill( getpid( ), SIGSTOP );
36  return ( 0 );
37 }
38 
39 int
40 main( int argc, char **argv )
41 {
42  int status, retval, num_tests = 2, tmp;
44  int PAPI_event, PAPI_event2, mask1, mask2;
45  int num_events1, num_events2;
46  long long **values;
47  long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc;
48  char event_name[PAPI_MAX_STR_LEN], add_event_str[PAPI_MAX_STR_LEN];
49  const PAPI_component_info_t *cmpinfo;
50  pid_t pid, pid2;
51  double ratio1,ratio2;
52 
53  /* Set TESTS_QUIET variable */
54  tests_quiet( argc, argv );
55 
56  /* Initialize the library */
58  if ( retval != PAPI_VER_CURRENT ) {
59  test_fail_exit( __FILE__, __LINE__, "PAPI_library_init", retval );
60  }
61 
62  /* get the component info and check if we support attach */
63  if ( ( cmpinfo = PAPI_get_component_info( 0 ) ) == NULL ) {
64  test_fail_exit( __FILE__, __LINE__, "PAPI_get_component_info", 0 );
65  }
66 
67  if ( cmpinfo->attach == 0 ) {
68  test_skip( __FILE__, __LINE__,
69  "Platform does not support attaching", 0 );
70  }
71 
72  /* fork off first child */
73  pid = fork( );
74  if ( pid < 0 ) {
75  test_fail_exit( __FILE__, __LINE__, "fork()", PAPI_ESYS );
76  }
77  if ( pid == 0 ) {
79  }
80 
81  /* fork off second child, does twice as much */
82  pid2 = fork( );
83  if ( pid2 < 0 ) {
84  test_fail_exit( __FILE__, __LINE__, "fork()", PAPI_ESYS );
85  }
86  if ( pid2 == 0 ) {
88  }
89 
90  /* add PAPI_TOT_CYC and one of the events in
91  PAPI_FP_INS, PAPI_FP_OPS or PAPI_TOT_INS,
92  depending on the availability of the event
93  on the platform */
94  EventSet1 = add_two_events( &num_events1, &PAPI_event, &mask1 );
95  EventSet2 = add_two_events( &num_events2, &PAPI_event2, &mask2 );
96 
97  if ( cmpinfo->attach_must_ptrace ) {
98  if ( ptrace( PTRACE_ATTACH, pid, NULL, NULL ) == -1 ) {
99  perror( "ptrace(PTRACE_ATTACH)" );
100  return 1 ;
101  }
102  if ( waitpid( pid, &status, 0 ) == -1 ) {
103  perror( "waitpid()" );
104  exit( 1 );
105  }
106  if ( WIFSTOPPED( status ) == 0 ) {
107  test_fail( __FILE__, __LINE__,
108  "Child process didnt return true to WIFSTOPPED", 0 );
109  }
110 
111  if ( ptrace( PTRACE_ATTACH, pid2, NULL, NULL ) == -1 ) {
112  perror( "ptrace(PTRACE_ATTACH)" );
113  return 1;
114  }
115  if ( waitpid( pid2, &status, 0 ) == -1 ) {
116  perror( "waitpid()" );
117  exit( 1 );
118  }
119  if ( WIFSTOPPED( status ) == 0 ) {
120  test_fail( __FILE__, __LINE__,
121  "Child process didnt return true to WIFSTOPPED", 0 );
122  }
123  }
124 
125  retval = PAPI_attach( EventSet1, ( unsigned long ) pid );
126  if ( retval != PAPI_OK ) {
127  test_fail( __FILE__, __LINE__, "PAPI_attach", retval );
128  }
129 
130  retval = PAPI_attach( EventSet2, ( unsigned long ) pid2 );
131  if ( retval != PAPI_OK ) {
132  test_fail( __FILE__, __LINE__, "PAPI_attach", retval );
133  }
134 
135  retval = PAPI_event_code_to_name( PAPI_event, event_name );
136  if ( retval != PAPI_OK ) {
137  test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval );
138  }
139  sprintf( add_event_str, "PAPI_add_event[%s]", event_name );
140 
141  /* num_events1 is greater than num_events2 so don't worry. */
142 
143  values = allocate_test_space( num_tests, num_events1 );
144 
145  /* Gather before values */
146  elapsed_us = PAPI_get_real_usec( );
147  elapsed_cyc = PAPI_get_real_cyc( );
148  elapsed_virt_us = PAPI_get_virt_usec( );
149  elapsed_virt_cyc = PAPI_get_virt_cyc( );
150 
151  /* Wait for the SIGSTOP. */
152  if ( cmpinfo->attach_must_ptrace ) {
153  if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
154  perror( "ptrace(PTRACE_CONT)" );
155  return 1;
156  }
157  if ( waitpid( pid, &status, 0 ) == -1 ) {
158  perror( "waitpid()" );
159  exit( 1 );
160  }
161  if ( WIFSTOPPED( status ) == 0 ) {
162  test_fail( __FILE__, __LINE__,
163  "Child process didn't return true to WIFSTOPPED", 0 );
164  }
165  if ( WSTOPSIG( status ) != SIGSTOP ) {
166  test_fail( __FILE__, __LINE__,
167  "Child process didn't stop on SIGSTOP", 0 );
168  }
169 
170  if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) {
171  perror( "ptrace(PTRACE_CONT)" );
172  return 1;
173  }
174  if ( waitpid( pid2, &status, 0 ) == -1 ) {
175  perror( "waitpid()" );
176  exit( 1 );
177  }
178  if ( WIFSTOPPED( status ) == 0 ) {
179  test_fail( __FILE__, __LINE__,
180  "Child process didn't return true to WIFSTOPPED", 0 );
181  }
182  if ( WSTOPSIG( status ) != SIGSTOP ) {
183  test_fail( __FILE__, __LINE__,
184  "Child process didn't stop on SIGSTOP", 0 );
185  }
186  }
187 
188  /* start first child */
189  retval = PAPI_start( EventSet1 );
190  if ( retval != PAPI_OK ) {
191  test_fail( __FILE__, __LINE__, "PAPI_start", retval );
192  }
193 
194  /* start second child */
195  retval = PAPI_start( EventSet2 );
196  if ( retval != PAPI_OK ) {
197  test_fail( __FILE__, __LINE__, "PAPI_start", retval );
198  }
199 
200  /* Wait for the SIGSTOP. */
201  if ( cmpinfo->attach_must_ptrace ) {
202  if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
203  perror( "ptrace(PTRACE_ATTACH)" );
204  return 1;
205  }
206  if ( waitpid( pid, &status, 0 ) == -1 ) {
207  perror( "waitpid()" );
208  exit( 1 );
209  }
210  if ( WIFSTOPPED( status ) == 0 ) {
211  test_fail( __FILE__, __LINE__,
212  "Child process didn't return true to WIFSTOPPED", 0 );
213  }
214  if ( WSTOPSIG( status ) != SIGSTOP ) {
215  test_fail( __FILE__, __LINE__,
216  "Child process didn't stop on SIGSTOP", 0 );
217  }
218 
219  if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) {
220  perror( "ptrace(PTRACE_ATTACH)" );
221  return 1;
222  }
223  if ( waitpid( pid2, &status, 0 ) == -1 ) {
224  perror( "waitpid()" );
225  exit( 1 );
226  }
227  if ( WIFSTOPPED( status ) == 0 ) {
228  test_fail( __FILE__, __LINE__,
229  "Child process didn't return true to WIFSTOPPED", 0 );
230  }
231  if ( WSTOPSIG( status ) != SIGSTOP ) {
232  test_fail( __FILE__, __LINE__,
233  "Child process didn't stop on SIGSTOP", 0 );
234  }
235  }
236 
237  elapsed_virt_us = PAPI_get_virt_usec( ) - elapsed_virt_us;
238  elapsed_virt_cyc = PAPI_get_virt_cyc( ) - elapsed_virt_cyc;
239  elapsed_us = PAPI_get_real_usec( ) - elapsed_us;
240  elapsed_cyc = PAPI_get_real_cyc( ) - elapsed_cyc;
241 
242  /* stop first child */
243  retval = PAPI_stop( EventSet1, values[0] );
244  if ( retval != PAPI_OK ) {
245  printf( "Warning: PAPI_stop returned error %d, probably ok.\n",
246  retval );
247  }
248 
249  /* stop second child */
250  retval = PAPI_stop( EventSet2, values[1] );
251  if ( retval != PAPI_OK ) {
252  printf( "Warning: PAPI_stop returned error %d, probably ok.\n",
253  retval );
254  }
255 
256  remove_test_events( &EventSet1, mask1 );
257  remove_test_events( &EventSet2, mask2 );
258 
259  if ( cmpinfo->attach_must_ptrace ) {
260  if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
261  perror( "ptrace(PTRACE_CONT)" );
262  return 1;
263  }
264  if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) {
265  perror( "ptrace(PTRACE_CONT)" );
266  return 1;
267  }
268  }
269 
270  if ( waitpid( pid, &status, 0 ) == -1 ) {
271  perror( "waitpid()" );
272  exit( 1 );
273  }
274  if ( WIFEXITED( status ) == 0 ) {
275  test_fail( __FILE__, __LINE__,
276  "Child process didn't return true to WIFEXITED", 0 );
277  }
278 
279  if ( waitpid( pid2, &status, 0 ) == -1 ) {
280  perror( "waitpid()" );
281  exit( 1 );
282  }
283  if ( WIFEXITED( status ) == 0 ) {
284  test_fail( __FILE__, __LINE__,
285  "Child process didn't return true to WIFEXITED", 0 );
286  }
287 
288  /* This code isn't necessary as we know the child has exited, */
289  /* it *may* return an error if the component so chooses. You */
290  /* should use read() instead. */
291 
292  printf( "Test case: multiple 3rd party attach start, stop.\n" );
293  printf( "-----------------------------------------------\n" );
294  tmp = PAPI_get_opt( PAPI_DEFDOM, NULL );
295  printf( "Default domain is: %d (%s)\n", tmp,
297  tmp = PAPI_get_opt( PAPI_DEFGRN, NULL );
298  printf( "Default granularity is: %d (%s)\n", tmp,
300  printf( "Using %d iterations of c += a*b\n", NUM_FLOPS );
301  printf( "-------------------------------------------------------------------------\n" );
302 
303  sprintf( add_event_str, "(PID %jd) %-12s : \t", ( intmax_t ) pid,
304  event_name );
305  printf( TAB1, add_event_str, values[0][1] );
306  sprintf( add_event_str, "(PID %jd) PAPI_TOT_CYC : \t",
307  ( intmax_t ) pid );
308  printf( TAB1, add_event_str, values[0][0] );
309  sprintf( add_event_str, "(PID %jd) %-12s : \t", ( intmax_t ) pid2,
310  event_name );
311  printf( TAB1, add_event_str,values[1][1] );
312  sprintf( add_event_str, "(PID %jd) PAPI_TOT_CYC : \t",
313  ( intmax_t ) pid2 );
314  printf( TAB1, add_event_str, values[1][0] );
315  printf( TAB1, "Real usec : \t", elapsed_us );
316  printf( TAB1, "Real cycles : \t", elapsed_cyc );
317  printf( TAB1, "Virt usec : \t", elapsed_virt_us );
318  printf( TAB1, "Virt cycles : \t", elapsed_virt_cyc );
319 
320  printf
321  ( "-------------------------------------------------------------------------\n" );
322 
323  printf("Verification: pid %d results should be twice pid %d\n",pid2,pid );
324 
325  ratio1=(double)values[1][0]/(double)values[0][0];
326  ratio2=(double)values[1][1]/(double)values[0][1];
327 
328  printf("\t%lld/%lld = %lf\n",values[1][0],values[0][0],ratio1);
329 
330 
331  if ((ratio1 >2.15 ) || (ratio1 < 1.85)) {
332  printf("Ratio out of range, should be ~2.0 not %lf\n",ratio1);
333  test_fail( __FILE__, __LINE__,
334  "Error: Counter ratio not two", 0 );
335  }
336 
337  printf("\t%lld/%lld = %lf\n",values[1][1],values[0][1],ratio2);
338 
339  if ((ratio2 >2.75 ) || (ratio2 < 1.25)) {
340  printf("Ratio out of range, should be ~2.0, not %lf\n",ratio2);
341  test_fail( __FILE__, __LINE__,
342  "Known issue: Counter ratio not two", 0 );
343  }
344 
345  test_pass( __FILE__, values, num_tests );
346  return 0;
347 }
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:23
sprintf(splash[splash_line++],"\tIozone: Performance Test of File I/O\n")
int PAPI_stop(int EventSet, long long *values)
Definition: papi.c:2225
#define NUM_FLOPS
int mask1
Definition: zero_fork.c:41
int PAPI_event[2]
Definition: data_range.c:24
const PAPI_component_info_t * PAPI_get_component_info(int cidx)
Definition: papi.c:803
long long PAPI_get_virt_usec(void)
Definition: papi.c:6233
#define PAPI_NULL
Definition: fpapi.h:13
unsigned int attach
Definition: papi.h:657
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
char * stringify_granularity(int granularity)
Definition: test_utils.c:429
void test_skip(char *file, int line, char *call, int retval)
Definition: test_utils.c:614
long long PAPI_get_virt_cyc(void)
Definition: papi.c:6161
int num_events1
Definition: zero_fork.c:42
#define TAB1
Definition: papi_test.h:112
return PAPI_OK
Definition: linux-nvml.c:458
tests_quiet(argc, argv)
kill(master_listen_pid, SIGKILL)
#define printf
Definition: papi_test.h:125
static double
Definition: fileop.c:1281
test_pass(__FILE__, NULL, 0)
int int argc
Definition: iozone.c:1609
char ** argv
Definition: iozone.c:1610
test_fail(__FILE__, __LINE__,"PAPI_library_init", retval)
int PAPI_library_init(int version)
Definition: papi.c:495
char * stringify_all_domains(int domains)
Definition: test_utils.c:369
unsigned int attach_must_ptrace
Definition: papi.h:658
static int pid
int PAPI_get_opt(int option, PAPI_option_t *ptr)
Definition: papi.c:4030
long long elapsed_cyc
Definition: zero_fork.c:43
int wait_for_attach_and_loop(void)
Definition: attach2.c:31
void int num
Definition: iozone.c:22151
#define PAPI_DEFDOM
Definition: fpapi.h:49
int add_two_events(int *num_events, int *papi_event, int *mask)
Definition: test_utils.c:680
#define PAPI_VER_CURRENT
Definition: fpapi.h:14
#define PAPI_DEFGRN
Definition: fpapi.h:51
int EventSet2
Definition: rapl_overflow.c:12
int PAPI_event_code_to_name(int EventCode, char *out)
Definition: papi.c:920
#define PAPI_ESYS
Definition: fpapi.h:108
int num_tests
Definition: zero_fork.c:46
void do_flops(int n)
Definition: multiplex.c:23
long long PAPI_get_real_usec(void)
Definition: papi.c:6125
long long status
Definition: iozone.c:1335
int PAPI_attach(int EventSet, unsigned long tid)
Definition: papi.c:3100
long long PAPI_get_real_cyc(void)
Definition: papi.c:6078
int PAPI_start(int EventSet)
Definition: papi.c:2019
void test_fail_exit(char *file, int line, char *call, int retval)
Definition: test_utils.c:567
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
ssize_t retval
Definition: libasync.c:338
long long tmp
Definition: iozone.c:12031
long long elapsed_us
Definition: zero_fork.c:43
long long ** allocate_test_space(int num_tests, int num_events)
Definition: test_utils.c:107
int main(int argc, char **argv)
List all appio events codes and names.
void exit()
int remove_test_events(int *EventSet, int mask)
Definition: test_utils.c:277
int EventSet1
Definition: zero_fork.c:40