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