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

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

fixed the problem with pthread's _pool's dereference problem; improved Pthread2CIVL transformer.

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

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