source: buchla-68k/orig/MT/SMINIT.C@ f06df21

Last change on this file since f06df21 was 3ae31e9, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Imported original source code.

  • Property mode set to 100755
File size: 8.3 KB
Line 
1/*
2 =============================================================================
3 sminit.c -- Multi_Tasker -- Semphore functions
4 Version 12 -- 1988-04-17 -- D.N. Lynx Crowe
5 (c) Copyright 1988 -- D.N. Lynx Crowe
6 =============================================================================
7*/
8
9#include "stddefs.h"
10#include "biosdefs.h"
11#include "mtdefs.h"
12#include "debug.h"
13
14extern short setipl(); /* set processor IPL function */
15
16extern struct _mt_def *_MT_;
17
18/*
19 =============================================================================
20 SMInit() -- Initialize a sempaphore
21 =============================================================================
22*/
23
24SMInit(psem, n)
25SEM *psem;
26long n;
27{
28 register short oldipl;
29
30 oldipl = setipl(7); /* DISABLE INTERRUPTS */
31
32 *psem = (SEM)((n << 1) | 1L); /* set the semaphore counter */
33
34 setipl(oldipl); /* RESTORE INTERRUPTS */
35}
36
37/*
38
39*/
40
41/*
42 =============================================================================
43 SMStat() -- Check the status of a semaphore
44
45 -1 Awaited at least one process is waiting
46 0 Not signalled no signals, no waiting processes
47 1 Signalled at least one unreceived signal exists
48 =============================================================================
49*/
50
51short
52SMStat(psem)
53SEM *psem;
54{
55 register short oldipl, rv;
56 register long semval;
57
58 oldipl = setipl(7); /* DISABLE INTERRUPTS */
59
60 semval = (long)*psem; /* get semaphore value */
61
62 setipl(oldipl); /* RESTORE INTERRUPTS */
63
64 if (semval & 1L) { /* in use as a counter ? */
65
66 if (semval & ~1L)
67 rv = 1; /* signalled */
68 else
69 rv = 0; /* not signalled */
70
71 } else { /* ... used as a pointer */
72
73 if (semval & ~1L)
74 rv = -1; /* awaited */
75 else
76 rv = 0; /* not signalled */
77 }
78
79 return(rv); /* return semaphore status */
80}
81
82/*
83
84*/
85
86/*
87 =============================================================================
88 SMSig() -- Signal a semaphore
89 =============================================================================
90*/
91
92SMSig(psem)
93SEM *psem;
94{
95 register TCB *rcur, *rprv, *tcp;
96 register short oldipl;
97 register long semval;
98 register unsigned rpri;
99
100 DB_ENTR("SMSig");
101
102 if ((struct _mt_def *)NIL EQ _MT_)
103 _MT_ = (struct _mt_def *)XBIOS(X_MTDEFS);
104
105 oldipl = setipl(7); /* DISABLE INTERRUPTS */
106
107 semval = (long)*psem; /* get semaphore value */
108
109 if (semval & 1L) { /* is it a count ? (LSB EQ 1) */
110
111 if (~1L NE (semval & ~1L)) /* check for overflow */
112 semval += 2L; /* update the counter */
113
114 } else { /* ... it may be a queue (LSB EQ 0) */
115
116/*
117
118*/
119chksem:
120 if (semval) { /* is there something in the queue ? */
121
122 tcp = (TCB *)semval; /* extract TCB address */
123 semval = tcp->next; /* point to next TCB in queue */
124 tcp->next = (TCB *)0L; /* clear NEXT of TCB */
125 tcp->flags &= ~MTF_SWT; /* turn off 'wait' bit */
126
127 if (tcp->flags & MTF_STP) { /* 'stop' bit set ? */
128
129 tcp->flags &= ~MTF_STP; /* clear 'stop' bit */
130 goto chksem; /* try for another task */
131 }
132
133 rpri = tcp->pri; /* get priority of task to be enqueued */
134 rcur = (TCB *)&_MT_->mtp->RdyQ; /* point at ready queue */
135
136 while (TRUE) {
137
138 rprv = rcur; /* previous TCB = current TCB */
139 rcur = rprv->next; /* current TCB = next TCB */
140
141 if (rcur EQ (TCB *)NIL) /* enqueue here if next was NIL */
142 break;
143
144 if (rpri > rcur->pri) /* enqueue here if priority is greater */
145 break;
146 }
147
148 rprv->next = tcp; /* set next of previous TCB to new TCB */
149 tcp->next = rcur; /* set next of new TCB to old next */
150 tcp->flags |= MTF_RDY; /* set the ready flag in the new TCB */
151
152 } else { /* ... queue empty, treat as a counter */
153
154 semval = 3L; /* set the counter to 1 */
155 }
156 }
157
158 *psem = (SEM)semval; /* update the semaphore */
159
160 setipl(oldipl); /* RESTORE INTERRUPTS */
161 DB_EXIT("SMSig");
162}
163
164/*
165
166*/
167
168/*
169 =============================================================================
170 SMWait() -- Wait on a semaphore
171 =============================================================================
172*/
173
174SMWait(psem)
175register SEM *psem;
176{
177 register short oldipl;
178 register long semval;
179 register TCB *ptcb, *tcp;
180
181 DB_ENTR("SMWait");
182
183 if ((struct _mt_def *)NIL EQ _MT_)
184 _MT_ = (struct _mt_def *)XBIOS(X_MTDEFS);
185
186 oldipl = setipl(7); /* DISABLE INTERRUPTS */
187
188 semval = (long)*psem; /* get semaphore value */
189
190 if (semval & 1L) { /* is it a count ? (LSB EQ 1) */
191
192 if (semval & ~1L) { /* is count non-zero ? */
193
194 semval -= 2L; /* decrement count */
195 *psem = (SEM)semval; /* update semaphore */
196
197 setipl(oldipl); /* RESTORE INTERRUPTS */
198
199 DB_EXIT("SMWait - semaphore non-zero");
200 return; /* return -- we got a signal */
201
202 }
203
204 *psem = 0L; /* clear the semaphore */
205 }
206
207 ptcb = _MT_->mtp->CurP; /* point at current tcb */
208 tcp = (TCB *)*psem; /* point at head of SEM queue */
209
210 while (tcp->next) /* find end of queue */
211 tcp = tcp->next;
212
213 tcp->next = ptcb; /* add TCB to queue */
214 ptcb->next = (TCB *)0L; /* ... */
215 ptcb->flags |= MTF_SWT; /* indicate TCB is waiting */
216 MTNext(); /* swap tasks */
217 setipl(oldipl); /* RESTORE INTERRUPTS */
218 DB_EXIT("SMWait - signalled - 1");
219 return; /* return (we got a signal) */
220}
221
222/*
223
224*/
225
226/*
227 =============================================================================
228 SMCSig() -- Conditionally signal a semphore
229
230 -1 stopped task signalled
231 0 nothing signalled
232 1 waiting task signalled
233 =============================================================================
234*/
235
236short
237SMCSig(psem)
238SEM *psem;
239{
240 register TCB *rcur, *rprv, *tcp;
241 register short oldipl;
242 register long semval;
243 register unsigned rpri;
244
245 oldipl = setipl(7); /* DISABLE INTERRUPTS */
246
247 if ((struct _mt_def *)NIL EQ _MT_)
248 _MT_ = (struct _mt_def *)XBIOS(X_MTDEFS);
249
250 semval = (long)*psem; /* get semaphore value */
251
252 if (semval & 1L) { /* is it a count ? */
253
254 setipl(oldipl); /* RESTORE INTERRUPTS */
255
256 return(0); /* return -- nothing signalled */
257
258 } else {
259
260/*
261
262*/
263 if (semval & ~1L) { /* is there a waiting task ? */
264
265 tcp = (TCB *)semval; /* get TCB pointer */
266 tcp->flags &= ~MTF_SWT; /* clear the wait bit */
267 tcp->next = (TCB *)0L; /* clear NEXT of TCB */
268 semval = tcp->next; /* get next in queue */
269
270 if (tcp->flags & MTF_STP) { /* 'stop' bit set ? */
271
272 tcp->flags &= ~MTF_STP; /* clear 'stop' bit */
273 setipl(oldipl); /* RESTORE INTERRUPTS */
274 return(-1); /* return -- stopped task signalled */
275 }
276
277 rpri = tcp->pri; /* get priority of task to be enqueued */
278 rcur = (TCB *)&_MT_->mtp->RdyQ; /* point at the head of the queue */
279
280 while (TRUE) {
281
282 rprv = rcur; /* previous TCB = current TCB */
283 rcur = rprv->next; /* current TCB = next TCB */
284
285 if (rcur EQ (TCB *)NIL) /* enqueue here if next was NIL */
286 break;
287
288 if (rpri > rcur->pri) /* enqueue here if priority is greater */
289 break;
290 }
291
292 rprv->next = tcp; /* set next of previous TCB to new TCB */
293 tcp->next = rcur; /* set next of new TCB to old next */
294 tcp->flags |= MTF_RDY; /* set the ready flag in the new TCB */
295
296 setipl(oldipl); /* RESTORE INTERRUPTS */
297
298 return(1); /* return -- waiting task signalled */
299 }
300 }
301}
302
303/*
304
305*/
306
307/*
308 =============================================================================
309 SMCWait() -- Conditionally wait on a semaphore
310
311 TRUE Semaphore was non-zero, and was decremented
312 FALSE Semaphore was zero, or tasks were waiting for it
313 =============================================================================
314*/
315
316short
317SMCWait(psem)
318register SEM *psem;
319{
320 register short oldipl, rv;
321 register long semval;
322
323 DB_ENTR("SMCWait");
324 rv = FALSE; /* preset return value */
325
326 oldipl = setipl(7); /* DISABLE INTERRUPTS */
327
328 semval = (long)*psem; /* get semaphore value */
329
330 if (semval & 1L) { /* is it a count ? */
331
332 if (semval & ~1L) { /* is count non-zero ? */
333
334 semval -= 2L; /* decrement counter */
335 *psem = (SEM)semval; /* update semaphore */
336 rv = TRUE; /* set return value */
337 DB_CMNT("SMCWait - got signal");
338 }
339 }
340
341 setipl(oldipl); /* RESTORE INTERRUPTS */
342 DB_EXIT("SMCWait");
343 return(rv); /* return semaphore state */
344}
Note: See TracBrowser for help on using the repository browser.