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
00158 #include <cfg/os.h>
00159
00160 #include <compiler.h>
00161 #include <sys/atom.h>
00162 #include <sys/heap.h>
00163 #include <sys/timer.h>
00164 #include <sys/thread.h>
00165 #include <sys/event.h>
00166
00167 #ifdef NUTDEBUG
00168 #include <sys/osdebug.h>
00169 #include <stdio.h>
00170 #endif
00171
00172 #ifdef NUTTRACER
00173 #include <sys/tracer.h>
00174 #endif
00175
00180
00181
00192 void NutEventTimeout(HANDLE timer, void *arg)
00193 {
00194 NUTTHREADINFO *tqp;
00195 NUTTHREADINFO *volatile *tqpp = arg;
00196
00197
00198 NutEnterCritical();
00199 tqp = *tqpp;
00200 NutExitCritical();
00201
00202
00203
00204
00205
00206 if (tqp != SIGNALED) {
00207
00208
00209
00210
00211
00212
00213 while (tqp) {
00214 if (tqp->td_timer == timer) {
00215
00216
00217 NutEnterCritical();
00218 *tqpp = tqp->td_qnxt;
00219 if (tqp->td_qpec) {
00220 if (tqp->td_qnxt) {
00221 tqp->td_qnxt->td_qpec = tqp->td_qpec;
00222 }
00223 else {
00224 *tqpp = SIGNALED;
00225 }
00226 tqp->td_qpec = 0;
00227 }
00228 NutExitCritical();
00229
00230
00231 tqp->td_state = TDS_READY;
00232 NutThreadAddPriQueue(tqp, (NUTTHREADINFO **) & runQueue);
00233
00234
00235
00236
00237 tqp->td_timer = SIGNALED;
00238 break;
00239 }
00240 tqpp = &tqp->td_qnxt;
00241 tqp = tqp->td_qnxt;
00242 }
00243 }
00244 }
00245
00265 int NutEventWait(volatile HANDLE * qhp, uint32_t ms)
00266 {
00267 NUTTHREADINFO *tdp;
00268
00269
00270 NutEnterCritical();
00271 tdp = *qhp;
00272 NutExitCritical();
00273
00274
00275
00276
00277 if (tdp == SIGNALED) {
00278
00279 NutEnterCritical();
00280 *qhp = 0;
00281 NutExitCritical();
00282
00283
00284
00285
00286
00287 NutThreadYield();
00288 return 0;
00289 }
00290
00291
00292
00293
00294
00295 NutThreadRemoveQueue(runningThread, &runQueue);
00296 NutThreadAddPriQueue(runningThread, (NUTTHREADINFO **) qhp);
00297
00298
00299 runningThread->td_state = TDS_SLEEP;
00300 if (ms) {
00301 runningThread->td_timer = NutTimerStart(ms, NutEventTimeout, (void *) qhp, TM_ONESHOT);
00302 }
00303 else {
00304 runningThread->td_timer = 0;
00305 }
00306
00307
00308
00309
00310 #ifdef NUTTRACER
00311 TRACE_ADD_ITEM(TRACE_TAG_THREAD_WAIT,(int)runningThread);
00312 #endif
00313 NutThreadResume();
00314
00315
00316 if (runningThread->td_timer == SIGNALED) {
00317 runningThread->td_timer = 0;
00318 return -1;
00319 }
00320 return 0;
00321 }
00322
00342 int NutEventWaitNext(volatile HANDLE * qhp, uint32_t ms)
00343 {
00344
00345
00346
00347 NutEnterCritical();
00348 if (*qhp == SIGNALED)
00349 *qhp = 0;
00350 NutExitCritical();
00351
00352 return NutEventWait(qhp, ms);
00353 }
00354
00374 int NutEventPostAsync(volatile HANDLE * qhp)
00375 {
00376 NUTTHREADINFO *td;
00377
00378 NutEnterCritical();
00379 td = *qhp;
00380 NutExitCritical();
00381
00382
00383 if (td != SIGNALED) {
00384
00385
00386 if (td) {
00387
00388 NutEnterCritical();
00389 *qhp = td->td_qnxt;
00390 if (td->td_qpec) {
00391 if (td->td_qnxt) {
00392 td->td_qnxt->td_qpec = td->td_qpec;
00393 }
00394 else {
00395 *qhp = SIGNALED;
00396 }
00397 td->td_qpec = 0;
00398 }
00399 NutExitCritical();
00400
00401
00402 if (td->td_timer) {
00403 NutTimerStop(td->td_timer);
00404 td->td_timer = 0;
00405 }
00406
00407 td->td_state = TDS_READY;
00408 NutThreadAddPriQueue(td, (NUTTHREADINFO **) & runQueue);
00409
00410 return 1;
00411 }
00412
00413
00414 else {
00415 NutEnterCritical();
00416 *qhp = SIGNALED;
00417 NutExitCritical();
00418 }
00419 }
00420 return 0;
00421 }
00422
00442 int NutEventPost(volatile HANDLE * qhp)
00443 {
00444 int rc;
00445
00446 rc = NutEventPostAsync(qhp);
00447
00448
00449
00450
00451
00452 NutThreadYield();
00453
00454 return rc;
00455 }
00456
00474 int NutEventBroadcastAsync(volatile HANDLE * qhp)
00475 {
00476 int rc = 0;
00477 NUTTHREADINFO *tdp;
00478
00479
00480 NutEnterCritical();
00481 tdp = *qhp;
00482 NutExitCritical();
00483
00484 if (tdp == SIGNALED) {
00485 NutEnterCritical();
00486 *qhp = 0;
00487 NutExitCritical();
00488 }
00489 else if (tdp) {
00490 do {
00491 rc += NutEventPostAsync(qhp);
00492
00493 NutEnterCritical();
00494 tdp = *qhp;
00495 NutExitCritical();
00496 } while (tdp && tdp != SIGNALED);
00497 }
00498 return rc;
00499 }
00500
00519 int NutEventBroadcast(volatile HANDLE * qhp)
00520 {
00521 int rc = NutEventBroadcastAsync(qhp);
00522
00523 NutThreadYield();
00524
00525 return rc;
00526 }
00527