PAPI 7.1.0.0
Loading...
Searching...
No Matches
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 <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <sys/ptrace.h>
22#include <sys/wait.h>
23#include <inttypes.h>
24
25#include "papi.h"
26#include "papi_test.h"
27
28#include "do_loops.h"
29
30#ifdef _AIX
31#define _LINUX_SOURCE_COMPAT
32#endif
33
34#if defined(__FreeBSD__)
35# define PTRACE_ATTACH PT_ATTACH
36# define PTRACE_CONT PT_CONTINUE
37#endif
38
39#define MULTIPLIER 5
40
41static int
43{
44 kill( getpid( ), SIGSTOP );
45 do_flops( NUM_FLOPS * num );
46 kill( getpid( ), SIGSTOP );
47 return 0;
48}
49
50int
51main( int argc, char **argv )
52{
53 int status, retval, num_tests = 2, tmp;
55 int PAPI_event, PAPI_event2, mask1, mask2;
56 int num_events1, num_events2;
57 long long **values;
58 long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc;
59 char event_name[PAPI_MAX_STR_LEN], add_event_str[PAPI_2MAX_STR_LEN];
60 const PAPI_component_info_t *cmpinfo;
61 pid_t pid, pid2;
62 double ratio1,ratio2;
63
64 /* Set TESTS_QUIET variable */
65 tests_quiet( argc, argv );
66
67 /* Initialize the library */
69 if ( retval != PAPI_VER_CURRENT ) {
70 test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
71 }
72
73 /* get the component info and check if we support attach */
74 if ( ( cmpinfo = PAPI_get_component_info( 0 ) ) == NULL ) {
75 test_fail( __FILE__, __LINE__, "PAPI_get_component_info", 0 );
76 }
77
78 if ( cmpinfo->attach == 0 ) {
79 test_skip( __FILE__, __LINE__,
80 "Platform does not support attaching", 0 );
81 }
82
83 /* fork off first child */
84 pid = fork( );
85 if ( pid < 0 ) {
86 test_fail( __FILE__, __LINE__, "fork()", PAPI_ESYS );
87 }
88 if ( pid == 0 ) {
89 exit( wait_for_attach_and_loop( 1 ) );
90 }
91
92 /* fork off second child, does twice as much */
93 pid2 = fork( );
94 if ( pid2 < 0 ) {
95 test_fail( __FILE__, __LINE__, "fork()", PAPI_ESYS );
96 }
97 if ( pid2 == 0 ) {
99 }
100
101 /* add PAPI_TOT_CYC and one of the events in
102 PAPI_FP_INS, PAPI_FP_OPS or PAPI_TOT_INS,
103 depending on the availability of the event
104 on the platform */
106 EventSet2 = add_two_events( &num_events2, &PAPI_event2, &mask2 );
107
108 if ( cmpinfo->attach_must_ptrace ) {
109 if ( ptrace( PTRACE_ATTACH, pid, NULL, NULL ) == -1 ) {
110 perror( "ptrace(PTRACE_ATTACH)" );
111 return 1 ;
112 }
113 if ( waitpid( pid, &status, 0 ) == -1 ) {
114 perror( "waitpid()" );
115 exit( 1 );
116 }
117 if ( WIFSTOPPED( status ) == 0 ) {
118 test_fail( __FILE__, __LINE__,
119 "Child process didnt return true to WIFSTOPPED", 0 );
120 }
121
122 if ( ptrace( PTRACE_ATTACH, pid2, NULL, NULL ) == -1 ) {
123 perror( "ptrace(PTRACE_ATTACH)" );
124 return 1;
125 }
126 if ( waitpid( pid2, &status, 0 ) == -1 ) {
127 perror( "waitpid()" );
128 exit( 1 );
129 }
130 if ( WIFSTOPPED( status ) == 0 ) {
131 test_fail( __FILE__, __LINE__,
132 "Child process didnt return true to WIFSTOPPED", 0 );
133 }
134 }
135
136 retval = PAPI_attach( EventSet1, ( unsigned long ) pid );
137 if ( retval != PAPI_OK ) {
138 test_fail( __FILE__, __LINE__, "PAPI_attach", retval );
139 }
140
141 retval = PAPI_attach( EventSet2, ( unsigned long ) pid2 );
142 if ( retval != PAPI_OK ) {
143 test_fail( __FILE__, __LINE__, "PAPI_attach", retval );
144 }
145
146 strcpy(event_name, "PAPI_TOT_INS");
147 sprintf( add_event_str, "PAPI_add_event[%s]", event_name );
148
149 /* num_events1 is greater than num_events2 so don't worry. */
150
152
153 /* Gather before values */
156 elapsed_virt_us = PAPI_get_virt_usec( );
157 elapsed_virt_cyc = PAPI_get_virt_cyc( );
158
159 /* Wait for the SIGSTOP. */
160 if ( cmpinfo->attach_must_ptrace ) {
161 if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
162 perror( "ptrace(PTRACE_CONT)" );
163 return 1;
164 }
165 if ( waitpid( pid, &status, 0 ) == -1 ) {
166 perror( "waitpid()" );
167 exit( 1 );
168 }
169 if ( WIFSTOPPED( status ) == 0 ) {
170 test_fail( __FILE__, __LINE__,
171 "Child process didn't return true to WIFSTOPPED", 0 );
172 }
173 if ( WSTOPSIG( status ) != SIGSTOP ) {
174 test_fail( __FILE__, __LINE__,
175 "Child process didn't stop on SIGSTOP", 0 );
176 }
177
178 if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) {
179 perror( "ptrace(PTRACE_CONT)" );
180 return 1;
181 }
182 if ( waitpid( pid2, &status, 0 ) == -1 ) {
183 perror( "waitpid()" );
184 exit( 1 );
185 }
186 if ( WIFSTOPPED( status ) == 0 ) {
187 test_fail( __FILE__, __LINE__,
188 "Child process didn't return true to WIFSTOPPED", 0 );
189 }
190 if ( WSTOPSIG( status ) != SIGSTOP ) {
191 test_fail( __FILE__, __LINE__,
192 "Child process didn't stop on SIGSTOP", 0 );
193 }
194 }
195
196 /* start measuring in first child */
198 if ( retval != PAPI_OK ) {
199 test_fail( __FILE__, __LINE__, "PAPI_start", retval );
200 }
201
202 /* start measuring in second child */
204 if ( retval != PAPI_OK ) {
205 test_fail( __FILE__, __LINE__, "PAPI_start", retval );
206 }
207
208 /* Start first child and Wait for the SIGSTOP. */
209 if ( cmpinfo->attach_must_ptrace ) {
210 if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
211 perror( "ptrace(PTRACE_ATTACH)" );
212 return 1;
213 }
214 if ( waitpid( pid, &status, 0 ) == -1 ) {
215 perror( "waitpid()" );
216 exit( 1 );
217 }
218 if ( WIFSTOPPED( status ) == 0 ) {
219 test_fail( __FILE__, __LINE__,
220 "Child process didn't return true to WIFSTOPPED", 0 );
221 }
222 if ( WSTOPSIG( status ) != SIGSTOP ) {
223 test_fail( __FILE__, __LINE__,
224 "Child process didn't stop on SIGSTOP", 0 );
225 }
226
227 /* Start second child and Wait for the SIGSTOP. */
228 if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) {
229 perror( "ptrace(PTRACE_ATTACH)" );
230 return 1;
231 }
232 if ( waitpid( pid2, &status, 0 ) == -1 ) {
233 perror( "waitpid()" );
234 exit( 1 );
235 }
236 if ( WIFSTOPPED( status ) == 0 ) {
237 test_fail( __FILE__, __LINE__,
238 "Child process didn't return true to WIFSTOPPED", 0 );
239 }
240 if ( WSTOPSIG( status ) != SIGSTOP ) {
241 test_fail( __FILE__, __LINE__,
242 "Child process didn't stop on SIGSTOP", 0 );
243 }
244 }
245
246 elapsed_virt_us = PAPI_get_virt_usec( ) - elapsed_virt_us;
247 elapsed_virt_cyc = PAPI_get_virt_cyc( ) - elapsed_virt_cyc;
250
251 /* stop measuring and read first child */
253 if ( retval != PAPI_OK ) {
254 printf( "Warning: PAPI_stop returned error %d, probably ok.\n",
255 retval );
256 }
257
258 /* stop measuring and read second child */
260 if ( retval != PAPI_OK ) {
261 printf( "Warning: PAPI_stop returned error %d, probably ok.\n",
262 retval );
263 }
264
265 /* close down the measurements */
267 remove_test_events( &EventSet2, mask2 );
268
269 /* restart events so they can end */
270 if ( cmpinfo->attach_must_ptrace ) {
271 if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
272 perror( "ptrace(PTRACE_CONT)" );
273 return 1;
274 }
275 if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) {
276 perror( "ptrace(PTRACE_CONT)" );
277 return 1;
278 }
279 }
280
281 if ( waitpid( pid, &status, 0 ) == -1 ) {
282 perror( "waitpid()" );
283 exit( 1 );
284 }
285 if ( WIFEXITED( status ) == 0 ) {
286 test_fail( __FILE__, __LINE__,
287 "Child process didn't return true to WIFEXITED", 0 );
288 }
289
290 if ( waitpid( pid2, &status, 0 ) == -1 ) {
291 perror( "waitpid()" );
292 exit( 1 );
293 }
294 if ( WIFEXITED( status ) == 0 ) {
295 test_fail( __FILE__, __LINE__,
296 "Child process didn't return true to WIFEXITED", 0 );
297 }
298
299 /* This code isn't necessary as we know the child has exited, */
300 /* it *may* return an error if the component so chooses. You */
301 /* should use read() instead. */
302
303 if (!TESTS_QUIET) {
304 printf( "Test case: multiple 3rd party attach start, stop.\n" );
305 printf( "-----------------------------------------------\n" );
306 tmp = PAPI_get_opt( PAPI_DEFDOM, NULL );
307 printf( "Default domain is: %d (%s)\n", tmp,
309 tmp = PAPI_get_opt( PAPI_DEFGRN, NULL );
310 printf( "Default granularity is: %d (%s)\n", tmp,
312 printf( "Using %d iterations of c += a*b\n", NUM_FLOPS );
313 printf( "-------------------------------------------------------------------------\n" );
314
315 sprintf( add_event_str, "(PID %jd) %-12s : \t", ( intmax_t ) pid,
316 event_name );
317 printf( TAB1, add_event_str, values[0][1] );
318 sprintf( add_event_str, "(PID %jd) PAPI_TOT_CYC : \t",
319 ( intmax_t ) pid );
320 printf( TAB1, add_event_str, values[0][0] );
321 sprintf( add_event_str, "(PID %jd) %-12s : \t", ( intmax_t ) pid2,
322 event_name );
323 printf( TAB1, add_event_str,values[1][1] );
324 sprintf( add_event_str, "(PID %jd) PAPI_TOT_CYC : \t",
325 ( intmax_t ) pid2 );
326 printf( TAB1, add_event_str, values[1][0] );
327 printf( TAB1, "Real usec : \t", elapsed_us );
328 printf( TAB1, "Real cycles : \t", elapsed_cyc );
329 printf( TAB1, "Virt usec : \t", elapsed_virt_us );
330 printf( TAB1, "Virt cycles : \t", elapsed_virt_cyc );
331
332 printf( "-------------------------------------------------------------------------\n" );
333
334 printf("Verification: pid %d results should be %dx pid %d\n",
335 pid2,MULTIPLIER,pid );
336 }
337
338 /* FLOPS ratio */
339 ratio1=(double)values[1][0]/(double)values[0][0];
340
341 /* CYCLES ratio */
342 ratio2=(double)values[1][1]/(double)values[0][1];
343
344 if (!TESTS_QUIET) {
345 printf("\tFLOPS ratio %lld/%lld = %lf\n",
346 values[1][0],values[0][0],ratio1);
347 }
348
349 double ratio1_high,ratio1_low,ratio2_high,ratio2_low;
350
351 ratio1_high=(double)MULTIPLIER *1.10;
352 ratio1_low=(double)MULTIPLIER * 0.90;
353
354 if ((ratio1 > ratio1_high ) || (ratio1 < ratio1_low)) {
355 printf("Ratio out of range, should be ~%lf not %lf\n",
356 (double)MULTIPLIER, ratio1);
357 test_fail( __FILE__, __LINE__,
358 "Error: Counter ratio not two", 0 );
359 }
360
361 if (!TESTS_QUIET) {
362 printf("\tCycles ratio %lld/%lld = %lf\n",
363 values[1][1],values[0][1],ratio2);
364 }
365
366 ratio2_high=(double)MULTIPLIER *1.20;
367 ratio2_low=(double)MULTIPLIER * 0.80;
368
369 if ((ratio2 > ratio2_high ) || (ratio2 < ratio2_low )) {
370 printf("Ratio out of range, should be ~%lf, not %lf\n",
371 (double)MULTIPLIER, ratio2);
372 test_fail( __FILE__, __LINE__,
373 "Known issue: Counter ratio not two", 0 );
374 }
375
376 test_pass( __FILE__ );
377
378 return 0;
379}
double tmp
static int wait_for_attach_and_loop(void)
Definition: attach2.c:41
Attach PAPI event set to the specified thread id.
get information about a specific software component
Get PAPI library or event set options.
get real time counter value in clock cycles Returns the total real time passed since some arbitrary s...
get real time counter value in microseconds
get virtual time counter value in clock cycles
get virtual time counter values in microseconds
initialize the PAPI library.
Start counting hardware events in an event set.
Stop counting hardware events in an event set.
int PAPI_event[2]
Definition: data_range.c:30
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29
#define PAPI_VER_CURRENT
Definition: f90papi.h:54
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_NULL
Definition: f90papi.h:78
#define PAPI_DEFGRN
Definition: f90papi.h:26
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_ESYS
Definition: f90papi.h:136
#define PAPI_2MAX_STR_LEN
Definition: f90papi.h:180
#define PAPI_DEFDOM
Definition: f90papi.h:188
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
#define MULTIPLIER
Definition: multiattach.c:39
void do_flops(int n)
Definition: multiplex.c:23
int TESTS_QUIET
Definition: test_utils.c:18
Return codes and api definitions.
int kill(__pid_t __pid, int __sig) __attribute__((__nothrow__
int tests_quiet(int argc, char **argv)
Definition: test_utils.c:376
char * stringify_all_domains(int domains)
Definition: test_utils.c:293
char * stringify_granularity(int granularity)
Definition: test_utils.c:353
#define TAB1
Definition: papi_test.h:98
void PAPI_NORETURN test_fail(const char *file, int line, const char *call, int retval)
Definition: test_utils.c:491
long long ** allocate_test_space(int num_tests, int num_events)
Definition: test_utils.c:46
void PAPI_NORETURN test_pass(const char *filename)
Definition: test_utils.c:432
int add_two_events(int *num_events, int *papi_event, int *mask)
Definition: test_utils.c:640
void PAPI_NORETURN test_skip(const char *file, int line, const char *call, int retval)
Definition: test_utils.c:584
int remove_test_events(int *EventSet, int mask)
Definition: test_utils.c:201
int main()
Definition: pernode.c:20
int EventSet2
Definition: rapl_overflow.c:17
#define NUM_FLOPS
Definition: sdsc-mpx.c:24
static int pid
unsigned int attach
Definition: papi.h:658
unsigned int attach_must_ptrace
Definition: papi.h:659
int EventSet1
Definition: zero_fork.c:47
int num_events1
Definition: zero_fork.c:49
int mask1
Definition: zero_fork.c:48
long long elapsed_cyc
Definition: zero_fork.c:50
long long elapsed_us
Definition: zero_fork.c:50
int num_tests
Definition: zero_fork.c:53
int retval
Definition: zero_fork.c:53