[3ae31e9] | 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 |
|
---|
| 14 | extern short setipl(); /* set processor IPL function */
|
---|
| 15 |
|
---|
| 16 | extern struct _mt_def *_MT_;
|
---|
| 17 |
|
---|
| 18 | /*
|
---|
| 19 | =============================================================================
|
---|
| 20 | SMInit() -- Initialize a sempaphore
|
---|
| 21 | =============================================================================
|
---|
| 22 | */
|
---|
| 23 |
|
---|
| 24 | SMInit(psem, n)
|
---|
| 25 | SEM *psem;
|
---|
| 26 | long 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 |
|
---|
| 51 | short
|
---|
| 52 | SMStat(psem)
|
---|
| 53 | SEM *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 |
|
---|
| 92 | SMSig(psem)
|
---|
| 93 | SEM *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 | */
|
---|
| 119 | chksem:
|
---|
| 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 |
|
---|
| 174 | SMWait(psem)
|
---|
| 175 | register 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 |
|
---|
| 236 | short
|
---|
| 237 | SMCSig(psem)
|
---|
| 238 | SEM *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 |
|
---|
| 316 | short
|
---|
| 317 | SMCWait(psem)
|
---|
| 318 | register 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 | }
|
---|