source: CIVL/examples/pthread/pthread.cvh@ 37bfb99

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

Updated examples and pthread.cvh

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

  • Property mode set to 100644
File size: 11.7 KB
Line 
1#include <civlc.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <assert.h>
5#include <stdbool.h>
6
7//Mutex types
8#define PTHREAD_MUTEX_DEFAULT 0
9#define PTHREAD_MUTEX_NORMAL 0
10#define PTHREAD_MUTEX_RECURSIVE 1
11#define PTHREAD_MUTEX_ERRORCHECK 2
12
13//Mutex Robustness Types
14#define PTHREAD_MUTEX_STALLED 0
15#define PTHREAD_MUTEX_ROBUST 1
16
17//Attribute Constants
18#define PTHREAD_CREATE_DETACHED 0
19#define PTHREAD_CREATE_JOINABLE 1
20
21//Mutex initializer
22#define __LOCK_INITIALIZER 0
23#define PTHREAD_MUTEX_INITIALIZER {0,0,0,PTHREAD_MUTEX_NORMAL,__LOCK_INITIALIZER}
24#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER,0}
25
26/* pthread_attr_t struct definition
27*/
28typedef struct {
29 void *stackaddr;
30 size_t stacksize;
31 size_t guardsize;
32 int detachstate;
33 int inheritsched;
34 int contentionscope;
35 int policy;
36} pthread_attr_t;
37
38/* pthread_t struct definition
39Contains a $proc and a pthread_attr_t which describes how it interacts with other threads and certain methods
40*/
41typedef struct {
42 $proc thr;
43 const pthread_attr_t *attr;
44} pthread_t;
45
46/* pthread_attr_init method definition
47 As stated in the specification, 'The pthread_attr_init( ) function shall initialize a thread attributes object attr with the default
48 value for all of the individual attributes used by a given implementation.' At the moment, the pthread_attr_t is very basic, but will
49 be improved upon at a later date.
50*/
51int pthread_attr_init(pthread_attr_t *attr){
52 attr->stacksize = 0;
53 attr->guardsize = 0;
54 attr->detachstate = PTHREAD_CREATE_DETACHED;
55 //attr->inheritsched = PTHREAD_EXPLICIT_SCHED;
56 //attr->scope = PTHREAD_SCOPE_SYSTEM;
57 attr->stackaddr = NULL;
58 //attr->policy = SCHED_OTHER;
59 return 0;
60}
61
62/* pthread_attr_destroy method definition
63 As stated in the specification, 'The pthread_attr_destroy( ) function shall destroy a thread attributes object. An implementation
64 may cause pthread_attr_destroy( ) to set attr to an implementation-defined invalid value. A
65 destroyed attr attributes object can be reinitialized using pthread_attr_init( ); the results of
66 otherwise referencing the object after it has been destroyed are undefined.'
67 This implementation effectively uninitializes the attr variable, which works according with the specification's requirements.
68*/
69int pthread_attr_destroy(pthread_attr_t *attr)
70{
71 pthread_attr_t blank;
72 *attr = blank;
73 return 0;
74}
75
76//Set the detachstate attribute
77int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
78{
79 attr->detachstate = detachstate;
80 return 0;
81}
82
83//Return the detachstate attribute
84int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
85{
86 *detachstate = attr->detachstate;
87 return 0;
88}
89
90//Set scheduling inheritance
91int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched)
92{
93 attr->inheritsched = inheritsched;
94 return 0;
95}
96
97//Return the scheduling inheritance
98int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched)
99{
100 *inheritsched = attr->inheritsched;
101 return 0;
102}
103
104/*Set scheduling contention scope
105int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
106{
107 attr->scope = contentionscope;
108 return 0;
109}
110
111//Return the scheduling contention scope
112int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope)
113{
114 *contentionscope = attr->scope;
115 return 0;
116}
117*/
118
119//Set the starting address of the stack of the thread
120int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
121{
122 attr->stackaddr = stackaddr;
123 return 0;
124}
125
126//Return the address for the stack
127int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
128{
129 *stackaddr = attr->stackaddr;
130 return 0;
131}
132
133//Set stack size
134int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
135{
136 attr->stacksize = stacksize;
137 return 0;
138}
139
140//Return the stack size
141int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
142{
143 *stacksize = attr->stacksize;
144 return 0;
145}
146
147//Set guard size
148int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
149{
150 attr->guardsize = guardsize;
151 return 0;
152}
153
154// Return guard size
155int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
156{
157 *guardsize = attr->guardsize;
158 return 0;
159}
160
161//Set scheduling policy
162int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
163{
164 attr->policy = policy;
165 return 0;
166}
167
168// Return scheduling policy
169int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
170{
171 *policy = attr->policy;
172 return 0;
173}
174
175/* pthread_mutexattr_t struct definition
176Fields: robust: defines the robustness of the mutex
177
178
179*/
180typedef struct {
181 int robust;
182 int pshared;
183 int protocol;
184 int type;
185 int prioceiling;
186}pthread_mutexattr_t;
187
188int pthread_mutexattr_init(pthread_mutexattr_t *attr){
189 attr->robust = 0;
190 attr->pshared = 0;
191 attr->protocol = 0;
192 attr->type = 0;
193 attr->prioceiling = 0;
194 return 0;
195}
196
197int pthread_mutexattr_destroy(pthread_mutexattr_t *attr){
198 pthread_mutexattr_t blank;
199 *attr = blank;
200 return 0;
201}
202
203/* pthread_mutex_t struct definition
204Fields: count - used for recursive mutex, incremented when locked, decremented when unlocked, mutex released when count is 0
205owner - current process owner of the mutex
206lock - int of 0 or 1, respectively 0 if unlocked, 1 if locked
207*/
208typedef struct {
209 int count;
210 $proc owner;
211 int lock;
212 int prioceiling;
213 pthread_mutexattr_t *attr;
214} pthread_mutex_t;
215
216//Initializes mutex as unlocked and with attributes defined by attr
217int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr){
218 if(attr == NULL){
219 mutex->attr = (pthread_mutexattr_t *)malloc(sizeof(pthread_mutexattr_t));
220 mutex->attr->robust = 0;
221 mutex->attr->pshared = 0;
222 mutex->attr->protocol = 0;
223 mutex->attr->type = PTHREAD_MUTEX_DEFAULT;
224 mutex->attr->prioceiling = 0;
225 }
226 else{
227 mutex->attr = (pthread_mutexattr_t *)malloc(sizeof(pthread_mutexattr_t));
228 mutex->attr = attr;
229 }
230 mutex->lock = 0;
231 mutex->count = 0;
232 mutex->owner = $proc_null;
233 return 0;
234}
235
236int pthread_mutex_destroy(pthread_mutex_t *mutex){
237 pthread_mutex_t blank;
238 *mutex = blank;
239 return 0;
240}
241
242/*
243typedef struct {
244 int pshared;
245 clockid_t clock_id;
246}pthread_condattr_t;
247*/
248
249/* pthread_cond_t struct definition
250Fields: procount - specifies the number of processes/threads still waiting on this condition variable
251signal - Boolean value stating whether the condition is satisfied (indicated by 1) or not (0)
252*/
253typedef struct {
254 int proccount;
255 _Bool signal;
256} pthread_cond_t;
257
258/* Initializes the condition variable so that it begins with 0 processes waiting on it as well as a signal set to be zero
259 **Needs to be modified to work with condition attributes as the second parameter
260*/
261void pthread_cond_init(pthread_cond_t *cond, void *arg){
262 cond->proccount = 0;
263 cond->signal = 0;
264}
265
266/* Unitializes the condition parameter and then frees the data used to store it. If certains threads are still waiting when
267 pthread_cond_destroy is called, an error will be triggered.
268*/
269int pthread_cond_destroy(pthread_cond_t *cond){
270 if(cond->proccount != 0){
271 $assert($false, "ERROR: Threads still waiting on specified condition variable");
272 }
273 else{
274 pthread_cond_t blank;
275 *cond = blank;
276 }
277 return 0;
278}
279
280int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg){
281 thread->thr = $spawn start_routine(arg);
282 if(attr == NULL){
283 thread->attr = (pthread_attr_t *)malloc(sizeof(pthread_attr_t));
284 thread->attr->stackaddr = NULL;
285 thread->attr->stacksize = 0;
286 thread->attr->guardsize = 0;
287 thread->attr->detachstate = 1;
288 thread->attr->inheritsched = 0;
289 thread->attr->contentionscope = 0;
290 thread->attr->policy = 0;
291 }
292 else{
293 thread->attr = (pthread_attr_t *)malloc(sizeof(pthread_attr_t));
294 thread->attr->stackaddr = attr->stackaddr;
295 thread->attr->stacksize = attr->stacksize;
296 thread->attr->guardsize = attr->guardsize;
297 thread->attr->detachstate = attr->detachstate;
298 thread->attr->inheritsched = attr->inheritsched;
299 thread->attr->contentionscope = attr->contentionscope;
300 thread->attr->policy = attr->policy;
301 }
302 return 0;
303}
304
305/* Causes current thread to wait on thread specified as a paremeter. If specified thread's detachstate field is set as PTHREAD_CREATE_DETACHED,
306 error will be returned stating the the thread cannot be joined.
307*/
308int pthread_join(pthread_t thread, void **value_ptr) {
309 if(thread.attr != NULL){
310 if(thread.attr->detachstate == 0){
311 $assert($false, "Thread is designated as unjoinable");
312 return 1;
313 }
314 }
315 $wait(thread.thr);
316 return 0;
317}
318
319/* Calls CIVL $exit method causing the current thread to immediately terminate
320
321*/
322int pthread_exit(void *arg, _Bool isMain, pthread_t *arr, int len){
323 if(isMain){
324 for(int i = 0; i<len; i++)
325 $wait(arr[i].thr);
326 }
327 $exit();
328 return 0;
329}
330
331int pthread_detach(pthread_t thread);
332
333/* pthread_mutex_lock takes in a mutex variable and acts accordingly to its current state and type
334 PTHREAD_MUTEX_NORMAL: Checks to see whether mutex is already locked and behaves accordingly
335 locked and owner: Relock error, returns 0
336 locked and not owner: Waits until mutex is unlocked and then locks and becomes owner
337 unlocked and not owner: Locks the mutex and becomes owner
338 PTHREAD_MUTEX_RECURSIVE
339*/
340int pthread_mutex_lock(pthread_mutex_t *mutex) {
341 $atomic{
342 if (mutex->attr->type == PTHREAD_MUTEX_NORMAL){
343 if (mutex->lock != 0)
344 {
345 if(mutex->owner == $proc_null){
346 $when(mutex->lock == 0);
347 }
348 else{
349 if(mutex->owner == $self){
350 $assert($false, "ERROR: Relock attempted");
351 return 0;
352 }
353 else{
354 $when(mutex->lock == 0);
355 }
356 }
357 }
358 mutex->owner = $self;
359 mutex->lock = 1;
360 }
361 else {
362 int tmp = mutex->lock;
363 mutex->lock = 1;
364 if (tmp == 0) { // Attempts lock and checks for whether lock is already locked
365 mutex->count = 1;
366 mutex->owner = $self;
367 }
368 else {
369 //Checks for ownership, otherwise returns error
370 if(mutex->owner == $self)
371 {
372 // Checks for recursive mutex, otherwise returns an error
373 if (mutex->attr->type == 1) {
374 mutex->count++;
375 if(mutex->count==0){
376 mutex->lock = 0;
377 mutex->owner = $proc_null;
378 }
379 }
380 else {
381 $assert($false);
382 return 0;
383 }
384 }
385 else {
386 $assert($false);
387 return 0;
388 }
389 }
390 }
391 return 0;
392 }
393}
394
395
396int pthread_mutex_unlock(pthread_mutex_t *mutex) {
397 $atomic{
398 if (mutex->attr->type == 0 || mutex->attr->type == 2) {
399 int idx;
400 // Attempts unlock, if already unlocked, returns error
401 if (mutex->lock == 0) {
402 $assert($false, "Attempting to unlock unlocked lock\n");
403 return 0;
404 }
405 else {
406 mutex->lock = 0;
407 mutex->owner = $proc_null;
408 }
409 }
410 else {
411 //Checks for ownership of thread, if not, returns error
412 if(mutex->owner == $self)
413 {
414 //Checks for recursive mutex
415 _Bool tmp = !(mutex->attr->type == 1);
416 if (--mutex->count == 0){
417 mutex->lock = 0;
418 mutex->owner = $proc_null;
419 }
420 }
421 else {
422 $assert($false);
423 return 0;
424 }
425 }
426 return 0;
427 }
428}
429
430
431int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex){
432 if(mutex->owner != $self)
433 {
434 printf("Mutex not owned by thread");
435 $assert($false);
436 return 0;
437 }
438 $atomic{
439 cond->proccount= cond->proccount+1;
440 pthread_mutex_unlock(mutex);
441 $when(cond->signal);
442 cond->signal = false;
443 --cond->proccount;
444 $when(mutex->lock == 0){pthread_mutex_lock(mutex);}
445 return 0;
446 }
447}
448
449int pthread_cond_signal(pthread_cond_t *cond){
450 cond->signal = true;
451 return 0;
452}
453
454int pthread_cond_broadcast(pthread_cond_t *cond){
455 while(cond->proccount > 0){
456 cond->signal = true;
457 }
458 return 0;
459}
460
461
462
463
464
Note: See TracBrowser for help on using the repository browser.