source: CIVL/examples/pthread/pthread.cvh@ 4ceb0ef

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

added pthread.cvh

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

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