-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mutex_destroy.c
148 lines (118 loc) · 3.42 KB
/
mutex_destroy.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <libc.h>
/*
What:
The current thread initializes and then destroys lots of mutexes.
Expected:
There are no errors as we are destroying the initialized mutex right after
it is initialized.
*/
int mutex_destroy_success(void)
{
int ret = -1;
int mutex_id;
for (int i = 0; i < 1000; i++)
{
mutex_id = mutex_init();
if (mutex_id < 0)
return false;
ret = mutex_destroy(mutex_id);
if (ret < 0)
return false;
}
return true;
}
/*
What:
The current thread tries to perform the mutex_destroy syscall with wrong params,
one param wrong at a time.
Expected:
No mutex is destroyed when passing invalid parameters to the mutex_destroy syscall.
The errno variable is set to EINVAL as we passed invalid parameters.
Notice that our system supports 20 mutexes and we are passing smaller or greater
mutex ids from the range 0-19. Also a mutex cannot be destroyed if it was not
initialized or was already destroyed before.
*/
int mutex_destroy_EINVAL(void)
{
int ret = -1;
int mutex_id;
mutex_id = mutex_init();
if (mutex_id < 0)
return false;
ret = mutex_destroy(mutex_id);
if (ret < 0)
return false;
ret = mutex_destroy(mutex_id);
if (ret >= 0 || errno != EINVAL)
return false;
ret = mutex_destroy(11);
if (ret >= 0 || errno != EINVAL)
return false;
ret = mutex_destroy(-31);
if (ret >= 0 || errno != EINVAL)
return false;
ret = mutex_destroy(31);
if (ret >= 0 || errno != EINVAL)
return false;
return true;
}
/*
What:
The current thread tries to destroy a mutex that is being used at the moment.
Expected:
The mutex is not destroyed and the errno variable is set to EBUSY as mutexes
cannot be destroyed if they are being used at the moment (locked).
*/
int mutex_destroy_EBUSY(void)
{
int ret = -1;
int mutex_id;
mutex_id = mutex_init();
if (mutex_id < 0)
return false;
ret = mutex_lock(mutex_id);
if (ret < 0)
return false;
ret = mutex_destroy(mutex_id);
if (ret >= 0 || errno != EBUSY)
return false;
// Unlock and destroy initialized mutex in order to execute other tests correctly
mutex_unlock(mutex_id);
ret = mutex_destroy(mutex_id);
if (ret < 0)
return false;
return true;
}
/*
What:
A new process is created which creates a new mutex and the parent process tries to
destroy it.
Expected:
The mutex is not destroyed and the errno variable is set to EPERM as mutexes
cannot be destroyed if you are not the process which initialized it.
Notice that we hardcoded the mutex_id in the mutex_destroy syscall on the parent
process in order to make the test simpler.
*/
int mutex_destroy_EPERM(void)
{
int ret = -1;
ret = fork();
if (ret < 0)
return false;
if (ret == 0)
{
int mutex_id = mutex_init();
delay(500); // Let enough time so that the parent process restarts execution and tries to destroy the new mutex
// Destroy mutex initialized in order to execute other tests correctly
mutex_destroy(mutex_id);
exit();
}
else
{
delay(250); // Let enough time so that the new process starts execution and initializes a new mutex
ret = mutex_destroy(0);
if (ret >= 0 || errno != EPERM)
return false;
}
return true;
}