/* * Copyright 2002-2019 Intel Corporation. * * This software is provided to you as Sample Source Code as defined in the accompanying * End User License Agreement for the Intel(R) Software Development Products ("Agreement") * section 1.L. * * This software and the related documents are provided as is, with no express or implied * warranties, other than those that are expressly stated in the License. */ #include "control_chain.H" #include "parse_control.H" #include "alarm_manager.H" #include "controller_events.H" using namespace std; using namespace CONTROLLER; UINT32 CONTROL_CHAIN::global_id = 0; /// @cond INTERNAL_DOXYGEN CONTROL_CHAIN::CONTROL_CHAIN(CONTROL_MANAGER* control_mngr, VOID* event_handler, BOOL vector_chain){ _control_mngr = control_mngr; _name = ""; _wait_for_id = NO_WAIT; _repeat_token = 1; _id = global_id; _event_handler = event_handler; _block_fire = FALSE; global_id++; _vector_chain = vector_chain; _vector_index = 0; memset(_repeat,0,sizeof(_repeat)); } VOID CONTROL_CHAIN::Fire(EVENT_TYPE eventID, CONTEXT* ctx, VOID * ip, THREADID tid, BOOL bcast, UINT32 alarm_id) { // Check if fire is block for this chain if (_block_fire) return; //roll the event to the tool only if it is not a precondition if (eventID != EVENT_PRECOND){ _control_mngr->Fire(eventID, ctx, ip, tid, bcast,_event_handler, this); } // Check if fire is block for this chain before we arm the next event if (_block_fire) return; if (_alarms[alarm_id]->ArmNext()){ ArmNextAlarm(alarm_id, tid, bcast); } } // Late fire event VOID CONTROL_CHAIN::LateFire(EVENT_TYPE eventID, CONTEXT* ctx, VOID * ip, THREADID tid, BOOL bcast, UINT32 alarm_id) { // Check if fire is block for this chain if (_block_fire) return; _control_mngr->LateFire(eventID, ctx, ip, tid, bcast); } VOID CONTROL_CHAIN::Activate(){ //activate the first alarm in the chain only if the chain does not "wait" if (_wait_for_id == NO_WAIT){ _alarms[0]->Activate(); } } VOID CONTROL_CHAIN::ArmChain(UINT32 tid){ _alarms[0]->ArmTID(tid); } VOID CONTROL_CHAIN::Arm(UINT32 tid, BOOL bcast, UINT32 alarm_id){ if (bcast || _alarms[alarm_id]->HasGlobalCounter()){ //if we are in broadcast arm all threads in the next alarm _alarms[alarm_id]->ArmAll(); } else{ _alarms[alarm_id]->ArmTID(tid); } } VOID CONTROL_CHAIN::Parse(const string& chain_str) { vector control_str; PARSER::SplitArgs(",",chain_str,control_str); for (UINT32 i=0; iHasLateHandler(), _vector_chain,_vector_index); _alarms.push_back(alarm_mngr); } } } BOOL CONTROL_CHAIN::NeedContext(){ return _control_mngr->PassContext(); } BOOL CONTROL_CHAIN::NeedToRepeat(UINT32 tid){ if (_repeat[tid] < _repeat_token || _repeat_token == REPEAT_INDEFINITELY){ return TRUE; } return FALSE; } VOID CONTROL_CHAIN::ArmNextAlarm(UINT32 alarm_id, UINT32 tid, BOOL bcast){ UINT32 last_alarm_id = _alarms.size() - 1; if (alarm_id < last_alarm_id){ //we still have alarm after this one Arm(tid,bcast,alarm_id+1); } else{ //we are in the last alarm check the repeat _repeat[tid]++; if (NeedToRepeat(tid)){ Arm(tid,bcast,0); } else{ ArmWaitingChains(tid); } } } VOID CONTROL_CHAIN::SetWaitFor(const string& chain_name){ UINT32 id = _control_mngr->GetChainId(chain_name); SetWaitFor(id); } VOID CONTROL_CHAIN::SetWaitFor(UINT32 chain_id){ CONTROL_CHAIN* chain = _control_mngr->ChainById(chain_id); if (chain == NULL){ stringstream s; s << "chain id " << chain_id << " does not exists"; ASSERT(FALSE, s.str()); } _wait_for_id = chain_id; chain->AddWaitingChain(this); } VOID CONTROL_CHAIN::AddWaitingChain(CONTROL_CHAIN* chain){ _waiting_chains.push_back(chain); } VOID CONTROL_CHAIN::ArmWaitingChains(UINT32 tid){ list::iterator iter = _waiting_chains.begin(); for(; iter != _waiting_chains.end(); iter++){ CONTROL_CHAIN* chain = *iter; chain->ArmChain(tid); } } //print debug massages - only when the debug knob is used VOID CONTROL_CHAIN::DebugPrint(){ for (UINT32 i = 0; i < _alarms.size(); i++){ _alarms[i]->Print(); } cerr << "REPEAT: " << _repeat_token << endl; cerr << "NAME: " << _name << endl; cerr << "WAIT FOR: " << _wait_for_id << endl; } BOOL CONTROL_CHAIN::HasStartEvent(){ for (UINT32 i = 0; i < _alarms.size(); i++){ if (_alarms[i]->HasStartEvent()){ return TRUE; } } return FALSE; } VOID CONTROL_CHAIN::SetUniformAlarm(ALARM_MANAGER* uniform_alarm){ if (_control_mngr->_uniform_alarm){ ASSERT(FALSE,"Only one uniform control is allowed"); } _control_mngr->_uniform_alarm = uniform_alarm; } EVENT_TYPE CONTROL_CHAIN::EventStringToType(const string& event_name){ return _control_mngr->EventStringToType(event_name); } // Set late handler in all alarms VOID CONTROL_CHAIN::SetLateHandler(){ for (UINT32 i = 0; i < _alarms.size(); i++){ _alarms[i]->SetLateHandler(); } } /// @endcond