File: testcore1.c

package info (click to toggle)
gasnet 2025.8.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 17,424 kB
  • sloc: ansic: 114,758; cpp: 5,158; sh: 4,847; makefile: 2,715; perl: 1,774
file content (255 lines) | stat: -rw-r--r-- 6,434 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/* $Source: bitbucket.org:berkeleylab/gasnet.git/tests/testcore1.c $
 * Copyright 2002, Christian Bell <csbell@cs.berkeley.edu>
 * Terms of use are as specified in license.txt
 *
 * Description: GASNet Core Monotonic checksum test
 * This stress tests the ability of the core to successfully send
 * AM Requests/Replies through get and/or put functions.
 *
 * Get version:
 * 1. Node A generates 'n' random seeds and keeps a local checksum for each
 *    . .(barrier)
 * 2. Node B gets the 'n' seeds from Node A and keeps its checksum for each
 *    . .(barrier)
 * 3. Node A gets the checksum hashes from Node B and compares them against
 *    its own copy once the gets are sync'd
 *
 * Put version:
 * Steps 2 and 3 are puts for each other node.
 */

#include "test.h"

#define DEBUG_TRACE
#define CHKSUM_LENGTH	8
#define CHKSUM_NUM	64
#define CHKSUM_TOTAL	CHKSUM_LENGTH*CHKSUM_NUM
#define TESTSafe(x, msg) do {					\
	    if (!(x)) {  printf msg; gasnet_exit(1); } } while (0)

typedef struct {
	uint32_t	seed;
	unsigned char	chksum[CHKSUM_TOTAL];
} monoseed_t;

monoseed_t	 *_mseed;

static gex_Client_t      myclient;
static gex_EP_t    myep;
static gex_TM_t myteam;
static gex_Segment_t     mysegment;

int	myproc;
int	numproc;
int	peerproc;
int	numprocs;
gasnet_seginfo_t *seginfo_table;

/* Test specific globals */
int		 chksum_iters = 0;
gasnett_atomic_t chksum_success  = gasnett_atomic_init(0);
gasnett_atomic_t chksum_received = gasnett_atomic_init(0);

#define CHKSUM_DUMP(chksum) do {			\
		int i = 0;				\
		uint8_t *c = (uint8_t *)chksum;		\
		printf("0x");				\
		for (i = 0; i < CHKSUM_TOTAL; i++)	\
			printf("%0x", c[i]);		\
	} while (0);

#ifdef VERBOSE
void
monoseed_trace(int iter, int seed, void *chksum_loc, void *chksum_rem)
{
	printf("%d> iter=%4d, seed=%12d, chksum_local=", myproc, iter, seed); 
	CHKSUM_DUMP(chksum_loc);
	
	if (chksum_rem != NULL) {
		printf(" chksum_remote=");
		CHKSUM_DUMP(chksum_rem);
	}
	printf("\n"); fflush(stdout);
}
#else
#define monoseed_trace(iter, seed, chksum_loc, chksum_rem)
#endif

void
chksum_gen(int seed, void *buf)
{
	int		i;
	uint64_t	chksum;
        uint8_t         *p = buf;

	chksum = test_checksum((void *)&seed, 4);
	for (i = 0; i < CHKSUM_NUM; i++) {
		chksum = test_checksum((void *)&chksum, CHKSUM_LENGTH);
		memcpy(p, &chksum, CHKSUM_LENGTH);
		p += CHKSUM_LENGTH;
	}
	return;
}

void
monoseed_init(int num)
{
	int 		i;

	if (myproc % 2 == 0) {
		_mseed = (monoseed_t *) test_malloc(sizeof(monoseed_t) * num);
	        srand((int)TIME());

		for (i = 0; i < num; i++) {
			_mseed[i].seed = (int) rand() + 1;
			chksum_gen(_mseed[i].seed, &_mseed[i].chksum);
		}
	}
	return;
}

void
chksum_test(int iters)
{
	int	i;
	int	iamsender, iamreceiver;
	int     received;
#ifdef VERBOSE
	int     nloop = 0;
#endif

	iamsender = (myproc % 2 == 0);
	iamreceiver = !iamsender;

	BARRIER();

	if (iamsender) {
		for (i = 0; i < iters; i++)
			gex_AM_RequestShort2(myteam, (gex_Rank_t)peerproc, 
				201, 0, i, _mseed[i].seed);
	}

	while ( (received = gasnett_atomic_read(&chksum_received,0)) < iters ) {
		/*
		if (iamreceiver) {
			if (received % 5 == 0) {
				printf("sleep 1\n");
				sleep(1);
			}
		}
		*/
#ifdef VERBOSE
	    nloop++;
	    if (nloop % 1000 == 0) {
		printf("TEST[%d] nloop = %d chksum_received = %d\n",
		       myproc,nloop,received);
	    }
#endif
	    gasnet_AMPoll();
	}
#ifdef VERBOSE
	printf("TEST[%d] COMPLETE: nloop = %d chksum_received = %d\n",
	       myproc,nloop,received);
#endif

	BARRIER();

	if (iamsender) {
	        int success = gasnett_atomic_read(&chksum_success,0);
		printf("chksum_test(%d) passed %d/%d\n", chksum_iters, 
		    success, received);
	}
}


