Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00161 #include <cfg/os.h>
00162
00163 #include <compiler.h>
00164 #include <sys/atom.h>
00165 #include <sys/heap.h>
00166 #include <sys/timer.h>
00167 #include <sys/thread.h>
00168 #include <sys/event.h>
00169 #include <sys/nutdebug.h>
00170
00171 #ifdef NUTDEBUG
00172 #include <sys/osdebug.h>
00173 #include <stdio.h>
00174 #endif
00175
00176 #ifdef NUTTRACER
00177 #include <sys/tracer.h>
00178 #endif
00179
00184
00185
00196 void NutEventTimeout(HANDLE timer, void *arg)
00197 {
00198 NUTTHREADINFO *tqp;
00199 NUTTHREADINFO *volatile *tqpp = arg;
00200
00201 NUTASSERT(tqpp != NULL);
00202
00203
00204 NutEnterCritical();
00205 tqp = *tqpp;
00206 NutExitCritical();
00207
00208
00209
00210
00211
00212 if (tqp != SIGNALED) {
00213
00214
00215
00216
00217
00218
00219 while (tqp) {
00220 if (tqp->td_timer == timer) {
00221
00222
00223 NutEnterCritical();
00224 *tqpp = tqp->td_qnxt;
00225 if (tqp->td_qpec) {
00226 if (tqp->td_qnxt) {
00227 tqp->td_qnxt->td_qpec = tqp->td_qpec;
00228 }
00229 else {
00230 *tqpp = SIGNALED;
00231 }
00232 tqp->td_qpec = 0;
00233 }
00234 NutExitCritical();
00235
00236
00237 tqp->td_state = TDS_READY;
00238 NutThreadAddPriQueue(tqp, (NUTTHREADINFO **) & runQueue);
00239
00240
00241
00242
00243 tqp->td_timer = SIGNALED;
00244 break;
00245 }
00246 tqpp = &tqp->td_qnxt;
00247 tqp = tqp->td_qnxt;
00248 }
00249 }
00250 }
00251
00271 int NutEventWait(volatile HANDLE * qhp, uint32_t ms)
00272 {
00273 NUTTHREADINFO *tdp;
00274
00275 NUTASSERT(qhp != NULL);
00276
00277
00278 NutEnterCritical();
00279 tdp = *qhp;
00280 NutExitCritical();
00281
00282
00283
00284
00285 if (tdp == SIGNALED) {
00286
00287 NutEnterCritical();
00288 *qhp = 0;
00289 NutExitCritical();
00290
00291
00292
00293
00294
00295 NutThreadYield();
00296 return 0;
00297 }
00298
00299
00300
00301
00302
00303 NutThreadRemoveQueue(runningThread, &runQueue);
00304 NutThreadAddPriQueue(runningThread, (NUTTHREADINFO **) qhp);
00305
00306
00307 runningThread->td_state = TDS_SLEEP;
00308 if (ms) {
00309 runningThread->td_timer = NutTimerStart(ms, NutEventTimeout, (void *) qhp, TM_ONESHOT);
00310 }
00311 else {
00312 runningThread->td_timer = 0;
00313 }
00314
00315
00316
00317
00318 #ifdef NUTTRACER
00319 TRACE_ADD_ITEM(TRACE_TAG_THREAD_WAIT,(int)runningThread);
00320 #endif
00321 NutThreadResume();
00322
00323
00324 if (runningThread->td_timer == SIGNALED) {
00325 runningThread->td_timer = 0;
00326 return -1;
00327 }
00328 return 0;
00329 }
00330
00350 int NutEventWaitNext(volatile HANDLE * qhp, uint32_t ms)
00351 {
00352 NUTASSERT(qhp != NULL);
00353
00354
00355
00356
00357 NutEnterCritical();
00358 if (*qhp == SIGNALED)
00359 *qhp = 0;
00360 NutExitCritical();
00361
00362 return NutEventWait(qhp, ms);
00363 }
00364
00384 int NutEventPostAsync(volatile HANDLE * qhp)
00385 {
00386 NUTTHREADINFO *td;
00387
00388 NUTASSERT(qhp != NULL);
00389
00390 NutEnterCritical();
00391 td = *qhp;
00392 NutExitCritical();
00393
00394
00395 if (td != SIGNALED) {
00396
00397
00398 if (td) {
00399
00400 NutEnterCritical();
00401 *qhp = td->td_qnxt;
00402 if (td->td_qpec) {
00403 if (td->td_qnxt) {
00404 td->td_qnxt->td_qpec = td->td_qpec;
00405 }
00406 else {
00407 *qhp = SIGNALED;
00408 }
00409 td->td_qpec = 0;
00410 }
00411 NutExitCritical();
00412
00413
00414 if (td->td_timer) {
00415 NutTimerStop(td->td_timer);
00416 td->td_timer = 0;
00417 }
00418
00419 td->td_state = TDS_READY;
00420 NutThreadAddPriQueue(td, (NUTTHREADINFO **) & runQueue);
00421
00422 return 1;
00423 }
00424
00425
00426 else {
00427 NutEnterCritical();
00428 *qhp = SIGNALED;
00429 NutExitCritical();
00430 }
00431 }
00432 return 0;
00433 }
00434
00454 int NutEventPost(volatile HANDLE * qhp)
00455 {
00456 int rc;
00457
00458 rc = NutEventPostAsync(qhp);
00459
00460
00461
00462
00463
00464 NutThreadYield();
00465
00466 return rc;
00467 }
00468
00486 int NutEventBroadcastAsync(volatile HANDLE * qhp)
00487 {
00488 int rc = 0;
00489 NUTTHREADINFO *tdp;
00490
00491 NUTASSERT(qhp != NULL);
00492
00493
00494 NutEnterCritical();
00495 tdp = *qhp;
00496 NutExitCritical();
00497
00498 if (tdp == SIGNALED) {
00499 NutEnterCritical();
00500 *qhp = 0;
00501 NutExitCritical();
00502 }
00503 else if (tdp) {
00504 do {
00505 rc += NutEventPostAsync(qhp);
00506
00507 NutEnterCritical();
00508 tdp = *qhp;
00509 NutExitCritical();
00510 } while (tdp && tdp != SIGNALED);
00511 }
00512 return rc;
00513 }
00514
00533 int NutEventBroadcast(volatile HANDLE * qhp)
00534 {
00535 int rc = NutEventBroadcastAsync(qhp);
00536
00537 NutThreadYield();
00538
00539 return rc;
00540 }
00541