1 /* 2 * Copyright 2021, Andrew Lindesay <apl@lindesay.co.nz>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "ThreadedProcessNode.h" 8 9 #include <unistd.h> 10 11 #include "AbstractProcess.h" 12 #include "Logger.h" 13 14 15 #define TIMEOUT_UNTIL_STARTED_SECS 10 16 #define TIMEOUT_UNTIL_STOPPED_SECS 10 17 18 19 ThreadedProcessNode::ThreadedProcessNode(AbstractProcess* process) 20 : 21 AbstractProcessNode(process), 22 fWorker(B_BAD_THREAD_ID) 23 24 { 25 } 26 27 28 ThreadedProcessNode::~ThreadedProcessNode() 29 { 30 } 31 32 33 /*! Considered to be protected from concurrent access by the ProcessCoordinator 34 */ 35 36 status_t 37 ThreadedProcessNode::StartProcess() 38 { 39 if (fWorker != B_BAD_THREAD_ID) 40 return B_BUSY; 41 42 HDINFO("[Node<%s>] initiating threaded", Process()->Name()); 43 44 fWorker = spawn_thread(&_StartProcess, Process()->Name(), 45 B_NORMAL_PRIORITY, Process()); 46 47 if (fWorker >= 0) { 48 resume_thread(fWorker); 49 return _SpinUntilProcessState(PROCESS_RUNNING | PROCESS_COMPLETE, 50 TIMEOUT_UNTIL_STARTED_SECS); 51 } 52 53 return B_ERROR; 54 } 55 56 57 /*! Considered to be protected from concurrent access by the ProcessCoordinator 58 */ 59 60 status_t 61 ThreadedProcessNode::StopProcess() 62 { 63 Process()->SetListener(NULL); 64 status_t stopResult = Process()->Stop(); 65 status_t waitResult = _SpinUntilProcessState(PROCESS_COMPLETE, 66 TIMEOUT_UNTIL_STOPPED_SECS); 67 68 // if the thread is still running then it will be necessary to tear it 69 // down. 70 71 if (waitResult != B_OK) { 72 HDINFO("[%s] process did not stop within timeout - will be stopped " 73 "uncleanly", Process()->Name()); 74 kill_thread(fWorker); 75 } 76 77 if (stopResult != B_OK) 78 return stopResult; 79 80 if (waitResult != B_OK) 81 return waitResult; 82 83 return B_OK; 84 } 85 86 87 /*! This method is the initial function that is invoked on starting a new 88 thread. It will start a process that is part of the bulk-load. 89 */ 90 91 /*static*/ status_t 92 ThreadedProcessNode::_StartProcess(void* cookie) 93 { 94 AbstractProcess* process = static_cast<AbstractProcess*>(cookie); 95 bigtime_t start = system_time(); 96 97 HDINFO("[Node<%s>] starting process in thread", process->Name()); 98 process->Run(); 99 HDINFO("[Node<%s>] finished process in thread %f seconds", process->Name(), 100 (system_time() - start) / 1000000.0); 101 102 return B_OK; 103 } 104