Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/tests/cdt/tsafehash.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1999-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#include "dttest.h"
21
22
#include <sys/mman.h>
23
24
/* Test concurrency usage of the method Dtrhset.
25
**
26
** Written by Kiem-Phong Vo
27
*/
28
29
#ifndef N_PROC
30
#define N_PROC 64
31
#endif
32
33
#define N_OBJ (N_PROC*64*1024) /* #objects to insert */
34
#define SEARCH 4 /* #searches while inserting */
35
#define PROGRESS (N_OBJ/(N_PROC*4)) /* amount done */
36
37
#define FORMAT "%09d" /* 9-digit numbers with zero-filled */
38
39
#define INSERT 001 /* to tell if an object was inserted */
40
#define DELETE 002 /* to tell if an object was deleted */
41
42
typedef struct _obj_s
43
{ Dtlink_t link;
44
unsigned int flag; /* INSERT/DELETE state */
45
char str[12]; /* string representation */
46
} Obj_t;
47
48
typedef struct _proc_s
49
{ Obj_t* obj; /* list of objects to add */
50
ssize_t objn; /* number of objects in list */
51
} Proc_t;
52
53
typedef struct _state_s
54
{ unsigned int insert; /* insertion states */
55
unsigned int idone;
56
unsigned int delete; /* deletion states */
57
unsigned int ddone;
58
} State_t;
59
60
typedef struct _disc_s
61
{ Dtdisc_t disc;
62
unsigned int lock;
63
unsigned char* addr;
64
ssize_t size;
65
} Disc_t;
66
67
static Disc_t *Disc; /* shared discipline structure */
68
static Obj_t *Obj; /* shared object list */
69
static Proc_t Proc[N_PROC]; /* process workloads */
70
static int Pnum = N_PROC+1; /* start as parent */
71
72
static int Icount; /* # insertions done */
73
static int Dcount; /* # deletions done */
74
75
static State_t *State; /* insert/delete states */
76
77
/* memory allocator for shared dictionary - no freeing here */
78
static Void_t* memory(Dt_t* dt, Void_t* addr, size_t size, Dtdisc_t* disc)
79
{
80
int k;
81
Disc_t *dc = (Disc_t*)disc;
82
83
if(addr || size <= 0 ) /* no freeing */
84
return NIL(Void_t*);
85
86
for(k = 0;; asorelax(1<<k), k = (k+1)&07 )
87
if(asocasint(&dc->lock, 0, 1) == 0) /* get exclusive use first */
88
break;
89
90
size = ((size + sizeof(Void_t*) - 1)/sizeof(Void_t*))*sizeof(Void_t*);
91
if(size <= dc->size)
92
{ addr = (Void_t*)dc->addr;
93
dc->addr += size;
94
dc->size -= size;
95
}
96
else terror("Out of shared memory");
97
98
asocasint(&dc->lock, 1, 0); /* release exclusive use */
99
100
return addr;
101
}
102
103
static void sigchild(int sig)
104
{ pid_t pid;
105
int status;
106
char *st, buf[128];
107
108
pid = wait(&status);
109
if(WIFSIGNALED(status))
110
{ int sig = WTERMSIG(status);
111
sprintf(buf,"signal %s", sig == 8 ? "fpe" : sig == 11 ? "segv" : "whatever");
112
st = buf;
113
}
114
else if(WCOREDUMP(status))
115
st = "coredump";
116
else st = "normal";
117
118
tinfo("Child process %d exited (%s)", pid, st);
119
signal(SIGCHLD, sigchild);
120
}
121
122
static void workload(Dt_t* dt, Proc_t* proc, int p)
123
{
124
Obj_t *os, *or;
125
ssize_t k, s;
126
pid_t pid = getpid();
127
128
Pnum = p+1; /* always positive */
129
130
/* insert objects in 'p' */
131
asoincint(&State->insert); /* signaling that we are ready to go */
132
while(asogetint(&State->insert) != N_PROC) /* wait until all processes are set */
133
usleep(100);
134
for(k = 0; k < proc->objn; ++k)
135
{ if(k && k%PROGRESS == 0)
136
tinfo("\tProcess %d(%d): insertion passing %d", p, pid, k);
137
138
or = proc->obj+k;
139
if((os = dtinsert(dt,or)) != or)
140
tinfo("\t\tProcess %d(%d): Insert %s, get %0x", p,pid,or->str,os);
141
else os->flag |= INSERT;
142
if((os = dtsearch(dt, or)) != or)
143
tinfo("\t\tProcess %d(%d): Just inserted %s but not found", p,pid,or->str);
144
Icount += 1;
145
146
if(k > SEARCH ) /* search a few elements known to be inserted */
147
{ for(s = 0; s < SEARCH; ++s)
148
{ ssize_t r = random()%k;
149
or = proc->obj+r;
150
os = dtsearch(dt,or);
151
if(os != or)
152
tinfo("\t\tProcess %d(%d): Srch %s(Max %s) get %0x",
153
p,pid, or->str, proc->obj[k].str, os);
154
}
155
}
156
}
157
tinfo("Process %d(%d): insertion done", p,pid);
158
asoincint(&State->idone); /* signaling that this workload has been inserted */
159
while(asogetint(&State->idone) > 0) /* wait until parent signal ok to continue */
160
usleep(100);
161
162
/* delete objects in 'p' and also in "foe" of p */
163
asoincint(&State->delete); /* signaling that we are ready to delete */
164
while(asogetint(&State->delete) != N_PROC) /* wait until all processes are set */
165
usleep(100);
166
for(k = 0; k < proc->objn; ++k)
167
{ if(k && k%PROGRESS == 0)
168
tinfo("\tProcess %d(%d): deletion passing %d", p, pid, k);
169
170
if(dtdelete(dt, proc->obj+k) == Proc[p].obj+k )
171
proc->obj[k].flag |= DELETE;
172
Dcount += 1;
173
174
if(k > SEARCH)
175
{ for(s = 0; s < SEARCH; ++s)
176
{ ssize_t r = random()%k;
177
or = proc->obj+r;
178
if(dtsearch(dt,or) )
179
tinfo("\t\tProcess %d(%d): Search %s !NULL",p,pid,or->str);
180
}
181
}
182
}
183
asoincint(&State->ddone); /* signaling that workload has been deleted */
184
tinfo("Process %d(%d): deletion done", p, pid);
185
}
186
187
tmain()
188
{
189
ssize_t k, z, objn;
190
Obj_t *o;
191
Dt_t *dt;
192
pid_t pid[N_PROC];
193
int zerof;
194
195
taso(ASO_PROCESS);
196
tchild();
197
198
if((zerof = open("/dev/zero", O_RDWR)) < 0)
199
terror("Can't open /dev/zero");
200
201
/* get shared memory */
202
if((k = 4*N_OBJ*sizeof(Void_t*)) < 64*1024*1024 )
203
k = 64*1024*1024;
204
z = sizeof(State_t) /* insert/delete states */ +
205
sizeof(Disc_t) /* discipline */ +
206
N_OBJ*sizeof(Obj_t) /* Obj */ +
207
k; /* table memory */
208
State = (State_t*)mmap(0,z,PROT_READ|PROT_WRITE,MAP_SHARED,zerof,0);
209
if(!State || State == (State_t*)(-1))
210
terror("mmap failed");
211
Disc = (Disc_t*)(State+1);
212
Obj = (Obj_t*)(Disc+1);
213
Disc->addr = (unsigned char*)(Obj+N_OBJ);
214
Disc->size = k;
215
216
memset(State, 0, sizeof(State_t));
217
218
/* construct the objects to be inserted */
219
for(k = 0; k < N_OBJ; ++k)
220
{ Obj[k].flag = 0;
221
sprintf(Obj[k].str, FORMAT, k);
222
}
223
224
/* construct the work-load for each process */
225
objn = N_OBJ/N_PROC;
226
Proc[0].obj = &Obj[0];
227
Proc[0].objn = objn;
228
for(k = 1; k < N_PROC; ++k)
229
{ Proc[k].obj = Proc[k-1].obj + Proc[k-1].objn;
230
Proc[k].objn = k < (N_PROC-1) ? objn : N_OBJ - (k*objn);
231
}
232
233
/* now create the shared dictionary */
234
Disc->disc.key = DTOFFSET(Obj_t,str);
235
Disc->disc.size = 0;
236
Disc->disc.link = 0;
237
Disc->disc.makef = NIL(Dtmake_f);
238
Disc->disc.freef = NIL(Dtfree_f);
239
Disc->disc.comparf = NIL(Dtcompar_f);
240
Disc->disc.hashf = NIL(Dthash_f);
241
Disc->disc.memoryf = memory;
242
Disc->disc.eventf = NIL(Dtevent_f);
243
if(!(dt = dtopen(&Disc->disc, Dtset)) )
244
terror("Cannot open dictionary");
245
if(dtcustomize(dt, DT_SHARE, 1) != DT_SHARE )
246
terror("Cannot turn on share mode");
247
248
#if N_PROC == 1
249
Pnum = 1;
250
workload(dt, Proc, 0);
251
#else
252
signal(SIGCHLD, sigchild);
253
for(k = 0; k < N_PROC; ++k)
254
{ if((pid[k] = fork()) < 0 )
255
terror("Can't create child process");
256
else if(pid[k] > 0) /* parent */
257
tinfo("Just launched process %d (pid=%d)", k, pid[k]);
258
else
259
{ Pnum = k+1;
260
signal(SIGCHLD,SIG_IGN);
261
workload(dt, Proc+k, k);
262
texit(0);
263
}
264
}
265
#endif
266
267
tinfo("\ttsafehash: Insertion #procs=%d (free shared mem=%d)", k, Disc->size);
268
for(k = 0;; asorelax(1<<k), k = (k+1)&07)
269
if(asogetint(&State->idone) == N_PROC)
270
break;
271
tinfo("\ttsafehash: Insertion completed, checking integrity");
272
273
for(k = 0; k < N_OBJ; ++k)
274
if(!dtsearch(dt, Obj+k) )
275
terror("Failed to find object %s", Obj[k].str);
276
277
asocasint(&State->idone, N_PROC, 0);
278
279
tinfo("\ttsafehash: Deletion (free shared mem=%d)", Disc->size);
280
for(k = 0;; asorelax(1<<k), k = (k+1)&07 )
281
if(asogetint(&State->ddone) == N_PROC) /* wait until all are deleted */
282
break;
283
if(dtfirst(dt) )
284
terror("Dictionary not empty after deletion!");
285
286
z = 0;
287
for(k = 0; k < N_OBJ; ++k)
288
if((Obj[k].flag & DELETE) )
289
z += 1;
290
if(z != N_OBJ)
291
twarn("Some deletion was not properly recorded?");
292
293
tinfo("\ttsafehash: All testing done.");
294
twait(pid, -N_PROC);
295
296
texit(0);
297
}
298
299