source: CIVL/include/impls/pthread.cvl@ 1aaefd4

main test-branch
Last change on this file since 1aaefd4 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: 29.0 KB
RevLine 
[bf584ca]1#ifndef __CIVL_PTHREAD__
[27ff0f4]2#define __CIVL_PTHREAD__
3
[bf584ca]4#include <civlc.cvh>
[27ff0f4]5#include <stdbool.h>
6#include <concurrency.cvh>
7#include <pthread.h>
8#include <seq.cvh>
9
[d66b03b]10const $scope _root = $here;
[7686067e]11struct pthread_mutexattr_t{
12 int robust;
13 int pshared;
14 int protocol;
15 int type;
16 int prioceiling;
17};
18
19struct pthread_mutex_t{
20 int count;
21 $proc ownerid;
22 int lock;
23 int prioceiling;
24 pthread_mutexattr_t attr;
25};
[27ff0f4]26
27/* pthread_barrierattr_t
28*/
29struct pthread_barrierattr_t{
30 int pshared;
31};
32
33/* pthread_barrier_t
34 A structure which contains a global barrier which each of the threads must key into.
35*/
36struct pthread_barrier_t{
37 pthread_barrierattr_t attr;
38 int numThrds;
39 int size;
40 $gbarrier barr;
41};
42
43/* pthread_spinlock_t
44 Very simple locking mechanism, spins until the lock is free.
45*/
46struct pthread_spinlock_t{
47 $proc owner;
48 _Bool lock;
49 int pshared;
50};
51
52/* Implemented struct definitions */
53
[f35991e]54/* pthread_t struct definition
55 Description: The pthread_t is a struct containing a $proc variable as well as a thread attribute which defines
56 its interactions with other threads. It encapsulates the $proc and allows attributes to apply to it.
57 Fields: thr: the $proc variable that is the heart of the thread
58 attr: see above
59*/
60
61struct _pthread_t{
62 $proc thr;
63 const pthread_attr_t attr;
64 _Bool terminated;
65 void** exitValue;
66};
67
[27ff0f4]68/* pthread_attr_t struct definition
69 Description: This struct corresponds to the pthread_attr_t which is the attribute of a pthread_t. It's fields
70 define the way the pthread_t is able to interact (join/detach), (memory capacity), (scope) etc.
71
72 Fields:
73 int detachstate: Defines a threads ability to join with two values: PTHREAD_CREATE_DETACHED and PTHREAD_CREATE_JOINABLE
74 int inheritsched: The inheritance scheduling policy of the thread
75 int contentionscope: Defines the contention scope of the thread
76 int schedpolicy: Determines the scheduling policy of the thread
77
78*/
[f35991e]79struct _pthread_attr_t{
[27ff0f4]80 int detachstate;
81 int inheritsched;
82 int contentionscope;
83 int schedpolicy;
84 //sched_param param;
85};
86
87/* pthread_mutexattr_t struct definition
88 Description: The pthread_mutexattr_t defines multiple attributes of a mutex and controls its interactions with threads
89 Fields: robust: defines the robustness of the mutex; if robust and the owning thread terminates, it will notify the
90 next thread of this to prevent deadlocks and other errors
91 pshared: defines the process shared element of the thread and which processes can interact with the mutex
92 protocol: defines the priority protocol of the mutex and which threads may interact first
93 type: defines the type of the mutex as either PTHREAD_MUTEX_DEFAULT/NORMAL, PTHREAD_MUTEX_ERRORCHECK, or
94 PTHREAD_MUTEX_RECURSIVE, each explained in pthread_mutex_lock below
95 prioceiling: defines the lowest priority the mutex's critical section can be at
96*/
97
98
99/* pthread_rwlockattr_t
100*/
101struct pthread_rwlockattr_t{
102 int pshared;
103};
104
105/* pthread_rwlock_t struct definition
106 Description: Reader-writer lock. When a reader has the lock other readers may operate, but not the writer.
107 Only a single writer can operate at one time and locks out readers
108*/
109struct pthread_rwlock_t{
110 $proc rdowners[];
111 int rdlocks[];
112 _Bool empty;
113 $proc wrowner;
114 _Bool wrlock;
115 pthread_rwlockattr_t attr;
116};
117
118
119/* pthread_cond_t struct definition
120 Description: The pthread_cond_t is another locking mechanism which interacts with the mutex variable. When
121 the mutex is locked, the condition can be accessed, leading the accessing thread to unlock it, and sleep
122 until the signal is given
123 Fields: proccount - specifies the number of processes/threads still waiting on this condition variable
124 signal - Boolean value stating whether the condition is satisfied (indicated by 1) or not (0)
125*/
126
127struct pthread_cond_t{
128 _Bool signal;
[5be774af]129 _Bool broadcast;
[27ff0f4]130};
131
132/* pthread_t struct definition
133 Description: The pthread_t is a struct containing a $proc variable as well as a thread attribute which defines
134 its interactions with other threads. It encapsulates the $proc and allows attributes to apply to it.
135 Fields: thr: the $proc variable that is the heart of the thread
136 attr: see above
137*/
138
139struct pthread_t{
140 $proc thr;
141 const pthread_attr_t attr;
142 _Bool terminated;
[26a4016]143 void** exitValue;
[27ff0f4]144};
145
[5a778db]146extern pthread_mutex_t PTHREAD_MUTEX_INITIALIZER = {0,$proc_null,0,0,{0,0,0,0,0}};
[7686067e]147$pthread_gpool_t $pthread_gpool = $pthread_gpool_create($here);
148
[27ff0f4]149/**
150 * Initializes a spinlock with the default values defined for it by an implementation
151 * Corresponding specification: p.
152 *
153 * @param *slock
154 * The spinlock to be initialized.
155 * @param pshared
156 * The process shared attribute that the spinlock shall take as its field
157 *
158 * @return Returns 0 upon successful completion
159 */
160
161int pthread_spin_init(pthread_spinlock_t *slock, int pshared){
162 slock->owner = $proc_null;
163 slock->lock = true;
164 slock->pshared = 0;
165 return 0;
166}
167
168int pthread_spin_destroy(pthread_spinlock_t *slock){
169 pthread_spinlock_t blank;
170 *slock = blank;
171 return 0;
172}
173
174int pthread_spin_lock(pthread_spinlock_t *slock){
175 $atomic{
176 $when(!slock->lock && slock->owner == $proc_null){
177 slock->lock = true;
178 slock->owner == $self;
179 }
180 }
181 return 0;
182}
183
184int pthread_spin_unlock(pthread_spinlock_t *slock){
185 $atomic{
186 slock->owner = $proc_null;
187 slock->lock = false;
188 }
189 return 0;
190}
191
192int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t * attr){
193 if(attr==NULL){
194 rwlock->attr.pshared = PTHREAD_PROCESS_PRIVATE;
195 }
196 else{
197 rwlock->attr = *attr;
198 }
199 int zero = 0;
200 $proc nu = $proc_null;
201 rwlock->wrowner = $proc_null;
202 rwlock->wrlock = false;
203 rwlock->empty = true;
204 return 0;
205}
206
207int pthread_rwlock_destroy(pthread_rwlock_t *rwlock){
208 pthread_rwlock_t blank;
209
210 *rwlock = blank;
211 return 0;
212}
213
214int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock){
215 $when(!rwlock->wrlock){
[adb696b]216 // Remove any function calls
[27ff0f4]217 $atomic{
218 int len = $seq_length(&(rwlock->rdowners));
219 int one = 1;
220 _Bool found = false;
221
222 for(int x = 0; x < len; x++){
223 if(rwlock->rdowners[x] == $self){
224 found = true;
225 rwlock->rdlocks[x]++;
226 break;
227 }
228 }
229
230 if(!found){
231 $proc s = $self;
232 $seq_insert(&(rwlock->rdowners), len, &s, 1);
233 $seq_insert(&(rwlock->rdlocks), len, &one, 1);
234 }
235 rwlock->empty = false;
236 }
237 }
238 return 0;
239}
240
241int pthread_rwlock_unlock(pthread_rwlock_t *rwlock){
[adb696b]242 // Remove function calls from atomic
[27ff0f4]243 $atomic{
244 _Bool found = false;
245 int len = $seq_length(&(rwlock->rdowners));
246 for(int x = 0; x < len; x++){
247 if(rwlock->rdowners[x] == $self){
248 found = true;
249 rwlock->rdlocks[x]--;
250 if(rwlock->rdlocks[x] == 0){
251 $seq_remove(&(rwlock->rdowners), x, NULL, 1);
252 $seq_remove(&(rwlock->rdlocks), x, NULL, 1);
253 len--;
254 x--;
255 break;
256 }
257 }
258 }
259 if(!found){
260 if(rwlock->wrowner == $self){
261 rwlock->wrowner = $proc_null;
262 rwlock->wrlock = false;
263 }
264 }
265 if($seq_length(&(rwlock->rdowners)) == 0){
266 rwlock->empty = true;
267 }
268 return 0;
269 }
270}
271
272int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock){
273 $when(rwlock->empty && !(rwlock->wrlock)){
274 $atomic{
275 rwlock->wrlock = true;
276 rwlock->wrowner = $self;
277 }
278 }
279 return 0;
280}
281
282
283int pthread_barrierattr_init(pthread_barrierattr_t *attr){
284 attr->pshared = 0;
285 return 0;
286}
287
288int pthread_barrierattr_destroy(pthread_barrierattr_t *attr){
289 pthread_barrierattr_t blank;
290 *attr = blank;
291 return 0;
292}
293
294/**
295 * Initializes a barrier with the default values defined for it by an implementation
296 * or with the values defined by the barrier attribute parameter
297 * Corresponding specification: p.
298 *
299 * @param *barrier
300 * The barrier to be initialized.
301 * @param *attr
302 * The mutex attribute which the mutex shall take as it's field. May also
303 * be null for default values to be initialized.
304 * @return Returns 0 upon successful completion
305 */
306int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, int count){
307 if(attr == NULL){
308 barrier->attr.pshared = 0;
309 }
310 else{
311 barrier->attr = *attr;
312 }
[d66b03b]313 barrier->barr = $gbarrier_create(_root, count);
[27ff0f4]314 barrier->size = count;
315 barrier->numThrds = 0;
316 return 0;
317}
318
319/**
320 * Uninitializes the specified barrier variable.
321 * Corresponding specification: p.
322 *
323 * @param *barrier
324 * The barrier to be uninitialized.
325 * @return Returns 0 upon successful completion
326 */
327
328int pthread_barrier_destroy(pthread_barrier_t *barrier){
329 $gbarrier_destroy(barrier->barr);
330 pthread_barrier_t blank;
331 *barrier = blank;
332 return 0;
333}
334
335/**
336 * Creates local barrier for a thead and places it in the global barrier. It then proceeds to call the
337 * $barrier_call, forcing the thread to wait until the release of the global barrier. The global barrier
338 * and local barrier are then destroyed.
339 *
340 * @param *barrier
341 * The barrier containing the global barrier to be waited upon
342 *
343 * @return Returns PTHREAD_BARRIER_SERIAL_THREAD from one exiting thread, and 0 from each of the rest
344 */
345
346int pthread_barrier_wait(pthread_barrier_t *barrier){
347 $barrier locbarr;
[adb696b]348 //Remove function calls from atomic
[27ff0f4]349 $atomic{
350 locbarr = $barrier_create($here, barrier->barr, barrier->numThrds);
351 barrier->numThrds++;
352 $barrier_call(locbarr);
353
354 $barrier_destroy(locbarr);
355 $gbarrier_destroy(barrier->barr);
356 if(barrier->numThrds == barrier->size){
357 barrier->numThrds--;
358 return PTHREAD_BARRIER_SERIAL_THREAD;
359 }
360 else{
361 return 0;
362 }
363 }
364}
365
366
367/**
368 * Initializes an attribute with the default values defined for it by an implementation.
369 * Corresponding specification: p. 1532-4
370 *
371 * @param *attr
372 * The attribute to be initialized.
373 * @return Returns 0 upon successful completion
374 */
375
376int pthread_attr_init(pthread_attr_t *attr){
377 attr->detachstate = PTHREAD_CREATE_JOINABLE;
378 //attr->inheritsched = PTHREAD_EXPLICIT_SCHED;
379 attr->contentionscope = PTHREAD_SCOPE_SYSTEM;
380 //attr->schedpolicy = SCHED_OTHER;
381 return 0;
382}
383
384/**
385 * Uninitializes the specified attr variable.
386 * Corresponding specification: p. 1532-4
387 *
388 * @param *attr
389 * The attribute to be uninitialized.
390 * @return Returns 0 upon successful completion
391 */
392
393int pthread_attr_destroy(pthread_attr_t *attr)
394{
395 pthread_attr_t blank;
396
397 *attr = blank;
398 return 0;
399}
400
401
402/**
403 * Sets the detachstate field of the attribute
404 * Corresponding specification: p. 1535-6
405 *
406 * @param *attr
407 * The attribute to have it's detachstate set
408 * @param detachstate
409 * The detachstate to which the attribute's detachstate is set
410 * @return Returns 0 upon successful completion
411 */
412
413int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
414{
415 attr->detachstate = detachstate;
416 return 0;
417}
418
419/**
420 * Stores the detachstate value of the attribute in an alternate location
421 * Corresponding specification: p. 1535-6
422 *
423 * @param *attr
424 * The attribute whose detachstate is to be stored
425 * @param *detachstate
426 * The location at which the detachstate is to be stored
427 * @return Returns 0 upon successful completion
428 */
429
430int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
431{
432 *detachstate = attr->detachstate;
433 return 0;
434}
435
436/**
437 * Initializes an attribute with the default values defined for it by an implementation.
438 * Corresponding specification: p. 1647-51
439 *
440 * @param *attr
441 * The attribute to be initialized.
442 * @return Returns 0 upon successful completion
443 */
444
445int pthread_mutexattr_init(pthread_mutexattr_t *attr){
446 attr->robust = 0;
447 attr->pshared = 0;
448 attr->protocol = 0;
449 attr->type = 0;
450 attr->prioceiling = 0;
451 return 0;
452}
453
454/**
455 * Uninitializes the specified attr variable.
456 * Corresponding specification: p. 1647-51
457 *
458 * @param *attr
459 * The attribute to be uninitialized.
460 * @return Returns 0 upon successful completion
461 */
462
463int pthread_mutexattr_destroy(pthread_mutexattr_t *attr){
464 pthread_mutexattr_t blank;
465
466 *attr = blank;
467 return 0;
468}
469
470/**
471 * Stores the robustness value in an alternate location
472 * Corresponding specification: p. 1659-1660
473 *
474 * @param *attr
475 * The attribute whose robustness is to be stored
476 * @param *robust
477 * The location at which the attribute's robustness is to be stored
478 * @return Returns 0 upon successful completion
479 */
480
481int pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robust){
482 *robust = attr->robust;
483 return 0;
484}
485
486/**
487 * Sets the robustness field of the attribute
488 * Corresponding specification: p. 1659-1660
489 *
490 * @param *attr
491 * The attribute to have it's robustness set
492 * @param robust
493 * The robustness to which the attribute's robustness is set
494 * @return Returns 0 upon successful completion
495 */
496
497int pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust){
498 attr->robust = robust;
499 return 0;
500}
501
502/**
503 * Stores the process shared variable in an alternate location
504 * Corresponding specification: p. 1657-8
505 *
506 * @param *attr
507 * The attribute whose process shared variable is to be stored
508 * @param *detachstate
509 * The location at which the attribute's process shared variable is to be stored
510 * @return Returns 0 upon successful completion
511 */
512
513int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared){
514 *pshared = attr->pshared;
515 return 0;
516}
517
518/**
519 * Sets the process shared variable field of the attribute
520 * Corresponding specification: p. 1657-8
521 *
522 * @param *attr
523 * The attribute to have it's process shared variable set
524 * @param detachstate
525 * The process shared variable to which the attribute's process shared variable is set
526 * @return Returns 0 upon successful completion
527 */
528
529int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared){
530 attr->pshared = pshared;
531 return 0;
532}
533
534/**
535 * Stores the protocol value in an alternate location
536 * Corresponding specification: p. 1654-56
537 *
538 * @param *attr
539 * The attribute whose protocol is to be stored
540 * @param *detachstate
541 * The location at which the attribute's protocol is to be stored
542 * @return Returns 0 upon successful completion
543 */
544
545int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol){
546 *protocol = attr->protocol;
547 return 0;
548}
549
550/**
551 * Sets the protocol field of the attribute
552 * Corresponding specification: p. 1654-56
553 *
554 * @param *attr
555 * The protocol to have it's protocol set
556 * @param detachstate
557 * The protocol to which the attribute's protocol is set
558 * @return Returns 0 upon successful completion
559 */
560int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol){
561 attr->protocol = protocol;
562 return 0;
563}
564
565/**
566 * Stores the type value in an alternate location
567 * Corresponding specification: p. 1709-10
568 *
569 * @param *attr
570 * The attribute whose type is to be stored
571 * @param *detachstate
572 * The location at which the attribute's type is to be stored
573 * @return Returns 0 upon successful completion
574 */
575int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type){
576 *type = attr->type;
577 return 0;
578}
579
580/**
581 * Sets the type field of the attribute
582 * Corresponding specification: p. 1709-10
583 *
584 * @param *attr
585 * The attribute to have it's type set
586 * @param detachstate
587 * The type to which the attribute's type is set
588 * @return Returns 0 upon successful completion
589 */
590int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type){
591 attr->type = type;
592 return 0;
593}
594
595/**
596 * Stores the priority ceiling value in an alternate location
597 * Corresponding specification: p. 1700-1
598 *
599 * @param *attr
600 * The attribute whose priority ceiling is to be stored
601 * @param *detachstate
602 * The location at which the attribute's priority ceiling is to be stored
603 * @return Returns 0 upon successful completion
604 */
605
606int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *prioceiling){
607 *prioceiling = attr->prioceiling;
608 return 0;
609}
610
611/**
612 * Sets the priority ceiling field of the attribute
613 * Corresponding specification: p. 1700-1
614 *
615 * @param *attr
616 * The attribute to have it's priority ceiling set
617 * @param detachstate
618 * The priority ceiling to which the attribute's priority ceiling is set
619 * @return Returns 0 upon successful completion
620 */
621
622int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling){
623 attr->prioceiling = prioceiling;
624 return 0;
625}
626
627
628/**
629 * Initializes a mutex with the default values defined for it by an implementation
630 * or with the values defined by the mutex attribute parameter
631 * Corresponding specification: p. 1676-81
632 *
633 * @param *mutex
634 * The mutex to be initialized.
635 * @param *attr
636 * The mutex attribute which the mutex shall take as it's field. May also
637 * be null for default values to be initialized.
638 * @return Returns 0 upon successful completion
639 */
640
641int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr){
642 if(attr == NULL){
643 mutex->attr.robust = 0;
644 mutex->attr.pshared = 0;
645 mutex->attr.protocol = 0;
646 mutex->attr.type = PTHREAD_MUTEX_NORMAL;
647 mutex->attr.prioceiling = 0;
648 }
649 else{
650 mutex->attr = *attr;
651 }
652 mutex->lock = 0;
653 mutex->count = 0;
[dee2717]654 mutex->ownerid = $proc_null;
[27ff0f4]655 return 0;
656}
657
658/**
659 * Uninitializes the specified mutex variable.
660 * Corresponding specification: p. 1676-81
661 *
662 * @param *mutex
663 * The mutex to be uninitialized.
664 * @return Returns 0 upon successful completion
665 */
666
667int pthread_mutex_destroy(pthread_mutex_t *mutex){
668 pthread_mutex_t blank;
669
670 *mutex = blank;
671 return 0;
672}
673
674/**
675 * Initializes an condition with the default values defined for it by an implementation.
676 * Corresponding specification: p. 1630-32
677 *
678 * @param *cond
679 * The condition to be initialized.
680 * @param *arg
681 * Should be changed to condition attribute
682 * @return Returns 0 upon successful completion
683 */
[7a8ac04]684int pthread_cond_init(pthread_cond_t * restrict cond, const pthread_condattr_t * restrict arg){
[27ff0f4]685 cond->signal = 0;
[5be774af]686 cond->broadcast = 0;
[27ff0f4]687 return 0;
688}
689
690
691/**
692 * Uninitializes the specified cond variable.
693 * Corresponding specification: p. 1630-2
694 *
695 * @param *cond
696 * The condition to be uninitialized.
697 * @return Returns 0 upon successful completion
698 */
699
700int pthread_cond_destroy(pthread_cond_t *cond){
701 pthread_cond_t blank;
702 *cond = blank;
703 return 0;
704}
705
706int pthread_equal(pthread_t t1, pthread_t t2){
[fd6d345]707 if(t1.thr==$proc_null || t2.thr==$proc_null)
[26a4016]708 return 0;
[27ff0f4]709 if(t1.thr == t2.thr){
710 return 1;
711 }
712 return 0;
713}
714
715/**
716 * Defines a pthread_t by assigning it an attribute value (by value so the original attribute's state is
717 * irrelevant), and spawning a process as the thr field with arguments void *arg
718 * Corresponding specification: p. 1649-51
719 *
720 * @param *thread
721 * The thread to be created with fields set from the other parameters.
722 * @param *attr
723 * The attribute to be assigned to the thread
724 * @param *startroutine
725 * The process to be spawned as the thread's actual 'thread'
726 * @param *arg
727 * The argument to be passed to the spawned function
728 *
729 * @return Returns 0 upon successful completion
730 */
731
732int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg){
[adb696b]733 //Remove function calls from atomic
[27ff0f4]734 $atomic{
735 thread->thr = $spawn start_routine(arg);
736 if(attr == NULL){
737 thread->attr.detachstate = PTHREAD_CREATE_JOINABLE;
738 thread->attr.inheritsched = 0;
739 thread->attr.contentionscope = 0;
740 thread->attr.schedpolicy = 0;
741 }
742 else{
743 thread->attr = *attr;
744 }
745 thread->terminated = false;
[a1f42a0]746 thread->exitValue = NULL;
[dee2717]747 $pthread_gpool_add($pthread_gpool, thread);
[27ff0f4]748 }
749 return 0;
750}
751
752/**
753 * Causes current thread to wait on thread specified as a parameter. If specified thread's detachstate field is set as PTHREAD_CREATE_DETACHED,
754 * error will be returned stating the the thread cannot be joined. The value_ptr of pthread_exit shall be passed to any joining thread to the
755 * terminated thread using pthread_join's value_ptr
756 * Corresponding specification: p. 1617-9
757 *
758 * @param thread
759 * The thread to be waited on by the current thread.
760 * @param **value_ptr
761 * The location at which the pthread_exit output is accessible
762 *
763 * @return Returns 0 upon successful completion
764 */
765
766int pthread_join(pthread_t thread, void **value_ptr){
[e51a6a0]767 //#ifndef _SVCOMP
[27ff0f4]768 if(&thread.attr != NULL){
769 if(thread.attr.detachstate == PTHREAD_CREATE_DETACHED){
[3ff27cf]770 $assert($false, "Thread is designated as unjoinable");
[27ff0f4]771 return 1;
772 }
773 }
[e51a6a0]774 //#endif
[27ff0f4]775 $wait(thread.thr);
776 if(value_ptr!=NULL)
[26a4016]777 *value_ptr = thread.exitValue;
[27ff0f4]778 return 0;
779}
780
[1c7be08]781void pthread_exit(void *value_ptr){
782 return;
783}
784
[27ff0f4]785/**
786 * Causes current thread to immediately terminate; if currently in the main method as specified by the
787 * isMain parameter, the main method will wait for each thread to terminate before it terminates. The value
788 * value_ptr will be made accessible in the location stated in pthread_join
789 * Corresponding specification: p. 1655-6
790 *
791 * @param *value_ptr
792 * The value to be stored in the location stated by pthread_join
793 * @param isMain
794 * Is this thread the main thread?
795 * @param *arr
796 * The array of threads which need to be waited upon by the main thread
797 * @param len
798 * The length of the array of threads to be waited upon
799 * @return Returns 0 upon successful completion
800 */
[1ee1046]801/*void $pthread_exit(void *value_ptr, $pthread_pool_t $pthread_pool);
802{
[26a4016]803 $pthread_pool_terminates($pthread_pool, value_ptr);
804 $free($pthread_pool);
805 $exit();
[1ee1046]806}*/
[dee2717]807
[bb09d30]808void $pthread_exit_main(void *value_ptr, $pthread_pool_t $pthread_pool){
809 $free($pthread_pool);
[535f33e]810 $pthread_gpool_join($pthread_gpool);
811 /*int len = $pthread_gpool_size($pthread_gpool);
[dee2717]812
813 for(int i = 0; i<len; i++){
814 $proc tid = $pthread_gpool_thread($pthread_gpool, i);
815
816 $wait(tid);
[1ee1046]817 }
[dee2717]818 $free($pthread_gpool);
[1ee1046]819 */
[c227167]820 //$exit();
[27ff0f4]821}
822
[a4a7cf0]823pthread_t $pthread_self($pthread_pool_t pool){
[26a4016]824 return $pthread_pool_thread(pool);
825}
826
827
[27ff0f4]828/**
829 * Takes in a mutex variable and acts accordingly to its current state and type
830 * PTHREAD_MUTEX_NORMAL: Checks to see whether mutex is already locked and behaves accordingly
831 * locked and owner: Relock error, returns 0
832 * locked and not owner: Waits until mutex is unlocked and then locks and becomes owner
833 * unlocked and not owner: Locks the mutex and becomes owner
834 * PTHREAD_MUTEX_RECURSIVE: A recursive mutex increments its count when it is locked and decremented when
835 * it is unlocked and the lock is released when the count reaches 0.
836 * PTHREAD_MUTEX_ERRORCHECK: Implemented similarly to PTHREAD_MUTEX_NORMAL, but notifies the user of errors
837 * Corresponding specification: p. 1686-9
838 *
839 * @param *mutex
840 * The mutex to be locked
841 * @return Returns 0 upon successful completion, EOWNERDEAD upon termination of owner,
842 */
843
844
[a4a7cf0]845int $pthread_mutex_lock(pthread_mutex_t *mutex, $pthread_pool_t $pthread_pool){
[c5f07b7]846 _Bool owner_term = $pthread_pool_is_terminated($pthread_pool, mutex->ownerid);
847
848 $atomic{
849 if (owner_term)
850 if (mutex->attr.robust != PTHREAD_MUTEX_ROBUST)
851 $assert($false, "Deadlock: owner terminated without robust mutex");
852 else
853 return EOWNERDEAD;
854 if(mutex->lock==0) {
855 mutex->ownerid = $self;
856 mutex->lock = 1;
857 mutex->count = 1;
[27ff0f4]858 return 0;
[c5f07b7]859 }
860 // lock != 0:
861 if (mutex->attr.type == PTHREAD_MUTEX_NORMAL) {
862 if (mutex->ownerid == $self)
863 $assert($false, "Deadlock: attempted to relock a lock with PTHREAD_MUTEX_NORMAL"
864 " attribute");
865 } else if (mutex->attr.type == PTHREAD_MUTEX_ERRORCHECK) {
866 if (mutex->ownerid == $self)
867 return EDEADLK;
868 } else if (mutex->ownerid == $self) {
869 if (mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) {
870 mutex->count++;
871 return 0;
872 } else
873 $assert($false, "Undefined behavior: attempted to relock a lock with"
874 " PTHREAD_MUTEX_DEFAULT attribute");
[27ff0f4]875 }
876 }
[c5f07b7]877 // wait for the lock:
878 $when(mutex->lock == 0)
879 return $pthread_mutex_lock(mutex, $pthread_pool);
[27ff0f4]880 return 0;
881}
882
883/**
884 * Takes in a mutex variable and acts similarly to pthread_mutex_lock except that
885 * if the mutex is locked, it will return immeditately. In the case of a recursive mutex, the count will
886 * be incremented and will return successfully.
887 * Corresponding specification: p. 1686-9
888 *
889 * @param *mutex
890 * The mutex to be locked
891 * @return Returns 0 upon successful completion
892 */
[dee2717]893//Manchun: check me
[27ff0f4]894int pthread_mutex_trylock(pthread_mutex_t *mutex){
895 $atomic{
896 if (mutex->attr.type == PTHREAD_MUTEX_NORMAL){
897 if (mutex->lock != 0) {
898 return EBUSY;
899 }
[dee2717]900 mutex->ownerid = $self;
[27ff0f4]901 mutex->lock = 1;
902 }
903 else {
904 int tmp = mutex->lock;
905
906 mutex->lock = 1;
907 if (tmp == 0) { // Attempts lock and checks for whether lock is already locked
908 mutex->count = 1;
[dee2717]909 mutex->ownerid = $self;
[27ff0f4]910 }
911 else {
912 //Checks for ownership, otherwise returns error
[dee2717]913 if(mutex->ownerid == $self){
[27ff0f4]914 // Checks for recursive mutex, otherwise returns an error
915 if (mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) {
916 mutex->count++;
917 }
918 else {
[3ff27cf]919 $assert(($false));
[27ff0f4]920 return 0;
921 }
922 }
923 else {
924 return EBUSY;
925 }
926 }
927 }
928 return 0;
929 }
930}
931
932/**
933 * Takes in a mutex variable and acts accordingly to its current state and type
934 * PTHREAD_MUTEX_NORMAL: Checks to see whether mutex is already unlocked and behaves accordingly
935 * unlocked: returns error
936 * locked: unlocks
937 * PTHREAD_MUTEX_RECURSIVE: A recursive mutex increments its count when it is locked and decremented when
938 * it is unlocked and the lock is released when the count reaches 0.
939 * PTHREAD_MUTEX_ERRORCHECK: Currently implemented similarly to PTHREAD_MUTEX_NORMAL
940 * Corresponding specification: p. 1686-9
941 *
942 * @param *mutex
943 * The mutex to be unlocked
944 * @return Returns 0 upon successful completion
945 */
946
947int pthread_mutex_unlock(pthread_mutex_t *mutex){
948 $atomic{
949 if (mutex->attr.type == PTHREAD_MUTEX_NORMAL || mutex->attr.type == PTHREAD_MUTEX_ERRORCHECK) {
950 // Attempts unlock, if already unlocked, returns error
951 if (mutex->lock == 0) {
[3ff27cf]952 $assert($false, "Attempting to unlock unlocked lock\n");
[27ff0f4]953 return 0;
954 }
955 else {
956 mutex->lock = 0;
[dee2717]957 mutex->ownerid = $proc_null;
[27ff0f4]958 }
959 }
960 else {
961 //Checks for ownership of thread, if not, returns error
[dee2717]962 if(mutex->ownerid == $self)
[27ff0f4]963 {
964 if (--mutex->count == 0){
965 mutex->lock = 0;
[dee2717]966 mutex->ownerid = $proc_null;
[27ff0f4]967 }
968 }
969 else {
[3ff27cf]970 $assert(($false));
[27ff0f4]971 return 0;
972 }
973 }
974 return 0;
975 }
976}
977
978/**
979 * Checks for robustness of mutex: if robust, the mutex is unlocked, otherwise an error is caused
980 * and EINVAL is returned
981 * Corresponding specification: p. 1674-5
982 *
983 * @param *mutex
984 * The mutex to be marked as consistent
985 * @return Returns 0 upon successful completion, EINVAL upon non-robust mutex input
986 */
987
988int pthread_mutex_consistent(pthread_mutex_t *mutex){
989 if(mutex->attr.robust == PTHREAD_MUTEX_ROBUST){
990 mutex->lock = 0;
991 return 0;
992 }
[3ff27cf]993 $assert(($false));
[27ff0f4]994 return EINVAL;
995}
996
997/**
998 * Checks for calling thread as owner of the mutex, then increments proccount, unlocks the mutex
999 * and sleeps. Awakens upon signal and decrements proccount and locks mutex.
1000 * Corresponding specification: p. 1634-9
1001 *
1002 * @param *cond
1003 * The condition to be waited upon until a signal is given
1004 * @param *mutex
1005 * The mutex used to lock other threads out
1006 * @return Returns 0 upon successful completion, EINVAL upon non-robust mutex input
1007 */
1008
[a4a7cf0]1009int $pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, $pthread_pool_t $pthread_pool){
[dee2717]1010 if(mutex->ownerid != $self){
[3ff27cf]1011 $assert(($false));
[27ff0f4]1012 return 0;
1013 }
1014 cond->signal = false;
1015 pthread_mutex_unlock(mutex);
[ca1d4ed]1016 $when(cond->signal != 0 || cond->broadcast != 0)
1017 cond->signal = false;
[a4a7cf0]1018 $when(mutex->lock == 0){$pthread_mutex_lock(mutex, $pthread_pool);}
[27ff0f4]1019 return 0;
1020}
1021
1022/**
1023 * Signals the condition by setting the signal to true
1024 * Corresponding specification: p. 1627-30
1025 *
1026 * @param *cond
1027 * The condition to be signalled
1028 * @return Returns 0 upon successful completion
1029 */
1030
1031int pthread_cond_signal(pthread_cond_t *cond){
1032 cond->signal = true;
1033 return 0;
1034}
1035
1036/**
1037 * Repeated signals the condition until all processes waiting have been signalled and awoken
1038 * Corresponding specification: p. 1627-30
1039 *
1040 * @param *cond
1041 * The condition to be signalled repeatedly
1042 * @return Returns 0 upon successful completion
1043 */
1044
1045int pthread_cond_broadcast(pthread_cond_t *cond){
[5be774af]1046 cond->broadcast = true;
[27ff0f4]1047 return 0;
1048}
1049
1050#endif
Note: See TracBrowser for help on using the repository browser.