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

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

added system function _add_thread() for supporting pthread_exit().

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

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