forked from Imagelibrary/seL4
SELFOUR-276: Add MCP field to threads.
Where MCP = Maximum Controlled Priority This commit adds: * seL4_TCB_SetMCPriority and changes the arguments to * seL4_TCB_Configure As of this commit, a thread cannot create or set a threads priority (including itself) above its mcp. Previously the kernel did this check against a threads priority, which prevented a thread from setting it's own priority down and then up again.
This commit is contained in:
@@ -98,6 +98,15 @@ wordFromMessageInfo(seL4_MessageInfo_t mi)
|
||||
return mi.words[0];
|
||||
}
|
||||
|
||||
static inline seL4_PrioProps_t CONST
|
||||
prioPropsFromWord(word_t w)
|
||||
{
|
||||
seL4_PrioProps_t pp;
|
||||
pp.words[0] = w;
|
||||
|
||||
return pp;
|
||||
}
|
||||
|
||||
#define allRights cap_rights_new(true, true, true)
|
||||
#define noWrite cap_rights_new(true, true, false)
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ void switchToThread(tcb_t *thread) VISIBLE;
|
||||
void switchToIdleThread(void);
|
||||
void setDomain(tcb_t *tptr, dom_t dom);
|
||||
void setPriority(tcb_t *tptr, prio_t prio);
|
||||
void setMCPriority(tcb_t *tptr, prio_t mcp);
|
||||
void scheduleTCB(tcb_t *tptr);
|
||||
void attemptSwitchTo(tcb_t *tptr);
|
||||
void switchIfRequiredTo(tcb_t *tptr);
|
||||
|
||||
@@ -213,6 +213,9 @@ struct tcb {
|
||||
/* Domain, 1 byte (packed to 4) */
|
||||
dom_t tcbDomain;
|
||||
|
||||
/* maximum controlled priorioty, 1 byte (packed to 4) */
|
||||
prio_t tcbMCP;
|
||||
|
||||
/* Priority, 1 byte (packed to 4) */
|
||||
prio_t tcbPriority;
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ exception_t decodeWriteRegisters(cap_t cap, word_t length, word_t *buffer);
|
||||
exception_t decodeTCBConfigure(cap_t cap, word_t length,
|
||||
cte_t* slot, extra_caps_t rootCaps, word_t *buffer);
|
||||
exception_t decodeSetPriority(cap_t cap, word_t length, word_t *buffer);
|
||||
exception_t decodeSetMCPriority(cap_t cap, word_t length, word_t *buffer);
|
||||
exception_t decodeSetIPCBuffer(cap_t cap, word_t length,
|
||||
cte_t* slot, extra_caps_t excaps, word_t *buffer);
|
||||
exception_t decodeSetSpace(cap_t cap, word_t length,
|
||||
@@ -83,7 +84,8 @@ enum thread_control_flag {
|
||||
thread_control_update_priority = 0x1,
|
||||
thread_control_update_ipc_buffer = 0x2,
|
||||
thread_control_update_space = 0x4,
|
||||
thread_control_update_all = 0x7,
|
||||
thread_control_update_mcp = 0x8,
|
||||
thread_control_update_all = 0xF,
|
||||
};
|
||||
|
||||
typedef word_t thread_control_flag_t;
|
||||
@@ -91,7 +93,7 @@ typedef word_t thread_control_flag_t;
|
||||
exception_t invokeTCB_Suspend(tcb_t *thread);
|
||||
exception_t invokeTCB_Resume(tcb_t *thread);
|
||||
exception_t invokeTCB_ThreadControl(tcb_t *target, cte_t* slot, cptr_t faultep,
|
||||
prio_t priority, cap_t cRoot_newCap,
|
||||
prio_t mcp, prio_t priority, cap_t cRoot_newCap,
|
||||
cte_t *cRoot_srcSlot, cap_t vRoot_newCap,
|
||||
cte_t *vRoot_srcSlot, word_t bufferAddr,
|
||||
cap_t bufferCap, cte_t *bufferSrcSlot,
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
</method>
|
||||
<method id="TCBConfigure" name="Configure">
|
||||
<param dir="in" name="fault_ep" type="seL4_Word"/>
|
||||
<param dir="in" name="priority" type="seL4_Uint8"/>
|
||||
<param dir="in" name="priority" type="seL4_PrioProps_t"/>
|
||||
<param dir="in" name="cspace_root" type="seL4_CNode"/>
|
||||
<param dir="in" name="cspace_root_data" type="seL4_CapData_t"/>
|
||||
<param dir="in" name="vspace_root" type="seL4_CNode"/>
|
||||
@@ -54,6 +54,9 @@
|
||||
<method id="TCBSetPriority" name="SetPriority">
|
||||
<param dir="in" name="priority" type="seL4_Uint8"/>
|
||||
</method>
|
||||
<method id="TCBSetMCPriority" name="SetMCPriority">
|
||||
<param dir="in" name="mcc" type="seL4_Uint8"/>
|
||||
</method>
|
||||
<method id="TCBSetIPCBuffer" name="SetIPCBuffer">
|
||||
<param dir="in" name="buffer" type="seL4_Word"/>
|
||||
<param dir="in" name="bufferFrame" type="seL4_CPtr"/>
|
||||
|
||||
@@ -18,3 +18,9 @@ block seL4_MessageInfo {
|
||||
field extraCaps 2
|
||||
field length 7
|
||||
}
|
||||
|
||||
block seL4_PrioProps {
|
||||
padding 16
|
||||
field mcp 8
|
||||
field prio 8
|
||||
}
|
||||
|
||||
@@ -219,6 +219,7 @@ def init_data_types(wordsize):
|
||||
|
||||
# seL4 Structures
|
||||
BitFieldType("seL4_CapData_t", wordsize, wordsize),
|
||||
BitFieldType("seL4_PrioProps_t", wordsize, wordsize),
|
||||
|
||||
# Object types
|
||||
CapType("seL4_CPtr", wordsize),
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
\newcommand{\archflagsdesc}{Architecture dependent flags. These have no meaning on \ifxeightsix{either IA-32 or}\fi{} ARM.}
|
||||
|
||||
\newcommand{\threadpriodesc}{The thread's new priority.}
|
||||
\newcommand{\threadmaxpriodesc}{The thread's new maximum controlled priority.}
|
||||
\newcommand{\threadcspacerootdesc}{The new CSpace root.}
|
||||
\newcommand{\threadcspacedatadesc}{Optionally set the guard and guard size of the new root CNode. If set to zero, this parameter has no effect.}
|
||||
\newcommand{\threadvspacerootdesc}{The new VSpace root.}
|
||||
@@ -270,6 +271,7 @@ complete the \apifunc{seL4\_Untyped\_Retype}{untyped_retype} request.
|
||||
\inputapidoc{tcb_resume}
|
||||
\inputapidoc{tcb_setipcbuffer}
|
||||
\inputapidoc{tcb_setpriority}
|
||||
\inputapidoc{tcb_setmcpriority}
|
||||
\inputapidoc{tcb_setspace}
|
||||
\inputapidoc{tcb_suspend}
|
||||
\inputapidoc{tcb_writeregisters}
|
||||
|
||||
21
manual/parts/api/tcb_setmcpriority.tex
Normal file
21
manual/parts/api/tcb_setmcpriority.tex
Normal file
@@ -0,0 +1,21 @@
|
||||
%
|
||||
% Copyright 2014, General Dynamics C4 Systems
|
||||
%
|
||||
% This software may be distributed and modified according to the terms of
|
||||
% the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
||||
% See "LICENSE_GPLv2.txt" for details.
|
||||
%
|
||||
% @TAG(GD_GPL)
|
||||
%
|
||||
|
||||
\apidoc
|
||||
{tcb_setmcpriority}
|
||||
{TCB - Set Maximum Controlled Priority}
|
||||
{Change a thread's maximum controlled priority}
|
||||
{static inline int seL4\_TCB\_SetMCPriority }
|
||||
{
|
||||
\param{seL4\_TCB}{\_service}{\tcbcapdesc}
|
||||
\param{uint8\_t}{mcp}{\threadmaxpriodesc}
|
||||
}
|
||||
{\errorenumdesc}
|
||||
{See \autoref{sec:sched}}
|
||||
@@ -58,10 +58,12 @@ deleted.
|
||||
\label{sec:sched}
|
||||
|
||||
seL4 uses a preemptive round-robin scheduler with 256 priority levels.
|
||||
When a thread creates or modifies another thread, it can only set the
|
||||
other thread's priority to be lower than or equal to its own. Thread priority can be
|
||||
All threads have a maximum controlled priority (MCP) and a priority, the latter being the effective
|
||||
priority of the thread.
|
||||
When a thread creates or modifies a thread (including itself), it can only set the
|
||||
other thread's priority and MCP to be less than or equal to its own MCP. Thread priority and MCP can be
|
||||
set with \apifunc{seL4\_TCB\_Configure}{tcb_configure} and
|
||||
\apifunc{seL4\_TCB\_SetPriority}{tcb_setpriority} methods.
|
||||
\apifunc{seL4\_TCB\_SetPriority}{tcb_setpriority}, \apifunc{seL4\_TCB\_SetMCPriority}{tcb_setmcpriority} methods.
|
||||
|
||||
\subsection{Exceptions}
|
||||
|
||||
|
||||
@@ -413,6 +413,7 @@ create_initial_thread(
|
||||
|
||||
/* initialise TCB */
|
||||
tcb->tcbPriority = seL4_MaxPrio;
|
||||
tcb->tcbMCP = seL4_MaxPrio;
|
||||
setupReplyMaster(tcb);
|
||||
setThreadState(tcb, ThreadState_Running);
|
||||
ksSchedulerAction = tcb;
|
||||
|
||||
@@ -360,6 +360,12 @@ setDomain(tcb_t *tptr, dom_t dom)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
setMCPriority(tcb_t *tptr, prio_t mcp)
|
||||
{
|
||||
tptr->tcbMCP = mcp;
|
||||
}
|
||||
|
||||
void
|
||||
setPriority(tcb_t *tptr, prio_t prio)
|
||||
{
|
||||
|
||||
130
src/object/tcb.c
130
src/object/tcb.c
@@ -24,6 +24,42 @@
|
||||
#include <util.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NULL_PRIO 0
|
||||
|
||||
static exception_t
|
||||
checkPrio(prio_t prio)
|
||||
{
|
||||
prio_t mcp;
|
||||
|
||||
mcp = ksCurThread->tcbMCP;
|
||||
/* can't create a thread with prio greater than our own mcp */
|
||||
if (prio > mcp) {
|
||||
current_syscall_error.type = seL4_RangeError;
|
||||
current_syscall_error.rangeErrorMin = seL4_MinPrio;
|
||||
current_syscall_error.rangeErrorMax = mcp;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
return EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
static exception_t
|
||||
checkMCP(prio_t mcp)
|
||||
{
|
||||
if (checkPrio(mcp) != EXCEPTION_NONE) {
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
if (mcp > seL4_MaxPrio) {
|
||||
current_syscall_error.type = seL4_RangeError;
|
||||
current_syscall_error.rangeErrorMin = seL4_MinPrio;
|
||||
current_syscall_error.rangeErrorMax = seL4_MaxPrio;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
return EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
addToBitmap(word_t dom, word_t prio)
|
||||
{
|
||||
@@ -319,6 +355,9 @@ decodeTCBInvocation(word_t invLabel, word_t length, cap_t cap,
|
||||
case TCBSetPriority:
|
||||
return decodeSetPriority(cap, length, buffer);
|
||||
|
||||
case TCBSetMCPriority:
|
||||
return decodeSetMCPriority(cap, length, buffer);
|
||||
|
||||
case TCBSetIPCBuffer:
|
||||
return decodeSetIPCBuffer(cap, length, slot, excaps, buffer);
|
||||
|
||||
@@ -486,8 +525,10 @@ decodeTCBConfigure(cap_t cap, word_t length, cte_t* slot,
|
||||
cap_t bufferCap, cRootCap, vRootCap;
|
||||
deriveCap_ret_t dc_ret;
|
||||
cptr_t faultEP;
|
||||
word_t prio;
|
||||
seL4_PrioProps_t props;
|
||||
prio_t prio, mcp;
|
||||
word_t cRootData, vRootData, bufferAddr;
|
||||
exception_t status;
|
||||
|
||||
if (length < 5 || rootCaps.excaprefs[0] == NULL
|
||||
|| rootCaps.excaprefs[1] == NULL
|
||||
@@ -497,11 +538,11 @@ decodeTCBConfigure(cap_t cap, word_t length, cte_t* slot,
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
faultEP = getSyscallArg(0, buffer);
|
||||
prio = getSyscallArg(1, buffer);
|
||||
cRootData = getSyscallArg(2, buffer);
|
||||
vRootData = getSyscallArg(3, buffer);
|
||||
bufferAddr = getSyscallArg(4, buffer);
|
||||
faultEP = getSyscallArg(0, buffer);
|
||||
props = prioPropsFromWord(getSyscallArg(1, buffer));
|
||||
cRootData = getSyscallArg(2, buffer);
|
||||
vRootData = getSyscallArg(3, buffer);
|
||||
bufferAddr = getSyscallArg(4, buffer);
|
||||
|
||||
cRootSlot = rootCaps.excaprefs[0];
|
||||
cRootCap = rootCaps.excaprefs[0]->cap;
|
||||
@@ -510,13 +551,23 @@ decodeTCBConfigure(cap_t cap, word_t length, cte_t* slot,
|
||||
bufferSlot = rootCaps.excaprefs[2];
|
||||
bufferCap = rootCaps.excaprefs[2]->cap;
|
||||
|
||||
prio = prio & MASK(8);
|
||||
prio = seL4_PrioProps_get_prio(props);
|
||||
mcp = seL4_PrioProps_get_mcp(props);
|
||||
|
||||
if (prio > ksCurThread->tcbPriority) {
|
||||
userError("TCB Configure: Requested priority %d too high (max %d).",
|
||||
(int)prio, (int)(ksCurThread->tcbPriority));
|
||||
current_syscall_error.type = seL4_IllegalOperation;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
status = checkPrio(prio);
|
||||
if (status != EXCEPTION_NONE) {
|
||||
userError("TCB Configure: Requested priority %lu too high (max %lu).",
|
||||
(unsigned long) prio, (unsigned long) ksCurThread->tcbMCP);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = checkMCP(mcp);
|
||||
if (status != EXCEPTION_NONE) {
|
||||
userError("Requested maximum controlled priority %lu too high (max %lu),",
|
||||
(unsigned long) mcp,
|
||||
(unsigned long) prio >= seL4_MaxPrio ? seL4_MaxPrio :
|
||||
ksCurThread->tcbMCP);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (bufferAddr == 0) {
|
||||
@@ -578,7 +629,7 @@ decodeTCBConfigure(cap_t cap, word_t length, cte_t* slot,
|
||||
setThreadState(ksCurThread, ThreadState_Restart);
|
||||
return invokeTCB_ThreadControl(
|
||||
TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), slot,
|
||||
faultEP, prio,
|
||||
faultEP, mcp, prio,
|
||||
cRootCap, cRootSlot,
|
||||
vRootCap, vRootSlot,
|
||||
bufferAddr, bufferCap,
|
||||
@@ -589,6 +640,7 @@ exception_t
|
||||
decodeSetPriority(cap_t cap, word_t length, word_t *buffer)
|
||||
{
|
||||
prio_t newPrio;
|
||||
exception_t status;
|
||||
|
||||
if (length < 1) {
|
||||
userError("TCB SetPriority: Truncated message.");
|
||||
@@ -600,24 +652,53 @@ decodeSetPriority(cap_t cap, word_t length, word_t *buffer)
|
||||
|
||||
/* assuming here seL4_MaxPrio is of form 2^n - 1 */
|
||||
newPrio = newPrio & MASK(8);
|
||||
status = checkPrio(newPrio);
|
||||
if (status != EXCEPTION_NONE) {
|
||||
userError("TCB SetPriority: Requested priority %lu too high (max %lu).",
|
||||
(unsigned long) newPrio, (unsigned long ) ksCurThread->tcbMCP);
|
||||
return status;
|
||||
|
||||
if (newPrio > ksCurThread->tcbPriority) {
|
||||
userError("TCB SetPriority: Requested priority %d too high (max %d).",
|
||||
(int)newPrio, (int)ksCurThread->tcbPriority);
|
||||
current_syscall_error.type = seL4_IllegalOperation;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
setThreadState(ksCurThread, ThreadState_Restart);
|
||||
return invokeTCB_ThreadControl(
|
||||
TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), NULL,
|
||||
0, newPrio,
|
||||
0, NULL_PRIO, newPrio,
|
||||
cap_null_cap_new(), NULL,
|
||||
cap_null_cap_new(), NULL,
|
||||
0, cap_null_cap_new(),
|
||||
NULL, thread_control_update_priority);
|
||||
}
|
||||
|
||||
exception_t
|
||||
decodeSetMCPriority(cap_t cap, word_t length, word_t *buffer)
|
||||
{
|
||||
prio_t newMcp;
|
||||
exception_t status;
|
||||
|
||||
if (length < 1) {
|
||||
userError("TCB SetMCPriority: Truncated message.");
|
||||
current_syscall_error.type = seL4_TruncatedMessage;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
newMcp = (prio_t) getSyscallArg(0, buffer);
|
||||
|
||||
status = checkMCP(newMcp);
|
||||
if (status != EXCEPTION_NONE) {
|
||||
return status;
|
||||
}
|
||||
|
||||
setThreadState(ksCurThread, ThreadState_Restart);
|
||||
return invokeTCB_ThreadControl(
|
||||
TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), NULL,
|
||||
0, newMcp, NULL_PRIO,
|
||||
cap_null_cap_new(), NULL,
|
||||
cap_null_cap_new(), NULL,
|
||||
0, cap_null_cap_new(),
|
||||
NULL, thread_control_update_mcp);
|
||||
}
|
||||
|
||||
exception_t
|
||||
decodeSetIPCBuffer(cap_t cap, word_t length, cte_t* slot,
|
||||
extra_caps_t excaps, word_t *buffer)
|
||||
@@ -656,8 +737,7 @@ decodeSetIPCBuffer(cap_t cap, word_t length, cte_t* slot,
|
||||
setThreadState(ksCurThread, ThreadState_Restart);
|
||||
return invokeTCB_ThreadControl(
|
||||
TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), slot,
|
||||
0,
|
||||
0, /* used to be prioInvalid, but it doesn't matter */
|
||||
0, NULL_PRIO, NULL_PRIO,
|
||||
cap_null_cap_new(), NULL,
|
||||
cap_null_cap_new(), NULL,
|
||||
cptr_bufferPtr, bufferCap,
|
||||
@@ -735,7 +815,7 @@ decodeSetSpace(cap_t cap, word_t length, cte_t* slot,
|
||||
return invokeTCB_ThreadControl(
|
||||
TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), slot,
|
||||
faultEP,
|
||||
0, /* used to be prioInvalid, but it doesn't matter */
|
||||
NULL_PRIO, NULL_PRIO,
|
||||
cRootCap, cRootSlot,
|
||||
vRootCap, vRootSlot,
|
||||
0, cap_null_cap_new(), NULL, thread_control_update_space);
|
||||
@@ -870,7 +950,7 @@ invokeTCB_Resume(tcb_t *thread)
|
||||
|
||||
exception_t
|
||||
invokeTCB_ThreadControl(tcb_t *target, cte_t* slot,
|
||||
cptr_t faultep, prio_t priority,
|
||||
cptr_t faultep, prio_t mcp, prio_t priority,
|
||||
cap_t cRoot_newCap, cte_t *cRoot_srcSlot,
|
||||
cap_t vRoot_newCap, cte_t *vRoot_srcSlot,
|
||||
word_t bufferAddr, cap_t bufferCap,
|
||||
@@ -884,6 +964,10 @@ invokeTCB_ThreadControl(tcb_t *target, cte_t* slot,
|
||||
target->tcbFaultHandler = faultep;
|
||||
}
|
||||
|
||||
if (updateFlags & thread_control_update_mcp) {
|
||||
setMCPriority(target, mcp);
|
||||
}
|
||||
|
||||
if (updateFlags & thread_control_update_priority) {
|
||||
setPriority(target, priority);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user