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

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

Added new folders for examples and created test for error in casting (VoidCastTest)

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

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