source: CIVL/text/include/pthread.cvh@ f35edef

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

Added pthread library enabler and others

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

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