source: CIVL/examples/pthread/pthread.cvh@ 325d439

1.23 2.0 main test-branch
Last change on this file since 325d439 was 6fe2cd9, checked in by John Edenhofner <johneden@…>, 12 years ago

Almost done

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

  • Property mode set to 100644
File size: 17.9 KB
Line 
1/*
2 All specification references correspond to pages in the Standard for Information Technology–
3Portable Operating System Interface (POSIX ® )IEEE Computer Society Base Specifications, Issue 7.
4
5Standard modifications to each translation:
6header files are altered
7errors are changed to assertion violations with appropriate messages
8appropriate definitions are changed to input variables
9*/
10
11#include <civlc.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <assert.h>
15#include <stdbool.h>
16
17//Mutex types
18#define PTHREAD_MUTEX_DEFAULT 0
19#define PTHREAD_MUTEX_NORMAL 0
20#define PTHREAD_MUTEX_RECURSIVE 1
21#define PTHREAD_MUTEX_ERRORCHECK 2
22
23//Mutex Robustness Types
24#define PTHREAD_MUTEX_STALLED 0
25#define PTHREAD_MUTEX_ROBUST 1
26
27//Attribute Constants
28#define PTHREAD_CREATE_DETACHED 0
29#define PTHREAD_CREATE_JOINABLE 1
30
31//Mutex initializer
32#define __LOCK_INITIALIZER 0
33#define PTHREAD_MUTEX_INITIALIZER {0,0,0,PTHREAD_MUTEX_NORMAL,__LOCK_INITIALIZER}
34#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER,0}
35
36/* Struct definitions */
37
38/* pthread_attr_t struct definition
39 Description: This struct corresponds to the pthread_attr_t which is the attribute of a pthread_t. It's fields
40 define the way the pthread_t is able to interact (join/detach), (memory capacity), (scope) etc.
41
42 Fields: void * stackaddr: The address of the attr's stack in memory
43 size_t stacksize: The memory capacity for the attr's stack
44 size_t guardsize: The guardsize attribute controls the size of the guard area for the created thread’s stack. The
45 guardsize attribute provides protection against overflow of the stack pointer.
46 int detachstate: Defines a threads ability to join with two values: PTHREAD_CREATE_DETACHED and PTHREAD_CREATE_JOINABLE
47 int inheritsched: The inheritance scheduling policy of the thread
48 int contentionscope: Defines the contention scope of the thread
49 int schedpolicy: Determines the scheduling policy of the thread
50
51*/
52
53typedef struct {
54 void *stackaddr;
55 size_t stacksize;
56 size_t guardsize;
57 int detachstate;
58 int inheritsched;
59 int contentionscope;
60 int schedpolicy;
61} pthread_attr_t;
62
63/* pthread_mutexattr_t struct definition
64 Description: The pthread_mutexattr_t defines multiple attributes of a mutex and controls its interactions with threads
65 Fields: robust: defines the robustness of the mutex; if robust and the owning thread terminates, it will notify the
66 next thread of this to prevent deadlocks and other errors
67 pshared: defines the process shared element of the thread and which processes can interact with the mutex
68 protocol: defines the priority protocol of the mutex and which threads may interact first
69 type: defines the type of the mutex as either PTHREAD_MUTEX_DEFAULT/NORMAL, PTHREAD_MUTEX_ERRORCHECK, or
70 PTHREAD_MUTEX_RECURSIVE, each explained in pthread_mutex_lock below
71 prioceiling: defines the lowest priority the mutex's critical section can be at
72*/
73
74typedef struct {
75 int robust;
76 int pshared;
77 int protocol;
78 int type;
79 int prioceiling;
80}pthread_mutexattr_t;
81
82/* pthread_mutex_t struct definition
83 Description: The pthread_mutex_t is a locking mechanism for threads to interact with in order to control the scheduling
84 of the threads. It can be locked, which allows for blocking of other threads waiting on the mutex and unlocked, allowing
85 access. It has a pthread_mutexattr_t which defines its behavior.
86 Fields: count - used for recursive mutex, incremented when locked, decremented when unlocked, mutex released when count is 0
87 owner - current process owner of the mutex
88 lock - int of 0 or 1, respectively 0 if unlocked, 1 if locked
89 prioceiling - allows locking without adherence to the priority ceiling
90 attr - see above
91*/
92
93typedef struct {
94 int count;
95 $proc owner;
96 int lock;
97 int prioceiling;
98 pthread_mutexattr_t *attr;
99} pthread_mutex_t;
100
101//Unimplemented
102/*
103typedef struct {
104 int pshared;
105 clockid_t clock_id;
106}pthread_condattr_t;
107*/
108
109/* pthread_cond_t struct definition
110 Description: The pthread_cond_t is another locking mechanism which interacts with the mutex variable. When
111 the mutex is locked, the condition can be accessed, leading the accessing thread to unlock it, and sleep
112 until the signal is given
113 Fields: proccount - specifies the number of processes/threads still waiting on this condition variable
114 signal - Boolean value stating whether the condition is satisfied (indicated by 1) or not (0)
115*/
116
117typedef struct {
118 int proccount;
119 _Bool signal;
120} pthread_cond_t;
121
122/* pthread_t struct definition
123 Description: The pthread_t is a struct containing a $proc variable as well as a thread attribute which defines
124 its interactions with other threads. It encapsulates the $proc and allows attributes to apply to it.
125 Fields: thr: the $proc variable that is the heart of the thread
126 attr: see above
127*/
128
129typedef struct {
130 $proc thr;
131 const pthread_attr_t *attr;
132} pthread_t;
133
134/* pthread_attr_init method definition
135 The pthread_attr_init() initializes an attribute with the default values defined for it by an implementation.
136 At the moment, the pthread_attr_t is very basic, only supporting joining/detaching but will be improved
137 upon at a later date.
138 Corresponding specification: p. 153
139*/
140
141int pthread_attr_init(pthread_attr_t *attr){
142 attr->stacksize = 0;
143 attr->guardsize = 0;
144 attr->detachstate = PTHREAD_CREATE_DETACHED;
145 //attr->inheritsched = PTHREAD_EXPLICIT_SCHED;
146 //attr->scope = PTHREAD_SCOPE_SYSTEM;
147 attr->stackaddr = NULL;
148 //attr->schedpolicy = SCHED_OTHER;
149 return 0;
150}
151
152/* pthread_attr_destroy method definition
153 This implementation effectively uninitializes the attr variable, which works accordingly with the specification's requirements.
154 Corresponding specification: p. 153/4
155*/
156int pthread_attr_destroy(pthread_attr_t *attr)
157{
158 pthread_attr_t blank;
159
160 *attr = blank;
161 return 0;
162}
163
164//Set the detachstate attribute
165//Corresponding specification: p. 153/4
166int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
167{
168 attr->detachstate = detachstate;
169 return 0;
170}
171
172//Return the detachstate attribute
173//Corresponding specification: p. 153/4
174int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
175{
176 *detachstate = attr->detachstate;
177 return 0;
178}
179
180//Set scheduling inheritance
181//Corresponding specification: p. 153/4
182int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched)
183{
184 attr->inheritsched = inheritsched;
185 return 0;
186}
187
188//Return the scheduling inheritance
189//Corresponding specification: p. 153/4
190int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched)
191{
192 *inheritsched = attr->inheritsched;
193 return 0;
194}
195
196/*Set scheduling contention scope
197//Corresponding specification: p. 153/4
198int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
199{
200 attr->scope = contentionscope;
201 return 0;
202}
203
204//Return the scheduling contention scope
205//Corresponding specification: p. 153/4
206int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope)
207{
208 *contentionscope = attr->scope;
209 return 0;
210}
211*/
212
213//Set the starting address of the stack of the thread
214//Corresponding specification: p. 153/4
215int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
216{
217 attr->stackaddr = stackaddr;
218 return 0;
219}
220
221//Return the address for the stack
222//Corresponding specification: p. 153/4
223int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
224{
225 *stackaddr = attr->stackaddr;
226 return 0;
227}
228
229//Set stack size
230//Corresponding specification: p. 153/4
231int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
232{
233 attr->stacksize = stacksize;
234 return 0;
235}
236
237//Return the stack size
238//Corresponding specification: p. 153/4
239int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
240{
241 *stacksize = attr->stacksize;
242 return 0;
243}
244
245//Set guard size
246//Corresponding specification: p. 153/4
247int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
248{
249 attr->guardsize = guardsize;
250 return 0;
251}
252
253// Return guard size
254//Corresponding specification: p. 153/4
255int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
256{
257 *guardsize = attr->guardsize;
258 return 0;
259}
260
261//Set scheduling policy
262//Corresponding specification: p. 153/4
263int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
264{
265 attr->schedpolicy = policy;
266 return 0;
267}
268
269// Return scheduling policy
270//Corresponding specification: p. 153/4
271int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
272{
273 *policy = attr->schedpolicy;
274 return 0;
275}
276
277/* pthread_mutexattr_init method definition
278 This method defines the default values for each of the mutexattr's field
279 //Corresponding specification: p. 165
280*/
281
282int pthread_mutexattr_init(pthread_mutexattr_t *attr){
283 attr->robust = 0;
284 attr->pshared = 0;
285 attr->protocol = 0;
286 attr->type = 0;
287 attr->prioceiling = 0;
288 return 0;
289}
290
291/* pthread_mutexattr_destroy method definition
292 This implementation effectively uninitializes the attr variable, which works accordingly with the specification's requirements.
293 //Corresponding specification: p. 165
294*/
295
296int pthread_mutexattr_destroy(pthread_mutexattr_t *attr){
297 pthread_mutexattr_t blank;
298
299 *attr = blank;
300 return 0;
301}
302
303/* pthread_mutex_init method definition
304 This method initializes each of the mutex's default values as well as being able to take values from another attribute
305 if desired, otherwise the attribute field may be NULL
306 //Corresponding specification: p. 164
307*/
308
309int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr){
310 if(attr == NULL){
311 mutex->attr = (pthread_mutexattr_t *)malloc(sizeof(pthread_mutexattr_t));
312 mutex->attr->robust = 0;
313 mutex->attr->pshared = 0;
314 mutex->attr->protocol = 0;
315 mutex->attr->type = PTHREAD_MUTEX_DEFAULT;
316 mutex->attr->prioceiling = 0;
317 }
318 else{
319 mutex->attr = (pthread_mutexattr_t *)malloc(sizeof(pthread_mutexattr_t));
320 mutex->attr = attr;
321 }
322 mutex->lock = 0;
323 mutex->count = 0;
324 mutex->owner = $proc_null;
325 return 0;
326}
327
328/* pthread_mutex_destroy method definition
329 This implementation effectively uninitializes the mutex variable, which works accordingly with the specification's requirements.
330 //Corresponding specification: p. 164
331*/
332
333int pthread_mutex_destroy(pthread_mutex_t *mutex){
334 pthread_mutex_t blank;
335
336 *mutex = blank;
337 return 0;
338}
339
340/* pthread_cond_init method definition
341 Initializes the condition variable so that it begins with 0 processes waiting on it as well as a signal set to be zero
342 **Needs to be modified to work with condition attributes as the second parameter
343 //Corresponding specification: p. 158
344*/
345
346void pthread_cond_init(pthread_cond_t *cond, void *arg){
347 cond->proccount = 0;
348 cond->signal = 0;
349}
350
351
352
353/* pthread_cond_destroy method definition
354 This implementation effectively uninitializes the cond variable, which works accordingly with the specification's requirements.
355 If any threads are still waiting on the condition upon destruction, an error is returned.
356 //Corresponding specification: p. 158
357*/
358
359int pthread_cond_destroy(pthread_cond_t *cond){
360 if(cond->proccount != 0){
361 $assert($false, "ERROR: Threads still waiting on specified condition variable");
362 }
363 else{
364 pthread_cond_t blank;
365 *cond = blank;
366 }
367 return 0;
368}
369
370/* pthread_create method definition
371 Description: Defines a pthread_t by assigning it an attribute value (by value so the original attribute's state is
372 irrelevant), and spawning a process as the thr field with arguments void *arg
373 //Corresponding specification: p. 160
374*/
375
376int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg){
377 thread->thr = $spawn start_routine(arg);
378 if(attr == NULL){
379 thread->attr = (pthread_attr_t *)malloc(sizeof(pthread_attr_t));
380 thread->attr->stackaddr = NULL;
381 thread->attr->stacksize = 0;
382 thread->attr->guardsize = 0;
383 thread->attr->detachstate = 1;
384 thread->attr->inheritsched = 0;
385 thread->attr->contentionscope = 0;
386 thread->attr->schedpolicy = 0;
387 }
388 else{
389 thread->attr = (pthread_attr_t *)malloc(sizeof(pthread_attr_t));
390 thread->attr->stackaddr = attr->stackaddr;
391 thread->attr->stacksize = attr->stacksize;
392 thread->attr->guardsize = attr->guardsize;
393 thread->attr->detachstate = attr->detachstate;
394 thread->attr->inheritsched = attr->inheritsched;
395 thread->attr->contentionscope = attr->contentionscope;
396 thread->attr->schedpolicy = attr->schedpolicy;
397 }
398 return 0;
399}
400
401/* pthread_join method definition
402 Description: Causes current thread to wait on thread specified as a parameter. If specified thread's detachstate field is set as PTHREAD_CREATE_DETACHED,
403 error will be returned stating the the thread cannot be joined.
404 //Corresponding specification: p. 160
405*/
406
407int pthread_join(pthread_t thread, void **value_ptr){
408 if(thread.attr != NULL){
409 if(thread.attr->detachstate == 0){
410 $assert($false, "Thread is designated as unjoinable");
411 return 1;
412 }
413 }
414 $wait(thread.thr);
415 return 0;
416}
417
418/* pthread_exit method definition
419 Description: Causes current thread to immediately terminate; if currently in the main method as specified by the
420 isMain parameter, the main method will wait for each thread to terminate before it terminates
421 //Corresponding specification: p. 160
422*/
423
424int pthread_exit(void *arg, _Bool isMain, pthread_t *arr, int len){
425 if(isMain){
426 for(int i = 0; i<len; i++)
427 $wait(arr[i].thr);
428 }
429 $exit();
430 return 0;
431}
432
433//Unimplemented
434int pthread_detach(pthread_t thread);
435
436/* pthread_mutex_lock method definition
437 Description: pthread_mutex_lock takes in a mutex variable and acts accordingly to its current state and type
438 PTHREAD_MUTEX_NORMAL: Checks to see whether mutex is already locked and behaves accordingly
439 locked and owner: Relock error, returns 0
440 locked and not owner: Waits until mutex is unlocked and then locks and becomes owner
441 unlocked and not owner: Locks the mutex and becomes owner
442 PTHREAD_MUTEX_RECURSIVE: A recursive mutex increments its count when it is locked and decremented when
443 it is unlocked and the lock is released when the count reaches 0.
444 PTHREAD_MUTEX_ERRORCHECK: Currently implemented similarly to PTHREAD_MUTEX_NORMAL
445 //Corresponding specification: p. 163
446*/
447
448int pthread_mutex_lock(pthread_mutex_t *mutex){
449 $atomic{
450 if (mutex->attr->type == PTHREAD_MUTEX_NORMAL){
451 if (mutex->lock != 0) {
452 if(mutex->owner == $proc_null){
453 $when(mutex->lock == 0);
454 }
455 else{
456 if(mutex->owner == $self){
457 $assert($false, "ERROR: Relock attempted");
458 return 0;
459 }
460 else{
461 $when(mutex->lock == 0);
462 }
463 }
464 }
465 mutex->owner = $self;
466 mutex->lock = 1;
467 }
468 else {
469 int tmp = mutex->lock;
470 mutex->lock = 1;
471 if (tmp == 0) { // Attempts lock and checks for whether lock is already locked
472 mutex->count = 1;
473 mutex->owner = $self;
474 }
475 else {
476 //Checks for ownership, otherwise returns error
477 if(mutex->owner == $self){
478 // Checks for recursive mutex, otherwise returns an error
479 if (mutex->attr->type == 1) {
480 mutex->count++;
481 if(mutex->count==0){
482 mutex->lock = 0;
483 mutex->owner = $proc_null;
484 }
485 }
486 else {
487 $assert($false);
488 return 0;
489 }
490 }
491 else {
492 $assert($false);
493 return 0;
494 }
495 }
496 }
497 return 0;
498 }
499}
500
501/* pthread_mutex_lock method definition
502 Description: pthread_mutex_lock takes in a mutex variable and acts accordingly to its current state and type
503 PTHREAD_MUTEX_NORMAL: Checks to see whether mutex is already unlocked and behaves accordingly
504 unlocked: returns error
505 locked: unlocks
506 PTHREAD_MUTEX_RECURSIVE: A recursive mutex increments its count when it is locked and decremented when
507 it is unlocked and the lock is released when the count reaches 0.
508 PTHREAD_MUTEX_ERRORCHECK: Currently implemented similarly to PTHREAD_MUTEX_NORMAL
509 //Corresponding specification: p. 163
510*/
511
512int pthread_mutex_unlock(pthread_mutex_t *mutex){
513 $atomic{
514 if (mutex->attr->type == 0 || mutex->attr->type == 2) {
515 int idx;
516 // Attempts unlock, if already unlocked, returns error
517 if (mutex->lock == 0) {
518 $assert($false, "Attempting to unlock unlocked lock\n");
519 return 0;
520 }
521 else {
522 mutex->lock = 0;
523 mutex->owner = $proc_null;
524 }
525 }
526 else {
527 //Checks for ownership of thread, if not, returns error
528 if(mutex->owner == $self)
529 {
530 //Checks for recursive mutex
531 _Bool tmp = !(mutex->attr->type == 1);
532 if (--mutex->count == 0){
533 mutex->lock = 0;
534 mutex->owner = $proc_null;
535 }
536 }
537 else {
538 $assert($false);
539 return 0;
540 }
541 }
542 return 0;
543 }
544}
545
546/* pthread_cond_wait method definition
547 Description: Checks for calling thread as owner of the mutex, then increments proccount, unlocks the mutex
548 and sleeps. Awakens upon signal and decrements proccount and locks mutex.
549 //Corresponding specification: p. 158
550*/
551
552int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex){
553 if(mutex->owner != $self){
554 printf("Mutex not owned by thread");
555 $assert($false);
556 return 0;
557 }
558 cond->proccount= cond->proccount+1;
559 pthread_mutex_unlock(mutex);
560
561 $when(cond->signal);
562 cond->signal = false;
563 --cond->proccount;
564 $when(mutex->lock == 0){pthread_mutex_lock(mutex);}
565 return 0;
566}
567
568/* pthread_cond_signal method definition
569 Description: Signals the condition by setting the signal to true
570 //Corresponding specification: p. 158
571*/
572
573int pthread_cond_signal(pthread_cond_t *cond){
574 cond->signal = true;
575 return 0;
576}
577
578/* pthread_cond_broadcast method definition
579 Description: Repeated signals the condition until all processes waiting have been signalled and awoken
580 //Corresponding specification: p. 157
581*/
582
583int pthread_cond_broadcast(pthread_cond_t *cond){
584 while(cond->proccount > 0){
585 cond->signal = true;
586 }
587 return 0;
588}
589
590
591
592
593
Note: See TracBrowser for help on using the repository browser.