-
Notifications
You must be signed in to change notification settings - Fork 1
/
gtthread_mutex.c
122 lines (107 loc) · 3.36 KB
/
gtthread_mutex.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/**********************************************************************
gtthread_mutex.c.
This file contains the implementation of the mutex subset of the
gtthreads library. The locks can be implemented with a simple queue.
**********************************************************************/
/*
Include as needed
*/
#include "gtthread.h"
#include "steque.h"
#include <stdlib.h>
extern steque_t* readyqueue;
extern steque_t* terminatequeue;
static steque_t* mutexqueue = NULL;
gtthread_mutex_node* Allocatenewmutexnode() {
static long currentmutexid = 0;
gtthread_mutex_node *newmutexnode = (gtthread_mutex_node *) malloc (sizeof(gtthread_mutex_node));
newmutexnode->mutex = (gtthread_mutex_t *) malloc (sizeof(gtthread_mutex_t));
newmutexnode->mutex->mutexid = currentmutexid++;
newmutexnode->holder = NULL;
return newmutexnode;
}
/*
The gtthread_mutex_init() function is analogous to
pthread_mutex_init with the default parameters enforced.
There is no need to create a static initializer analogous to
PTHREAD_MUTEX_INITIALIZER.
*/
int gtthread_mutex_init(gtthread_mutex_t* mutex){
if(mutex != NULL) {
if (mutexqueue == NULL) {
mutexqueue = (steque_t *) malloc (sizeof(steque_t));
}
gtthread_mutex_node* newnode = Allocatenewmutexnode();
mutex->mutexid = newnode->mutex->mutexid;
steque_enqueue(mutexqueue, (steque_item) newnode);
return 0;
}
return -1;
}
/*
The gtthread_mutex_lock() is analogous to pthread_mutex_lock.
Returns zero on success.
*/
int gtthread_mutex_lock(gtthread_mutex_t* mutex){
if (mutex == NULL || mutexqueue == NULL) return -1;
int queuesize = steque_size(mutexqueue);
while(queuesize >0) {
gtthread_mutex_node *head=steque_front(mutexqueue);
if (head->mutex->mutexid == mutex->mutexid)
{
gtthread *currentthread = (gtthread *)steque_front(readyqueue);
if ( currentthread != NULL) {
while(head->holder);
head->holder = currentthread;
return 0;
}
}
steque_cycle(mutexqueue);
queuesize--;
}
return -1;
}
/*
The gtthread_mutex_unlock() is analogous to pthread_mutex_unlock.
Returns zero on success.
*/
int gtthread_mutex_unlock(gtthread_mutex_t *mutex){
if (mutex == NULL || mutexqueue == NULL) return -1;
int queuesize = steque_size(mutexqueue);
while(queuesize >0) {
gtthread_mutex_node *head=steque_front(mutexqueue);
if (head->mutex->mutexid == mutex->mutexid)
{
gtthread *currentthread = (gtthread *)steque_front(readyqueue);
if ( currentthread == head->holder) {
head->holder = NULL;
return 0;
}
}
steque_cycle(mutexqueue);
queuesize--;
}
return -1;
}
/*
The gtthread_mutex_destroy() function is analogous to
pthread_mutex_destroy and frees any resourcs associated with the mutex.
*/
int gtthread_mutex_destroy(gtthread_mutex_t *mutex){
if (mutex == NULL || mutexqueue == NULL) return -1;
int queuesize = steque_size(mutexqueue);
while(queuesize >0) {
gtthread_mutex_node *head=steque_front(mutexqueue);
if (head->mutex->mutexid == mutex->mutexid)
{
if (head->holder!=NULL) return -1;
free(head->mutex);
steque_pop(mutexqueue);
free(head);
return 0;
}
steque_cycle(mutexqueue);
queuesize--;
}
return -1;
}