paul@392 | 1 | = Program Loading = |
paul@392 | 2 | |
paul@392 | 3 | The provision of [[Paging|paging]] of file content leads to the possibility of |
paul@392 | 4 | demand paging for programs, enabling them to be loaded into memory dynamically |
paul@392 | 5 | and to have only the active portions of those programs resident. To achieve |
paul@392 | 6 | this, programs must be appropriately initialised in new tasks, with a page |
paul@392 | 7 | fault handler configured to provide program file content whenever a region of |
paul@392 | 8 | the program payload is encountered that is not currently resident in memory. |
paul@392 | 9 | |
paul@564 | 10 | <<TableOfContents(2,3)>> |
paul@564 | 11 | |
paul@564 | 12 | == Program Initialisation == |
paul@564 | 13 | |
paul@564 | 14 | To load and initialise a program, a new task must be created, defining a |
paul@564 | 15 | separate address space for the program and allowing it to operate |
paul@564 | 16 | independently of other programs. For a program to actually run, a thread of |
paul@564 | 17 | execution must be created so that the program's instructions can be read and |
paul@564 | 18 | processed. |
paul@564 | 19 | |
paul@392 | 20 | == Internal Page Fault Handlers == |
paul@392 | 21 | |
paul@392 | 22 | When satisfying page faults for a task, one approach involves situating the |
paul@392 | 23 | page fault handler within the task itself, this managing the available memory |
paul@392 | 24 | regions and employing receive windows when requesting memory pages. |
paul@392 | 25 | |
paul@392 | 26 | The general arrangement involving such internal page fault handlers for a |
paul@392 | 27 | program in a task is as follows: |
paul@392 | 28 | |
paul@392 | 29 | ######## A graph showing the internal paging mechanism |
paul@392 | 30 | |
paul@392 | 31 | {{{#!graphviz |
paul@392 | 32 | #format svg |
paul@392 | 33 | #transform notugly |
paul@392 | 34 | digraph internal_paging { |
paul@392 | 35 | node [fontsize="12.0",fontname="sans-serif",shape=box]; |
paul@392 | 36 | edge [fontsize="12.0",fontname="sans-serif"]; |
paul@392 | 37 | rankdir=LR; |
paul@392 | 38 | |
paul@392 | 39 | TaskMemory [shape=record,label="Task Memory |<s> stack | ... |<d> data | ... |<c> code"]; |
paul@392 | 40 | |
paul@392 | 41 | subgraph { |
paul@392 | 42 | rank=same; |
paul@392 | 43 | |
paul@392 | 44 | InternalPager; |
paul@392 | 45 | InternalPager_note [shape=note,style=filled,fillcolor=gold,label="Resides in\nsame task and\ndefines scope of\nfault resolution"]; |
paul@392 | 46 | |
paul@392 | 47 | InternalPager -> InternalPager_note [dir=none,style=dotted]; |
paul@392 | 48 | } |
paul@392 | 49 | |
paul@392 | 50 | subgraph { |
paul@392 | 51 | rank=same; |
paul@392 | 52 | |
paul@392 | 53 | Regions [shape=record,label="Regions | |
paul@392 | 54 | {<s> stack |<sd> stack-dataspace } | |
paul@392 | 55 | {<d> data | <dd> data-dataspace } | |
paul@392 | 56 | {<c> code |<cd> code-dataspace } |..."]; |
paul@392 | 57 | |
paul@392 | 58 | ReceiveFlexpage [shape=note,label="Flexpage\n(receive window)"]; |
paul@392 | 59 | |
paul@392 | 60 | Flexpage [shape=note]; |
paul@392 | 61 | Flexpage_note [shape=note,style=filled,fillcolor=gold,label="Satisfies\nmemory\naccess"]; |
paul@392 | 62 | |
paul@392 | 63 | Flexpage -> Flexpage_note [dir=none,style=dotted]; |
paul@392 | 64 | } |
paul@392 | 65 | |
paul@392 | 66 | subgraph { |
paul@392 | 67 | rank=same; |
paul@392 | 68 | |
paul@392 | 69 | ResourceD [label="Resource\n(Pager)"]; |
paul@392 | 70 | ResourceD_note [shape=note,style=filled,fillcolor=gold,label="Provides access\nto file content"]; |
paul@392 | 71 | |
paul@392 | 72 | ResourceD -> ResourceD_note [dir=none,style=dotted]; |
paul@392 | 73 | } |
paul@392 | 74 | |
paul@392 | 75 | ProgramFile [shape=record,label="Program File | ... |<d> data |<c> code | ..."]; |
paul@392 | 76 | |
paul@392 | 77 | /* Page fault handling. */ |
paul@392 | 78 | |
paul@392 | 79 | TaskMemory:d -> InternalPager [label="page fault"]; |
paul@392 | 80 | |
paul@392 | 81 | InternalPager -> Regions:d [label="find region"]; |
paul@392 | 82 | |
paul@392 | 83 | Regions:dd -> ResourceD [style=dashed]; |
paul@392 | 84 | |
paul@392 | 85 | InternalPager -> ReceiveFlexpage [dir=none]; |
paul@392 | 86 | ReceiveFlexpage -> ResourceD [label="map"]; |
paul@392 | 87 | |
paul@392 | 88 | ResourceD -> ProgramFile:d [style=dashed]; |
paul@392 | 89 | |
paul@392 | 90 | ResourceD -> Flexpage [dir=none]; |
paul@392 | 91 | Flexpage -> InternalPager; |
paul@392 | 92 | } |
paul@392 | 93 | }}} |
paul@392 | 94 | |
paul@392 | 95 | ######## |
paul@392 | 96 | |
paul@392 | 97 | == External Page Fault Handlers == |
paul@392 | 98 | |
paul@564 | 99 | Another approach is to employ an external page fault handler in the creating |
paul@392 | 100 | task. When a page fault occurs, the external handler ensures that the |
paul@392 | 101 | appropriate content has been brought into its own memory space. It then |
paul@392 | 102 | returns a flexpage from the handler routine to resolve the fault. |
paul@392 | 103 | |
paul@392 | 104 | ######## A graph showing the external paging mechanism |
paul@392 | 105 | |
paul@392 | 106 | {{{#!graphviz |
paul@392 | 107 | #format svg |
paul@392 | 108 | #transform notugly |
paul@392 | 109 | digraph external_paging { |
paul@392 | 110 | node [fontsize="12.0",fontname="sans-serif",shape=box]; |
paul@392 | 111 | edge [fontsize="12.0",fontname="sans-serif"]; |
paul@392 | 112 | rankdir=LR; |
paul@392 | 113 | |
paul@392 | 114 | TaskMemory [shape=record,label="Task Memory |<s> stack | ... |<d> data | ... |<c> code"]; |
paul@392 | 115 | |
paul@392 | 116 | subgraph { |
paul@392 | 117 | rank=same; |
paul@392 | 118 | |
paul@392 | 119 | ExternalPager_note [shape=note,style=filled,fillcolor=gold,label="Resides in\nseparate task"]; |
paul@392 | 120 | ExternalPager; |
paul@392 | 121 | |
paul@392 | 122 | ExternalPager_note -> ExternalPager [dir=none,style=dotted]; |
paul@392 | 123 | |
paul@392 | 124 | MappedFlexpage [shape=note,label="Flexpage\n(positioned)"]; |
paul@392 | 125 | MappedFlexpage_note [shape=note,style=filled,fillcolor=gold,label="Satisfies\nmemory\naccess"]; |
paul@392 | 126 | |
paul@392 | 127 | MappedFlexpage -> MappedFlexpage_note [dir=none,style=dotted]; |
paul@392 | 128 | } |
paul@392 | 129 | |
paul@392 | 130 | subgraph { |
paul@392 | 131 | rank=same; |
paul@392 | 132 | |
paul@392 | 133 | Regions [shape=record,label="Regions | |
paul@392 | 134 | {<s> stack |<sd> stack-dataspace } | |
paul@392 | 135 | {<d> data | <dd> data-dataspace } | |
paul@392 | 136 | {<c> code |<cd> code-dataspace } |..."]; |
paul@392 | 137 | |
paul@392 | 138 | L4Re [shape=ellipse,label="L4Re paging\nfunctionality"]; |
paul@392 | 139 | L4Re_note [shape=note,style=filled,fillcolor=gold,label="Supports normal\naccess to file content"]; |
paul@392 | 140 | |
paul@392 | 141 | L4Re -> L4Re_note [dir=none,style=dotted]; |
paul@392 | 142 | |
paul@392 | 143 | Flexpage [shape=note]; |
paul@392 | 144 | } |
paul@392 | 145 | |
paul@392 | 146 | subgraph { |
paul@392 | 147 | rank=same; |
paul@392 | 148 | |
paul@392 | 149 | ResourceD [label="Resource\n(Pager)"]; |
paul@392 | 150 | ResourceD_note [shape=note,style=filled,fillcolor=gold,label="Provides access\nto file content"]; |
paul@392 | 151 | |
paul@392 | 152 | ResourceD -> ResourceD_note [dir=none,style=dotted]; |
paul@392 | 153 | } |
paul@392 | 154 | |
paul@392 | 155 | ProgramFile [shape=record,label="Program File | ... |<d> data |<c> code | ..."]; |
paul@392 | 156 | |
paul@392 | 157 | /* Page fault handling. */ |
paul@392 | 158 | |
paul@392 | 159 | TaskMemory:d -> ExternalPager [label="page fault"]; |
paul@392 | 160 | |
paul@392 | 161 | ExternalPager -> Regions:d [label="find region"]; |
paul@392 | 162 | |
paul@392 | 163 | Regions:dd -> ResourceD [style=dashed]; |
paul@392 | 164 | |
paul@392 | 165 | ExternalPager -> L4Re; |
paul@392 | 166 | L4Re -> ResourceD [label="map"]; |
paul@392 | 167 | |
paul@392 | 168 | ResourceD -> ProgramFile:d [style=dashed]; |
paul@392 | 169 | |
paul@392 | 170 | ResourceD -> Flexpage [dir=none]; |
paul@392 | 171 | Flexpage -> ExternalPager; |
paul@392 | 172 | |
paul@392 | 173 | ExternalPager -> MappedFlexpage [dir=none]; |
paul@392 | 174 | MappedFlexpage -> TaskMemory:d; |
paul@392 | 175 | } |
paul@392 | 176 | }}} |
paul@392 | 177 | |
paul@392 | 178 | ######## |
paul@392 | 179 | |
paul@564 | 180 | This arrangement may be used to support a program deployed in a task. Since an |
paul@564 | 181 | internal page fault handler is just another kind of program, this external |
paul@564 | 182 | pager arrangement can be constrained to only supporting an internal page fault |
paul@564 | 183 | handler deployed in a task. |
paul@564 | 184 | |
paul@392 | 185 | == Configuring Programs == |
paul@392 | 186 | |
paul@392 | 187 | To provide an internal page fault handler alongside an actual program to be |
paul@392 | 188 | run, the following arrangement is used: |
paul@392 | 189 | |
paul@392 | 190 | ######## A graph showing the configuration arrangement |
paul@392 | 191 | |
paul@392 | 192 | {{{#!graphviz |
paul@392 | 193 | #format svg |
paul@392 | 194 | #transform notugly |
paul@392 | 195 | digraph program_configuration { |
paul@392 | 196 | node [fontsize="12.0",fontname="sans-serif",shape=box]; |
paul@392 | 197 | edge [fontsize="12.0",fontname="sans-serif"]; |
paul@392 | 198 | rankdir=LR; |
paul@392 | 199 | |
paul@392 | 200 | subgraph { |
paul@392 | 201 | rank=min; |
paul@392 | 202 | |
paul@392 | 203 | CreatingTask_note [shape=note,style=filled,fillcolor=gold,label="Responsible for\ncreating the\nnew task"]; |
paul@392 | 204 | CreatingTask [label="Creating task"]; |
paul@392 | 205 | |
paul@392 | 206 | CreatingTask_note -> CreatingTask [dir=none,style=dotted]; |
paul@392 | 207 | } |
paul@392 | 208 | |
paul@392 | 209 | subgraph { |
paul@392 | 210 | rank=max; |
paul@392 | 211 | |
paul@392 | 212 | IPCGate_note [shape=note,style=filled,fillcolor=gold,label="Created for sharing\nbetween the tasks"]; |
paul@392 | 213 | IPCGate [shape=octagon,label="IPC gate"]; |
paul@392 | 214 | |
paul@392 | 215 | IPCGate_note -> IPCGate [dir=none,style=dotted]; |
paul@392 | 216 | } |
paul@392 | 217 | |
paul@392 | 218 | InitCaps [shape=record,label="<head> Initial capabilities | {<s> \"server\" |<c> capability }"]; |
paul@392 | 219 | |
paul@392 | 220 | subgraph { |
paul@392 | 221 | rank=same; |
paul@392 | 222 | |
paul@392 | 223 | InternalPager; |
paul@392 | 224 | InternalPager_note [shape=note,style=filled,fillcolor=gold,label="Starts and binds\nto IPC gate"]; |
paul@392 | 225 | |
paul@392 | 226 | InternalPager -> InternalPager_note [dir=none,style=dotted]; |
paul@392 | 227 | |
paul@392 | 228 | Program; |
paul@392 | 229 | Program_note [shape=note,style=filled,fillcolor=gold,label="Starts and references\npager via IPC gate"]; |
paul@392 | 230 | |
paul@392 | 231 | Program -> Program_note [dir=none,style=dotted]; |
paul@392 | 232 | } |
paul@392 | 233 | |
paul@392 | 234 | /* Create and transfer IPC gate for binding. */ |
paul@392 | 235 | |
paul@392 | 236 | CreatingTask -> IPCGate [label="create"]; |
paul@392 | 237 | CreatingTask -> InitCaps:head [label="define"]; |
paul@392 | 238 | InitCaps:c -> IPCGate; |
paul@392 | 239 | |
paul@392 | 240 | /* Thread initiation. */ |
paul@392 | 241 | |
paul@392 | 242 | CreatingTask -> InternalPager [label="start"]; |
paul@392 | 243 | InternalPager -> InitCaps:s [label="bind"]; |
paul@392 | 244 | |
paul@392 | 245 | CreatingTask -> Program [label="start"]; |
paul@392 | 246 | Program -> IPCGate -> InternalPager [style=dashed]; |
paul@392 | 247 | } |
paul@392 | 248 | }}} |
paul@392 | 249 | |
paul@392 | 250 | ######## |