source: CIVL/examples/pthread/threader/scull_true.c@ e0fc189

1.23 2.0 main test-branch
Last change on this file since e0fc189 was e3151da, checked in by Ziqing Luo <ziqing@…>, 11 years ago

re-organized example directory

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@1763 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 8.4 KB
Line 
1extern int __VERIFIER_nondet_int();
2/* Testcase from Threader's distribution. For details see:
3 http://www.model.in.tum.de/~popeea/research/threader
4*/
5
6#include <pthread.h>
7#include "scull_safe.h"
8#define assert(e) if (!(e)) ERROR: goto ERROR;
9
10inode i;
11pthread_mutex_t lock;
12
13/* =====================================================
14 Model for the Linux kernel API
15 ===================================================== */
16inline int down_interruptible() {
17 pthread_mutex_lock(&lock);
18 return 0; // lock is held
19}
20
21inline void up() {
22 pthread_mutex_unlock(&lock);
23 return;
24}
25
26#define container_of(dev) dev
27
28inline unsigned_long copy_to_user(char to, char from, unsigned_long n) {
29 to = from;
30 return __VERIFIER_nondet_int();
31}
32
33inline unsigned_long copy_from_user(char to, char from, unsigned_long n) {
34 to = from;
35 return __VERIFIER_nondet_int();
36}
37
38inline int __get_user(int size, void_ptr ptr)
39{
40 return __VERIFIER_nondet_int();
41}
42
43inline int __put_user(int size, void_ptr ptr)
44{
45 return __VERIFIER_nondet_int();
46}
47
48
49/* =====================================================
50 A model for the device-driver functions
51 ===================================================== */
52/*
53 * scull.h -- definitions for the char module
54 *
55 * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
56 * Copyright (C) 2001 O'Reilly & Associates
57 *
58 * The source code in this file can be freely used, adapted,
59 * and redistributed in source or binary form, so long as an
60 * acknowledgment appears in derived source files. The citation
61 * should list that the code comes from the book "Linux Device
62 * Drivers" by Alessandro Rubini and Jonathan Corbet, published
63 * by O'Reilly & Associates. No warranty is attached;
64 * we cannot take responsibility for errors or fitness for use.
65 *
66 * $Id: scull.h,v 1.15 2004/11/04 17:51:18 rubini Exp $
67 */
68
69int scull_quantum = SCULL_QUANTUM;
70int scull_qset = SCULL_QSET;
71int dev_data;
72int dev_quantum;
73int dev_qset;
74unsigned_long dev_size;
75int __X__; //variable to test mutual exclusion
76
77/*
78 * Empty out the scull device; must be called with the device
79 * semaphore held.
80 */
81int scull_trim(scull_dev dev)
82{
83 int qset = dev_qset;
84
85 dev_size = 0;
86 dev_quantum = scull_quantum;
87 dev_qset = scull_qset;
88 dev_data = 0;
89 return 0;
90}
91
92
93/*
94 * Open and close
95 */
96
97inline int scull_open(int tid, inode i, file filp)
98{
99 scull_dev dev;
100
101 dev = container_of(i);
102 filp = dev;
103
104 if (down_interruptible())
105 return -ERESTARTSYS;
106
107 __X__ = 2; /* check mutual exclusion */
108 scull_trim(dev); /* ignore errors */
109 assert(__X__ >= 2); /* check mutual exclusion */
110 up();
111 return 0; /* success */
112}
113
114#define scull_release(i, filp) 0
115
116/*
117 * Follow the list
118 */
119inline scull_qset_type scull_follow(scull_dev dev, int n) {
120 return __VERIFIER_nondet_int();
121}
122
123/*
124 * Data management: read and write
125 */
126
127inline ssize_t scull_read(int tid, file filp, char buf, size_t count,
128 loff_t f_pos)
129{
130 scull_dev dev = filp;
131 scull_qset_type dptr; /* the first listitem */
132 int quantum = dev_quantum, qset = dev_qset;
133 int itemsize = quantum * qset; /* how many bytes in the listitem */
134 int item, s_pos, q_pos, rest;
135 ssize_t retval = 0;
136
137 if (down_interruptible())
138 return -ERESTARTSYS;
139
140 __X__ = 0; /* check mutual exclusion */
141
142 if (f_pos >= dev_size)
143 goto out;
144 if (f_pos+count >= dev_size)
145 count = dev_size - f_pos;
146
147 /* find listitem, qset index, and offset in the quantum */
148 item = f_pos / itemsize;
149 rest = f_pos;
150 s_pos = rest / quantum; q_pos = rest;
151
152 /* follow the list up to the right position (defined elsewhere) */
153 dptr = scull_follow(dev, item);
154
155 /* read only up to the end of this quantum */
156 if (count > quantum - q_pos)
157 count = quantum - q_pos;
158
159 if (copy_to_user(buf, dev_data + s_pos + q_pos, count)) {
160 retval = -EFAULT;
161 goto out;
162 }
163 f_pos += count;
164 retval = count;
165
166 assert(__X__ <= 0); /* check mutual exclusion */
167
168 out:
169 up();
170 return retval;
171}
172
173inline ssize_t scull_write(int tid, file filp, char buf, size_t count,
174 loff_t f_pos)
175{
176 scull_dev dev = filp;
177 scull_qset_type dptr;
178 int quantum = dev_quantum, qset = dev_qset;
179 int itemsize = quantum * qset;
180 int item, s_pos, q_pos, rest;
181 ssize_t retval = -ENOMEM; /* value used in "goto out" statements */
182
183 if (down_interruptible())
184 return -ERESTARTSYS;
185
186 /* find listitem, qset index and offset in the quantum */
187 item = f_pos / itemsize;
188 rest = f_pos;
189 s_pos = rest / quantum; q_pos = rest;
190
191 /* follow the list up to the right position */
192 dptr = scull_follow(dev, item);
193 if (dptr == 0)
194 goto out;
195
196 /* write only up to the end of this quantum */
197 if (count > quantum - q_pos)
198 count = quantum - q_pos;
199
200 __X__ = 1; /* check mutual exclusion */
201
202 if (copy_from_user(dev_data+s_pos+q_pos, buf, count)) {
203 retval = -EFAULT;
204 goto out;
205 }
206 f_pos += count;
207 retval = count;
208
209 /* update the size */
210 if (dev_size < f_pos)
211 dev_size = f_pos;
212
213 assert(__X__ == 1); /* check mutual exclusion */
214
215 out:
216 up();
217 return retval;
218}
219
220/*
221 * The ioctl() implementation
222 */
223
224inline int scull_ioctl(inode i, file filp,
225 unsigned_int cmd, unsigned_long arg)
226{
227
228 int err = 0, tmp;
229 int retval = 0;
230
231 switch(cmd) {
232
233 case SCULL_IOCRESET:
234 scull_quantum = SCULL_QUANTUM;
235 scull_qset = SCULL_QSET;
236 break;
237
238 case SCULL_IOCSQUANTUM: /* Set: arg points to the value */
239 retval = __get_user(scull_quantum, arg);
240 break;
241
242 case SCULL_IOCTQUANTUM: /* Tell: arg is the value */
243 scull_quantum = arg;
244 break;
245
246 case SCULL_IOCGQUANTUM: /* Get: arg is pointer to result */
247 retval = __put_user(scull_quantum, arg);
248 break;
249
250 case SCULL_IOCQQUANTUM: /* Query: return it (it's positive) */
251 return scull_quantum;
252
253 case SCULL_IOCXQUANTUM: /* eXchange: use arg as pointer */
254 tmp = scull_quantum;
255 retval = __get_user(scull_quantum, arg);
256 if (retval == 0)
257 retval = __put_user(tmp, arg);
258 break;
259
260 case SCULL_IOCHQUANTUM: /* sHift: like Tell + Query */
261 tmp = scull_quantum;
262 scull_quantum = arg;
263 return tmp;
264
265 case SCULL_IOCSQSET:
266 retval = __get_user(scull_qset, arg);
267 break;
268
269 case SCULL_IOCTQSET:
270 scull_qset = arg;
271 break;
272
273 case SCULL_IOCGQSET:
274 retval = __put_user(scull_qset, arg);
275 break;
276
277 case SCULL_IOCQQSET:
278 return scull_qset;
279
280 case SCULL_IOCXQSET:
281 tmp = scull_qset;
282 retval = __get_user(scull_qset, arg);
283 if (retval == 0)
284 retval = __put_user(tmp, arg);
285 break;
286
287 case SCULL_IOCHQSET:
288 tmp = scull_qset;
289 scull_qset = arg;
290 return tmp;
291
292
293 default: /* redundant, as cmd was checked against MAXNR */
294 return -ENOTTY;
295 }
296 return retval;
297
298}
299
300
301/*
302 * The "extended" operations -- only seek
303 */
304
305inline loff_t scull_llseek(file filp, loff_t off, int whence, loff_t f_pos)
306{
307 scull_dev dev = filp;
308 loff_t newpos;
309
310 switch(whence) {
311 case 0: /* SEEK_SET */
312 newpos = off;
313 break;
314
315 case 1: /* SEEK_CUR */
316 newpos = filp + f_pos + off;
317 break;
318
319 case 2: /* SEEK_END */
320 newpos = dev_size + off;
321 break;
322
323 default: /* can't happen */
324 return -EINVAL;
325 }
326 if (newpos < 0) return -EINVAL;
327 filp = newpos;
328 return newpos;
329}
330
331/*
332 * Finally, the module stuff
333 */
334
335/*
336 * The cleanup function is used to handle initialization failures as well.
337 * Thefore, it must be careful to work correctly even if some of the items
338 * have not been initialized
339 */
340inline void scull_cleanup_module(void)
341{
342 scull_dev dev;
343 scull_trim(dev);
344
345}
346
347inline int scull_init_module()
348{
349 int result = 0;
350 return 0;
351
352 fail:
353 scull_cleanup_module();
354 return result;
355}
356
357
358/* =====================================================
359 User program calling functions from the device driver
360 ===================================================== */
361void *loader() {
362 scull_init_module();
363 scull_cleanup_module();
364}
365
366void *thread1() {
367 file filp;
368 char buf;
369 size_t count = 10;
370 loff_t off = 0;
371 scull_open(tid1, i, filp);
372 scull_read(tid1, filp, buf, count, off);
373 scull_release(i, filp);
374}
375
376void *thread2() {
377 file filp;
378 char buf;
379 size_t count = 10;
380 loff_t off = 0;
381 scull_open(tid2, i, filp);
382 scull_write(tid2, filp, buf, count, off);
383 scull_release(i, filp);
384}
385
386int main() {
387 pthread_t t1, t2, t3;
388 pthread_mutex_init(&lock, FILE_WITH_LOCK_UNLOCKED);
389 pthread_create(&t1, 0, loader, 0);
390 pthread_create(&t2, 0, thread1, 0);
391 pthread_create(&t3, 0, thread2, 0);
392 pthread_join(t1, 0);
393 pthread_join(t2, 0);
394 pthread_join(t3, 0);
395 pthread_mutex_destroy(&lock);
396 return 0;
397}
Note: See TracBrowser for help on using the repository browser.