source: CIVL/text/include/pthread.cvh@ 50f834b

1.23 2.0 main test-branch
Last change on this file since 50f834b was 7c7ed59, checked in by John Edenhofner <johneden@…>, 12 years ago

Moved pthread.cvh to include

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

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