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

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

Updated pthread_barrier_t and made an example to begin to test it

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

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