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
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00181 #include <cfg/os.h>
00182 #include <cfg/memory.h>
00183
00184 #include <string.h>
00185
00186 #include <sys/types.h>
00187 #include <sys/heap.h>
00188 #include <sys/atom.h>
00189 #include <sys/timer.h>
00190 #include <sys/event.h>
00191 #include <sys/thread.h>
00192
00193 #ifdef NUTDEBUG
00194 #include <sys/osdebug.h>
00195 #endif
00196
00197 #ifdef NUTTRACER
00198 #include <sys/tracer.h>
00199 #endif
00200
00205
00206 #if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00207
00208 extern void NutUnixThreadYieldHook(void);
00209 #endif
00210
00217 NUTTHREADINFO * runningThread;
00218
00225 NUTTHREADINFO * killedThread;
00226
00235 NUTTHREADINFO * nutThreadList;
00236
00244 NUTTHREADINFO * runQueue;
00245
00246
00247
00258 void NutThreadAddPriQueue(NUTTHREADINFO * td, NUTTHREADINFO * volatile *tqpp)
00259 {
00260 NUTTHREADINFO *tqp;
00261
00262 td->td_queue = (HANDLE) tqpp;
00263 td->td_qpec = 0;
00264
00265
00266
00267
00268
00269
00270 NutEnterCritical();
00271 tqp = *tqpp;
00272
00273 if (tqp == SIGNALED) {
00274 tqp = 0;
00275 td->td_qpec++;
00276 } else if (tqp) {
00277 NutExitCritical();
00278
00279
00280 while (tqp && tqp->td_priority <= td->td_priority) {
00281 tqpp = &tqp->td_qnxt;
00282 tqp = tqp->td_qnxt;
00283 }
00284
00285 NutEnterCritical();
00286 }
00287
00288 td->td_qnxt = tqp;
00289
00290 *tqpp = td;
00291 if (td->td_qnxt && td->td_qnxt->td_qpec) {
00292 td->td_qpec += td->td_qnxt->td_qpec;
00293 td->td_qnxt->td_qpec = 0;
00294 }
00295 NutExitCritical();
00296 }
00297
00308 void NutThreadRemoveQueue(NUTTHREADINFO * td, NUTTHREADINFO * volatile *tqpp)
00309 {
00310 NUTTHREADINFO *tqp;
00311
00312 NutEnterCritical();
00313 tqp = *tqpp;
00314 NutExitCritical();
00315
00316 if (tqp != SIGNALED) {
00317 while (tqp) {
00318 if (tqp == td) {
00319 NutEnterCritical();
00320 *tqpp = td->td_qnxt;
00321 if (td->td_qpec) {
00322 if (td->td_qnxt) {
00323 td->td_qnxt->td_qpec = td->td_qpec;
00324 }
00325 td->td_qpec = 0;
00326 }
00327 NutExitCritical();
00328
00329 td->td_qnxt = 0;
00330 td->td_queue = 0;
00331 break;
00332 }
00333 tqpp = &tqp->td_qnxt;
00334 tqp = tqp->td_qnxt;
00335 }
00336 }
00337 }
00338
00349 void NutThreadResume(void)
00350 {
00351 NUTTHREADINFO *td;
00352 NUTTHREADINFO **qhp;
00353 NUTTHREADINFO *tqp;
00354 u_int cnt;
00355
00356
00357
00358
00359 td = nutThreadList;
00360 while (td) {
00361 NutEnterCritical();
00362 cnt = td->td_qpec;
00363 NutExitCritical();
00364 if (cnt) {
00365
00366
00367 qhp = (NUTTHREADINFO **)(td->td_queue);
00368 NutEnterCritical();
00369 td->td_qpec--;
00370 tqp = *qhp;
00371 NutExitCritical();
00372 if (tqp != SIGNALED) {
00373 NutEventPostAsync((HANDLE *)qhp);
00374 }
00375 }
00376 td = td->td_next;
00377 }
00378
00379
00380
00381
00382
00383 NutTimerProcessElapsed();
00384
00385
00386 if (runningThread != runQueue) {
00387 #ifdef NUTTRACER
00388 TRACE_ADD_ITEM(TRACE_TAG_THREAD_YIELD,(int)runningThread);
00389 #endif
00390
00391 if (runningThread->td_state == TDS_RUNNING) {
00392 runningThread->td_state = TDS_READY;
00393 }
00394 NutEnterCritical();
00395 NutThreadSwitch();
00396 NutExitCritical();
00397 }
00398 }
00399
00417 void NutThreadWake(HANDLE timer, HANDLE th)
00418 {
00419
00420 ((NUTTHREADINFO *) th)->td_timer = 0;
00421 ((NUTTHREADINFO *) th)->td_state = TDS_READY;
00422 NutThreadAddPriQueue(th, (NUTTHREADINFO **) & runQueue);
00423 }
00424
00433 void NutThreadYield(void)
00434 {
00435
00436 #if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00437 NutEnterCritical();
00438 NutUnixThreadYieldHook();
00439 NutExitCritical();
00440 #endif
00441
00442
00443
00444
00445
00446
00447 if (runningThread->td_qnxt) {
00448 NutThreadRemoveQueue(runningThread, (NUTTHREADINFO **) & runQueue);
00449 NutThreadAddPriQueue(runningThread, (NUTTHREADINFO **) & runQueue);
00450 }
00451
00452
00453 NutThreadResume();
00454 }
00455
00483 u_char NutThreadSetPriority(u_char level)
00484 {
00485 u_char last = runningThread->td_priority;
00486
00487
00488
00489
00490
00491
00492 NutThreadRemoveQueue(runningThread, &runQueue);
00493 runningThread->td_priority = level;
00494 if (level < 255) {
00495 NutThreadAddPriQueue(runningThread, (NUTTHREADINFO **) & runQueue);
00496 } else {
00497 NutThreadKill();
00498 }
00499
00500
00501
00502
00503
00504 if (runningThread == runQueue) {
00505 runningThread->td_state = TDS_RUNNING;
00506 } else {
00507 runningThread->td_state = TDS_READY;
00508 #ifdef NUTTRACER
00509 TRACE_ADD_ITEM(TRACE_TAG_THREAD_SETPRIO,(int)runningThread);
00510 #endif
00511
00512 NutEnterCritical();
00513 NutThreadSwitch();
00514 NutExitCritical();
00515 }
00516
00517 return last;
00518 }
00519
00530 void NutThreadExit(void)
00531 {
00532 NutThreadSetPriority(255);
00533 }
00534
00544 void NutThreadDestroy(void)
00545 {
00546 if (killedThread) {
00547 NutStackFree(killedThread->td_memory);
00548 killedThread = 0;
00549 }
00550 }
00551
00559 void NutThreadKill(void)
00560 {
00561
00562 NUTTHREADINFO *pCur = nutThreadList;
00563 NUTTHREADINFO **pp = (NUTTHREADINFO **) & nutThreadList;
00564
00565
00566 NutThreadDestroy();
00567
00568
00569 while (pCur) {
00570 if (pCur == runningThread) {
00571 *pp = pCur->td_next;
00572 break;
00573 }
00574
00575 pp = (NUTTHREADINFO **) & pCur->td_next;
00576 pCur = pCur->td_next;
00577 }
00578
00579
00580 killedThread = runningThread;
00581 }
00582
00592 HANDLE GetThreadByName(char * name)
00593 {
00594 NUTTHREADINFO *tdp;
00595
00596 for (tdp = nutThreadList; tdp; tdp = tdp->td_next) {
00597 if (strcmp(tdp->td_name, name) == 0)
00598 return tdp;
00599 }
00600 return NULL;
00601 }
00602