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

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

Modified transformer, added new sequential tests

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