1.1 --- a/docs/wiki/ClientLibrary Wed Aug 10 23:58:38 2022 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,148 +0,0 @@
1.4 -= Client Library =
1.5 -
1.6 -The filesystem client library offers abstractions and a number of layers of
1.7 -functionality to support interaction with [[Components|components]] and the
1.8 -provision of higher-level mechanisms and abstractions for file access.
1.9 -
1.10 -<<TableOfContents(2,3)>>
1.11 -
1.12 -== File Data Structures ==
1.13 -
1.14 -Since files are accessed using file references, the `file_t` data structure is
1.15 -used to wrap such references and other relevant state. Thus, such structures
1.16 -can be broadly regarded as similar to the traditional `FILE` data structure.
1.17 -
1.18 -The fields of the `file_t` data structure are as follows:
1.19 -
1.20 -|| '''Field''' || '''Description''' ||
1.21 -|| `ref` || A reference to the component providing file content ||
1.22 -|| `memory` || The memory address of the exposed file region ||
1.23 -|| `start_pos` || The start position of the region in the file ||
1.24 -|| `end_pos` || The end position of the region in the file ||
1.25 -|| `data_end` || The amount or extent of populated data in the region ||
1.26 -|| `data_current` || The offset used to track client position in the region ||
1.27 -|| `size` || The total size of the file ||
1.28 -|| `object_flags` || Flags indicating support for certain file features ||
1.29 -|| `can_block` || Notification flags for blocking access to the file ||
1.30 -|| `notifications`|| Notification flags set for the file ||
1.31 -|| `flags` || The flags used to open the file ||
1.32 -
1.33 -== Client Programming Interface ==
1.34 -
1.35 -The client programming interface provides functions somewhat resembling the
1.36 -traditional C library and low-level Unix interfaces for file access, and these
1.37 -functions are intended to support such traditional interfaces.
1.38 -
1.39 -=== Files ===
1.40 -
1.41 -Files are opened and closed using the following functions:
1.42 -
1.43 -{{{
1.44 -file_t *client_open(const char *name, flags_t flags);
1.45 -}}}
1.46 -
1.47 -Each file endpoint may be closed using `client_close`.
1.48 -
1.49 -=== Pipes ===
1.50 -
1.51 -Pipes are opened using a special function:
1.52 -
1.53 -{{{
1.54 -long client_pipe(file_t **reader, file_t **writer, flags_t flags);
1.55 -}}}
1.56 -
1.57 -Each pipe endpoint may be closed using `client_close`.
1.58 -
1.59 -=== Closing Files and Pipes ===
1.60 -
1.61 -Closing files and pipes involves a common operation:
1.62 -
1.63 -{{{
1.64 -void client_close(file_t *file);
1.65 -}}}
1.66 -
1.67 -When client programs terminate, the freeing of their object capabilities
1.68 -should cause the closure of files and pipes, but programs may choose to close
1.69 -such resources explicitly.
1.70 -
1.71 -=== Reading and Writing ===
1.72 -
1.73 -Reading and writing files and pipes involves functions resembling the
1.74 -traditional low-level `read` and `write` functions:
1.75 -
1.76 -{{{
1.77 -offset_t client_read(file_t *file, void *buf, offset_t count);
1.78 -offset_t client_write(file_t *file, const void *buf, offset_t count);
1.79 -}}}
1.80 -
1.81 -=== Navigation in Files ===
1.82 -
1.83 -Support for navigation in files is provided using functions resembling the
1.84 -traditional higher-level `fseek` and `ftell` functions:
1.85 -
1.86 -{{{
1.87 -offset_t client_seek(file_t *file, offset_t offset, int whence);
1.88 -long client_tell(file_t *file);
1.89 -}}}
1.90 -
1.91 -=== Accessing Exposed Memory Regions ===
1.92 -
1.93 -Although the client library (and the provision of files) employs mapped
1.94 -memory, a function can be used to explicitly reference memory for file access:
1.95 -
1.96 -{{{
1.97 -void *client_mmap(file_t *file, offset_t position, offset_t length);
1.98 -}}}
1.99 -
1.100 -Pipes support a different mechanism for navigation involving the following
1.101 -functions:
1.102 -
1.103 -{{{
1.104 -long client_current_region(file_t *file);
1.105 -long client_next_region(file_t *file);
1.106 -}}}
1.107 -
1.108 -Such navigation functions for files and pipes do not need to be used where the
1.109 -higher-level reading, writing and seeking functions are in use.
1.110 -
1.111 -=== Flushing and Synchronisation ===
1.112 -
1.113 -For synchronisation purposes, either with the filesystem itself or with other
1.114 -users of the filesystem, a function resembling the traditional `fflush`
1.115 -function is provided:
1.116 -
1.117 -{{{
1.118 -long client_flush(file_t *file);
1.119 -}}}
1.120 -
1.121 -This updates the file data structure with new details of the file size, also
1.122 -updating any altered details of the extent of the data in the currently
1.123 -accessed region of the file.
1.124 -
1.125 -=== Notifications ===
1.126 -
1.127 -Since files and pipes may be accessed by multiple clients, necessarily for any
1.128 -sensible use of the latter, notifications can be configured to communicate a
1.129 -change in state to other users of these resources when they are accessed.
1.130 -
1.131 -Notification types are specified using values encoding a number of flags, and
1.132 -the following flags are available for this purpose:
1.133 -
1.134 -|| '''Flag''' || '''Notification Type''' ||
1.135 -|| `NOTIFY_CONTENT_AVAILABLE` || Content available to read ||
1.136 -|| `NOTIFY_PEER_CLOSED` || Other party has closed their endpoint ||
1.137 -|| `NOTIFY_SPACE_AVAILABLE` || Space available for writing ||
1.138 -
1.139 -=== Blocking Operations ===
1.140 -
1.141 -Reading and writing operations can be configured to block if data cannot be
1.142 -read or written respectively. The following function is provided for this
1.143 -purpose:
1.144 -
1.145 -{{{
1.146 -long client_set_blocking(file_t *file, notify_flags_t flags);
1.147 -}}}
1.148 -
1.149 -For pipes, blocking behaviour is the default and must be disabled explicitly,
1.150 -either by opening using the `O_NONBLOCK` flag or by calling
1.151 -`client_set_blocking` with no flags set.
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/docs/wiki/Client_Library Fri Aug 12 16:41:06 2022 +0200
2.3 @@ -0,0 +1,148 @@
2.4 += Client Library =
2.5 +
2.6 +The filesystem client library offers abstractions and a number of layers of
2.7 +functionality to support interaction with [[Components|components]] and the
2.8 +provision of higher-level mechanisms and abstractions for file access.
2.9 +
2.10 +<<TableOfContents(2,3)>>
2.11 +
2.12 +== File Data Structures ==
2.13 +
2.14 +Since files are accessed using file references, the `file_t` data structure is
2.15 +used to wrap such references and other relevant state. Thus, such structures
2.16 +can be broadly regarded as similar to the traditional `FILE` data structure.
2.17 +
2.18 +The fields of the `file_t` data structure are as follows:
2.19 +
2.20 +|| '''Field''' || '''Description''' ||
2.21 +|| `ref` || A reference to the component providing file content ||
2.22 +|| `memory` || The memory address of the exposed file region ||
2.23 +|| `start_pos` || The start position of the region in the file ||
2.24 +|| `end_pos` || The end position of the region in the file ||
2.25 +|| `data_end` || The amount or extent of populated data in the region ||
2.26 +|| `data_current` || The offset used to track client position in the region ||
2.27 +|| `size` || The total size of the file ||
2.28 +|| `object_flags` || Flags indicating support for certain file features ||
2.29 +|| `can_block` || Notification flags for blocking access to the file ||
2.30 +|| `notifications`|| Notification flags set for the file ||
2.31 +|| `flags` || The flags used to open the file ||
2.32 +
2.33 +== Client Programming Interface ==
2.34 +
2.35 +The client programming interface provides functions somewhat resembling the
2.36 +traditional C library and low-level Unix interfaces for file access, and these
2.37 +functions are intended to support such traditional interfaces.
2.38 +
2.39 +=== Files ===
2.40 +
2.41 +Files are opened and closed using the following functions:
2.42 +
2.43 +{{{
2.44 +file_t *client_open(const char *name, flags_t flags);
2.45 +}}}
2.46 +
2.47 +Each file endpoint may be closed using `client_close`.
2.48 +
2.49 +=== Pipes ===
2.50 +
2.51 +Pipes are opened using a special function:
2.52 +
2.53 +{{{
2.54 +long client_pipe(file_t **reader, file_t **writer, flags_t flags);
2.55 +}}}
2.56 +
2.57 +Each pipe endpoint may be closed using `client_close`.
2.58 +
2.59 +=== Closing Files and Pipes ===
2.60 +
2.61 +Closing files and pipes involves a common operation:
2.62 +
2.63 +{{{
2.64 +void client_close(file_t *file);
2.65 +}}}
2.66 +
2.67 +When client programs terminate, the freeing of their object capabilities
2.68 +should cause the closure of files and pipes, but programs may choose to close
2.69 +such resources explicitly.
2.70 +
2.71 +=== Reading and Writing ===
2.72 +
2.73 +Reading and writing files and pipes involves functions resembling the
2.74 +traditional low-level `read` and `write` functions:
2.75 +
2.76 +{{{
2.77 +offset_t client_read(file_t *file, void *buf, offset_t count);
2.78 +offset_t client_write(file_t *file, const void *buf, offset_t count);
2.79 +}}}
2.80 +
2.81 +=== Navigation in Files ===
2.82 +
2.83 +Support for navigation in files is provided using functions resembling the
2.84 +traditional higher-level `fseek` and `ftell` functions:
2.85 +
2.86 +{{{
2.87 +offset_t client_seek(file_t *file, offset_t offset, int whence);
2.88 +long client_tell(file_t *file);
2.89 +}}}
2.90 +
2.91 +=== Accessing Exposed Memory Regions ===
2.92 +
2.93 +Although the client library (and the provision of files) employs mapped
2.94 +memory, a function can be used to explicitly reference memory for file access:
2.95 +
2.96 +{{{
2.97 +void *client_mmap(file_t *file, offset_t position, offset_t length);
2.98 +}}}
2.99 +
2.100 +Pipes support a different mechanism for navigation involving the following
2.101 +functions:
2.102 +
2.103 +{{{
2.104 +long client_current_region(file_t *file);
2.105 +long client_next_region(file_t *file);
2.106 +}}}
2.107 +
2.108 +Such navigation functions for files and pipes do not need to be used where the
2.109 +higher-level reading, writing and seeking functions are in use.
2.110 +
2.111 +=== Flushing and Synchronisation ===
2.112 +
2.113 +For synchronisation purposes, either with the filesystem itself or with other
2.114 +users of the filesystem, a function resembling the traditional `fflush`
2.115 +function is provided:
2.116 +
2.117 +{{{
2.118 +long client_flush(file_t *file);
2.119 +}}}
2.120 +
2.121 +This updates the file data structure with new details of the file size, also
2.122 +updating any altered details of the extent of the data in the currently
2.123 +accessed region of the file.
2.124 +
2.125 +=== Notifications ===
2.126 +
2.127 +Since files and pipes may be accessed by multiple clients, necessarily for any
2.128 +sensible use of the latter, notifications can be configured to communicate a
2.129 +change in state to other users of these resources when they are accessed.
2.130 +
2.131 +Notification types are specified using values encoding a number of flags, and
2.132 +the following flags are available for this purpose:
2.133 +
2.134 +|| '''Flag''' || '''Notification Type''' ||
2.135 +|| `NOTIFY_CONTENT_AVAILABLE` || Content available to read ||
2.136 +|| `NOTIFY_PEER_CLOSED` || Other party has closed their endpoint ||
2.137 +|| `NOTIFY_SPACE_AVAILABLE` || Space available for writing ||
2.138 +
2.139 +=== Blocking Operations ===
2.140 +
2.141 +Reading and writing operations can be configured to block if data cannot be
2.142 +read or written respectively. The following function is provided for this
2.143 +purpose:
2.144 +
2.145 +{{{
2.146 +long client_set_blocking(file_t *file, notify_flags_t flags);
2.147 +}}}
2.148 +
2.149 +For pipes, blocking behaviour is the default and must be disabled explicitly,
2.150 +either by opening using the `O_NONBLOCK` flag or by calling
2.151 +`client_set_blocking` with no flags set.
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/docs/wiki/Departure Fri Aug 12 16:41:06 2022 +0200
3.3 @@ -0,0 +1,21 @@
3.4 += Departure =
3.5 +
3.6 +The Departure distribution aims to provide components and libraries to
3.7 +implement and deliver filesystem access in the L4 Runtime Environment. In
3.8 +particular, it acts as a research and testing vehicle for implementations of
3.9 +demand-paged files.
3.10 +
3.11 +== Topics ==
3.12 +
3.13 + * [[Client Library]] - convenience functions and structures to access
3.14 + filesystem objects
3.15 + * [[Components]] - server objects exposed at the system level that support
3.16 + filesystem access
3.17 + * [[Filesystem Access]] - mechanisms within filesystem servers to manage
3.18 + filesystem resources and content
3.19 + * [[Paging]] - the mechanism by which filesystem content is provided for use
3.20 + by client programs
3.21 + * [[Program Loading]] - the mechanism by which programs are loaded
3.22 + * [[Server Library]] - abstractions to expose and manage access to filesystem
3.23 + objects
3.24 + * [[Users]]
4.1 --- a/docs/wiki/FilesystemAccess Wed Aug 10 23:58:38 2022 +0200
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,611 +0,0 @@
4.4 -= Filesystem Access =
4.5 -
4.6 -Within the [[ServerLibrary|filesystem server library]], a number of different
4.7 -abstractions and mechanisms are employed to provide access to filesystem
4.8 -objects. An overview of these abstractions is presented below.
4.9 -
4.10 -######## A graph showing the relationships between filesystem access
4.11 -######## components
4.12 -
4.13 -{{{#!graphviz
4.14 -#format svg
4.15 -#transform notugly
4.16 -digraph components {
4.17 - node [fontsize="12.0",fontname="sans-serif",shape=box];
4.18 - edge [fontsize="12.0",fontname="sans-serif"];
4.19 - rankdir=LR;
4.20 -
4.21 - subgraph {
4.22 - rank=same;
4.23 -
4.24 - Opener_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfile open\noperation"];
4.25 - Opener;
4.26 -
4.27 - Opener_note -> Opener [dir=none,style=dotted];
4.28 - }
4.29 -
4.30 - subgraph {
4.31 - rank=same;
4.32 -
4.33 - ResourceRegistry_note [shape=note,style=filled,fillcolor=gold,label="Records\nopen file\nsessions"];
4.34 - ResourceRegistry;
4.35 -
4.36 - ResourceRegistry_note -> ResourceRegistry [dir=none,style=dotted];
4.37 - }
4.38 -
4.39 - subgraph {
4.40 - rank=same;
4.41 -
4.42 - Resource_note [shape=note,style=filled,fillcolor=gold,label="Provides\nfilesystem\ncontent"];
4.43 - Resource [label="Resource\n(Pager)"];
4.44 -
4.45 - Resource_note -> Resource [dir=none,style=dotted];
4.46 - }
4.47 -
4.48 - subgraph {
4.49 - rank=same;
4.50 -
4.51 - Provider_note [shape=note,style=filled,fillcolor=gold,label="Represents\nopen file"];
4.52 - Provider;
4.53 -
4.54 - Provider_note -> Provider [dir=none,style=dotted];
4.55 - }
4.56 -
4.57 - subgraph {
4.58 - rank=same;
4.59 -
4.60 - PageMapper_note [shape=note,style=filled,fillcolor=gold,label="Provides\npopulated\nfile pages"];
4.61 - PageMapper;
4.62 -
4.63 - PageMapper_note -> PageMapper [dir=none,style=dotted];
4.64 - }
4.65 -
4.66 - ProviderRegistry [shape=record,label="<head> ProviderRegistry | ... | { file-n | provider-n } | ... "];
4.67 -
4.68 - subgraph {
4.69 - rank=same;
4.70 -
4.71 - FileOpening_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfilesystem\nfunctionality"];
4.72 - FileOpening;
4.73 -
4.74 - FileOpening_note -> FileOpening [dir=none,style=dotted];
4.75 - }
4.76 -
4.77 - subgraph {
4.78 - rank=same;
4.79 -
4.80 - Accessor_note [shape=note,style=filled,fillcolor=gold,label="Populates\nfile pages"];
4.81 - Accessor;
4.82 - Accessor_note -> Accessor [dir=none,style=dotted];
4.83 - }
4.84 -
4.85 - /* Opening a file. */
4.86 -
4.87 - Opener -> ResourceRegistry -> Resource;
4.88 - ResourceRegistry -> FileOpening;
4.89 -
4.90 - Provider -> PageMapper;
4.91 - FileOpening -> Accessor;
4.92 -
4.93 - /* Closing a file. */
4.94 -
4.95 - Resource -> Provider -> ProviderRegistry:head;
4.96 -
4.97 - /* Open file management. */
4.98 -
4.99 - ResourceRegistry -> ProviderRegistry:head;
4.100 -}
4.101 -}}}
4.102 -
4.103 -########
4.104 -
4.105 -An `Opener` requests a `Resource` from a `ResourceRegistry`, each `Resource`
4.106 -acting as a [[ServerLibrary#Pager|`Pager`]] and providing the actual access
4.107 -mechanism to file content for a particular program. Since many programs may
4.108 -access the same file simultaneously, a `Provider` object represents a file
4.109 -opened in the system, retaining a `PageMapper` that coordinates the collective
4.110 -access to the file (see the [[Paging|paging documentation]] for more
4.111 -information).
4.112 -
4.113 -A `ProviderRegistry` maintains the record of opened files, yielding a new
4.114 -`Provider` for an unopened file or an existing `Provider` for a file that is
4.115 -already open. The `ProviderRegistry` monitors the usage of files, discarding
4.116 -any `Provider` no longer in use.
4.117 -
4.118 -== Opening Files ==
4.119 -
4.120 -Opening a file involves the identification of the filesystem object involved,
4.121 -the acquisition of a `Provider` representing the file, and the creation of a
4.122 -`Resource` to deliver file content to the requesting program.
4.123 -
4.124 -######## A graph showing the opening mechanism for an already-open file
4.125 -
4.126 -{{{#!graphviz
4.127 -#format svg
4.128 -#transform notugly
4.129 -digraph opening_open {
4.130 - node [fontsize="12.0",fontname="sans-serif",shape=box];
4.131 - edge [fontsize="12.0",fontname="sans-serif"];
4.132 - rankdir=LR;
4.133 -
4.134 - subgraph {
4.135 - rank=same;
4.136 -
4.137 - Opener_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfile open\noperation"];
4.138 - Opener;
4.139 -
4.140 - Opener_note -> Opener [dir=none,style=dotted];
4.141 - }
4.142 -
4.143 - subgraph {
4.144 - rank=same;
4.145 -
4.146 - ResourceRegistry_note [shape=note,style=filled,fillcolor=gold,label="Records\nopen file\nsessions"];
4.147 - ResourceRegistry;
4.148 -
4.149 - Resource_returned [label="Resource\n(Pager)"];
4.150 - Resource_returned_note [shape=note,style=filled,fillcolor=gold,label="Provides\nfilesystem\ncontent"];
4.151 -
4.152 - ResourceRegistry_note -> ResourceRegistry [dir=none,style=dotted];
4.153 - Resource_returned -> Resource_returned_note [dir=none,style=dotted];
4.154 - }
4.155 -
4.156 - subgraph {
4.157 - rank=same;
4.158 -
4.159 - Resource [label="Resource\n(Pager)"];
4.160 -
4.161 - FileOpening_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfilesystem\nfunctionality"];
4.162 - FileOpening;
4.163 -
4.164 - FileOpening_note -> FileOpening [dir=none,style=dotted];
4.165 - }
4.166 -
4.167 - subgraph {
4.168 - rank=max;
4.169 -
4.170 - ProviderRegistry_note [shape=note,style=filled,fillcolor=gold,label="Provides\nopen files"];
4.171 - ProviderRegistry;
4.172 -
4.173 - Provider;
4.174 - Provider_note [shape=note,style=filled,fillcolor=gold,label="Represents\nopen file"];
4.175 -
4.176 - ProviderRegistry_note -> ProviderRegistry [dir=none,style=dotted];
4.177 - Provider -> Provider_note [dir=none,style=dotted];
4.178 - }
4.179 -
4.180 - /* Obtaining a resource from the registry. */
4.181 -
4.182 - Opener -> ResourceRegistry [label="get_resource"];
4.183 - ResourceRegistry -> Resource_returned [dir=none];
4.184 - Resource_returned -> Opener;
4.185 -
4.186 - /* Obtaining a provider. */
4.187 -
4.188 - ResourceRegistry -> FileOpening [label="get_fileid"];
4.189 - ResourceRegistry -> ProviderRegistry [label="get(fileid)"];
4.190 - ProviderRegistry -> Provider;
4.191 -
4.192 - /* Obtaining the resource from the provider. */
4.193 -
4.194 - ResourceRegistry -> Provider [label="make_resource"];
4.195 - Provider -> Resource [dir=none];
4.196 - Resource -> ResourceRegistry;
4.197 -}
4.198 -}}}
4.199 -
4.200 -########
4.201 -
4.202 -Where a provider does not already exist, with the file not having been opened
4.203 -already, some extra interactions occur:
4.204 -
4.205 -######## A graph showing opening mechanism details for an unopened file
4.206 -
4.207 -{{{#!graphviz
4.208 -#format svg
4.209 -#transform notugly
4.210 -digraph opening_unopened {
4.211 - node [fontsize="12.0",fontname="sans-serif",shape=box];
4.212 - edge [fontsize="12.0",fontname="sans-serif"];
4.213 - rankdir=LR;
4.214 -
4.215 - Opener;
4.216 -
4.217 - ResourceRegistry;
4.218 -
4.219 - subgraph {
4.220 - rank=same;
4.221 -
4.222 - Provider_note [shape=note,style=filled,fillcolor=gold,label="Created\nand set in\nregistry"];
4.223 - Provider;
4.224 -
4.225 - Accessor;
4.226 - PageMapper;
4.227 - PageMapper_note [shape=note,style=filled,fillcolor=gold,label="Created\nfor provider"];
4.228 -
4.229 - Provider_note -> Provider [dir=none,style=dotted];
4.230 - PageMapper -> PageMapper_note [dir=none,style=dotted];
4.231 - }
4.232 -
4.233 - subgraph {
4.234 - rank=max;
4.235 -
4.236 - ProviderRegistry_note [shape=note,style=filled,fillcolor=gold,label="Records\nopen files"];
4.237 - ProviderRegistry;
4.238 - FileOpening;
4.239 - FileOpening_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfilesystem\nfunctionality"];
4.240 -
4.241 - ProviderRegistry_note -> ProviderRegistry [dir=none,style=dotted];
4.242 - FileOpening -> FileOpening_note [dir=none,style=dotted];
4.243 - }
4.244 -
4.245 - Opener -> ResourceRegistry [dir=none,style=dashed];
4.246 -
4.247 - /* Obtaining a new provider. */
4.248 -
4.249 - ResourceRegistry -> FileOpening [label="make_accessor"];
4.250 - FileOpening -> Accessor [dir=none];
4.251 - Accessor -> PageMapper -> ResourceRegistry;
4.252 -
4.253 - ResourceRegistry -> Provider [dir=none];
4.254 - Provider -> ProviderRegistry [label="set(fileid)"];
4.255 -}
4.256 -}}}
4.257 -
4.258 -########
4.259 -
4.260 -== Notifications ==
4.261 -
4.262 -Within the filesystem access architecture, users of files may act in ways that
4.263 -may notify other users of the same file. To support such notifications, an
4.264 -interface is provided for filesystem clients to subscribe and unsubscribe to
4.265 -notifications. The notifications themselves occur when files are opened,
4.266 -modified and closed. Pipes also generate notifications when a pipe reader
4.267 -makes more space available for the writer.
4.268 -
4.269 -######## A graph showing subscription to notifications
4.270 -
4.271 -{{{#!graphviz
4.272 -#format svg
4.273 -#transform notugly
4.274 -digraph notification_subscriptions {
4.275 - node [fontsize="12.0",fontname="sans-serif",shape=box];
4.276 - edge [fontsize="12.0",fontname="sans-serif"];
4.277 - rankdir=LR;
4.278 -
4.279 - subgraph {
4.280 - rank=same;
4.281 -
4.282 - Client1 [label="Client\nprogram"];
4.283 - Client2 [label="Client\nprogram"];
4.284 - }
4.285 -
4.286 - subgraph {
4.287 - rank=same;
4.288 -
4.289 - Notifier1_note [shape=note,style=filled,fillcolor=gold,label="Created for\nnotifications"];
4.290 - Notifier1 [label="Notifier"];
4.291 - Notifier2 [label="Notifier"];
4.292 -
4.293 - Notifier1_note -> Notifier1 -> Notifier2 [dir=none,style=dotted];
4.294 - }
4.295 -
4.296 - subgraph {
4.297 - rank=same;
4.298 -
4.299 - Resource1 [label="Resource\n(Pager)"];
4.300 - Resource2 [label="Resource\n(Pager)"];
4.301 - }
4.302 -
4.303 - subgraph {
4.304 - rank=same;
4.305 -
4.306 - Notifier1_subscribe_note [shape=note,style=filled,fillcolor=gold,label="Propagated to\nprovider"];
4.307 - Notifier1_subscribe [label="Notifier"];
4.308 - Notifier2_subscribe [label="Notifier"];
4.309 -
4.310 - Notifier1_subscribe_note -> Notifier1_subscribe -> Notifier2_subscribe [dir=none,style=dotted];
4.311 - }
4.312 -
4.313 - subgraph {
4.314 - rank=same;
4.315 -
4.316 - Provider_note [shape=note,style=filled,fillcolor=gold,label="Manages file\nsubscriptions"];
4.317 - Provider [label="Provider"];
4.318 -
4.319 - Provider_note -> Provider [dir=none,style=dotted];
4.320 - }
4.321 -
4.322 - /* Subscribing. */
4.323 -
4.324 - Client1 -> Notifier1 [dir=none];
4.325 - Notifier1 -> Resource1 [label="subscribe"];
4.326 -
4.327 - Resource1 -> Notifier1_subscribe [dir=none];
4.328 - Notifier1_subscribe -> Provider [label="subscribe"];
4.329 -
4.330 - Client2 -> Notifier2 [dir=none];
4.331 - Notifier2 -> Resource2 [label="subscribe"];
4.332 -
4.333 - Resource2 -> Notifier2_subscribe [dir=none];
4.334 - Notifier2_subscribe -> Provider [label="subscribe"];
4.335 -}
4.336 -}}}
4.337 -
4.338 -########
4.339 -
4.340 -An example of a notification scenario is given below:
4.341 -
4.342 -######## A graph showing notification
4.343 -
4.344 -{{{#!graphviz
4.345 -#format svg
4.346 -#transform notugly
4.347 -digraph notifications {
4.348 - node [fontsize="12.0",fontname="sans-serif",shape=box];
4.349 - edge [fontsize="12.0",fontname="sans-serif"];
4.350 - rankdir=LR;
4.351 -
4.352 - subgraph {
4.353 - rank=same;
4.354 -
4.355 - Client1 [label="Client\nprogram"];
4.356 - Client2 [label="Client\nprogram"];
4.357 - }
4.358 -
4.359 - subgraph {
4.360 - rank=same;
4.361 -
4.362 - Notifier1_note [shape=note,style=filled,fillcolor=gold,label="Registered for\nnotifications"];
4.363 - Notifier1 [label="Notifier"];
4.364 -
4.365 - Resource2 [label="Resource\n(Pager)"];
4.366 - Resource2_note [shape=note,style=filled,fillcolor=gold,label="Generates\nnotification"];
4.367 -
4.368 - Notifier1_note -> Notifier1 [dir=none,style=dotted];
4.369 - Resource2 -> Resource2_note [dir=none,style=dotted];
4.370 - }
4.371 -
4.372 - subgraph {
4.373 - rank=same;
4.374 -
4.375 - Provider_note [shape=note,style=filled,fillcolor=gold,label="Propagates\nnotifications"];
4.376 - Provider [label="Provider"];
4.377 -
4.378 - Provider_note -> Provider [dir=none,style=dotted];
4.379 - }
4.380 -
4.381 - /* A notification scenario. */
4.382 -
4.383 - Client2 -> Resource2 [label="resize"];
4.384 - Resource2 -> Provider [label="notify_others"];
4.385 - Provider -> Notifier1 [label="notify"];
4.386 - Client1 -> Notifier1 [label="wait"];
4.387 -}
4.388 -}}}
4.389 -
4.390 -########
4.391 -
4.392 -Notifications provide the basis for blocking reading and writing operations,
4.393 -with pipe endpoints depending on such blocking for efficient use of pipes. The
4.394 -interactions involved when transferring data through pipes are depicted below.
4.395 -
4.396 -######## A graph showing notifications employed by pipe endpoints
4.397 -
4.398 -{{{#!graphviz
4.399 -#format svg
4.400 -#transform notugly
4.401 -digraph pipe_notifications {
4.402 - node [fontsize="12.0",fontname="sans-serif",shape=box];
4.403 - edge [fontsize="12.0",fontname="sans-serif"];
4.404 - rankdir=LR;
4.405 -
4.406 - subgraph {
4.407 - rank=min;
4.408 -
4.409 - Client1_note [shape=note,style=filled,fillcolor=gold,label="Fill pipe\nthen request\nmore space"];
4.410 - Client1 [label="Client\nprogram\n(writer)"];
4.411 - Client1_wait_note [shape=note,style=filled,fillcolor=gold,label="Waiting after\nfilling pipe"];
4.412 - Client1_wait [label="Client\nprogram\n(writer)"];
4.413 -
4.414 - Client1_note -> Client1 [dir=none,style=dotted];
4.415 - Client1_wait_note -> Client1_wait [dir=none,style=dotted];
4.416 -
4.417 - Client1 -> Client1_wait_note [dir=none,style=invis];
4.418 - }
4.419 -
4.420 - subgraph {
4.421 - rank=max;
4.422 -
4.423 - Client2_note [shape=note,style=filled,fillcolor=gold,label="Waiting for\nmore content\nbefore reading"];
4.424 - Client2 [label="Client\nprogram\n(reader)"];
4.425 - Client2_read_note [shape=note,style=filled,fillcolor=gold,label="Empty pipe\nthen request\nmore content"];
4.426 - Client2_read [label="Client\nprogram\n(reader)"];
4.427 -
4.428 - Client2_note -> Client2 [dir=none,style=dotted];
4.429 - Client2_read_note -> Client2_read [dir=none,style=dotted];
4.430 - }
4.431 -
4.432 - subgraph {
4.433 - rank=same;
4.434 -
4.435 - Notifier1 [label="Notifier"];
4.436 - Resource1 [label="Resource\n(PipePager)"];
4.437 - }
4.438 -
4.439 - subgraph {
4.440 - rank=same;
4.441 -
4.442 - Notifier2 [label="Notifier"];
4.443 - Resource2 [label="Resource\n(PipePager)"];
4.444 - }
4.445 -
4.446 - subgraph {
4.447 - rank=same;
4.448 -
4.449 - PipePaging [label="Provider\n(PipePaging)"];
4.450 - PipePaging_space [label="Provider\n(PipePaging)"];
4.451 - }
4.452 -
4.453 - /* Making content available. */
4.454 -
4.455 - Client1 -> Resource1 [label="next_region"];
4.456 - Resource1 -> PipePaging [label="add_region"];
4.457 - PipePaging -> Notifier2 [label="notify"];
4.458 - Client2 -> Notifier2 [label="wait"];
4.459 -
4.460 - /* Making space available. */
4.461 -
4.462 - Client2_read -> Resource2 [label="next_region"];
4.463 - Resource2 -> PipePaging_space [label="next_region"];
4.464 - PipePaging_space -> Notifier1 [label="notify"];
4.465 - Client1_wait -> Notifier1 [label="wait"];
4.466 -}
4.467 -}}}
4.468 -
4.469 -########
4.470 -
4.471 -== Closing Files ==
4.472 -
4.473 -Files are closed when client programs release their references to the resource
4.474 -capabilities used to access files. The mechanism by which this is done
4.475 -involves the registration of an IRQ object that is bound to the same thread as
4.476 -the one used by resources to service file access requests. This IRQ object is
4.477 -associated with the IPC gate through which such requests occur, and the IRQ
4.478 -object is configured to deliver an interrupt message when the final reference
4.479 -to the IPC gate has been released.
4.480 -
4.481 -When a client program terminates, its references to capabilities should be
4.482 -released, and this should cause a reference counter associated with the IPC
4.483 -gate to decrement. Upon the loss of the final reference and the delivery of
4.484 -the interrupt, the server framework will call a `close` method on the
4.485 -`Resource` object concerned, this implementing the
4.486 -[[ServerLibrary#Accountable|`Accountable`]] interface.
4.487 -
4.488 -######## A graph showing the closing mechanism
4.489 -
4.490 -{{{#!graphviz
4.491 -#format svg
4.492 -#transform notugly
4.493 -digraph closing {
4.494 - node [fontsize="12.0",fontname="sans-serif",shape=box];
4.495 - edge [fontsize="12.0",fontname="sans-serif"];
4.496 - rankdir=LR;
4.497 -
4.498 - Client [label="Client\nprogram"];
4.499 -
4.500 - subgraph {
4.501 - rank=same;
4.502 -
4.503 - Gate_note [shape=note,style=filled,fillcolor=gold,label="Actual\nendpoint"];
4.504 - Gate [label="IPC gate",shape="octagon"];
4.505 - IRQ [shape="triangle"];
4.506 - ResourceServer;
4.507 - ResourceServer_note [shape=note,style=filled,fillcolor=gold,label="Handles\nrequests"];
4.508 -
4.509 - Gate_note -> Gate [dir=none,style=dotted];
4.510 - ResourceServer -> ResourceServer_note [dir=none,style=dotted];
4.511 - }
4.512 -
4.513 - Resource [label="Resource\n(Pager)"];
4.514 -
4.515 - Provider;
4.516 -
4.517 - ProviderRegistry;
4.518 -
4.519 - Client -> Gate [style=dashed,label="(release)"];
4.520 - Gate -> IRQ -> ResourceServer;
4.521 - ResourceServer -> Resource [label="close"];
4.522 - Resource -> Provider [label="notify_others\nunsubscribe"];
4.523 - Resource -> ProviderRegistry [label="detach"];
4.524 -}
4.525 -}}}
4.526 -
4.527 -########
4.528 -
4.529 -As a consequence of closing a file, an `unsubscribe` operation performed on
4.530 -the `Provider` should cause any `Notifier` objects associated with the
4.531 -`Resource` object to be released. Meanwhile, the `ResourceServer` will discard
4.532 -the `Resource` object before the server thread terminates.
4.533 -
4.534 -== Removing Files ==
4.535 -
4.536 -Unix filesystem semantics typically allow a file to be "unlinked" while still
4.537 -being accessed by a program, with accesses still being directed to the file,
4.538 -but with the file being removed from a directory and potentially being
4.539 -replaced by another file. To support this, a mechanism is provided to defer
4.540 -any removal of an open file.
4.541 -
4.542 -######## A graph showing the removal mechanism
4.543 -
4.544 -{{{#!graphviz
4.545 -#format svg
4.546 -#transform notugly
4.547 -digraph removing {
4.548 - node [fontsize="12.0",fontname="sans-serif",shape=box];
4.549 - edge [fontsize="12.0",fontname="sans-serif"];
4.550 - rankdir=LR;
4.551 -
4.552 - subgraph {
4.553 - rank=same;
4.554 -
4.555 - Client1_note [shape=note,style=filled,fillcolor=gold,label="Removing\nopen file"];
4.556 - Client1 [label="Client\nprogram"];
4.557 - Client2 [label="Client\nprogram"];
4.558 - Client2_note [shape=note,style=filled,fillcolor=gold,label="Closes\nopen file"];
4.559 -
4.560 - Client1_note -> Client1 [dir=none,style=dotted];
4.561 - Client2 -> Client2_note [dir=none,style=dotted];
4.562 -
4.563 - Client1 -> Client2 [dir=none,style=invis];
4.564 - }
4.565 -
4.566 - subgraph {
4.567 - rank=same;
4.568 -
4.569 - Resource [label="Resource\n(Pager)"];
4.570 - Opener;
4.571 - }
4.572 -
4.573 - subgraph {
4.574 - rank=same;
4.575 -
4.576 - Provider1 [label="Provider"];
4.577 - Provider1_note [shape=note,style=filled,fillcolor=gold,label="Maintains\nremoval\nstate"];
4.578 - Provider2 [label="Provider"];
4.579 -
4.580 - Provider1 -> Provider1_note -> Provider2 [dir=none,style=dotted];
4.581 - }
4.582 -
4.583 - ProviderRegistry1 [label="ProviderRegistry"];
4.584 - ProviderRegistry2 [label="ProviderRegistry"];
4.585 -
4.586 - subgraph {
4.587 - rank=same;
4.588 -
4.589 - FileOpening;
4.590 - Accessor_note [shape=note,style=filled,fillcolor=gold,label="Performing\nfilesystem\noperations"];
4.591 - Accessor;
4.592 -
4.593 - FileOpening -> Accessor_note -> Accessor [dir=none,style=dotted];
4.594 - }
4.595 -
4.596 - /* Removing the file while it remains open. */
4.597 -
4.598 - Client1 -> Opener [label="remove\n(via context)"];
4.599 - Opener -> ResourceRegistry [label="remove_provider"];
4.600 - ResourceRegistry -> FileOpening [label="get_fileid\nunlink_object"];
4.601 - ResourceRegistry -> ProviderRegistry1 [label="get(fileid)"];
4.602 - ResourceRegistry -> Provider1 [label="remove_pending"];
4.603 -
4.604 - /* File closure and deferred removal. */
4.605 -
4.606 - Client2 -> Resource [label="close"];
4.607 - Resource -> Provider2 [label="notify_others\nunsubscribe"];
4.608 - Resource -> ProviderRegistry2 [label="detach"];
4.609 - ProviderRegistry2 -> Provider2 [label="remove"];
4.610 - Provider2 -> Accessor [label="remove"];
4.611 -}
4.612 -}}}
4.613 -
4.614 -########
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/docs/wiki/Filesystem_Access Fri Aug 12 16:41:06 2022 +0200
5.3 @@ -0,0 +1,611 @@
5.4 += Filesystem Access =
5.5 +
5.6 +Within the [[ServerLibrary|filesystem server library]], a number of different
5.7 +abstractions and mechanisms are employed to provide access to filesystem
5.8 +objects. An overview of these abstractions is presented below.
5.9 +
5.10 +######## A graph showing the relationships between filesystem access
5.11 +######## components
5.12 +
5.13 +{{{#!graphviz
5.14 +#format svg
5.15 +#transform notugly
5.16 +digraph components {
5.17 + node [fontsize="12.0",fontname="sans-serif",shape=box];
5.18 + edge [fontsize="12.0",fontname="sans-serif"];
5.19 + rankdir=LR;
5.20 +
5.21 + subgraph {
5.22 + rank=same;
5.23 +
5.24 + Opener_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfile open\noperation"];
5.25 + Opener;
5.26 +
5.27 + Opener_note -> Opener [dir=none,style=dotted];
5.28 + }
5.29 +
5.30 + subgraph {
5.31 + rank=same;
5.32 +
5.33 + ResourceRegistry_note [shape=note,style=filled,fillcolor=gold,label="Records\nopen file\nsessions"];
5.34 + ResourceRegistry;
5.35 +
5.36 + ResourceRegistry_note -> ResourceRegistry [dir=none,style=dotted];
5.37 + }
5.38 +
5.39 + subgraph {
5.40 + rank=same;
5.41 +
5.42 + Resource_note [shape=note,style=filled,fillcolor=gold,label="Provides\nfilesystem\ncontent"];
5.43 + Resource [label="Resource\n(Pager)"];
5.44 +
5.45 + Resource_note -> Resource [dir=none,style=dotted];
5.46 + }
5.47 +
5.48 + subgraph {
5.49 + rank=same;
5.50 +
5.51 + Provider_note [shape=note,style=filled,fillcolor=gold,label="Represents\nopen file"];
5.52 + Provider;
5.53 +
5.54 + Provider_note -> Provider [dir=none,style=dotted];
5.55 + }
5.56 +
5.57 + subgraph {
5.58 + rank=same;
5.59 +
5.60 + PageMapper_note [shape=note,style=filled,fillcolor=gold,label="Provides\npopulated\nfile pages"];
5.61 + PageMapper;
5.62 +
5.63 + PageMapper_note -> PageMapper [dir=none,style=dotted];
5.64 + }
5.65 +
5.66 + ProviderRegistry [shape=record,label="<head> ProviderRegistry | ... | { file-n | provider-n } | ... "];
5.67 +
5.68 + subgraph {
5.69 + rank=same;
5.70 +
5.71 + FileOpening_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfilesystem\nfunctionality"];
5.72 + FileOpening;
5.73 +
5.74 + FileOpening_note -> FileOpening [dir=none,style=dotted];
5.75 + }
5.76 +
5.77 + subgraph {
5.78 + rank=same;
5.79 +
5.80 + Accessor_note [shape=note,style=filled,fillcolor=gold,label="Populates\nfile pages"];
5.81 + Accessor;
5.82 + Accessor_note -> Accessor [dir=none,style=dotted];
5.83 + }
5.84 +
5.85 + /* Opening a file. */
5.86 +
5.87 + Opener -> ResourceRegistry -> Resource;
5.88 + ResourceRegistry -> FileOpening;
5.89 +
5.90 + Provider -> PageMapper;
5.91 + FileOpening -> Accessor;
5.92 +
5.93 + /* Closing a file. */
5.94 +
5.95 + Resource -> Provider -> ProviderRegistry:head;
5.96 +
5.97 + /* Open file management. */
5.98 +
5.99 + ResourceRegistry -> ProviderRegistry:head;
5.100 +}
5.101 +}}}
5.102 +
5.103 +########
5.104 +
5.105 +An `Opener` requests a `Resource` from a `ResourceRegistry`, each `Resource`
5.106 +acting as a [[ServerLibrary#Pager|`Pager`]] and providing the actual access
5.107 +mechanism to file content for a particular program. Since many programs may
5.108 +access the same file simultaneously, a `Provider` object represents a file
5.109 +opened in the system, retaining a `PageMapper` that coordinates the collective
5.110 +access to the file (see the [[Paging|paging documentation]] for more
5.111 +information).
5.112 +
5.113 +A `ProviderRegistry` maintains the record of opened files, yielding a new
5.114 +`Provider` for an unopened file or an existing `Provider` for a file that is
5.115 +already open. The `ProviderRegistry` monitors the usage of files, discarding
5.116 +any `Provider` no longer in use.
5.117 +
5.118 +== Opening Files ==
5.119 +
5.120 +Opening a file involves the identification of the filesystem object involved,
5.121 +the acquisition of a `Provider` representing the file, and the creation of a
5.122 +`Resource` to deliver file content to the requesting program.
5.123 +
5.124 +######## A graph showing the opening mechanism for an already-open file
5.125 +
5.126 +{{{#!graphviz
5.127 +#format svg
5.128 +#transform notugly
5.129 +digraph opening_open {
5.130 + node [fontsize="12.0",fontname="sans-serif",shape=box];
5.131 + edge [fontsize="12.0",fontname="sans-serif"];
5.132 + rankdir=LR;
5.133 +
5.134 + subgraph {
5.135 + rank=same;
5.136 +
5.137 + Opener_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfile open\noperation"];
5.138 + Opener;
5.139 +
5.140 + Opener_note -> Opener [dir=none,style=dotted];
5.141 + }
5.142 +
5.143 + subgraph {
5.144 + rank=same;
5.145 +
5.146 + ResourceRegistry_note [shape=note,style=filled,fillcolor=gold,label="Records\nopen file\nsessions"];
5.147 + ResourceRegistry;
5.148 +
5.149 + Resource_returned [label="Resource\n(Pager)"];
5.150 + Resource_returned_note [shape=note,style=filled,fillcolor=gold,label="Provides\nfilesystem\ncontent"];
5.151 +
5.152 + ResourceRegistry_note -> ResourceRegistry [dir=none,style=dotted];
5.153 + Resource_returned -> Resource_returned_note [dir=none,style=dotted];
5.154 + }
5.155 +
5.156 + subgraph {
5.157 + rank=same;
5.158 +
5.159 + Resource [label="Resource\n(Pager)"];
5.160 +
5.161 + FileOpening_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfilesystem\nfunctionality"];
5.162 + FileOpening;
5.163 +
5.164 + FileOpening_note -> FileOpening [dir=none,style=dotted];
5.165 + }
5.166 +
5.167 + subgraph {
5.168 + rank=max;
5.169 +
5.170 + ProviderRegistry_note [shape=note,style=filled,fillcolor=gold,label="Provides\nopen files"];
5.171 + ProviderRegistry;
5.172 +
5.173 + Provider;
5.174 + Provider_note [shape=note,style=filled,fillcolor=gold,label="Represents\nopen file"];
5.175 +
5.176 + ProviderRegistry_note -> ProviderRegistry [dir=none,style=dotted];
5.177 + Provider -> Provider_note [dir=none,style=dotted];
5.178 + }
5.179 +
5.180 + /* Obtaining a resource from the registry. */
5.181 +
5.182 + Opener -> ResourceRegistry [label="get_resource"];
5.183 + ResourceRegistry -> Resource_returned [dir=none];
5.184 + Resource_returned -> Opener;
5.185 +
5.186 + /* Obtaining a provider. */
5.187 +
5.188 + ResourceRegistry -> FileOpening [label="get_fileid"];
5.189 + ResourceRegistry -> ProviderRegistry [label="get(fileid)"];
5.190 + ProviderRegistry -> Provider;
5.191 +
5.192 + /* Obtaining the resource from the provider. */
5.193 +
5.194 + ResourceRegistry -> Provider [label="make_resource"];
5.195 + Provider -> Resource [dir=none];
5.196 + Resource -> ResourceRegistry;
5.197 +}
5.198 +}}}
5.199 +
5.200 +########
5.201 +
5.202 +Where a provider does not already exist, with the file not having been opened
5.203 +already, some extra interactions occur:
5.204 +
5.205 +######## A graph showing opening mechanism details for an unopened file
5.206 +
5.207 +{{{#!graphviz
5.208 +#format svg
5.209 +#transform notugly
5.210 +digraph opening_unopened {
5.211 + node [fontsize="12.0",fontname="sans-serif",shape=box];
5.212 + edge [fontsize="12.0",fontname="sans-serif"];
5.213 + rankdir=LR;
5.214 +
5.215 + Opener;
5.216 +
5.217 + ResourceRegistry;
5.218 +
5.219 + subgraph {
5.220 + rank=same;
5.221 +
5.222 + Provider_note [shape=note,style=filled,fillcolor=gold,label="Created\nand set in\nregistry"];
5.223 + Provider;
5.224 +
5.225 + Accessor;
5.226 + PageMapper;
5.227 + PageMapper_note [shape=note,style=filled,fillcolor=gold,label="Created\nfor provider"];
5.228 +
5.229 + Provider_note -> Provider [dir=none,style=dotted];
5.230 + PageMapper -> PageMapper_note [dir=none,style=dotted];
5.231 + }
5.232 +
5.233 + subgraph {
5.234 + rank=max;
5.235 +
5.236 + ProviderRegistry_note [shape=note,style=filled,fillcolor=gold,label="Records\nopen files"];
5.237 + ProviderRegistry;
5.238 + FileOpening;
5.239 + FileOpening_note [shape=note,style=filled,fillcolor=gold,label="Exposes\nfilesystem\nfunctionality"];
5.240 +
5.241 + ProviderRegistry_note -> ProviderRegistry [dir=none,style=dotted];
5.242 + FileOpening -> FileOpening_note [dir=none,style=dotted];
5.243 + }
5.244 +
5.245 + Opener -> ResourceRegistry [dir=none,style=dashed];
5.246 +
5.247 + /* Obtaining a new provider. */
5.248 +
5.249 + ResourceRegistry -> FileOpening [label="make_accessor"];
5.250 + FileOpening -> Accessor [dir=none];
5.251 + Accessor -> PageMapper -> ResourceRegistry;
5.252 +
5.253 + ResourceRegistry -> Provider [dir=none];
5.254 + Provider -> ProviderRegistry [label="set(fileid)"];
5.255 +}
5.256 +}}}
5.257 +
5.258 +########
5.259 +
5.260 +== Notifications ==
5.261 +
5.262 +Within the filesystem access architecture, users of files may act in ways that
5.263 +may notify other users of the same file. To support such notifications, an
5.264 +interface is provided for filesystem clients to subscribe and unsubscribe to
5.265 +notifications. The notifications themselves occur when files are opened,
5.266 +modified and closed. Pipes also generate notifications when a pipe reader
5.267 +makes more space available for the writer.
5.268 +
5.269 +######## A graph showing subscription to notifications
5.270 +
5.271 +{{{#!graphviz
5.272 +#format svg
5.273 +#transform notugly
5.274 +digraph notification_subscriptions {
5.275 + node [fontsize="12.0",fontname="sans-serif",shape=box];
5.276 + edge [fontsize="12.0",fontname="sans-serif"];
5.277 + rankdir=LR;
5.278 +
5.279 + subgraph {
5.280 + rank=same;
5.281 +
5.282 + Client1 [label="Client\nprogram"];
5.283 + Client2 [label="Client\nprogram"];
5.284 + }
5.285 +
5.286 + subgraph {
5.287 + rank=same;
5.288 +
5.289 + Notifier1_note [shape=note,style=filled,fillcolor=gold,label="Created for\nnotifications"];
5.290 + Notifier1 [label="Notifier"];
5.291 + Notifier2 [label="Notifier"];
5.292 +
5.293 + Notifier1_note -> Notifier1 -> Notifier2 [dir=none,style=dotted];
5.294 + }
5.295 +
5.296 + subgraph {
5.297 + rank=same;
5.298 +
5.299 + Resource1 [label="Resource\n(Pager)"];
5.300 + Resource2 [label="Resource\n(Pager)"];
5.301 + }
5.302 +
5.303 + subgraph {
5.304 + rank=same;
5.305 +
5.306 + Notifier1_subscribe_note [shape=note,style=filled,fillcolor=gold,label="Propagated to\nprovider"];
5.307 + Notifier1_subscribe [label="Notifier"];
5.308 + Notifier2_subscribe [label="Notifier"];
5.309 +
5.310 + Notifier1_subscribe_note -> Notifier1_subscribe -> Notifier2_subscribe [dir=none,style=dotted];
5.311 + }
5.312 +
5.313 + subgraph {
5.314 + rank=same;
5.315 +
5.316 + Provider_note [shape=note,style=filled,fillcolor=gold,label="Manages file\nsubscriptions"];
5.317 + Provider [label="Provider"];
5.318 +
5.319 + Provider_note -> Provider [dir=none,style=dotted];
5.320 + }
5.321 +
5.322 + /* Subscribing. */
5.323 +
5.324 + Client1 -> Notifier1 [dir=none];
5.325 + Notifier1 -> Resource1 [label="subscribe"];
5.326 +
5.327 + Resource1 -> Notifier1_subscribe [dir=none];
5.328 + Notifier1_subscribe -> Provider [label="subscribe"];
5.329 +
5.330 + Client2 -> Notifier2 [dir=none];
5.331 + Notifier2 -> Resource2 [label="subscribe"];
5.332 +
5.333 + Resource2 -> Notifier2_subscribe [dir=none];
5.334 + Notifier2_subscribe -> Provider [label="subscribe"];
5.335 +}
5.336 +}}}
5.337 +
5.338 +########
5.339 +
5.340 +An example of a notification scenario is given below:
5.341 +
5.342 +######## A graph showing notification
5.343 +
5.344 +{{{#!graphviz
5.345 +#format svg
5.346 +#transform notugly
5.347 +digraph notifications {
5.348 + node [fontsize="12.0",fontname="sans-serif",shape=box];
5.349 + edge [fontsize="12.0",fontname="sans-serif"];
5.350 + rankdir=LR;
5.351 +
5.352 + subgraph {
5.353 + rank=same;
5.354 +
5.355 + Client1 [label="Client\nprogram"];
5.356 + Client2 [label="Client\nprogram"];
5.357 + }
5.358 +
5.359 + subgraph {
5.360 + rank=same;
5.361 +
5.362 + Notifier1_note [shape=note,style=filled,fillcolor=gold,label="Registered for\nnotifications"];
5.363 + Notifier1 [label="Notifier"];
5.364 +
5.365 + Resource2 [label="Resource\n(Pager)"];
5.366 + Resource2_note [shape=note,style=filled,fillcolor=gold,label="Generates\nnotification"];
5.367 +
5.368 + Notifier1_note -> Notifier1 [dir=none,style=dotted];
5.369 + Resource2 -> Resource2_note [dir=none,style=dotted];
5.370 + }
5.371 +
5.372 + subgraph {
5.373 + rank=same;
5.374 +
5.375 + Provider_note [shape=note,style=filled,fillcolor=gold,label="Propagates\nnotifications"];
5.376 + Provider [label="Provider"];
5.377 +
5.378 + Provider_note -> Provider [dir=none,style=dotted];
5.379 + }
5.380 +
5.381 + /* A notification scenario. */
5.382 +
5.383 + Client2 -> Resource2 [label="resize"];
5.384 + Resource2 -> Provider [label="notify_others"];
5.385 + Provider -> Notifier1 [label="notify"];
5.386 + Client1 -> Notifier1 [label="wait"];
5.387 +}
5.388 +}}}
5.389 +
5.390 +########
5.391 +
5.392 +Notifications provide the basis for blocking reading and writing operations,
5.393 +with pipe endpoints depending on such blocking for efficient use of pipes. The
5.394 +interactions involved when transferring data through pipes are depicted below.
5.395 +
5.396 +######## A graph showing notifications employed by pipe endpoints
5.397 +
5.398 +{{{#!graphviz
5.399 +#format svg
5.400 +#transform notugly
5.401 +digraph pipe_notifications {
5.402 + node [fontsize="12.0",fontname="sans-serif",shape=box];
5.403 + edge [fontsize="12.0",fontname="sans-serif"];
5.404 + rankdir=LR;
5.405 +
5.406 + subgraph {
5.407 + rank=min;
5.408 +
5.409 + Client1_note [shape=note,style=filled,fillcolor=gold,label="Fill pipe\nthen request\nmore space"];
5.410 + Client1 [label="Client\nprogram\n(writer)"];
5.411 + Client1_wait_note [shape=note,style=filled,fillcolor=gold,label="Waiting after\nfilling pipe"];
5.412 + Client1_wait [label="Client\nprogram\n(writer)"];
5.413 +
5.414 + Client1_note -> Client1 [dir=none,style=dotted];
5.415 + Client1_wait_note -> Client1_wait [dir=none,style=dotted];
5.416 +
5.417 + Client1 -> Client1_wait_note [dir=none,style=invis];
5.418 + }
5.419 +
5.420 + subgraph {
5.421 + rank=max;
5.422 +
5.423 + Client2_note [shape=note,style=filled,fillcolor=gold,label="Waiting for\nmore content\nbefore reading"];
5.424 + Client2 [label="Client\nprogram\n(reader)"];
5.425 + Client2_read_note [shape=note,style=filled,fillcolor=gold,label="Empty pipe\nthen request\nmore content"];
5.426 + Client2_read [label="Client\nprogram\n(reader)"];
5.427 +
5.428 + Client2_note -> Client2 [dir=none,style=dotted];
5.429 + Client2_read_note -> Client2_read [dir=none,style=dotted];
5.430 + }
5.431 +
5.432 + subgraph {
5.433 + rank=same;
5.434 +
5.435 + Notifier1 [label="Notifier"];
5.436 + Resource1 [label="Resource\n(PipePager)"];
5.437 + }
5.438 +
5.439 + subgraph {
5.440 + rank=same;
5.441 +
5.442 + Notifier2 [label="Notifier"];
5.443 + Resource2 [label="Resource\n(PipePager)"];
5.444 + }
5.445 +
5.446 + subgraph {
5.447 + rank=same;
5.448 +
5.449 + PipePaging [label="Provider\n(PipePaging)"];
5.450 + PipePaging_space [label="Provider\n(PipePaging)"];
5.451 + }
5.452 +
5.453 + /* Making content available. */
5.454 +
5.455 + Client1 -> Resource1 [label="next_region"];
5.456 + Resource1 -> PipePaging [label="add_region"];
5.457 + PipePaging -> Notifier2 [label="notify"];
5.458 + Client2 -> Notifier2 [label="wait"];
5.459 +
5.460 + /* Making space available. */
5.461 +
5.462 + Client2_read -> Resource2 [label="next_region"];
5.463 + Resource2 -> PipePaging_space [label="next_region"];
5.464 + PipePaging_space -> Notifier1 [label="notify"];
5.465 + Client1_wait -> Notifier1 [label="wait"];
5.466 +}
5.467 +}}}
5.468 +
5.469 +########
5.470 +
5.471 +== Closing Files ==
5.472 +
5.473 +Files are closed when client programs release their references to the resource
5.474 +capabilities used to access files. The mechanism by which this is done
5.475 +involves the registration of an IRQ object that is bound to the same thread as
5.476 +the one used by resources to service file access requests. This IRQ object is
5.477 +associated with the IPC gate through which such requests occur, and the IRQ
5.478 +object is configured to deliver an interrupt message when the final reference
5.479 +to the IPC gate has been released.
5.480 +
5.481 +When a client program terminates, its references to capabilities should be
5.482 +released, and this should cause a reference counter associated with the IPC
5.483 +gate to decrement. Upon the loss of the final reference and the delivery of
5.484 +the interrupt, the server framework will call a `close` method on the
5.485 +`Resource` object concerned, this implementing the
5.486 +[[ServerLibrary#Accountable|`Accountable`]] interface.
5.487 +
5.488 +######## A graph showing the closing mechanism
5.489 +
5.490 +{{{#!graphviz
5.491 +#format svg
5.492 +#transform notugly
5.493 +digraph closing {
5.494 + node [fontsize="12.0",fontname="sans-serif",shape=box];
5.495 + edge [fontsize="12.0",fontname="sans-serif"];
5.496 + rankdir=LR;
5.497 +
5.498 + Client [label="Client\nprogram"];
5.499 +
5.500 + subgraph {
5.501 + rank=same;
5.502 +
5.503 + Gate_note [shape=note,style=filled,fillcolor=gold,label="Actual\nendpoint"];
5.504 + Gate [label="IPC gate",shape="octagon"];
5.505 + IRQ [shape="triangle"];
5.506 + ResourceServer;
5.507 + ResourceServer_note [shape=note,style=filled,fillcolor=gold,label="Handles\nrequests"];
5.508 +
5.509 + Gate_note -> Gate [dir=none,style=dotted];
5.510 + ResourceServer -> ResourceServer_note [dir=none,style=dotted];
5.511 + }
5.512 +
5.513 + Resource [label="Resource\n(Pager)"];
5.514 +
5.515 + Provider;
5.516 +
5.517 + ProviderRegistry;
5.518 +
5.519 + Client -> Gate [style=dashed,label="(release)"];
5.520 + Gate -> IRQ -> ResourceServer;
5.521 + ResourceServer -> Resource [label="close"];
5.522 + Resource -> Provider [label="notify_others\nunsubscribe"];
5.523 + Resource -> ProviderRegistry [label="detach"];
5.524 +}
5.525 +}}}
5.526 +
5.527 +########
5.528 +
5.529 +As a consequence of closing a file, an `unsubscribe` operation performed on
5.530 +the `Provider` should cause any `Notifier` objects associated with the
5.531 +`Resource` object to be released. Meanwhile, the `ResourceServer` will discard
5.532 +the `Resource` object before the server thread terminates.
5.533 +
5.534 +== Removing Files ==
5.535 +
5.536 +Unix filesystem semantics typically allow a file to be "unlinked" while still
5.537 +being accessed by a program, with accesses still being directed to the file,
5.538 +but with the file being removed from a directory and potentially being
5.539 +replaced by another file. To support this, a mechanism is provided to defer
5.540 +any removal of an open file.
5.541 +
5.542 +######## A graph showing the removal mechanism
5.543 +
5.544 +{{{#!graphviz
5.545 +#format svg
5.546 +#transform notugly
5.547 +digraph removing {
5.548 + node [fontsize="12.0",fontname="sans-serif",shape=box];
5.549 + edge [fontsize="12.0",fontname="sans-serif"];
5.550 + rankdir=LR;
5.551 +
5.552 + subgraph {
5.553 + rank=same;
5.554 +
5.555 + Client1_note [shape=note,style=filled,fillcolor=gold,label="Removing\nopen file"];
5.556 + Client1 [label="Client\nprogram"];
5.557 + Client2 [label="Client\nprogram"];
5.558 + Client2_note [shape=note,style=filled,fillcolor=gold,label="Closes\nopen file"];
5.559 +
5.560 + Client1_note -> Client1 [dir=none,style=dotted];
5.561 + Client2 -> Client2_note [dir=none,style=dotted];
5.562 +
5.563 + Client1 -> Client2 [dir=none,style=invis];
5.564 + }
5.565 +
5.566 + subgraph {
5.567 + rank=same;
5.568 +
5.569 + Resource [label="Resource\n(Pager)"];
5.570 + Opener;
5.571 + }
5.572 +
5.573 + subgraph {
5.574 + rank=same;
5.575 +
5.576 + Provider1 [label="Provider"];
5.577 + Provider1_note [shape=note,style=filled,fillcolor=gold,label="Maintains\nremoval\nstate"];
5.578 + Provider2 [label="Provider"];
5.579 +
5.580 + Provider1 -> Provider1_note -> Provider2 [dir=none,style=dotted];
5.581 + }
5.582 +
5.583 + ProviderRegistry1 [label="ProviderRegistry"];
5.584 + ProviderRegistry2 [label="ProviderRegistry"];
5.585 +
5.586 + subgraph {
5.587 + rank=same;
5.588 +
5.589 + FileOpening;
5.590 + Accessor_note [shape=note,style=filled,fillcolor=gold,label="Performing\nfilesystem\noperations"];
5.591 + Accessor;
5.592 +
5.593 + FileOpening -> Accessor_note -> Accessor [dir=none,style=dotted];
5.594 + }
5.595 +
5.596 + /* Removing the file while it remains open. */
5.597 +
5.598 + Client1 -> Opener [label="remove\n(via context)"];
5.599 + Opener -> ResourceRegistry [label="remove_provider"];
5.600 + ResourceRegistry -> FileOpening [label="get_fileid\nunlink_object"];
5.601 + ResourceRegistry -> ProviderRegistry1 [label="get(fileid)"];
5.602 + ResourceRegistry -> Provider1 [label="remove_pending"];
5.603 +
5.604 + /* File closure and deferred removal. */
5.605 +
5.606 + Client2 -> Resource [label="close"];
5.607 + Resource -> Provider2 [label="notify_others\nunsubscribe"];
5.608 + Resource -> ProviderRegistry2 [label="detach"];
5.609 + ProviderRegistry2 -> Provider2 [label="remove"];
5.610 + Provider2 -> Accessor [label="remove"];
5.611 +}
5.612 +}}}
5.613 +
5.614 +########
6.1 --- a/docs/wiki/Filesystems Wed Aug 10 23:58:38 2022 +0200
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,19 +0,0 @@
6.4 -= Filesystems =
6.5 -
6.6 -This distribution aims to provide components and libraries to implement and
6.7 -deliver filesystem access in the L4 Runtime Environment.
6.8 -
6.9 -== Topics ==
6.10 -
6.11 - * [[ClientLibrary|Client Library]] - convenience functions and structures to
6.12 - access filesystem objects
6.13 - * [[Components]] - server objects exposed at the system level that support
6.14 - filesystem access
6.15 - * [[FilesystemAccess|Filesystem Access]] - mechanisms within filesystem
6.16 - servers to manage filesystem resources and content
6.17 - * [[Paging]] - the mechanism by which filesystem content is provided for use
6.18 - by client programs
6.19 - * [[ProgramLoading|Program Loading]] - the mechanism by which programs are loaded
6.20 - * [[ServerLibrary|Server Library]] - abstractions to expose and manage access
6.21 - to filesystem objects
6.22 - * [[Users]]
7.1 --- a/docs/wiki/ProgramLoading Wed Aug 10 23:58:38 2022 +0200
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,236 +0,0 @@
7.4 -= Program Loading =
7.5 -
7.6 -The provision of [[Paging|paging]] of file content leads to the possibility of
7.7 -demand paging for programs, enabling them to be loaded into memory dynamically
7.8 -and to have only the active portions of those programs resident. To achieve
7.9 -this, programs must be appropriately initialised in new tasks, with a page
7.10 -fault handler configured to provide program file content whenever a region of
7.11 -the program payload is encountered that is not currently resident in memory.
7.12 -
7.13 -== Internal Page Fault Handlers ==
7.14 -
7.15 -When satisfying page faults for a task, one approach involves situating the
7.16 -page fault handler within the task itself, this managing the available memory
7.17 -regions and employing receive windows when requesting memory pages.
7.18 -
7.19 -The general arrangement involving such internal page fault handlers for a
7.20 -program in a task is as follows:
7.21 -
7.22 -######## A graph showing the internal paging mechanism
7.23 -
7.24 -{{{#!graphviz
7.25 -#format svg
7.26 -#transform notugly
7.27 -digraph internal_paging {
7.28 - node [fontsize="12.0",fontname="sans-serif",shape=box];
7.29 - edge [fontsize="12.0",fontname="sans-serif"];
7.30 - rankdir=LR;
7.31 -
7.32 - TaskMemory [shape=record,label="Task Memory |<s> stack | ... |<d> data | ... |<c> code"];
7.33 -
7.34 - subgraph {
7.35 - rank=same;
7.36 -
7.37 - InternalPager;
7.38 - InternalPager_note [shape=note,style=filled,fillcolor=gold,label="Resides in\nsame task and\ndefines scope of\nfault resolution"];
7.39 -
7.40 - InternalPager -> InternalPager_note [dir=none,style=dotted];
7.41 - }
7.42 -
7.43 - subgraph {
7.44 - rank=same;
7.45 -
7.46 - Regions [shape=record,label="Regions |
7.47 - {<s> stack |<sd> stack-dataspace } |
7.48 - {<d> data | <dd> data-dataspace } |
7.49 - {<c> code |<cd> code-dataspace } |..."];
7.50 -
7.51 - ReceiveFlexpage [shape=note,label="Flexpage\n(receive window)"];
7.52 -
7.53 - Flexpage [shape=note];
7.54 - Flexpage_note [shape=note,style=filled,fillcolor=gold,label="Satisfies\nmemory\naccess"];
7.55 -
7.56 - Flexpage -> Flexpage_note [dir=none,style=dotted];
7.57 - }
7.58 -
7.59 - subgraph {
7.60 - rank=same;
7.61 -
7.62 - ResourceD [label="Resource\n(Pager)"];
7.63 - ResourceD_note [shape=note,style=filled,fillcolor=gold,label="Provides access\nto file content"];
7.64 -
7.65 - ResourceD -> ResourceD_note [dir=none,style=dotted];
7.66 - }
7.67 -
7.68 - ProgramFile [shape=record,label="Program File | ... |<d> data |<c> code | ..."];
7.69 -
7.70 - /* Page fault handling. */
7.71 -
7.72 - TaskMemory:d -> InternalPager [label="page fault"];
7.73 -
7.74 - InternalPager -> Regions:d [label="find region"];
7.75 -
7.76 - Regions:dd -> ResourceD [style=dashed];
7.77 -
7.78 - InternalPager -> ReceiveFlexpage [dir=none];
7.79 - ReceiveFlexpage -> ResourceD [label="map"];
7.80 -
7.81 - ResourceD -> ProgramFile:d [style=dashed];
7.82 -
7.83 - ResourceD -> Flexpage [dir=none];
7.84 - Flexpage -> InternalPager;
7.85 -}
7.86 -}}}
7.87 -
7.88 -########
7.89 -
7.90 -== External Page Fault Handlers ==
7.91 -
7.92 -Another approach that may be used to support an internal page fault handler
7.93 -deployed in a task is to employ an external page fault handler in the creating
7.94 -task. When a page fault occurs, the external handler ensures that the
7.95 -appropriate content has been brought into its own memory space. It then
7.96 -returns a flexpage from the handler routine to resolve the fault.
7.97 -
7.98 -######## A graph showing the external paging mechanism
7.99 -
7.100 -{{{#!graphviz
7.101 -#format svg
7.102 -#transform notugly
7.103 -digraph external_paging {
7.104 - node [fontsize="12.0",fontname="sans-serif",shape=box];
7.105 - edge [fontsize="12.0",fontname="sans-serif"];
7.106 - rankdir=LR;
7.107 -
7.108 - TaskMemory [shape=record,label="Task Memory |<s> stack | ... |<d> data | ... |<c> code"];
7.109 -
7.110 - subgraph {
7.111 - rank=same;
7.112 -
7.113 - ExternalPager_note [shape=note,style=filled,fillcolor=gold,label="Resides in\nseparate task"];
7.114 - ExternalPager;
7.115 -
7.116 - ExternalPager_note -> ExternalPager [dir=none,style=dotted];
7.117 -
7.118 - MappedFlexpage [shape=note,label="Flexpage\n(positioned)"];
7.119 - MappedFlexpage_note [shape=note,style=filled,fillcolor=gold,label="Satisfies\nmemory\naccess"];
7.120 -
7.121 - MappedFlexpage -> MappedFlexpage_note [dir=none,style=dotted];
7.122 - }
7.123 -
7.124 - subgraph {
7.125 - rank=same;
7.126 -
7.127 - Regions [shape=record,label="Regions |
7.128 - {<s> stack |<sd> stack-dataspace } |
7.129 - {<d> data | <dd> data-dataspace } |
7.130 - {<c> code |<cd> code-dataspace } |..."];
7.131 -
7.132 - L4Re [shape=ellipse,label="L4Re paging\nfunctionality"];
7.133 - L4Re_note [shape=note,style=filled,fillcolor=gold,label="Supports normal\naccess to file content"];
7.134 -
7.135 - L4Re -> L4Re_note [dir=none,style=dotted];
7.136 -
7.137 - Flexpage [shape=note];
7.138 - }
7.139 -
7.140 - subgraph {
7.141 - rank=same;
7.142 -
7.143 - ResourceD [label="Resource\n(Pager)"];
7.144 - ResourceD_note [shape=note,style=filled,fillcolor=gold,label="Provides access\nto file content"];
7.145 -
7.146 - ResourceD -> ResourceD_note [dir=none,style=dotted];
7.147 - }
7.148 -
7.149 - ProgramFile [shape=record,label="Program File | ... |<d> data |<c> code | ..."];
7.150 -
7.151 - /* Page fault handling. */
7.152 -
7.153 - TaskMemory:d -> ExternalPager [label="page fault"];
7.154 -
7.155 - ExternalPager -> Regions:d [label="find region"];
7.156 -
7.157 - Regions:dd -> ResourceD [style=dashed];
7.158 -
7.159 - ExternalPager -> L4Re;
7.160 - L4Re -> ResourceD [label="map"];
7.161 -
7.162 - ResourceD -> ProgramFile:d [style=dashed];
7.163 -
7.164 - ResourceD -> Flexpage [dir=none];
7.165 - Flexpage -> ExternalPager;
7.166 -
7.167 - ExternalPager -> MappedFlexpage [dir=none];
7.168 - MappedFlexpage -> TaskMemory:d;
7.169 -}
7.170 -}}}
7.171 -
7.172 -########
7.173 -
7.174 -== Configuring Programs ==
7.175 -
7.176 -To provide an internal page fault handler alongside an actual program to be
7.177 -run, the following arrangement is used:
7.178 -
7.179 -######## A graph showing the configuration arrangement
7.180 -
7.181 -{{{#!graphviz
7.182 -#format svg
7.183 -#transform notugly
7.184 -digraph program_configuration {
7.185 - node [fontsize="12.0",fontname="sans-serif",shape=box];
7.186 - edge [fontsize="12.0",fontname="sans-serif"];
7.187 - rankdir=LR;
7.188 -
7.189 - subgraph {
7.190 - rank=min;
7.191 -
7.192 - CreatingTask_note [shape=note,style=filled,fillcolor=gold,label="Responsible for\ncreating the\nnew task"];
7.193 - CreatingTask [label="Creating task"];
7.194 -
7.195 - CreatingTask_note -> CreatingTask [dir=none,style=dotted];
7.196 - }
7.197 -
7.198 - subgraph {
7.199 - rank=max;
7.200 -
7.201 - IPCGate_note [shape=note,style=filled,fillcolor=gold,label="Created for sharing\nbetween the tasks"];
7.202 - IPCGate [shape=octagon,label="IPC gate"];
7.203 -
7.204 - IPCGate_note -> IPCGate [dir=none,style=dotted];
7.205 - }
7.206 -
7.207 - InitCaps [shape=record,label="<head> Initial capabilities | {<s> \"server\" |<c> capability }"];
7.208 -
7.209 - subgraph {
7.210 - rank=same;
7.211 -
7.212 - InternalPager;
7.213 - InternalPager_note [shape=note,style=filled,fillcolor=gold,label="Starts and binds\nto IPC gate"];
7.214 -
7.215 - InternalPager -> InternalPager_note [dir=none,style=dotted];
7.216 -
7.217 - Program;
7.218 - Program_note [shape=note,style=filled,fillcolor=gold,label="Starts and references\npager via IPC gate"];
7.219 -
7.220 - Program -> Program_note [dir=none,style=dotted];
7.221 - }
7.222 -
7.223 - /* Create and transfer IPC gate for binding. */
7.224 -
7.225 - CreatingTask -> IPCGate [label="create"];
7.226 - CreatingTask -> InitCaps:head [label="define"];
7.227 - InitCaps:c -> IPCGate;
7.228 -
7.229 - /* Thread initiation. */
7.230 -
7.231 - CreatingTask -> InternalPager [label="start"];
7.232 - InternalPager -> InitCaps:s [label="bind"];
7.233 -
7.234 - CreatingTask -> Program [label="start"];
7.235 - Program -> IPCGate -> InternalPager [style=dashed];
7.236 -}
7.237 -}}}
7.238 -
7.239 -########
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/docs/wiki/Program_Loading Fri Aug 12 16:41:06 2022 +0200
8.3 @@ -0,0 +1,236 @@
8.4 += Program Loading =
8.5 +
8.6 +The provision of [[Paging|paging]] of file content leads to the possibility of
8.7 +demand paging for programs, enabling them to be loaded into memory dynamically
8.8 +and to have only the active portions of those programs resident. To achieve
8.9 +this, programs must be appropriately initialised in new tasks, with a page
8.10 +fault handler configured to provide program file content whenever a region of
8.11 +the program payload is encountered that is not currently resident in memory.
8.12 +
8.13 +== Internal Page Fault Handlers ==
8.14 +
8.15 +When satisfying page faults for a task, one approach involves situating the
8.16 +page fault handler within the task itself, this managing the available memory
8.17 +regions and employing receive windows when requesting memory pages.
8.18 +
8.19 +The general arrangement involving such internal page fault handlers for a
8.20 +program in a task is as follows:
8.21 +
8.22 +######## A graph showing the internal paging mechanism
8.23 +
8.24 +{{{#!graphviz
8.25 +#format svg
8.26 +#transform notugly
8.27 +digraph internal_paging {
8.28 + node [fontsize="12.0",fontname="sans-serif",shape=box];
8.29 + edge [fontsize="12.0",fontname="sans-serif"];
8.30 + rankdir=LR;
8.31 +
8.32 + TaskMemory [shape=record,label="Task Memory |<s> stack | ... |<d> data | ... |<c> code"];
8.33 +
8.34 + subgraph {
8.35 + rank=same;
8.36 +
8.37 + InternalPager;
8.38 + InternalPager_note [shape=note,style=filled,fillcolor=gold,label="Resides in\nsame task and\ndefines scope of\nfault resolution"];
8.39 +
8.40 + InternalPager -> InternalPager_note [dir=none,style=dotted];
8.41 + }
8.42 +
8.43 + subgraph {
8.44 + rank=same;
8.45 +
8.46 + Regions [shape=record,label="Regions |
8.47 + {<s> stack |<sd> stack-dataspace } |
8.48 + {<d> data | <dd> data-dataspace } |
8.49 + {<c> code |<cd> code-dataspace } |..."];
8.50 +
8.51 + ReceiveFlexpage [shape=note,label="Flexpage\n(receive window)"];
8.52 +
8.53 + Flexpage [shape=note];
8.54 + Flexpage_note [shape=note,style=filled,fillcolor=gold,label="Satisfies\nmemory\naccess"];
8.55 +
8.56 + Flexpage -> Flexpage_note [dir=none,style=dotted];
8.57 + }
8.58 +
8.59 + subgraph {
8.60 + rank=same;
8.61 +
8.62 + ResourceD [label="Resource\n(Pager)"];
8.63 + ResourceD_note [shape=note,style=filled,fillcolor=gold,label="Provides access\nto file content"];
8.64 +
8.65 + ResourceD -> ResourceD_note [dir=none,style=dotted];
8.66 + }
8.67 +
8.68 + ProgramFile [shape=record,label="Program File | ... |<d> data |<c> code | ..."];
8.69 +
8.70 + /* Page fault handling. */
8.71 +
8.72 + TaskMemory:d -> InternalPager [label="page fault"];
8.73 +
8.74 + InternalPager -> Regions:d [label="find region"];
8.75 +
8.76 + Regions:dd -> ResourceD [style=dashed];
8.77 +
8.78 + InternalPager -> ReceiveFlexpage [dir=none];
8.79 + ReceiveFlexpage -> ResourceD [label="map"];
8.80 +
8.81 + ResourceD -> ProgramFile:d [style=dashed];
8.82 +
8.83 + ResourceD -> Flexpage [dir=none];
8.84 + Flexpage -> InternalPager;
8.85 +}
8.86 +}}}
8.87 +
8.88 +########
8.89 +
8.90 +== External Page Fault Handlers ==
8.91 +
8.92 +Another approach that may be used to support an internal page fault handler
8.93 +deployed in a task is to employ an external page fault handler in the creating
8.94 +task. When a page fault occurs, the external handler ensures that the
8.95 +appropriate content has been brought into its own memory space. It then
8.96 +returns a flexpage from the handler routine to resolve the fault.
8.97 +
8.98 +######## A graph showing the external paging mechanism
8.99 +
8.100 +{{{#!graphviz
8.101 +#format svg
8.102 +#transform notugly
8.103 +digraph external_paging {
8.104 + node [fontsize="12.0",fontname="sans-serif",shape=box];
8.105 + edge [fontsize="12.0",fontname="sans-serif"];
8.106 + rankdir=LR;
8.107 +
8.108 + TaskMemory [shape=record,label="Task Memory |<s> stack | ... |<d> data | ... |<c> code"];
8.109 +
8.110 + subgraph {
8.111 + rank=same;
8.112 +
8.113 + ExternalPager_note [shape=note,style=filled,fillcolor=gold,label="Resides in\nseparate task"];
8.114 + ExternalPager;
8.115 +
8.116 + ExternalPager_note -> ExternalPager [dir=none,style=dotted];
8.117 +
8.118 + MappedFlexpage [shape=note,label="Flexpage\n(positioned)"];
8.119 + MappedFlexpage_note [shape=note,style=filled,fillcolor=gold,label="Satisfies\nmemory\naccess"];
8.120 +
8.121 + MappedFlexpage -> MappedFlexpage_note [dir=none,style=dotted];
8.122 + }
8.123 +
8.124 + subgraph {
8.125 + rank=same;
8.126 +
8.127 + Regions [shape=record,label="Regions |
8.128 + {<s> stack |<sd> stack-dataspace } |
8.129 + {<d> data | <dd> data-dataspace } |
8.130 + {<c> code |<cd> code-dataspace } |..."];
8.131 +
8.132 + L4Re [shape=ellipse,label="L4Re paging\nfunctionality"];
8.133 + L4Re_note [shape=note,style=filled,fillcolor=gold,label="Supports normal\naccess to file content"];
8.134 +
8.135 + L4Re -> L4Re_note [dir=none,style=dotted];
8.136 +
8.137 + Flexpage [shape=note];
8.138 + }
8.139 +
8.140 + subgraph {
8.141 + rank=same;
8.142 +
8.143 + ResourceD [label="Resource\n(Pager)"];
8.144 + ResourceD_note [shape=note,style=filled,fillcolor=gold,label="Provides access\nto file content"];
8.145 +
8.146 + ResourceD -> ResourceD_note [dir=none,style=dotted];
8.147 + }
8.148 +
8.149 + ProgramFile [shape=record,label="Program File | ... |<d> data |<c> code | ..."];
8.150 +
8.151 + /* Page fault handling. */
8.152 +
8.153 + TaskMemory:d -> ExternalPager [label="page fault"];
8.154 +
8.155 + ExternalPager -> Regions:d [label="find region"];
8.156 +
8.157 + Regions:dd -> ResourceD [style=dashed];
8.158 +
8.159 + ExternalPager -> L4Re;
8.160 + L4Re -> ResourceD [label="map"];
8.161 +
8.162 + ResourceD -> ProgramFile:d [style=dashed];
8.163 +
8.164 + ResourceD -> Flexpage [dir=none];
8.165 + Flexpage -> ExternalPager;
8.166 +
8.167 + ExternalPager -> MappedFlexpage [dir=none];
8.168 + MappedFlexpage -> TaskMemory:d;
8.169 +}
8.170 +}}}
8.171 +
8.172 +########
8.173 +
8.174 +== Configuring Programs ==
8.175 +
8.176 +To provide an internal page fault handler alongside an actual program to be
8.177 +run, the following arrangement is used:
8.178 +
8.179 +######## A graph showing the configuration arrangement
8.180 +
8.181 +{{{#!graphviz
8.182 +#format svg
8.183 +#transform notugly
8.184 +digraph program_configuration {
8.185 + node [fontsize="12.0",fontname="sans-serif",shape=box];
8.186 + edge [fontsize="12.0",fontname="sans-serif"];
8.187 + rankdir=LR;
8.188 +
8.189 + subgraph {
8.190 + rank=min;
8.191 +
8.192 + CreatingTask_note [shape=note,style=filled,fillcolor=gold,label="Responsible for\ncreating the\nnew task"];
8.193 + CreatingTask [label="Creating task"];
8.194 +
8.195 + CreatingTask_note -> CreatingTask [dir=none,style=dotted];
8.196 + }
8.197 +
8.198 + subgraph {
8.199 + rank=max;
8.200 +
8.201 + IPCGate_note [shape=note,style=filled,fillcolor=gold,label="Created for sharing\nbetween the tasks"];
8.202 + IPCGate [shape=octagon,label="IPC gate"];
8.203 +
8.204 + IPCGate_note -> IPCGate [dir=none,style=dotted];
8.205 + }
8.206 +
8.207 + InitCaps [shape=record,label="<head> Initial capabilities | {<s> \"server\" |<c> capability }"];
8.208 +
8.209 + subgraph {
8.210 + rank=same;
8.211 +
8.212 + InternalPager;
8.213 + InternalPager_note [shape=note,style=filled,fillcolor=gold,label="Starts and binds\nto IPC gate"];
8.214 +
8.215 + InternalPager -> InternalPager_note [dir=none,style=dotted];
8.216 +
8.217 + Program;
8.218 + Program_note [shape=note,style=filled,fillcolor=gold,label="Starts and references\npager via IPC gate"];
8.219 +
8.220 + Program -> Program_note [dir=none,style=dotted];
8.221 + }
8.222 +
8.223 + /* Create and transfer IPC gate for binding. */
8.224 +
8.225 + CreatingTask -> IPCGate [label="create"];
8.226 + CreatingTask -> InitCaps:head [label="define"];
8.227 + InitCaps:c -> IPCGate;
8.228 +
8.229 + /* Thread initiation. */
8.230 +
8.231 + CreatingTask -> InternalPager [label="start"];
8.232 + InternalPager -> InitCaps:s [label="bind"];
8.233 +
8.234 + CreatingTask -> Program [label="start"];
8.235 + Program -> IPCGate -> InternalPager [style=dashed];
8.236 +}
8.237 +}}}
8.238 +
8.239 +########
9.1 --- a/docs/wiki/ServerLibrary Wed Aug 10 23:58:38 2022 +0200
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,245 +0,0 @@
9.4 -= Server Library =
9.5 -
9.6 -Within the filesystem server library, a number of different abstractions and
9.7 -mechanisms are employed to provide access to filesystem objects.
9.8 -
9.9 -<<TableOfContents(2,3)>>
9.10 -
9.11 -This document uses C-style interface syntax since the components operating
9.12 -within the described mechanisms will themselves be described using such
9.13 -syntax.
9.14 -
9.15 -== Accountable ==
9.16 -
9.17 -This interface provides the following operations:
9.18 -
9.19 -{{{
9.20 -void attach();
9.21 -unsigned int detach();
9.22 -}}}
9.23 -
9.24 -Its purpose is to provide reference counting for components, with the `attach`
9.25 -operation incrementing the number of users of a component, and with the
9.26 -`detach` operation decrementing the number of users and returning the
9.27 -resulting number of users. When components no longer have any attached users,
9.28 -they may perform operations to tidy up after themselves and permit their
9.29 -deallocation.
9.30 -
9.31 -== Accessors ==
9.32 -
9.33 -Accessors provide the means of accessing filesystem object data and metadata.
9.34 -Conceptually, files and directories are both exposed by accessors, although
9.35 -the interfaces and mechanisms may differ between these types of objects.
9.36 -
9.37 -=== Directory Accessors ===
9.38 -
9.39 -Currently, directory accessors provide support for traversing directory
9.40 -listings, obtaining the relevant filesystem metadata using the underlying
9.41 -filesystem access library.
9.42 -
9.43 -=== File Accessors ===
9.44 -
9.45 -File content is accessed through an interface with the following operations:
9.46 -
9.47 -{{{
9.48 -void close();
9.49 -void fill(Flexpage *flexpage);
9.50 -void flush(Flexpage *flexpage);
9.51 -offset_t get_size();
9.52 -void set_size(offset_t size);
9.53 -}}}
9.54 -
9.55 -The operations need to be supported with actual filesystem operations. For
9.56 -example, ext2-based filesystems employ a specific abstraction which invokes
9.57 -library functions provided by the `libext2fs` package.
9.58 -
9.59 -== Providers ==
9.60 -
9.61 -Providers encapsulate the essential functionality for accessing filesystem
9.62 -objects. Implementing the `Accountable` interface, they are shared by
9.63 -resources and discarded when no resources are using them.
9.64 -
9.65 -The following operations are supported by providers:
9.66 -
9.67 -{{{
9.68 -ProviderRegistry *registry();
9.69 -long make_resource(offset_t *size, object_flags_t *object_flags, Resource **resource);
9.70 -bool removal_pending();
9.71 -void remove();
9.72 -void remove_pending(bool remove);
9.73 -}}}
9.74 -
9.75 -Providers are associated with filesystem objects in a registry which can be
9.76 -obtained from each provider using the `registry` operation.
9.77 -
9.78 -Providers also support the creation of resources through which each user of a
9.79 -provider exercises its use of that provider. The `make_resource` operation
9.80 -performs the creation and returns size, flags and resource instance details.
9.81 -
9.82 -The removal of providers can be directed using the `remove_pending` and
9.83 -`remove` operations. Where `remove_pending` has been called with a true value
9.84 -as its parameter, the `removal_pending` operation will also return a true
9.85 -value, and upon the provider being discarded, the `remove` operation will be
9.86 -invoked. The `remove` operation performs the appropriate underlying operation
9.87 -to remove the object being provided.
9.88 -
9.89 -Typically, removal of providers is managed by the provider registry when
9.90 -resources are closed and detached from providers.
9.91 -
9.92 -######## A graph showing the removal mechanism
9.93 -
9.94 -{{{#!graphviz
9.95 -#format svg
9.96 -#transform notugly
9.97 -digraph provider_removal {
9.98 - node [fontsize="12.0",fontname="sans-serif",shape=box];
9.99 - edge [fontsize="12.0",fontname="sans-serif"];
9.100 - rankdir=LR;
9.101 -
9.102 - ResourceServer -> Resource [label="close"];
9.103 - Resource -> ProviderRegistry [label="detach"];
9.104 - ProviderRegistry -> Provider [label="remove"];
9.105 -}
9.106 -}}}
9.107 -
9.108 -########
9.109 -
9.110 -== Resources ==
9.111 -
9.112 -Resources are objects accessed by clients that support a basic level of
9.113 -accounting and management.
9.114 -
9.115 -The base interface of a resource is as follows:
9.116 -
9.117 -{{{
9.118 -void activate();
9.119 -void close();
9.120 -}}}
9.121 -
9.122 -Activation of a resource is an optional operation that performs any
9.123 -initialisation before a resource is made available to its user.
9.124 -
9.125 -In practice, other operations are required to make resources useful.
9.126 -
9.127 -In some cases, resources provide the mechanism by which each user of a
9.128 -filesystem object may access that object independently. They would then
9.129 -effectively provide a session in which accesses can occur.
9.130 -
9.131 -=== Directory Resources ===
9.132 -
9.133 -Directory resources primarily expose the contents of directories in the
9.134 -filesystem to a user. They employ directory accessors which concern themselves
9.135 -with the actual filesystem content.
9.136 -
9.137 -[[Components#Directories|Directory components]] are provided using directory
9.138 -resources.
9.139 -
9.140 -<<Anchor(Pager)>>
9.141 -=== Pagers or File Resources ===
9.142 -
9.143 -Pagers are resources that support dataspace access operations, thus allowing
9.144 -the resources to expose filesystem content in mapped memory regions to a
9.145 -particular user of the object providing the content.
9.146 -
9.147 -[[Components#Files|File components]] and [[Components#Pipes|pipe components]]
9.148 -are provided using pagers.
9.149 -
9.150 -=== Filesystem Resources ===
9.151 -
9.152 -Filesystem resources provide the entry point for access to a filesystem by
9.153 -other components or programs. Since filesystems often enforce identity-based
9.154 -access controls, a filesystem resource will typically support the
9.155 -`open_for_user` operation in various forms, with the result of this operation
9.156 -being the instantiation of an `OpenerResource` configured for the indicated
9.157 -user identity.
9.158 -
9.159 -== Registries ==
9.160 -
9.161 -The basic mechanism for obtaining a resource involves a registry, as
9.162 -illustrated by the following diagram.
9.163 -
9.164 -######## A graph showing the use of a registry in obtaining resources
9.165 -
9.166 -{{{#!graphviz
9.167 -#format svg
9.168 -#transform notugly
9.169 -digraph registry {
9.170 - node [fontsize="12.0",fontname="sans-serif",shape=box];
9.171 - edge [fontsize="12.0",fontname="sans-serif"];
9.172 - rankdir=LR;
9.173 -
9.174 - subgraph {
9.175 - node [label="OpenerContextResource"];
9.176 - rank=same;
9.177 -
9.178 - OpenerContextResource1 -> OpenerContextResource2 [dir=none,style=dotted];
9.179 - }
9.180 -
9.181 - subgraph {
9.182 - node [label="OpenerResource"];
9.183 - rank=same;
9.184 -
9.185 - OpenerResource1 -> OpenerResource2 [dir=none,style=dotted];
9.186 - }
9.187 -
9.188 - subgraph {
9.189 - rank=same;
9.190 -
9.191 - ResourceRegistry -> Resource;
9.192 - }
9.193 -
9.194 - subgraph {
9.195 - rank=same;
9.196 -
9.197 - ProviderRegistry -> Provider;
9.198 - }
9.199 -
9.200 - OpenerContextResource1 -> OpenerResource1 [label="open"];
9.201 - OpenerResource1 -> ResourceRegistry [label="get_resource"];
9.202 - ResourceRegistry -> ProviderRegistry [label="get/set"];
9.203 -
9.204 - Provider -> Resource -> OpenerResource2 -> OpenerContextResource2;
9.205 -}
9.206 -}}}
9.207 -
9.208 -########
9.209 -
9.210 -The `ResourceRegistry` coordinates access to filesystem resources and, through
9.211 -synchronisation, prevents conflicting operations from occurring concurrently.
9.212 -For example, a removal operation on a file may not be allowed to occur while
9.213 -an opening operation is in progress.
9.214 -
9.215 -To achieve this, a common lock is employed to serialise access, with any
9.216 -underlying filesystem operations being initiated from the registry while the
9.217 -lock is held. An object providing the `FileOpening` interface for a filesystem
9.218 -provides such operations, and the following interaction pattern is thereby
9.219 -employed:
9.220 -
9.221 -######## A graph showing the registry coordinating filesystem operations
9.222 -
9.223 -{{{#!graphviz
9.224 -#format svg
9.225 -#transform notugly
9.226 -digraph registry_operations {
9.227 - node [fontsize="12.0",fontname="sans-serif",shape=box];
9.228 - edge [fontsize="12.0",fontname="sans-serif"];
9.229 - rankdir=LR;
9.230 -
9.231 - OpenerContextResource -> OpenerResource -> ResourceRegistry -> FileOpening;
9.232 -}
9.233 -}}}
9.234 -
9.235 -########
9.236 -
9.237 -Since the `ResourceRegistry` functionality is generic, it could be specialised
9.238 -for each filesystem or be configured with an appropriate reference to a
9.239 -`FileOpening` object. The `OpenerResource` would then be generic, invoking the
9.240 -registry which would, in turn, invoke the opening object.
9.241 -
9.242 -However, the chosen approach is to permit `OpenerResource` objects to
9.243 -implement the `FileOpening` interface for each filesystem, meaning that the
9.244 -`ResourceRegistry` will end up being called by the opener and then invoking
9.245 -the opener in return. This is slightly more convenient than the alternative
9.246 -since the opener can be configured with a given user identity, and such
9.247 -identity details will ultimately be employed when accessing the underlying
9.248 -filesystem itself.
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/docs/wiki/Server_Library Fri Aug 12 16:41:06 2022 +0200
10.3 @@ -0,0 +1,245 @@
10.4 += Server Library =
10.5 +
10.6 +Within the filesystem server library, a number of different abstractions and
10.7 +mechanisms are employed to provide access to filesystem objects.
10.8 +
10.9 +<<TableOfContents(2,3)>>
10.10 +
10.11 +This document uses C-style interface syntax since the components operating
10.12 +within the described mechanisms will themselves be described using such
10.13 +syntax.
10.14 +
10.15 +== Accountable ==
10.16 +
10.17 +This interface provides the following operations:
10.18 +
10.19 +{{{
10.20 +void attach();
10.21 +unsigned int detach();
10.22 +}}}
10.23 +
10.24 +Its purpose is to provide reference counting for components, with the `attach`
10.25 +operation incrementing the number of users of a component, and with the
10.26 +`detach` operation decrementing the number of users and returning the
10.27 +resulting number of users. When components no longer have any attached users,
10.28 +they may perform operations to tidy up after themselves and permit their
10.29 +deallocation.
10.30 +
10.31 +== Accessors ==
10.32 +
10.33 +Accessors provide the means of accessing filesystem object data and metadata.
10.34 +Conceptually, files and directories are both exposed by accessors, although
10.35 +the interfaces and mechanisms may differ between these types of objects.
10.36 +
10.37 +=== Directory Accessors ===
10.38 +
10.39 +Currently, directory accessors provide support for traversing directory
10.40 +listings, obtaining the relevant filesystem metadata using the underlying
10.41 +filesystem access library.
10.42 +
10.43 +=== File Accessors ===
10.44 +
10.45 +File content is accessed through an interface with the following operations:
10.46 +
10.47 +{{{
10.48 +void close();
10.49 +void fill(Flexpage *flexpage);
10.50 +void flush(Flexpage *flexpage);
10.51 +offset_t get_size();
10.52 +void set_size(offset_t size);
10.53 +}}}
10.54 +
10.55 +The operations need to be supported with actual filesystem operations. For
10.56 +example, ext2-based filesystems employ a specific abstraction which invokes
10.57 +library functions provided by the `libext2fs` package.
10.58 +
10.59 +== Providers ==
10.60 +
10.61 +Providers encapsulate the essential functionality for accessing filesystem
10.62 +objects. Implementing the `Accountable` interface, they are shared by
10.63 +resources and discarded when no resources are using them.
10.64 +
10.65 +The following operations are supported by providers:
10.66 +
10.67 +{{{
10.68 +ProviderRegistry *registry();
10.69 +long make_resource(offset_t *size, object_flags_t *object_flags, Resource **resource);
10.70 +bool removal_pending();
10.71 +void remove();
10.72 +void remove_pending(bool remove);
10.73 +}}}
10.74 +
10.75 +Providers are associated with filesystem objects in a registry which can be
10.76 +obtained from each provider using the `registry` operation.
10.77 +
10.78 +Providers also support the creation of resources through which each user of a
10.79 +provider exercises its use of that provider. The `make_resource` operation
10.80 +performs the creation and returns size, flags and resource instance details.
10.81 +
10.82 +The removal of providers can be directed using the `remove_pending` and
10.83 +`remove` operations. Where `remove_pending` has been called with a true value
10.84 +as its parameter, the `removal_pending` operation will also return a true
10.85 +value, and upon the provider being discarded, the `remove` operation will be
10.86 +invoked. The `remove` operation performs the appropriate underlying operation
10.87 +to remove the object being provided.
10.88 +
10.89 +Typically, removal of providers is managed by the provider registry when
10.90 +resources are closed and detached from providers.
10.91 +
10.92 +######## A graph showing the removal mechanism
10.93 +
10.94 +{{{#!graphviz
10.95 +#format svg
10.96 +#transform notugly
10.97 +digraph provider_removal {
10.98 + node [fontsize="12.0",fontname="sans-serif",shape=box];
10.99 + edge [fontsize="12.0",fontname="sans-serif"];
10.100 + rankdir=LR;
10.101 +
10.102 + ResourceServer -> Resource [label="close"];
10.103 + Resource -> ProviderRegistry [label="detach"];
10.104 + ProviderRegistry -> Provider [label="remove"];
10.105 +}
10.106 +}}}
10.107 +
10.108 +########
10.109 +
10.110 +== Resources ==
10.111 +
10.112 +Resources are objects accessed by clients that support a basic level of
10.113 +accounting and management.
10.114 +
10.115 +The base interface of a resource is as follows:
10.116 +
10.117 +{{{
10.118 +void activate();
10.119 +void close();
10.120 +}}}
10.121 +
10.122 +Activation of a resource is an optional operation that performs any
10.123 +initialisation before a resource is made available to its user.
10.124 +
10.125 +In practice, other operations are required to make resources useful.
10.126 +
10.127 +In some cases, resources provide the mechanism by which each user of a
10.128 +filesystem object may access that object independently. They would then
10.129 +effectively provide a session in which accesses can occur.
10.130 +
10.131 +=== Directory Resources ===
10.132 +
10.133 +Directory resources primarily expose the contents of directories in the
10.134 +filesystem to a user. They employ directory accessors which concern themselves
10.135 +with the actual filesystem content.
10.136 +
10.137 +[[Components#Directories|Directory components]] are provided using directory
10.138 +resources.
10.139 +
10.140 +<<Anchor(Pager)>>
10.141 +=== Pagers or File Resources ===
10.142 +
10.143 +Pagers are resources that support dataspace access operations, thus allowing
10.144 +the resources to expose filesystem content in mapped memory regions to a
10.145 +particular user of the object providing the content.
10.146 +
10.147 +[[Components#Files|File components]] and [[Components#Pipes|pipe components]]
10.148 +are provided using pagers.
10.149 +
10.150 +=== Filesystem Resources ===
10.151 +
10.152 +Filesystem resources provide the entry point for access to a filesystem by
10.153 +other components or programs. Since filesystems often enforce identity-based
10.154 +access controls, a filesystem resource will typically support the
10.155 +`open_for_user` operation in various forms, with the result of this operation
10.156 +being the instantiation of an `OpenerResource` configured for the indicated
10.157 +user identity.
10.158 +
10.159 +== Registries ==
10.160 +
10.161 +The basic mechanism for obtaining a resource involves a registry, as
10.162 +illustrated by the following diagram.
10.163 +
10.164 +######## A graph showing the use of a registry in obtaining resources
10.165 +
10.166 +{{{#!graphviz
10.167 +#format svg
10.168 +#transform notugly
10.169 +digraph registry {
10.170 + node [fontsize="12.0",fontname="sans-serif",shape=box];
10.171 + edge [fontsize="12.0",fontname="sans-serif"];
10.172 + rankdir=LR;
10.173 +
10.174 + subgraph {
10.175 + node [label="OpenerContextResource"];
10.176 + rank=same;
10.177 +
10.178 + OpenerContextResource1 -> OpenerContextResource2 [dir=none,style=dotted];
10.179 + }
10.180 +
10.181 + subgraph {
10.182 + node [label="OpenerResource"];
10.183 + rank=same;
10.184 +
10.185 + OpenerResource1 -> OpenerResource2 [dir=none,style=dotted];
10.186 + }
10.187 +
10.188 + subgraph {
10.189 + rank=same;
10.190 +
10.191 + ResourceRegistry -> Resource;
10.192 + }
10.193 +
10.194 + subgraph {
10.195 + rank=same;
10.196 +
10.197 + ProviderRegistry -> Provider;
10.198 + }
10.199 +
10.200 + OpenerContextResource1 -> OpenerResource1 [label="open"];
10.201 + OpenerResource1 -> ResourceRegistry [label="get_resource"];
10.202 + ResourceRegistry -> ProviderRegistry [label="get/set"];
10.203 +
10.204 + Provider -> Resource -> OpenerResource2 -> OpenerContextResource2;
10.205 +}
10.206 +}}}
10.207 +
10.208 +########
10.209 +
10.210 +The `ResourceRegistry` coordinates access to filesystem resources and, through
10.211 +synchronisation, prevents conflicting operations from occurring concurrently.
10.212 +For example, a removal operation on a file may not be allowed to occur while
10.213 +an opening operation is in progress.
10.214 +
10.215 +To achieve this, a common lock is employed to serialise access, with any
10.216 +underlying filesystem operations being initiated from the registry while the
10.217 +lock is held. An object providing the `FileOpening` interface for a filesystem
10.218 +provides such operations, and the following interaction pattern is thereby
10.219 +employed:
10.220 +
10.221 +######## A graph showing the registry coordinating filesystem operations
10.222 +
10.223 +{{{#!graphviz
10.224 +#format svg
10.225 +#transform notugly
10.226 +digraph registry_operations {
10.227 + node [fontsize="12.0",fontname="sans-serif",shape=box];
10.228 + edge [fontsize="12.0",fontname="sans-serif"];
10.229 + rankdir=LR;
10.230 +
10.231 + OpenerContextResource -> OpenerResource -> ResourceRegistry -> FileOpening;
10.232 +}
10.233 +}}}
10.234 +
10.235 +########
10.236 +
10.237 +Since the `ResourceRegistry` functionality is generic, it could be specialised
10.238 +for each filesystem or be configured with an appropriate reference to a
10.239 +`FileOpening` object. The `OpenerResource` would then be generic, invoking the
10.240 +registry which would, in turn, invoke the opening object.
10.241 +
10.242 +However, the chosen approach is to permit `OpenerResource` objects to
10.243 +implement the `FileOpening` interface for each filesystem, meaning that the
10.244 +`ResourceRegistry` will end up being called by the opener and then invoking
10.245 +the opener in return. This is slightly more convenient than the alternative
10.246 +since the opener can be configured with a given user identity, and such
10.247 +identity details will ultimately be employed when accessing the underlying
10.248 +filesystem itself.