source: CIVL/text/include/pthread-c.cvl@ f69a3d3

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since f69a3d3 was b0045d9, checked in by John Edenhofner <johneden@…>, 12 years ago

Added tests, did transformation

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

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