source: CIVL/examples/pthread/pthread.cvh@ 761eb6f

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

Updated examples and Makefile

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

  • Property mode set to 100644
File size: 10.5 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 int kind;
214 pthread_mutexattr_t *attr;
215} pthread_mutex_t;
216
217//Initializes mutex as unlocked and with attributes defined by attr
218int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr){
219 mutex->attr = attr;
220 mutex->lock = 0;
221 mutex->count = 0;
222 mutex->owner = $proc_null;
223 mutex->kind = 0;
224 return 0;
225}
226
227int pthread_mutex_destroy(pthread_mutex_t *mutex){
228 pthread_mutex_t blank;
229 *mutex = blank;
230 return 0;
231}
232
233/*
234typedef struct {
235 int pshared;
236 clockid_t clock_id;
237}pthread_condattr_t;
238*/
239
240/* pthread_cond_t struct definition
241Fields: procount - specifies the number of processes/threads still waiting on this condition variable
242signal - Boolean value stating whether the condition is satisfied (indicated by 1) or not (0)
243*/
244typedef struct {
245 int proccount;
246 _Bool signal;
247} pthread_cond_t;
248
249/* Initializes the condition variable so that it begins with 0 processes waiting on it as well as a signal set to be zero
250 **Needs to be modified to work with condition attributes as the second parameter
251*/
252void pthread_cond_init(pthread_cond_t *cond, void *arg){
253 cond->proccount = 0;
254 cond->signal = 0;
255}
256
257/* Unitializes the condition parameter and then frees the data used to store it. If certains threads are still waiting when
258 pthread_cond_destroy is called, an error will be triggered.
259*/
260int pthread_cond_destroy(pthread_cond_t *cond){
261 if(cond->proccount != 0){
262 $assert($false, "ERROR: Threads still waiting on specified condition variable");
263 }
264 else{
265 pthread_cond_t blank;
266 *cond = blank;
267 }
268 return 0;
269}
270
271int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg){
272 thread->thr = $spawn start_routine(arg);
273 thread->attr = attr;
274 return 0;
275}
276
277/* Causes current thread to wait on thread specified as a paremeter. If specified thread's detachstate field is set as PTHREAD_CREATE_DETACHED,
278 error will be returned stating the the thread cannot be joined.
279*/
280int pthread_join(pthread_t thread, void **value_ptr) {
281 if(thread.attr != NULL){
282 if(thread.attr->detachstate == 0){
283 $assert($false, "Thread is designated as unjoinable");
284 return 1;
285 }
286 }
287 $wait(thread.thr);
288 return 0;
289}
290
291/* Calls CIVL $exit method causing the current thread to immediately terminate
292
293*/
294int pthread_exit(void *arg){
295 $exit();
296 return 0;
297}
298
299int pthread_detach(pthread_t thread);
300
301/* pthread_mutex_lock takes in a mutex variable and acts accordingly to its current state and type
302 PTHREAD_MUTEX_NORMAL: Checks to see whether mutex is already locked and behaves accordingly
303 locked and owner: Relock error, returns 0
304 locked and not owner: Waits until mutex is unlocked and then locks and becomes owner
305 unlocked and not owner: Locks the mutex and becomes owner
306 PTHREAD_MUTEX_RECURSIVE
307*/
308int pthread_mutex_lock(pthread_mutex_t *mutex) {
309 $atomic{
310 if (mutex->kind == PTHREAD_MUTEX_NORMAL){
311 if (mutex->lock != 0)
312 {
313 if(mutex->owner == $proc_null){
314 $when(mutex->lock == 0);
315 }
316 else{
317 if(mutex->owner == $self){
318 $assert($false, "ERROR: Relock attempted");
319 return 0;
320 }
321 else{
322 $when(mutex->lock == 0);
323 }
324 }
325 }
326 mutex->owner = $self;
327 mutex->lock = 1;
328 }
329 else {
330 int tmp = mutex->lock;
331 mutex->lock = 1;
332 if (tmp == 0) { // Attempts lock and checks for whether lock is already locked
333 mutex->count = 1;
334 mutex->owner = $self;
335 }
336 else {
337 //Checks for ownership, otherwise returns error
338 if(mutex->owner == $self)
339 {
340 // Checks for recursive mutex, otherwise returns an error
341 if (mutex->kind == 1) {
342 mutex->count++;
343 if(mutex->count==0){
344 mutex->lock = 0;
345 mutex->owner = $proc_null;
346 }
347 }
348 else {
349 $assert($false);
350 return 0;
351 }
352 }
353 else {
354 $assert($false);
355 return 0;
356 }
357 }
358 }
359 return 0;
360 }
361}
362
363
364int pthread_mutex_unlock(pthread_mutex_t *mutex) {
365 $atomic{
366 if (mutex->kind == 0 || mutex->kind == 2) {
367 int idx;
368 // Attempts unlock, if already unlocked, returns error
369 if (mutex->lock == 0) {
370 $assert($false, "Attempting to unlock unlocked lock\n");
371 return 0;
372 }
373 else {
374 mutex->lock = 0;
375 mutex->owner = $proc_null;
376 }
377 }
378 else {
379 //Checks for ownership of thread, if not, returns error
380 if(mutex->owner == $self)
381 {
382 //Checks for recursive mutex
383 _Bool tmp = !(mutex->kind == 1);
384 if (--mutex->count == 0){
385 mutex->lock = 0;
386 mutex->owner = $proc_null;
387 }
388 }
389 else {
390 $assert($false);
391 return 0;
392 }
393 }
394 return 0;
395 }
396}
397
398
399int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex){
400 if(mutex->owner != $self)
401 {
402 printf("Mutex not owned by thread");
403 $assert($false);
404 return 0;
405 }
406 cond->proccount= cond->proccount+1;
407 pthread_mutex_unlock(mutex);
408 $when(cond->signal);
409 cond->signal = 0;
410 --cond->proccount;
411 $when(mutex->lock == 0){pthread_mutex_lock(mutex);}
412 return 0;
413}
414
415int pthread_cond_signal(pthread_cond_t *cond){
416 cond->signal = 1;
417 return 0;
418}
419
420int pthread_cond_broadcast(pthread_cond_t *cond){
421 while(cond->proccount > 0){
422 cond->signal = 1;
423 }
424 return 0;
425}
426
427
428
429
430
431
432
Note: See TracBrowser for help on using the repository browser.