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

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

Added barrier definition as well as a few barrier methods

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

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