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

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

Added preprocessor macros as guards

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

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