/*
 * Format is
 * AMRequestShort2(dest, chksum_reqh, i, seed)
 *
 * chksum_reqh(i, seed) generates the checksum and replies with a Medium
 *
 * AMReplyMedium(token, chksum_reph, src, nbytes, i)
 *
 * chksum_reph(i, src, nbytes) compares src[nbytes] to its copy of the
 * checksum at i
 */
void chksum_reqh(gex_Token_t token, 
	gex_AM_Arg_t iter, gex_AM_Arg_t seed)
{
        unsigned char   chksum_reqbuf[CHKSUM_TOTAL];

	gasnett_atomic_increment(&chksum_received, 0);
	chksum_gen(seed, &chksum_reqbuf);
	monoseed_trace(iter, seed, &chksum_reqbuf, NULL);
	GASNET_Safe( 
	    gex_AM_ReplyMedium1(token, 202, &chksum_reqbuf, 
	        CHKSUM_TOTAL, GEX_EVENT_NOW, 0, iter));
	return;
}

void
chksum_reph(gex_Token_t token, 
	void *buf, size_t nbytes, gex_AM_Arg_t iter)
{
	gasnett_atomic_increment(&chksum_received, 0);
	assert_always(iter < chksum_iters && iter >= 0);
	assert_always(nbytes == CHKSUM_TOTAL);
	monoseed_trace(iter, _mseed[iter].seed, &_mseed[iter].chksum, buf);
	if (memcmp(&_mseed[iter].chksum, buf, CHKSUM_LENGTH) == 0) 
  	        gasnett_atomic_increment(&chksum_success, 0);
	else {
		printf("iter %3d failed! chksum_local=", (int)iter);
		CHKSUM_DUMP(&_mseed[iter].chksum);
		printf(" chksum_remote=");
		CHKSUM_DUMP(buf);
		printf("\n");
	}
	return;
}
	
/* Test handlers */

int
main(int argc, char **argv)
{
	int	iters = 0;
	gex_AM_Entry_t htable[] = {
		{ 201, (gex_AM_Fn_t)chksum_reqh, GEX_FLAG_AM_REQUEST|GEX_FLAG_AM_SHORT, 2 },
		{ 202, (gex_AM_Fn_t)chksum_reph, GEX_FLAG_AM_REPLY|GEX_FLAG_AM_MEDIUM, 1 }
	};

	/* call startup */
        GASNET_Safe(gex_Client_Init(&myclient, &myep, &myteam, "testcore1", &argc, &argv, 0));
        GASNET_Safe(gex_Segment_Attach(&mysegment, myteam, TEST_SEGSZ_REQUEST));
        GASNET_Safe(gex_EP_RegisterHandlers(myep, htable, sizeof(htable)/sizeof(gex_AM_Entry_t)));

	test_init("testcore1",0,"(iters)");

        assert(CHKSUM_TOTAL <= gex_AM_LUBReplyMedium());

	if (argc > 1) iters = atoi(argv[1]);
	if (!iters) iters = 1000;
        if (argc > 2) test_usage();
	

	/* get SPMD info */
	chksum_iters = iters;
	myproc = gex_TM_QueryRank(myteam);
	numprocs = gex_TM_QuerySize(myteam);
        /* Only allow even number for numprocs */
        if (numprocs % 2 != 0) {
          MSG0("WARNING: This test requires an even number of nodes. Test skipped.\n");
          gasnet_exit(0); /* exit 0 to prevent false negatives in test harnesses for smp-conduit */
        }
	peerproc = (myproc % 2) ? myproc-1 : myproc+1;

	seginfo_table = (gasnet_seginfo_t *) test_malloc(sizeof(gasnet_seginfo_t) * numprocs);

	printf("%d> starting monoseed_init(%d)\n", myproc, iters);
	monoseed_init(iters);
	printf("%d> starting chksums_test(%d)\n", myproc, iters);
	chksum_test(iters);

	gasnet_exit(0);
	return(0);
}