source: CIVL/text/include/pthread-functions.cvl@ dfb0fef

1.23 2.0 main test-branch
Last change on this file since dfb0fef was 7168bfa, checked in by Manchun Zheng <zmanchun@…>, 12 years ago

added $assert statement and implemented its semantics; updated examples/libraries according to the new syntax of $assert.

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

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