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

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

minor correction to pthread library.

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

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