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

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

Modified each slightly

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

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