source: CIVL/examples/pthread/threader/scull_true-unreach-call.c@ bb03188

main test-branch
Last change on this file since bb03188 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

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

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