Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/tests/cdt/tvthread.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 <vmalloc.h>
23
#include <pthread.h>
24
#include <sys/mman.h>
25
26
/* Test concurrency by volleying objects between two dictionaries. */
27
28
#define N_THREADS 16 /* #players */
29
#define N_OBJ 100000 /* #objects */
30
31
/* an object to be bounced back and forth */
32
typedef struct obj_s
33
{ int value; /* decimal value */
34
int ins[2]; /* #insertion into Dict[0,1] */
35
int del[2]; /* #deletion from Dict[0,1] */
36
} Obj_t;
37
38
/* Cdt discipline to allocate memory from a vmalloc region */
39
typedef struct _mydisc_s
40
{ Dtdisc_t disc; /* cdt discipline */
41
Vmalloc_t* vm; /* vmalloc region */
42
} Mydisc_t;
43
44
static Dt_t *Dict[2];
45
static int Nthreads;
46
47
/* allocate data from the shared memory region */
48
Void_t* mymemory(Dt_t* dt, Void_t* data, size_t size, Dtdisc_t* disc)
49
{
50
return vmresize(((Mydisc_t*)disc)->vm, data, size, 0);
51
}
52
53
/* compare two objects by their integer keys */
54
static int mycompare(Dt_t* dt, Void_t* key1, Void_t* key2, Dtdisc_t* disc)
55
{
56
return *((int*)key1) - *((int*)key2);
57
}
58
59
unsigned int myhash(Dt_t* dt, Void_t* key, Dtdisc_t* disc)
60
{
61
return *((unsigned*)key);
62
}
63
64
/* open a shared dictionary */
65
static Dt_t* opendictionary(Mydisc_t* dc)
66
{
67
Vmalloc_t *vm;
68
Dt_t *dt;
69
70
/* create region to allocate memory from */
71
if(!(vm = vmopen(Vmdcsystem, Vmbest, VM_SHARE)) )
72
terror("Couldn't create vmalloc region");
73
74
/* discipline for objects identified by their decimal values */
75
dc->disc.key = (ssize_t)DTOFFSET(Obj_t,value);
76
dc->disc.size = (ssize_t)sizeof(int);
77
dc->disc.link = -1;
78
dc->disc.makef = (Dtmake_f)0;
79
dc->disc.freef = (Dtfree_f)0;
80
dc->disc.comparf = mycompare;
81
dc->disc.hashf = myhash;
82
dc->disc.memoryf = mymemory;
83
dc->disc.eventf = (Dtevent_f)0;
84
dc->vm = vm;
85
86
if(!(dt = dtopen(&dc->disc, Dtrhset)) ) /* open dictionary with hash-trie */
87
terror("Can't open dictionary");
88
dtcustomize(dt, DT_SHARE, 1); /* turn on concurrent access mode */
89
90
return dt;
91
}
92
93
/* swap objects from one dictionary to another */
94
static void* volley(void* arg)
95
{
96
int deldt, insdt, n_move, dir, k;
97
Obj_t obj, *o, *rv;
98
99
Nthreads += 1; /* wait until all threads have been started */
100
while(Nthreads < N_THREADS)
101
asorelax(1);
102
103
if((deldt = (int)((long)arg)) < 0 || deldt > 1)
104
terror("Thread number must be 0 or 1, not %d", deldt);
105
insdt = !deldt;
106
107
n_move = 0;
108
for(dir = 1; dir >= -1; dir -= 2)
109
{ for(k = dir > 0 ? 0 : N_OBJ-1; k >= 0 && k < N_OBJ; k += dir)
110
{ obj.value = k;
111
if(!(o = dtsearch(Dict[deldt], &obj)) )
112
continue;
113
114
if((rv = dtdelete(Dict[deldt], o)) == o )
115
{ asoincint(&o->del[deldt]);
116
117
if((rv = dtinsert(Dict[insdt], o)) != o )
118
terror("Insert %d failed", o->value);
119
120
asoincint(&o->ins[insdt]);
121
122
n_move += 1;
123
}
124
else if(rv)
125
terror("Unknown object %d", rv->value);
126
127
if(k%100 == 0)
128
asorelax(1);
129
}
130
}
131
tinfo("Move %d (Dict[%d] -> Dict[%d])", n_move, deldt, insdt);
132
133
return 0;
134
}
135
136
tmain()
137
{
138
pthread_t thread[N_THREADS];
139
size_t k, p, n;
140
Mydisc_t disc[2];
141
Obj_t *o, *list[2], obj;
142
143
topts();
144
taso(ASO_THREAD);
145
146
/* create two dictionaries to volley objects back and forth */
147
for(n = 0; n < 2; ++n)
148
{ if(!(Dict[n] = opendictionary(&disc[n])) )
149
terror("Can't open dictionary %d", n);
150
151
/* make objects */
152
if(!(list[n] = vmalloc(disc[n].vm, (N_OBJ/2)*sizeof(Obj_t))) )
153
terror("vmalloc failed %d", n);
154
memset(list[n], 0, (N_OBJ/2)*sizeof(Obj_t) );
155
156
for(o = list[n], k = 0; k < N_OBJ/2; ++k, ++o)
157
{ o->value = n == 0 ? k : k+N_OBJ/2;
158
159
if(dtinsert(Dict[n], o) != o)
160
terror("Insert failed n=%d k=%d", n, k);
161
if(dtsearch(Dict[n],o) != o) /* verify insert succeeded */
162
terror("Search failed n=%d k=%d", n, k);
163
164
o->ins[n] += 1;
165
}
166
}
167
168
for(p = 0; p < N_THREADS; ++p )
169
pthread_create(&thread[p], 0, volley, (void*)((long)(p%2)) );
170
171
for(p = 0; p < N_THREADS; ++p )
172
pthread_join(thread[p], 0);
173
174
tinfo("\tCheck integrity");
175
n = dtsize(Dict[0]);
176
p = dtsize(Dict[1]);
177
tinfo("Dict[0]=%d Dict[1]=%d", n, p);
178
if((n+p) != N_OBJ)
179
{ for(k = 0; k < N_OBJ; ++k)
180
{ obj.value = k;
181
if((o = dtsearch(Dict[0], &obj)) )
182
continue;
183
if((o = dtsearch(Dict[1], &obj)) )
184
continue;
185
twarn("%d not found", k);
186
dtsearch(Dict[0], &obj);
187
dtsearch(Dict[1], &obj);
188
}
189
190
terror("Expecting %d objects but got (Dict[0]=%d + Dict[1]=%d) = %d",
191
N_OBJ, n, p, n+p);
192
}
193
194
texit(0);
195
}
196
197