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

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

Reorganized files, implemented pthread_rwlock_t, modified headers etc.

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

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