00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "Kernel.h"
00015 #include "Profiler.h"
00016 #include "events/KernelTaskEvent.h"
00017 #include "EventManager.h"
00018 #include "StdHelpers.h"
00019 #include "Log.h"
00020
00021 namespace nrEngine {
00022
00023 std::list< SharedPtr<ITask> >::iterator Kernel::_loopIterator;
00024
00025
00026 Kernel::Kernel(){
00027 taskList.clear();
00028 pausedTaskList.clear();
00029 lastTaskID = 0;
00030 bTaskStarted = false;
00031 bInitializedRoot = false;
00032 _bSystemTasksAccessable = false;
00033 sendEvents(true);
00034 }
00035
00036
00037 Kernel::~Kernel(){
00038 StopExecution();
00039
00040 taskList.clear();
00041 pausedTaskList.clear();
00042
00043
00044 NR_Log(Log::LOG_KERNEL, "Kernel subsystem is down");
00045 }
00046
00047
00048 void Kernel::lockSystemTasks()
00049 {
00050 _bSystemTasksAccessable = true;
00051 }
00052
00053
00054 void Kernel::unlockSystemTasks()
00055 {
00056 _bSystemTasksAccessable = false;
00057 }
00058
00059
00060 Result Kernel::OneTick()
00061 {
00062
00063
00064 _nrEngineProfile("Kernel::OneTick");
00065
00066
00067 prepareRootTask();
00068
00069
00070 PipelineIterator it;
00071
00072
00073 for (it = taskList.begin(); it != taskList.end(); it++){
00074 if ((*it)->getTaskState() == TASK_STOPPED)
00075 _taskStart(*it);
00076 }
00077
00078
00079 it = taskList.begin();
00080
00081
00082
00083 _loopStartCycle();
00084 while (_loopGetNextTask(taskList.begin(), it, 0) == OK){
00085 SharedPtr<ITask>& t=(*it);
00086
00087 if (t && !t->_taskCanKill){
00088
00089
00090 if (t->getTaskState() == TASK_RUNNING){
00091
00092
00093 char name[256];
00094 sprintf(name, "%s::update", t->getTaskName());
00095 _nrEngineProfile(name);
00096
00097 t->updateTask();
00098
00099
00100 if (t->getTaskProperty() & TASK_RUN_ONCE)
00101 RemoveTask(t->getTaskID());
00102
00103 }
00104 }
00105 }
00106 _loopEndCycle();
00107
00108 PipelineIterator thisIt;
00109 TaskId tempID;
00110
00111
00112 for( it = taskList.begin(); it != taskList.end();){
00113
00114 SharedPtr<ITask> &t=(*it);
00115 bool killed = false;
00116
00117
00118 if(t && t->_taskCanKill){
00119
00120 _taskStop(t);
00121
00122
00123 tempID = t->getTaskID();
00124 NR_Log(Log::LOG_KERNEL, "Task (id=%d) removed", tempID);
00125 it = taskList.erase(it);
00126 killed = true;
00127
00128
00129 }else if (t->_orderChanged){
00130 ChangeTaskOrder(t->getTaskID(), t->getTaskOrder());
00131 }
00132
00133 if (!killed) it++;
00134 }
00135
00136
00137
00138 IThread::yield();
00139
00140
00141 return OK;
00142 }
00143
00144
00145
00146 void Kernel::prepareRootTask()
00147 {
00148 if (bInitializedRoot) return;
00149 bInitializedRoot = true;
00150
00151
00152 PipelineIterator it;
00153
00154 NR_Log(Log::LOG_KERNEL, "Create a system root task in the kernel");
00155
00156
00157
00158
00159 mRootTask.reset(new EmptyTask());
00160 mRootTask->setTaskName("KernelRoot");
00161 mRootTask->setTaskType(TASK_SYSTEM);
00162
00163
00164 lockSystemTasks();
00165 AddTask(mRootTask, ORDER_SYS_ROOT);
00166 unlockSystemTasks();
00167
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 Result Kernel::_taskStart(SharedPtr<ITask>& task)
00186 {
00187
00188
00189 if (!task)
00190 return KERNEL_NO_TASK_FOUND;
00191
00192
00193 if (task->getTaskProperty() & TASK_IS_THREAD){
00194
00195 SharedPtr<IThread> thread = boost::dynamic_pointer_cast<IThread, ITask>(task);
00196 thread->threadStart();
00197 task->setTaskState(TASK_RUNNING);
00198 task->onStartTask();
00199
00200 }else{
00201
00202
00203 if (task->getTaskState() == TASK_STOPPED)
00204 {
00205 task->setTaskState(TASK_RUNNING);
00206 task->onStartTask();
00207 }else if (task->getTaskState() == TASK_PAUSED){
00208 return ResumeTask(task->getTaskID());
00209 }
00210
00211 }
00212
00213
00214 if (bSendEvents){
00215 SharedPtr<Event> msg(new KernelStartTaskEvent(task->getTaskName(), task->getTaskID()));
00216 Engine::sEventManager()->emitSystem(msg);
00217 }
00218
00219
00220 return OK;
00221 }
00222
00223
00224 Result Kernel::_taskStop(SharedPtr<ITask>& task)
00225 {
00226 try{
00227
00228 if (!task)
00229 return KERNEL_NO_TASK_FOUND;
00230
00231
00232 if (task->getTaskProperty() & TASK_IS_THREAD){
00233
00234 SharedPtr<IThread> thread = boost::dynamic_pointer_cast<IThread, ITask>(task);
00235 NR_Log(Log::LOG_KERNEL, "Stop thread/task \"%s\" (id=%d)", task->getTaskName(), task->getTaskID());
00236 thread->threadStop();
00237
00238 }else{
00239
00240 NR_Log(Log::LOG_KERNEL, "Stop task \"%s\" (id=%d)",task->getTaskName(), task->getTaskID());
00241 task->stopTask();
00242 }
00243
00244 } catch (...){
00245 return UNKNOWN_ERROR;
00246 }
00247
00248
00249 if (bSendEvents){
00250 SharedPtr<Event> msg(new KernelStopTaskEvent(task->getTaskName(), task->getTaskID()));
00251 Engine::sEventManager()->emitSystem(msg);
00252 }
00253
00254
00255
00256 return OK;
00257
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 Result Kernel::Execute(){
00277 try{
00278
00279
00280 NR_Log(Log::LOG_KERNEL, "Kernel subsystem is active, start main loop");
00281
00282
00283 while (taskList.size()){
00284 OneTick();
00285 }
00286
00287 NR_Log(Log::LOG_KERNEL, "Stop kernel main loop");
00288
00289 } catch(...){
00290 return UNKNOWN_ERROR;
00291 }
00292
00293
00294 return OK;
00295
00296 }
00297
00298
00299
00300 TaskId Kernel::AddTask (SharedPtr<ITask> t, TaskOrder order, TaskProperty proper){
00301
00302 prepareRootTask();
00303
00304 _nrEngineProfile("Kernel::AddTask");
00305
00306 try {
00307
00308 t->_taskOrder = order;
00309
00310
00311 std::list< SharedPtr<ITask> >::iterator it;
00312 for (it = taskList.begin(); it != taskList.end(); it++){
00313 if ((*it) == t || (*it)->getTaskID() == t->getTaskID() || strcmp((*it)->getTaskName(),t->getTaskName())==0){
00314 NR_Log(Log::LOG_KERNEL, "Cannot add task \"%s\" because same task was already added!", t->getTaskName());
00315 return 0;
00316 }
00317 }
00318
00319 for (it = pausedTaskList.begin(); it != pausedTaskList.end(); it++){
00320 if ((*it) == t || (*it)->getTaskID() == t->getTaskID() || strcmp((*it)->getTaskName(),t->getTaskName())==0){
00321 NR_Log(Log::LOG_KERNEL, "Found same task in paused task std::list !");
00322 return 0;
00323 }
00324 }
00325
00326
00327 if (t->getTaskOrder() <= ORDER_SYS_LAST && t->getTaskType() == TASK_USER)
00328 {
00329 NR_Log(Log::LOG_KERNEL, "User task are not allowed to work on system order numbers");
00330 return 0;
00331 }
00332
00333
00334 t->setTaskProperty(proper);
00335 t->setTaskState(TASK_STOPPED);
00336 t->setTaskID(++lastTaskID);
00337
00338
00339 if (proper & TASK_IS_THREAD)
00340 NR_Log(Log::LOG_KERNEL, "Add Task \"%s\" as thread (id = %d)", t->getTaskName(), t->getTaskID());
00341 else
00342 NR_Log(Log::LOG_KERNEL, "Add Task \"%s\" at order = %s (id = %d)", t->getTaskName(), orderToString(int32(t->getTaskOrder())).c_str(), t->getTaskID());
00343
00344
00345 if (t->onAddTask() != OK){
00346 NR_Log(Log::LOG_KERNEL, "Cannot initalize Task because of Task internal error");
00347 return 0;
00348 }
00349
00350
00351 for( it=taskList.begin(); it != taskList.end(); it++){
00352 SharedPtr<ITask> &comp = (*it);
00353 if (comp->getTaskOrder() >= t->getTaskOrder()) break;
00354 }
00355
00356
00357 taskList.insert (it,t);
00358
00359 } catch(...){
00360 return UNKNOWN_ERROR;
00361 }
00362
00363
00364
00365 if (t->_taskOrder != ORDER_SYS_ROOT && !(t->getTaskProperty() & TASK_IS_THREAD))
00366 mRootTask->addTaskDependency(t);
00367
00368
00369 return t->getTaskID();
00370 }
00371
00372
00373
00374 Result Kernel::RemoveTask (TaskId id){
00375
00376 if (id == 0) return OK;
00377
00378 try{
00379
00380 NR_Log(Log::LOG_KERNEL, "Remove task with id=%d", id);
00381
00382
00383 PipelineIterator it;
00384
00385
00386 if (!_getTaskByID(id, it, TL_RUNNING | TL_SLEEPING)){
00387 NR_Log(Log::LOG_KERNEL, "No such Task (id=%d) found !!!", id);
00388 return KERNEL_NO_TASK_FOUND;
00389 }
00390
00391
00392 if (!areSystemTasksAccessable() && (*it)->getTaskType() == TASK_SYSTEM)
00393 {
00394 NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "You do not have rights to remove this task!");
00395 return KERNEL_NO_RIGHTS;
00396
00397 }else{
00398
00399 NR_Log(Log::LOG_KERNEL, "Prepare to die: \"%s\" (id=%d)", (*it)->getTaskName(), (*it)->getTaskID());
00400 (*it)->_taskCanKill = true;
00401 }
00402
00403 } catch(...){
00404 return UNKNOWN_ERROR;
00405 }
00406
00407
00408 return OK;
00409 }
00410
00411
00412
00413 Result Kernel::SuspendTask (TaskId id){
00414
00415 try{
00416
00417 NR_Log(Log::LOG_KERNEL, "Suspend task (id=%d)", id);
00418
00419
00420 PipelineIterator it;
00421
00422
00423 if (!_getTaskByID(id, it)){
00424 NR_Log(Log::LOG_KERNEL, "No task with id=%d found", id);
00425 return KERNEL_NO_TASK_FOUND;
00426 }else{
00427 SharedPtr<ITask> &t = (*it);
00428
00429 if (!areSystemTasksAccessable() && (*it)->getTaskType() == TASK_SYSTEM){
00430 NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "You do not have rights to suspend this task!");
00431 return KERNEL_NO_RIGHTS;
00432 }else{
00433
00434
00435 Result res = t->onSuspendTask();
00436 if (res == OK){
00437 t->setTaskState(TASK_PAUSED);
00438
00439
00440
00441 pausedTaskList.push_back(t);
00442 taskList.erase(it);
00443 NR_Log(Log::LOG_KERNEL, "Task id=%d is sleeping now", id);
00444
00445
00446 if (bSendEvents){
00447 SharedPtr<Event> msg(new KernelSuspendTaskEvent(t->getTaskName(), t->getTaskID()));
00448 Engine::sEventManager()->emitSystem(msg);
00449 }
00450
00451 }else{
00452 NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "Task id=%d can not suspend! Check this!", id);
00453 return res;
00454 }
00455 }
00456 }
00457
00458 } catch(...){
00459 return UNKNOWN_ERROR;
00460 }
00461
00462
00463 return OK;
00464 }
00465
00466
00467 Result Kernel::ResumeTask (TaskId id){
00468
00469 try{
00470
00471 NR_Log(Log::LOG_KERNEL, "Resume task (id=%d)", id);
00472
00473
00474 PipelineIterator it;
00475
00476
00477 if (!_getTaskByID(id, it, TL_SLEEPING)){
00478 NR_Log(Log::LOG_KERNEL, "No task with id=%d found", id);
00479 return KERNEL_NO_TASK_FOUND;
00480 }
00481
00482 SharedPtr<ITask> &t = (*it);
00483 if (!areSystemTasksAccessable() && (*it)->getTaskType() == TASK_SYSTEM){
00484 NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "You do not have rights to resume this task!");
00485 return KERNEL_NO_RIGHTS;
00486 }else{
00487
00488
00489 Result res = t->onResumeTask();
00490 if (res == OK){
00491 t->setTaskState(TASK_RUNNING);
00492
00493
00494 for( it = taskList.begin(); it != taskList.end(); it++){
00495 SharedPtr<ITask> &comp=(*it);
00496 if(comp->getTaskOrder() >= t->getTaskOrder()) break;
00497 }
00498 taskList.insert(it,t);
00499
00500
00501 if (_getTaskByID(id, it, TL_SLEEPING)){
00502 pausedTaskList.erase(it);
00503 }
00504
00505
00506 if (bSendEvents){
00507 SharedPtr<Event> msg(new KernelResumeTaskEvent(t->getTaskName(), t->getTaskID()));
00508 Engine::sEventManager()->emitSystem(msg);
00509 }
00510
00511 }else{
00512 NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "Task id=%d can not resume, so it stay in sleep mode", id);
00513 return res;
00514 }
00515 }
00516
00517 } catch(...){
00518 return UNKNOWN_ERROR;
00519 }
00520
00521
00522 return OK;
00523 }
00524
00525
00526 Result Kernel::StopExecution(){
00527
00528 try{
00529
00530 NR_Log(Log::LOG_KERNEL, "Stop the kernel subsystem");
00531
00532
00533 for(PipelineIterator it = taskList.begin(); it != taskList.end(); it++){
00534 NR_Log(Log::LOG_KERNEL, "Prepare to die: \"%s\" (id=%d)", (*it)->getTaskName(), (*it)->getTaskID());
00535 (*it)->_taskCanKill=true;
00536 }
00537
00538
00539 for(PipelineIterator it = pausedTaskList.begin(); it != pausedTaskList.end(); it++){
00540 NR_Log(Log::LOG_KERNEL, "Prepare to die: \"%s\" (id=%d)", (*it)->getTaskName(), (*it)->getTaskID());
00541 (*it)->_taskCanKill=true;
00542 }
00543
00544
00545 if (!taskList.size() && !pausedTaskList.size())
00546 NR_Log(Log::LOG_KERNEL, "There is no more tasks to be killed !");
00547
00548 } catch(...){
00549 return UNKNOWN_ERROR;
00550 }
00551
00552
00553 return OK;
00554
00555 }
00556
00557
00558
00559 Result Kernel::ChangeTaskOrder(TaskId id, TaskOrder order){
00560
00561 try{
00562
00563 NR_Log(Log::LOG_KERNEL, "Change order of task (id=%d) to %d", id, int32(order));
00564
00565
00566 PipelineIterator it;
00567
00568
00569 if (!_getTaskByID(id, it, TL_RUNNING | TL_SLEEPING)){
00570 NR_Log(Log::LOG_KERNEL, "No task with id=%d found", id);
00571 return KERNEL_NO_TASK_FOUND;
00572 }
00573
00574 SharedPtr<ITask> &t = (*it);
00575
00576
00577 if (order <= ORDER_SYS_LAST && t->getTaskType() == TASK_USER)
00578 {
00579 NR_Log(Log::LOG_KERNEL, "User task are not allowed to work on system order numbers!");
00580 return KERNEL_NO_RIGHTS;
00581 }
00582
00583
00584 if (!areSystemTasksAccessable() && (*it)->getTaskType() == TASK_SYSTEM){
00585 NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "You do not have rights to change the order of system task!");
00586 return KERNEL_NO_RIGHTS;
00587 }else{
00588
00589
00590 t->setTaskOrder(order);
00591 t->_orderChanged = false;
00592
00593
00594 pausedTaskList.sort();
00595 taskList.sort();
00596 }
00597
00598 } catch(...){
00599 return UNKNOWN_ERROR;
00600 }
00601
00602
00603 return OK;
00604 }
00605
00606
00607 bool Kernel::_getTaskByID(TaskId id, PipelineIterator& jt, int32 useList){
00608
00609
00610 std::list< SharedPtr<ITask> > *li = NULL;
00611
00612
00613 if ((useList & TL_RUNNING) == TL_RUNNING){
00614 li = &taskList;
00615
00616
00617 PipelineIterator it;
00618 for ( it = li->begin(); it != li->end(); it++){
00619 if ((*it)->getTaskID() == id){
00620 jt = it;
00621 return true;
00622 }
00623 }
00624 }
00625
00626
00627 if ((useList & TL_SLEEPING) == TL_SLEEPING){
00628 li = &pausedTaskList;
00629
00630
00631 PipelineIterator it;
00632 for ( it = li->begin(); it != li->end(); it++){
00633 if ((*it)->getTaskID() == id){
00634 jt = it;
00635 return true;
00636 }
00637 }
00638
00639 }
00640
00641
00642 return false;
00643 }
00644
00645
00646 bool Kernel::_getTaskByName(const std::string& name, PipelineIterator& it, int32 useList)
00647 {
00648
00649
00650 std::list< SharedPtr<ITask> > *li = NULL;
00651
00652
00653 if ((useList & TL_RUNNING) == TL_RUNNING){
00654 li = &taskList;
00655
00656
00657 PipelineIterator jt;
00658 for ( jt = li->begin(); jt != li->end(); jt++){
00659 if ((*jt)->getTaskName() == name){
00660 it = jt;
00661 return true;
00662 }
00663 }
00664 }
00665
00666
00667 if ((useList & TL_SLEEPING) == TL_SLEEPING){
00668 li = &pausedTaskList;
00669
00670
00671 PipelineIterator jt;
00672 for ( jt = li->begin(); jt != li->end(); jt++){
00673 if ((*jt)->getTaskName() == name){
00674 it = jt;
00675 return true;
00676 }
00677 }
00678 }
00679
00680
00681 return false;
00682 }
00683
00684
00685 SharedPtr<ITask> Kernel::getTaskByID(TaskId id){
00686 try{
00687
00688
00689 PipelineIterator it;
00690
00691
00692 if (!_getTaskByID(id, it, TL_RUNNING | TL_SLEEPING)){
00693 NR_Log(Log::LOG_KERNEL, "getTaskByID: No task with id=%d found", id);
00694 return SharedPtr<ITask>();
00695 }
00696
00697
00698 if (!areSystemTasksAccessable() && (*it)->getTaskType() == TASK_SYSTEM){
00699 NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "You do not have rights to access to this task!");
00700 return SharedPtr<ITask>();
00701 }
00702
00703 return *it;
00704
00705 } catch(...){
00706 return SharedPtr<ITask>();
00707 }
00708
00709 }
00710
00711
00712
00713 SharedPtr<ITask> Kernel::getTaskByName(const std::string& name){
00714 try{
00715
00716
00717 PipelineIterator it;
00718
00719
00720 if (!_getTaskByName(name, it, TL_RUNNING | TL_SLEEPING)){
00721 NR_Log(Log::LOG_KERNEL, "getTaskByName: No task with name=%s found", name.c_str());
00722 return SharedPtr<ITask>();
00723 }
00724
00725
00726 if (!areSystemTasksAccessable() && (*it)->getTaskType() == TASK_SYSTEM){
00727 NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "You do not have rights to access to this task!");
00728 return SharedPtr<ITask>();
00729 }
00730
00731 return *it;
00732
00733 } catch(...){
00734 return SharedPtr<ITask>();
00735 }
00736 }
00737
00738
00739 Result Kernel::_loopStartCycle()
00740 {
00741
00742
00743 _nrEngineProfile("Kernel::_loopStartCycle");
00744
00745
00746 _loopIterator = taskList.begin();
00747 while (_loopIterator != taskList.end())
00748 {
00749 (*_loopIterator)->_taskGraphColor = 0;
00750 _loopIterator ++;
00751 }
00752
00753 _loopIterator = pausedTaskList.begin();
00754 while (_loopIterator != pausedTaskList.end())
00755 {
00756 (*_loopIterator)->_taskGraphColor = 0;
00757 _loopIterator ++;
00758 }
00759
00760
00761 _loopIterator = taskList.begin();
00762
00763 return OK;
00764 }
00765
00766
00767 Result Kernel::_loopGetNextTask(PipelineIterator it, PipelineIterator& result, int depth)
00768 {
00769
00770 _nrEngineProfile("Kernel::_loopGetNextTask");
00771
00772
00773 if (it == taskList.end()) return KERNEL_END_REACHED;
00774
00775
00776 const SharedPtr<ITask>& t = *it;
00777
00778 if (t->_taskGraphColor == 1) return KERNEL_CIRCULAR_DEPENDENCY;
00779 if (t->_taskGraphColor == 2) return KERNEL_END_REACHED;
00780
00781 t->_taskGraphColor = 1;
00782
00783
00784 if (t->_taskDependencies.size() > 0)
00785 {
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 std::list<SharedPtr<ITask> >::iterator jt = t->_taskDependencies.begin();
00809 for (; jt != t->_taskDependencies.end(); jt ++)
00810 {
00811
00812 if ((*jt)->_taskGraphColor != 2){
00813 Result ret = _loopGetNextTask(jt, result, depth+1);
00814
00815
00816
00817 if (ret != OK){
00818 t->_taskGraphColor = 0;
00819 if (depth == 0 && ret != KERNEL_CIRCULAR_DEPENDENCY) return OK;
00820 return ret;
00821 }
00822 }
00823
00824 }
00825
00826
00827 }
00828
00829
00830 t->_taskGraphColor = 2;
00831 result = it;
00832 return KERNEL_LEAF_TASK;
00833
00834 }
00835
00836
00837 Result Kernel::_loopEndCycle()
00838 {
00839 return OK;
00840 }
00841
00842 };
00843