Debugger: Add/handle new suspend state for jobs.

- In addition to waiting for one or more dependent jobs to complete,
a job can now potentially wait for user input to proceed further. Add
a corresponding job_wait_status and respective handling in Worker.
This commit is contained in:
Rene Gollent 2013-12-01 21:10:51 -05:00
parent 004f41565e
commit 4605febacf
2 changed files with 59 additions and 4 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2012-2014, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
@ -114,6 +114,13 @@ Job::WaitFor(const JobKey& key)
}
status_t
Job::WaitForUserInput()
{
return fWorker->WaitForUserInput(this);
}
void
Job::SetWorker(Worker* worker)
{
@ -141,6 +148,7 @@ Job::SetWaitStatus(job_wait_status status)
fWaitStatus = status;
switch (fWaitStatus) {
case JOB_DEPENDENCY_ACTIVE:
case JOB_USER_INPUT_WAITING:
fState = JOB_STATE_WAITING;
break;
default:
@ -315,6 +323,25 @@ Worker::GetJob(const JobKey& key)
}
status_t
Worker::ResumeJob(Job* job)
{
AutoLocker<Worker> locker(this);
for (JobList::Iterator it = fSuspendedJobs.GetIterator(); it.Next();) {
if (it.Current() == job) {
it.Remove();
job->SetState(JOB_STATE_UNSCHEDULED);
fUnscheduledJobs.Add(job);
release_sem(fWorkToDoSem);
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
Worker::AddListener(const JobKey& key, JobListener* listener)
{
@ -359,6 +386,21 @@ Worker::WaitForJob(Job* waitingJob, const JobKey& key)
}
status_t
Worker::WaitForUserInput(Job* waitingJob)
{
AutoLocker<Worker> locker(this);
if (fTerminating || waitingJob->State() == JOB_STATE_ABORTED)
return B_INTERRUPTED;
waitingJob->SetWaitStatus(JOB_USER_INPUT_WAITING);
fSuspendedJobs.Add(waitingJob);
return B_OK;
}
/*static*/ status_t
Worker::_WorkerLoopEntry(void* data)
{
@ -439,10 +481,13 @@ Worker::_AbortJob(Job* job, bool removeFromTable)
break;
case JOB_STATE_WAITING:
job->Dependency()->DependentJobs().Remove(job);
{
Job* dependency = job->Dependency();
if (dependency != NULL)
dependency->DependentJobs().Remove(job);
job->SetDependency(NULL);
break;
}
case JOB_STATE_ACTIVE:
case JOB_STATE_FAILED:
case JOB_STATE_SUCCEEDED:

View File

@ -1,5 +1,6 @@
/*
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2014, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef WORKER_H
@ -31,7 +32,9 @@ enum job_wait_status {
JOB_DEPENDENCY_SUCCEEDED,
JOB_DEPENDENCY_FAILED,
JOB_DEPENDENCY_ABORTED,
JOB_DEPENDENCY_ACTIVE
JOB_DEPENDENCY_ACTIVE,
JOB_USER_INPUT_WAITING
// internal only
};
@ -88,6 +91,7 @@ public:
protected:
job_wait_status WaitFor(const JobKey& key);
status_t WaitForUserInput();
private:
friend class Worker;
@ -141,6 +145,10 @@ public:
void AbortJob(const JobKey& key);
Job* GetJob(const JobKey& key);
status_t ResumeJob(Job* job);
// only valid for jobs that are
// suspended pending user input
status_t AddListener(const JobKey& key,
JobListener* listener);
void RemoveListener(const JobKey& key,
@ -178,6 +186,7 @@ private:
private:
job_wait_status WaitForJob(Job* waitingJob, const JobKey& key);
status_t WaitForUserInput(Job* waitingJob);
static status_t _WorkerLoopEntry(void* data);
status_t _WorkerLoop();
@ -191,6 +200,7 @@ private:
JobTable fJobs;
JobList fUnscheduledJobs;
JobList fAbortedJobs;
JobList fSuspendedJobs;
sem_id fWorkToDoSem;
thread_id fWorkerThread;
volatile bool fTerminating;