The Pedigree Project  0.1
Scheduler.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #if defined(THREADS)
21 
22 #include "pedigree/kernel/process/Scheduler.h"
23 #include "pedigree/kernel/Log.h"
24 #include "pedigree/kernel/process/PerProcessorScheduler.h"
25 #include "pedigree/kernel/process/ProcessorThreadAllocator.h"
26 #include "pedigree/kernel/process/RoundRobinCoreAllocator.h"
27 #include "pedigree/kernel/processor/Processor.h"
28 #include "pedigree/kernel/processor/ProcessorInformation.h"
29 #include "pedigree/kernel/utilities/Iterator.h"
30 #include "pedigree/kernel/utilities/Vector.h"
31 #include "pedigree/kernel/utilities/assert.h"
32 #include "pedigree/kernel/utilities/utility.h"
33 
35 
36 // Scheduler can be used at times where it is not yet safe to do the useful
37 // "safer" Spinlock deadlock detection.
38 #define SCHEDULER_HAS_SAFE_SPINLOCKS true
39 
40 // Do we allow recursing in the Scheduler lock? Note that the lock surrounds
41 // memory operations (editing a List<T>), so if e.g. VirtualAddressSpace depends
42 // on Scheduler, you need to recurse.
43 #define SCHEDULER_HAS_RECURSIVE_SPINLOCKS true
44 
45 Scheduler::Scheduler()
46  : m_Processes(), m_NextPid(0), m_PTMap(), m_TPMap(), m_pKernelProcess(0),
47  m_pBspScheduler(0), m_SchedulerLock(false)
48 {
49 }
50 
51 bool Scheduler::initialise(Process *pKernelProcess)
52 {
54  ProcessorThreadAllocator::instance().setAlgorithm(pRoundRobin);
55 
56  m_pKernelProcess = pKernelProcess;
57 
59 
60 #ifdef MULTIPROCESSOR
61  size_t i = 0;
64  it != Processor::m_ProcessorInformation.end(); it++, i += 2)
65  {
66  procList.pushBack(&((*it)->getScheduler()));
67  }
68 #else
69  procList.pushBack(&Processor::information().getScheduler());
70 #endif
71 
72  m_pBspScheduler = &Processor::information().getScheduler();
73 
74  pRoundRobin->initialise(procList);
75 
76  return true;
77 }
78 
80 {
81  m_SchedulerLock.acquire(
82  SCHEDULER_HAS_RECURSIVE_SPINLOCKS, SCHEDULER_HAS_SAFE_SPINLOCKS);
83  m_TPMap.insert(pThread, &PPSched);
84  m_SchedulerLock.release();
85 }
86 
88 {
89  m_SchedulerLock.acquire(
90  SCHEDULER_HAS_RECURSIVE_SPINLOCKS, SCHEDULER_HAS_SAFE_SPINLOCKS);
91  PerProcessorScheduler *pPpSched = m_TPMap.lookup(pThread);
92  if (pPpSched)
93  {
94  pPpSched->removeThread(pThread);
95  m_TPMap.remove(pThread);
96  }
97  m_SchedulerLock.release();
98 }
99 
101 {
102  m_SchedulerLock.acquire(
103  SCHEDULER_HAS_RECURSIVE_SPINLOCKS, SCHEDULER_HAS_SAFE_SPINLOCKS);
104  PerProcessorScheduler *pPpSched = m_TPMap.lookup(pThread);
105  m_SchedulerLock.release();
106  return pPpSched != 0;
107 }
108 
110 {
111  m_SchedulerLock.acquire(
112  SCHEDULER_HAS_RECURSIVE_SPINLOCKS, SCHEDULER_HAS_SAFE_SPINLOCKS);
113  m_Processes.pushBack(pProcess);
114  size_t result = (m_NextPid += 1) - 1; // little dance for Atomic
115  m_SchedulerLock.release();
116  return result;
117 }
118 
120 {
121  m_SchedulerLock.acquire(
122  SCHEDULER_HAS_RECURSIVE_SPINLOCKS, SCHEDULER_HAS_SAFE_SPINLOCKS);
123  for (List<Process *>::Iterator it = m_Processes.begin();
124  it != m_Processes.end(); it++)
125  {
126  if (*it == pProcess)
127  {
128  m_Processes.erase(it);
129  break;
130  }
131  }
132  m_SchedulerLock.release();
133 }
134 
136 {
137  Processor::information().getScheduler().schedule();
138 }
139 
141 {
142  m_SchedulerLock.acquire(
143  SCHEDULER_HAS_RECURSIVE_SPINLOCKS, SCHEDULER_HAS_SAFE_SPINLOCKS);
144  size_t result = m_Processes.count();
145  m_SchedulerLock.release();
146  return result;
147 }
148 
150 {
151  m_SchedulerLock.acquire(
152  SCHEDULER_HAS_RECURSIVE_SPINLOCKS, SCHEDULER_HAS_SAFE_SPINLOCKS);
153  if (n >= m_Processes.count())
154  {
155  WARNING(
156  "Scheduler::getProcess(" << Dec << n
157  << ") parameter outside range.");
158  m_SchedulerLock.release();
159  return 0;
160  }
161 
162  size_t i = 0;
163  Process *pResult = 0;
164  for (List<Process *>::Iterator it = m_Processes.begin();
165  it != m_Processes.end(); it++)
166  {
167  if (i == n)
168  {
169  pResult = *it;
170  break;
171  }
172  i++;
173  }
174 
175  m_SchedulerLock.release();
176  return pResult;
177 }
178 
179 void Scheduler::threadStatusChanged(Thread *pThread)
180 {
181  m_SchedulerLock.acquire(
182  SCHEDULER_HAS_RECURSIVE_SPINLOCKS, SCHEDULER_HAS_SAFE_SPINLOCKS);
183  PerProcessorScheduler *pSched = m_TPMap.lookup(pThread);
184  assert(pSched);
185  m_SchedulerLock.release();
186 
187  pSched->threadStatusChanged(pThread);
188 }
189 
190 #endif
void pushBack(const T &value)
Definition: List.h:232
This class manages how processes and threads are scheduled across processors.
Definition: Scheduler.h:44
static Scheduler m_Instance
Definition: Scheduler.h:104
static ProcessorInformation & information()
Definition: Processor.cc:45
bool threadInSchedule(Thread *pThread)
Definition: Scheduler.cc:100
void removeProcess(Process *pProcess)
Definition: Scheduler.cc:119
#define WARNING(text)
Definition: Log.h:78
Definition: List.h:64
void removeThread(Thread *pThread)
Definition: Scheduler.cc:87
size_t getNumProcesses()
Definition: Scheduler.cc:140
#define assert(x)
Definition: assert.h:37
T * Iterator
Definition: Vector.h:37
Iterator begin()
Definition: List.h:123
void setAlgorithm(ThreadToCoreAllocationAlgorithm *pAlgorithm)
Sets the algorithm to use for allocating threads to cores.
Process * getProcess(size_t n)
Definition: Scheduler.cc:149
Definition: Thread.h:54
size_t addProcess(Process *pProcess)
Definition: Scheduler.cc:109
void yield()
Definition: Scheduler.cc:135
Definition: Log.h:138
static ProcessorInformation m_ProcessorInformation
Definition: Processor.h:386
void addThread(Thread *pThread, PerProcessorScheduler &PPSched)
Definition: Scheduler.cc:79
bool initialise(Process *pKernelProcess)
Definition: Scheduler.cc:51