thread2.c
4.56 KB
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#include <os.h>
#include <rmon.h>
#include "corefunc.h"
/*
* thread2
*
* Tests for:
* osDestroyThread (on runnable threads)
*
* Assumed working:
* osCreateThread
* osYieldThread
* osCreateMesgQueue
* osSendMesg
* osRecvMesg
* osGetIntMask
* osSetIntMask
*
* Description:
* Check that osDestroyThread with NULL argument takes running thread
* off run queue.
* Check that osDestroyThread with non-NULL argument takes given thread
* off run queue.
* Check that osDestroyThread does not affect interrupt mask
*/
#define NUM_LOG 5
#define NUM_SLAVES 2
static void slave1(void *);
static void slave2(void *);
static int logExecution(int);
static OSMesgQueue slaveMesgQueue;
static OSMesg slaveMesgBuf[NUM_SLAVES];
static OSThread slave1Thread, slave2Thread;
static char slave1Stack[STACKSIZE], slave2Stack[STACKSIZE];
static int logTab[NUM_LOG];
static int *logPtr = logTab;
static int expLogTab[NUM_LOG] = { 0, 1, 2, 0, 0 };
int
thread2(void)
{
OSIntMask savedMask, currentMask;
int i;
int addFailures, numFailures = 0;
savedMask = osSetIntMask(OS_IM_ALL);
/*
* Start two slave threads with the same priority as the master.
*/
osCreateMesgQueue(&slaveMesgQueue, slaveMesgBuf, NUM_SLAVES);
osCreateThread(&slave1Thread, 101, slave1, (void *)0,
slave1Stack+STACKSIZE, 10);
osStartThread(&slave1Thread);
osCreateThread(&slave2Thread, 102, slave2, (void *)0,
slave2Stack+STACKSIZE, 10);
osStartThread(&slave2Thread);
currentMask = osGetIntMask();
if (currentMask != OS_IM_ALL) {
osSyncPrintf("thread2: expected interrupt mask 0x%x, actual 0x%x\n",
OS_IM_ALL, currentMask);
numFailures++;
}
if (logExecution(0)) /* 0 */
numFailures++;
osYieldThread(); /* allow slaves to run */
currentMask = osGetIntMask();
if (currentMask != OS_IM_ALL) {
osSyncPrintf("thread2: expected interrupt mask 0x%x, actual 0x%x\n",
OS_IM_ALL, currentMask);
numFailures++;
}
/*
* The first slave has now run and destroyed itself.
* The second slave has just yielded to the master.
*/
if (logExecution(0)) /* 3 */
numFailures++;
/*
* Terminate the second slave. It should not run again.
*/
osDestroyThread(&slave2Thread);
if (logExecution(0)) /* 4 */
numFailures++;
currentMask = osGetIntMask();
if (currentMask != OS_IM_ALL) {
osSyncPrintf("thread2: expected interrupt mask 0x%x, actual 0x%x\n",
OS_IM_ALL, currentMask);
numFailures++;
}
for (i = 0; i < NUM_SLAVES; i++) {
(void)osRecvMesg(&slaveMesgQueue,
(OSMesg *)&addFailures, OS_MESG_BLOCK);
numFailures += addFailures;
}
/*
* Verify everybody ran when they were supposed to.
*/
if (logPtr != &logTab[NUM_LOG]) {
osSyncPrintf("thread2: log table underflow\n");
numFailures++;
}
for (i = 0; i < logPtr - logTab; i++) {
if (expLogTab[i] != logTab[i]) {
osSyncPrintf("thread2: expected log id %d, actual %d at entry %d\n",
expLogTab[i], logTab[i], i);
numFailures++;
}
}
/*
* Restore original interrupt mask and check it once more.
*/
currentMask = osSetIntMask(savedMask);
if (currentMask != OS_IM_ALL) {
osSyncPrintf("thread2: expected interrupt mask 0x%x, actual 0x%x\n",
OS_IM_ALL, currentMask);
numFailures++;
}
return(numFailures);
}
static void
slave1(void *arg)
{
OSIntMask currentMask;
int numFailures = 0;
/*
* The first slave will log its execution and then destroy itself.
*/
if (logExecution(1)) /* 1 */
numFailures++;
/*
* Have to send this now, since we shouldn't live beyond the destroy.
*/
osSendMesg(&slaveMesgQueue, (OSMesg)numFailures, OS_MESG_BLOCK);
osDestroyThread((OSThread *)NULL);
(void)logExecution(1); /* should not get here */
numFailures++;
}
static void
slave2(void *arg)
{
OSIntMask currentMask;
int numFailures = 0;
/*
* The second slave will log its execution, and then yield to the
* master which will terminate it.
*/
if (logExecution(2)) /* 2 */
numFailures++;
/*
* Have to send this now, since the master will destroy this slave
* after it gains control at the yield below.
*/
osSendMesg(&slaveMesgQueue, (OSMesg)numFailures, OS_MESG_BLOCK);
osYieldThread(); /* let master run */
(void)logExecution(2); /* should not get here */
}
static int
logExecution(int id)
{
if (logPtr >= &logTab[NUM_LOG]) {
osSyncPrintf("thread2: log table overflow\n");
return(1);
}
/*
osSyncPrintf("%d. log %d\n", logPtr-logTab, id);
*/
*logPtr++ = id;
return(0);
}