2 * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
4 * This program is licensed under the terms and conditions of the
5 * Apache License, version 2.0. The full text of the Apache License is at
6 * http://www.apache.org/licenses/LICENSE-2.0
16 #include <sys/types.h>
20 #include "CicoEvent.h"
21 #include "CicoEventInfo.h"
22 #include "CicoStateCore.h"
23 #include "CicoState.h"
24 #include "CicoHistoryState.h"
25 #include "CicoFinalState.h"
26 #include "CicoStateMachine.h"
27 #include "CicoStateMachineCreator.h"
28 #include "CicoSCSysResourceMonitor.h"
29 #include "CicoSCLifeCycleController.h"
30 #include "CicoSCSysResourceController.h"
32 #include "CicoSystemConfig.h"
34 //#include <Ecore_Evas.h>
36 const int gEV1000 = 1000; // CPU event
37 const int gEV1001 = 1001; // MEMORY event
39 const string gstrSRCCPU_LOW = "SRCCPU_LOW";
40 const string gstrSRCCPU_HIGH = "SRCCPU_HIGH";
41 const string gstrSRCMEM_LOW = "SRCMEM_LOW";
42 const string gstrSRCMEM_HIGH = "SRCMEM_HIGH";
44 static const string gstrStateMachineFileName = "CicoSCSysResourceSM.json";
46 bool g_RC_LOG = false;
47 int g_samplingWaitTimer = 200;
49 Ecore_Timer* g_SCResourceWatch = 0;
50 static Eina_Bool ico_SCResourceWatch(void *data)
52 if (g_RC_LOG) ICO_TRA("start data(%x)", data);
53 if ((NULL == data) || (0 == data)) {
54 if (g_RC_LOG) ICO_TRA("end");
55 return ECORE_CALLBACK_RENEW;
57 CicoSCSysResourceController* oCSCSRC = (CicoSCSysResourceController*)data;
59 // double tVal = (double)g_samplingWaitTimer / 100;
60 // ecore_timer_add(g_samplingWaitTimer, ico_SCResourceWatch, data);
61 if (g_RC_LOG) ICO_TRA("end");
62 return ECORE_CALLBACK_RENEW;
69 CicoSCSysResourceController::CicoSCSysResourceController()
77 m_rConf = CicoSystemConfig::getInstance()->getResourceConf();
79 g_RC_LOG = m_rConf->m_bLog;
80 if (-1 != m_rConf->m_sampling) {
81 g_samplingWaitTimer = m_rConf->m_sampling;
84 // cpu,cpuacct cgroup init
91 CicoSCSysResourceController::~CicoSCSysResourceController()
94 if (0 != g_SCResourceWatch) {
95 ecore_timer_del(g_SCResourceWatch);
98 if ((CicoStateMachine*)0 != m_stt) {
101 m_stt = (CicoStateMachine*)0;
102 ICO_TRA("delete CicoStateMachine");
105 if ((CicoSRCCPU_LOW*)0 != m_SRCCPU_LOW) {
107 m_SRCCPU_LOW = (CicoSRCCPU_LOW*)0;
108 ICO_TRA("delete CicoSRCCPU_LOW");
111 if ((CicoSRCCPU_HIGH*)0 != m_SRCCPU_HIGH) {
112 delete m_SRCCPU_HIGH;
113 m_SRCCPU_HIGH = (CicoSRCCPU_HIGH*)0;
114 ICO_TRA("delete CicoSRCCPU_HIGH");
117 if ((CicoSRCMEM_LOW*)0 != m_SRCMEM_LOW) {
119 m_SRCMEM_LOW = (CicoSRCMEM_LOW*)0;
120 ICO_TRA("delete CicoSRCMEM_LOW");
123 if ((CicoSRCMEM_HIGH*)0 != m_SRCMEM_HIGH) {
124 delete m_SRCMEM_HIGH;
125 m_SRCMEM_HIGH = (CicoSRCMEM_HIGH*)0;
126 ICO_TRA("delete CicoSRCMEM_HIGH");
129 if ((CicoSCSysResourceMonitor*)0 != m_monitor) {
131 m_monitor = (CicoSCSysResourceMonitor*)0;
132 ICO_TRA("delete CicoSCSysResourceMonitor");
140 bool CicoSCSysResourceController::startSysResource()
147 m_bDoIt = m_rConf->m_bDoIt;
148 if (false == m_bDoIt) {
152 // cpu,cpuacct cgroup init
153 init_cgroup(); // cgroup
154 m_monitor = new CicoSCSysResourceMonitor();
155 CicoSystemConfig* CSCSC = CicoSystemConfig::getInstance();
156 string filePath(CSCSC->getDefaultConf()->confdir);
157 filePath += string("/");
158 filePath += gstrStateMachineFileName;
160 CicoStateMachineCreator csmc;
161 m_stt = csmc.createFile(filePath);
162 if ((CicoStateMachine*)0 == m_stt) {
163 ICO_ERR("state machine create error(%s)", filePath.c_str());
168 m_SRCCPU_LOW = new CicoSRCCPU_LOW(this);
169 m_SRCCPU_HIGH = new CicoSRCCPU_HIGH(this);
170 m_SRCMEM_LOW = new CicoSRCMEM_LOW(this);
171 m_SRCMEM_HIGH = new CicoSRCMEM_HIGH(this);
173 CicoState* s = (CicoState*)m_stt->getState(gstrSRCCPU_LOW);
174 if ((CicoState*)0 != s) {
175 s->addEntryAction(m_SRCCPU_LOW);
176 s->addDoAction(m_SRCCPU_LOW);
178 s = (CicoState*)m_stt->getState(gstrSRCCPU_HIGH);
179 if ((CicoState*)0 != s) {
180 s->addEntryAction(m_SRCCPU_HIGH);
181 s->addDoAction(m_SRCCPU_HIGH);
183 s = (CicoState*)m_stt->getState(gstrSRCMEM_LOW);
184 if ((CicoState*)0 != s) {
185 s->addEntryAction(m_SRCMEM_LOW);
186 s->addDoAction(m_SRCMEM_LOW);
188 s = (CicoState*)m_stt->getState(gstrSRCMEM_HIGH);
189 if ((CicoState*)0 != s) {
190 s->addEntryAction(m_SRCMEM_HIGH);
191 s->addDoAction(m_SRCMEM_HIGH);
194 double tVal = (double)g_samplingWaitTimer / 100;
195 ICO_TRA("ECORE_TIMER(%f)", tVal);
196 g_SCResourceWatch = ecore_timer_add(tVal, ico_SCResourceWatch, this);
203 * @return true:change level false:no change
205 bool CicoSCSysResourceController::watch()
207 if (g_RC_LOG) ICO_TRA("start");
208 if ((CicoSCSysResourceMonitor*)0 == m_monitor) {
209 if (g_RC_LOG) ICO_TRA("end false");
213 m_monitor->monitoring();
214 int cpu = m_monitor->getCPUuser(); // application cpu
217 CicoEvent ev(gEV1000, cpu);
218 bool b = m_stt->eventEntry(ev);
219 if (g_RC_LOG) ICO_TRA("cpu %c, %d->%d", b? 't': 'f', m_cpu, cpu);
223 int mem = m_monitor->getUsageFreeMem(); // free memory
225 mem = (10000 - mem)/100; // free->used memory calc
226 CicoEvent ev(gEV1001, mem);
227 m_stt->eventEntry(ev);
231 if (g_RC_LOG) ICO_TRA("end %s", r? "true": "false");
236 * @brief CPU share control request
237 * @param pulus true:level up / false level down
239 void CicoSCSysResourceController::resourceControlCPUShares(bool bHight)
241 ICO_TRA("start %s", bHight? "true": "false");
242 if ((NULL == m_rConf) || (false == m_rConf->m_bDoIt)) {
246 if (true == m_rConf->m_cpuCtrl.empty()) {
251 int sz = m_rConf->m_cpuCtrl.size();
252 for (int i = 0; i < sz; i++) {
253 if (true == m_RCCpuShares[i].empty()) { // write target none
254 continue; // next target
256 int sharesVal = -1; // initialize cpu.shares value
257 if (true == bHight) {
258 if (m_cgrpCPU < (int)m_rConf->m_cpuCtrl[i]->m_hight.size()) {
259 sharesVal = m_rConf->m_cpuCtrl[i]->m_hight[m_cgrpCPU];
260 newCgrpCPU = m_cgrpCPU + 1;
261 ICO_DBG("m_hight[%d]=%d", m_cgrpCPU, sharesVal);
265 if (0 != m_cgrpCPU) {
266 int tmp = m_cgrpCPU - 1;
267 if (tmp < (int)m_rConf->m_cpuCtrl[i]->m_low.size()) {
268 sharesVal = m_rConf->m_cpuCtrl[i]->m_low[tmp];
270 ICO_DBG("m_low[%d]=%d", tmp, sharesVal);
274 if (0 <= sharesVal) {
275 replaceCgroupFile(m_RCCpuShares[i], sharesVal);
277 // else if (-9 == sharesVal) {
280 if (-1 != newCgrpCPU) { // control level value check
281 ICO_DBG("control level %d -> %d", m_cgrpCPU, newCgrpCPU);
282 m_cgrpCPU = newCgrpCPU; // set next control level
287 bool CicoSCSysResourceController::replaceCgroupFile(const std::string& tgt,
291 sprintf(sv, "%d", val);
292 return replaceCgroupFile(tgt, sv);
295 bool CicoSCSysResourceController::replaceCgroupFile(const std::string& tgt,
299 if (true == tgt.empty()) {
303 FILE *fp = fopen(tgt.c_str(), "wt");
305 ICO_TRA("end open error %s", tgt.c_str());
310 ICO_TRA("end Cmd(echo %s > %s", val, tgt.c_str());
315 * @brief memory limit control request
316 * @param pulus true:level up / false level down
318 void CicoSCSysResourceController::resourceControlMemLimit(bool bHight)
321 if ((NULL == m_rConf) || (false == m_rConf->m_bDoIt)) {
325 // TODO mk_k coming soon
326 if (true == bHight) {
328 ICO_TRA("hight (true)");
332 ICO_TRA("low (false)");
344 bool CicoSCSysResourceController::entryCgroupCPU(int pid, int grpNo)
346 ICO_TRA("start pid(%d), cgrpNo(%d)", pid, grpNo);
347 if (((0 > grpNo) || ((int)m_RCCpuTasks.size() <= grpNo)) ||
348 ((NULL == m_rConf) || (false == m_rConf->m_bDoIt))) {
349 ICO_TRA("end %d", m_RCCpuTasks.size());
355 sprintf(procdir, "/proc/%d/task", pid);
356 if (0 != stat(procdir, &statbuf)) {
357 ICO_TRA("end %s ng dir", procdir);
361 dp = opendir(procdir);
363 ICO_TRA("end opendir error");
367 while((ent = readdir(dp)) != NULL){
368 if (0 != isdigit(ent->d_name[0])) {
369 ICO_DBG("echo %s > %s", ent->d_name, m_RCCpuTasks[grpNo].c_str());
370 replaceCgroupFile(m_RCCpuTasks[grpNo], ent->d_name);
377 return replaceCgroupFile(m_RCCpuTasks[grpNo], pid);
382 * @brief initialize cgroup
384 void CicoSCSysResourceController::init_cgroup()
388 // memory cgroup directory get
389 init_cgroup_memory();
394 * @brief initialize cgroup cpu
396 void CicoSCSysResourceController::init_cgroup_cpu()
399 if ((NULL == m_rConf) || (false == m_rConf->m_bDoIt)) {
404 string sTasks(D_STRtasks);
405 string sShares(D_STRcpushares);
406 string t1(m_rConf->m_cpuCGRPPath);
407 if ('/' != t1[t1.size()-1]) {
411 d.push_back(m_rConf->m_cpuCGRPPath);
412 int sz = m_rConf->m_cpuCtrl.size();
413 for (int i = 0; i < sz; i++) {
414 CicoSCCpuResourceGrp* obj = m_rConf->m_cpuCtrl[i];
426 if (false == t2.empty()) {
427 if ('/' != t2[t2.size()-1]) {
434 m_RCCpuTasks.push_back(t3);
435 m_RCCpuShares.push_back(t4);
443 * @brief initialize cgroup memory
445 void CicoSCSysResourceController::init_cgroup_memory()
448 if ((NULL == m_rConf) || (false == m_rConf->m_bDoIt)) {
449 ICO_TRA("end error config class");
458 * @brief make directory
459 * @param d create directory target
461 void CicoSCSysResourceController::make_directorys(std::vector<std::string> dir)
465 for (int i = 0; i < sz; i++) {
466 if (true == dir[i].empty()) {
469 const char* dpath = dir[i].c_str();
470 struct stat stat_buf;
471 if (0 != stat(dpath, &stat_buf)) {
473 int r = mkdir(dpath, S_IRUSR| S_IWUSR| S_IXUSR| S_IRGRP|
474 S_IXGRP| S_IROTH| S_IXOTH);
475 ICO_DBG("%s create status(%d)", dpath, r);
482 * @brief Class ico System Resource Controller CPU LOW level
485 CicoSRCCPU_LOW::CicoSRCCPU_LOW(CicoSCSysResourceController* obj):
488 ICO_TRA("constructor");
489 m_val = -1; // cpu or memory usage value
490 m_baseVal = -1; // cpu or memory base usage value
492 m_rConf = CicoSystemConfig::getInstance()->getResourceConf();
496 * @brief Class ico System Resource Controller CPU LOW level
499 CicoSRCCPU_LOW::~CicoSRCCPU_LOW()
501 ICO_TRA("destructor");
506 * @brief resource control entry state
507 * @param ev event data
508 * @param stt state object
510 void CicoSRCCPU_LOW::onEntry(const CicoEvent& ev, const CicoState* stt, int)
513 int v2 = ev.getGCVi();
514 if (g_RC_LOG) ICO_TRA("start %s,%d,%d CicoSRCCPU_LOW::", stt->getName().c_str(), v1, v2);
517 m_cnt = m_rConf->m_retryCnt;
518 if (g_RC_LOG) ICO_TRA("end cnt(%d) CicoSRCCPU_LOW::", m_cnt);
522 * @brief cpu usage low resource control
523 * @param ev event data
524 * @param stt state object
526 void CicoSRCCPU_LOW::onDo(const CicoEvent& ev, const CicoState* stt, int)
528 int valN = ev.getGCVi();
529 if (g_RC_LOG) ICO_TRA("start o(%d), n(%d)CicoSRCCPU_LOW::", m_val, valN);
532 // When the value is greater than the previous
533 if (g_RC_LOG) ICO_TRA("end n(%d)->o(%d) CicoSRCCPU_LOW::", m_val, valN);
536 // When the value is less than the previous
537 int t = ((double)valN / (double)m_baseVal)*100;
539 m_cntlr->resourceControlCPUShares(false);
540 if (g_RC_LOG) ICO_DBG("CHG %d->%d CicoSRCCPU_LOW::",m_baseVal, valN);
544 if (valN < m_rConf->m_lowLimitVal) {
547 m_cntlr->resourceControlCPUShares(false);
548 if (g_RC_LOG) ICO_DBG("CHG %d->%d CicoSRCCPU_LOW::",m_baseVal, valN);
549 m_cnt = m_rConf->m_retryCnt;
554 if (g_RC_LOG) ICO_DBG("cnt rst V(%d) CicoSRCCPU_LOW::", valN);
555 m_cnt = m_rConf->m_retryCnt;
559 if (g_RC_LOG) ICO_TRA("end CicoSRCCPU_LOW::");
564 * @brief resource control exit state
565 * @param ev event data
566 * @param stt state object
568 void CicoSRCCPU_LOW::onExit(const CicoEvent&, const CicoState*, int)
570 if (g_RC_LOG) ICO_TRA("start CicoSRCCPU_LOW::");
573 if (g_RC_LOG) ICO_TRA("end CicoSRCCPU_LOW::");
577 * @brief Class ico System Resource Controller CPU HIGH level
580 CicoSRCCPU_HIGH::CicoSRCCPU_HIGH(CicoSCSysResourceController* obj):
583 ICO_TRA("constructor");
587 * @brief Class ico System Resource Controller CPU HIGH level
590 CicoSRCCPU_HIGH::~CicoSRCCPU_HIGH()
592 ICO_TRA("destructor");
596 * @brief cpu usage high resource control
597 * @param ev event data
598 * @param stt state object
600 void CicoSRCCPU_HIGH::onDo(const CicoEvent& ev, const CicoState* stt, int)
602 int valN = ev.getGCVi();
603 if (g_RC_LOG) ICO_TRA("start o(%d), n(%d) CicoSRCCPU_HIGH::", m_val, valN);
606 // When the value is less than the previous
607 if (g_RC_LOG) ICO_TRA("n(%d)<=o(%d) CicoSRCCPU_HIGH::", valN, m_val);
610 // When the value is greater than the previous
611 int t = ((double)(100-valN) / (double)(100-m_baseVal))*100;
613 m_cntlr->resourceControlCPUShares(true);
614 if (g_RC_LOG) ICO_DBG("%d->%d CicoSRCCPU_HIGH::", m_baseVal, valN);
618 if (valN > m_rConf->m_highLimitVal) {
620 if (g_RC_LOG) ICO_DBG("cnt(%d) CicoSRCCPU_HIGH::", m_cnt);
622 m_cntlr->resourceControlCPUShares(true);
623 if (g_RC_LOG) ICO_DBG("CicoSRCCPU_HIGH:: %d->%d",m_baseVal, valN);
624 m_cnt = m_rConf->m_retryCnt;
629 if (g_RC_LOG) ICO_DBG("CicoSRCCPU_HIGH:: (%d)", valN);
630 m_cnt = m_rConf->m_retryCnt;
634 if (g_RC_LOG) ICO_TRA("end CicoSRCCPU_HIGH::");
638 * @brief Class ico System Resource Controller MEMory LOW level
641 CicoSRCMEM_LOW::CicoSRCMEM_LOW(CicoSCSysResourceController* obj):
644 ICO_TRA("constructor CicoSRCMEM_LOW::");
648 * @brief Class ico System Resource Controller MEMory LOW level
651 CicoSRCMEM_LOW::~CicoSRCMEM_LOW()
653 ICO_TRA("destructor CicoSRCMEM_LOW::");
657 * @brief memory usage low resource control
658 * @param ev event data
659 * @param stt state object
661 void CicoSRCMEM_LOW::onDo(const CicoEvent& ev, const CicoState* stt, int)
663 int valN = ev.getGCVi();
664 if (g_RC_LOG) ICO_TRA("start o(%d), n(%d)", m_val, valN);
666 // When the value is greater than the previous
667 if (g_RC_LOG) ICO_TRA("n(%d)>=o(%d)", valN, m_val);
670 // When the value is less than the previous
671 int t = ((double)valN / (double)m_baseVal)*100;
673 m_cntlr->resourceControlMemLimit(false);
674 if (g_RC_LOG) ICO_TRA("BASE CHG %d->%d",m_baseVal, valN);
678 if (g_RC_LOG) ICO_TRA("end");
683 * @brief Class ico System Resource Controller MEMory HIGH level
686 CicoSRCMEM_HIGH::CicoSRCMEM_HIGH(CicoSCSysResourceController* obj):
689 ICO_TRA("constructor");
693 * @brief Class ico System Resource Controller MEMory HIGH level
696 CicoSRCMEM_HIGH::~CicoSRCMEM_HIGH()
698 ICO_TRA("destructor");
702 * @brief memory usage high resource control
703 * @param ev event data
704 * @param stt state object
706 void CicoSRCMEM_HIGH::onDo(const CicoEvent& ev, const CicoState* stt, int)
708 int valN = ev.getGCVi();
709 if (g_RC_LOG) ICO_TRA("start o(%d), n(%d)", m_val, valN);
711 // When the value is less than the previous
715 // When the value is greater than the previous
716 int t = ((double)(100-valN) / (double)(100-m_baseVal))*100;
718 m_cntlr->resourceControlMemLimit(true);
719 if (g_RC_LOG) ICO_TRA("BASE CHG %d -> %d", m_baseVal, valN);
723 if (g_RC_LOG) ICO_TRA("end");