-
Notifications
You must be signed in to change notification settings - Fork 44
Core Arbiter Notes
Jacqueline Speiser edited this page Jan 20, 2017
·
19 revisions
The core arbiter sits between the Arachne library and the kernel, and decides how to allocate cores amongst multiple applications.
- The arbiter needs to be told which cores it will control
- Throw an error if given all cores. At least one needs to be reserved for itself and other processes
- Kick all other processes (including itself) off of those cores. The arbiter runs at high priority (possibly even sched_fifo).
- Later, we can add the functionality to only take cores from the kernel when needed and to give them back when possible.
- Use a domain socket to talk to the arbiter
-
connect()
: Use at startup to establish connection with Arbiter- Exchange information about processId, shared memory page
-
setNumCores(priorityArray[])
: Given an array of the number of cores to allocate at each priority, the arbiter will allocate a certain number and communicate to the application via its shared memory page how many it has.send(priorities)
-
addThread(threadId)
: Called once per kernel thread to inform the arbiter about a processId/threadId relationshipsend(threadID)
connect()
-
blockUntilCoreAvailable()
: Called by individual threads-
send()
: Tells the arbiter that the given process has a thread that is going to block until given a core. -
recv()
: Blocks the caller until the arbiter decides to give the application a core (it's important thatsend
be called first so the Arbiter is aware that the thread is waiting on it)
-
- Use a shared memory page to read from the arbiter (makes polling efficient).
- This page tells the application which cores it has available.
- Use
shm_open()
create a domain socket for communication with applications (appSocket)
initialize set of sockets to epoll on to contain just appSocket's file descriptor
while (true):
epoll (blocking)
if new application joining:
add processId to list of processes
add new file descriptor to epoll list
else if new thread is joining the pool:
add threadId to list of threads for the sending process
add new file descriptor to epoll list
else if blockUntilCoreAvailable:
set thread's state information to sleeping
if we have other applications waiting for cores:
putThreadOnCore()
else if setNumCores:
decide on how many cores to grant
for each available core:
putThreadOnCore()
for the unavailable cores:
update shared memory pages of other applications to request they give back cores
set a timer for each application we're taking cores from
else if timeout on request to application:
move as many threads as you need to the general cpuset
for each thread waiting to be woken up:
putThreadOnCore()
function putThreadOnCore(processId, coreId): add thread to appropriate cpuset update shared memory page send(coreId) to a blocked thread that belongs to the given process
- If an application does not give up a core in a timely manner when asked to, the arbiter demotes threads by putting them in the cpuset with itself and all the other non-Arachne threads.
- TODO: come up with a more detailed policy
The Arachne library creates as many threads as there are cores. Each thread has the following main loop:
while (true):
blockUntilCoreAvailable()
run until the arbiter tells us via shared memory that we should yield
- Arbitration policy?
- How are we going to unit test?
- Logging?