Update documentation

This commit is contained in:
Rodrigo Arias 2022-09-05 20:17:56 +02:00
parent ac1ae8e69d
commit 903244d22b
4 changed files with 593 additions and 59 deletions

View File

@ -6,7 +6,7 @@ This file contains an exhaustive list of events supported by the emulator.
- All events refer to the current thread. - All events refer to the current thread.
- Descriptions must be kept short. - Descriptions must be kept short.
``` ```txt
********************************************************** **********************************************************
Please keep this list synchronized with the emulator code! Please keep this list synchronized with the emulator code!
********************************************************** **********************************************************
@ -141,27 +141,27 @@ KCI Is back in the CPU due to a context switch
6TC Task creation ends 6TC Task creation ends
6Tx Task execute 6Tx Task execute
6Te Task end 6Te Task end
6Tb Task block 6Tp Task pause
6Tu Task unblock 6Tr Task resume
6Yc Task type create (punctual event) 6Yc Task type create (punctual event)
6S[ Enters the scheduler serving mode
6S] Ends the scheduler serving mode
6Sa Begins to submit a ready task via addReadyTask()
6SA Ends submitting a ready task via addReadyTask()
6Sr Receives a task from another thread (punctual event) 6Sr Receives a task from another thread (punctual event)
6Ss Sends a task to another thread (punctual event) 6Ss Sends a task to another thread (punctual event)
6S@ Self-assigns itself a task (punctual event) 6S@ Self-assigns itself a task (punctual event)
6Sh Enters the hungry state, waiting for a task
6Sf Is no longer hungry 6W[ Begins the worker body loop, looking for tasks
6S[ Enters the scheduler server mode 6W] Ends the worker body loop
6S] Ends the scheduler server mode 6Wt Begins handling a task via handleTask()
6Su Begins a ready task submission via addReadyTask() 6WT Ends handling a task via handleTask()
6SU Ends a ready task submission via addReadyTask()
6U[ Starts to submit a task via submitTask() 6U[ Starts to submit a task via submitTask()
6U] Ends the submission of a task via submitTask() 6U] Ends the submission of a task via submitTask()
6Ha Attaches to Nanos6 as external thread
6HA Detaches from Nanos6 as external thread
6F[ Begins to spawn a function via spawnFunction() 6F[ Begins to spawn a function via spawnFunction()
6F] Ends spawning a function 6F] Ends spawning a function
@ -170,12 +170,21 @@ KCI Is back in the CPU due to a context switch
6Du Begins the unregistration of a task's accesses 6Du Begins the unregistration of a task's accesses
6DU Ends the unregistration of a task's accesses 6DU Ends the unregistration of a task's accesses
6Bu Begins to unblock a task
6BU Ends unblocking a task
6Bb Begins to block the current task via blockCurrentTask() 6Bb Begins to block the current task via blockCurrentTask()
6BB Ends blocking the current task via blockCurrentTask() 6BB Ends blocking the current task via blockCurrentTask()
6Bu Begins to unblock a task
6BU Ends unblocking a task
6Bw Enters taskWait() 6Bw Enters taskWait()
6BW Exits taskWait() 6BW Exits taskWait()
6Bf Enters taskFor() 6Bf Enters taskFor()
6BF Exits taskFor() 6BF Exits taskFor()
6He Sets itself as external thread
6HE Unsets itself as external thread
6Hw Sets itself as worker thread
6HW Unsets itself as worker thread
6Hl Sets itself as leader thread
6HL Unsets itself as leader thread
6Hm Sets itself as main thread
6HM Unsets itself as main thread
``` ```

View File

@ -89,59 +89,56 @@ presents that section as the current state of the execution, in this
case the section $`S_3`$. case the section $`S_3`$.
Additionally, the runtime sections $`S_i`$ are grouped together in Additionally, the runtime sections $`S_i`$ are grouped together in
subsystems, which form a closely related group of functions. The subsystems, which form a closely related group of functions. When there is no
complete list of subsystems and sections is shown below. instrumented section in the thread stack, the state is set to **No subsystem**.
The complete list of subsystems and sections is shown below.
When there is no instrumented section in the thread stack, the state is - **Task subsystem**: Controls the life cycle of tasks
set to **No subsystem**.
Task subsystem - **Body**: Executing the body of the task (user defined code).
: The **Task** subsystem contains the code that controls the life cycle
of tasks. It contains the following sections: - **Spawning function**: Spawning a function as task that will be submitted
for later execution.
- **Creating**: Creating a new task via `nanos6_create_task`
- **Submitting**: Submitting a recently created task via
`nanos6_submit_task`
- **Body**: Executing the body of the task (user defined code). - **Scheduler subsystem**: Queueing and dequeueing ready tasks.
- **Spawning function**: Spawning a function as task (it will be - **Serving tasks**: Inside the scheduler lock, serving tasks
submitted to the scheduler for later execution). to other threads
- **Adding ready tasks**: Adding tasks to the scheduler queues,
but outside of the scheduler lock.
- **Creating**: Creating a new task, through `nanos6_create_task`
- **Submitting**: Submitting a recently created task, through - **Worker subsystem**: Actions that relate to worker threads, which
`nanos6_submit_task` continuously try to execute new tasks.
Scheduler subsystem - **Looking for work**: Actively requesting tasks from the scheduler,
: The **Scheduler** system groups the actions that relate to the queueing registered but not holding the lock.
and dequeueing of ready tasks. It contains the following sections:
- **Handling task**: Processing a recently assigned task.
- **Waiting for tasks**: Actively waiting for tasks inside the - **Dependency subsystem**: Manages the registration of task
scheduler subsystem, registered but not holding the scheduler lock dependencies.
- **Serving tasks**: Inside the scheduler lock, serving tasks - **Registering**: Registering dependencies of a task
to other threads
- **Unregistering**: Releasing dependencies of a task because
it has ended
- **Adding ready tasks**: Adding tasks to the scheduler queues, - **Blocking subsystem**: Code that stops the thread execution.
but outside of the scheduler lock.
Dependency subsystem - **Taskwait**: Task is blocked due to a `taskwait` clause
: The **Dependency** system only contains the code that manages the
registration of task dependencies. It contains the following sections: - **Blocking current task**: Task is blocked through the Nanos6
blocking API
- **Registering**: Registering a task's dependencies
- **Unblocking remote task**: Unblocking a different task using the
- **Unregistering**: Releasing a task's dependencies because Nanos6 blocking API
it has ended
- **Wait for deadline**: Blocking a deadline task, which will be
Blocking subsystem re-enqueued when a certain amount of time has passed
: The **Blocking** subsystem deals with the code stops the thread
execution. It contains the following sections:
- **Taskwait**: Task is blocked while inside a taskwait
- **Blocking current task**: Task is blocked through the Nanos6
blocking API
- **Unblocking remote task**: Unblocking a different task using
the Nanos6 blocking API
- **Wait For**: Blocking a deadline task, which will be
re-enqueued when a certain amount of time has passed

326
doc/fig/palette.svg Normal file
View File

@ -0,0 +1,326 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg5"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
sodipodi:docname="palette.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.5126683"
inkscape:cx="337.15256"
inkscape:cy="253.85604"
inkscape:window-width="1914"
inkscape:window-height="1025"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<inkscape:grid
type="xygrid"
id="grid8317"
empcolor="#e4ff3f"
empopacity="0.25098039" />
</sodipodi:namedview>
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#54d200;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="task-executing-body"
width="10.583334"
height="10.583333"
x="7.9375"
y="7.9375005" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="21.520691"
y="14.202404"
id="text8213"><tspan
sodipodi:role="line"
id="tspan8211"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="21.520691"
y="14.202404">Task: Executing body</tspan></text>
<rect
style="fill:#666666;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect8319"
width="10.583334"
height="10.583333"
x="82.020836"
y="7.9375" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="96.294754"
y="14.544328"
id="text8323"><tspan
sodipodi:role="line"
id="tspan8321"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="96.294754"
y="14.544328">Worker: Waiting for work</tspan></text>
<rect
style="fill:#004468;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect8325"
width="10.583334"
height="10.583333"
x="7.9375"
y="34.395832" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="21.520691"
y="40.660736"
id="text8329"><tspan
sodipodi:role="line"
id="tspan8327"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="21.520691"
y="40.660736">Task: Creating</tspan></text>
<rect
style="fill:#8c2e2e;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect8331"
width="10.583334"
height="10.583333"
x="82.020836"
y="34.395832" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="96.065659"
y="41.002663"
id="text8335"><tspan
sodipodi:role="line"
id="tspan8333"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="96.065659"
y="41.002663">Block: Taskwait</tspan></text>
<rect
style="fill:#69b498;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect9063"
width="10.583334"
height="10.583333"
x="7.9374995"
y="21.166666" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="21.277811"
y="27.431568"
id="text9067"><tspan
sodipodi:role="line"
id="tspan9065"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="21.277811"
y="27.431568">Scheduler: Adding ready tasks</tspan></text>
<rect
style="fill:#730dff;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect11247"
width="10.583334"
height="10.583333"
x="7.9374995"
y="47.625" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="21.164124"
y="53.889904"
id="text11251"><tspan
sodipodi:role="line"
id="tspan11249"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="21.164124"
y="53.889904">Dependency: Registering</tspan></text>
<rect
style="fill:#4400ff;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect11253"
width="10.583334"
height="10.583333"
x="7.937499"
y="60.854164" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="21.164124"
y="67.119064"
id="text11257"><tspan
sodipodi:role="line"
id="tspan11255"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="21.164124"
y="67.119064">Dependency: Unregistering</tspan></text>
<rect
style="fill:#816803;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect13437"
width="10.583334"
height="10.583333"
x="82.020836"
y="60.854168" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="96.179344"
y="67.119072"
id="text13441"><tspan
sodipodi:role="line"
id="tspan13439"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="96.179344"
y="67.119072">Scheduler: Serving tasks</tspan></text>
<rect
style="fill:#483737;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect14940"
width="10.583334"
height="10.583333"
x="82.020836"
y="47.625" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="96.065659"
y="54.231831"
id="text14944"><tspan
sodipodi:role="line"
id="tspan14942"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="96.065659"
y="54.231831">Block: Taskfor</tspan></text>
<rect
style="fill:#333333;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect14946"
width="10.583334"
height="10.583333"
x="82.020836"
y="21.166666" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="96.294754"
y="27.773493"
id="text14950"><tspan
sodipodi:role="line"
id="tspan14948"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="96.294754"
y="27.773493">Worker: handling task</tspan></text>
<rect
style="fill:#a916a7;fill-opacity:1;stroke:none;stroke-width:0.264999"
id="rect18669"
width="10.583334"
height="10.583333"
x="7.9375"
y="74.083336" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="21.520691"
y="80.348236"
id="text18673"><tspan
sodipodi:role="line"
id="tspan18671"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
x="21.520691"
y="80.348236">Task: Subtmitting</tspan></text>
<use
x="0"
y="0"
xlink:href="#rect8319"
id="use26699"
transform="matrix(12.000002,0,0,0.25000006,-973.66686,97.234375)" />
<use
x="0"
y="0"
xlink:href="#rect14946"
id="use26701"
transform="matrix(4.9999992,0,0,0.25000008,-375.7083,93.927081)" />
<use
x="0"
y="0"
xlink:href="#task-executing-body"
id="use26703"
transform="matrix(4.2499997,0,0,0.24999998,5.9531158,97.234375)" />
<use
x="0"
y="0"
xlink:href="#rect8325"
id="use26705"
transform="matrix(0.74999999,0,0,0.25000006,60.192697,90.61979)" />
<use
x="0"
y="0"
xlink:href="#rect18669"
id="use26707"
transform="matrix(0.74999999,0,0,0.24999989,68.130197,80.697925)" />
<use
x="0"
y="0"
xlink:href="#rect8319"
id="use26719"
transform="matrix(11.999997,0,0,0.24999994,-973.66645,101.20313)" />
<use
x="0"
y="0"
xlink:href="#rect14946"
id="use28173"
transform="matrix(10.999997,0,0,0.25000008,-886.35397,97.895827)" />
<use
x="0"
y="0"
xlink:href="#task-executing-body"
id="use28175"
transform="matrix(10.249999,0,0,0.24999995,-62.838518,101.20313)" />
<use
x="0"
y="0"
xlink:href="#rect8331"
id="use28177"
transform="matrix(4.499999,0,0,0.25000002,-318.82282,94.588537)" />
<use
x="0"
y="0"
xlink:href="#rect8325"
id="use28179"
transform="matrix(1.239965,0,0,0.24999994,13.666176,94.588545)" />
<use
x="0"
y="0"
xlink:href="#rect18669"
id="use28183"
transform="matrix(0.54985987,0,0,0.25000004,35.515186,84.666658)" />
<use
x="0"
y="0"
xlink:href="#rect8319"
id="use28237"
transform="matrix(3.8245086,0,0,0.25000012,-259.84411,101.20312)" />
<use
x="0"
y="0"
xlink:href="#rect13437"
id="use28239"
transform="matrix(11.999996,0,0,0.24999991,-973.66636,80.036465)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

202
doc/fig/subsystem-stack.svg Normal file
View File

@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg5"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
sodipodi:docname="subsystem-stack.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.5126683"
inkscape:cx="416.15203"
inkscape:cy="244.60087"
inkscape:window-width="1914"
inkscape:window-height="1025"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<inkscape:grid
type="xygrid"
id="grid3825" />
</sodipodi:namedview>
<defs
id="defs2">
<marker
style="overflow:visible"
id="Arrow2"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="Arrow2"
markerWidth="7.6999998"
markerHeight="5.5999999"
viewBox="0 0 7.7 5.6"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.7)"
d="M -2,-4 9,0 -2,4 c 2,-2.33 2,-5.66 0,-8 z"
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
id="arrow2L" />
</marker>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#eee8d5;stroke:#000000;stroke-width:0.2"
id="rect3879"
width="58.208332"
height="7.9375"
x="21.166666"
y="22.489584" />
<rect
style="fill:#aaeeff;stroke:#000000;stroke-width:0.2"
id="rect3881"
width="58.208332"
height="7.9375"
x="21.166666"
y="30.427084" />
<rect
style="fill:#eee8d5;stroke:#000000;stroke-width:0.2"
id="rect3883"
width="58.208332"
height="7.9375"
x="21.166666"
y="38.364582" />
<rect
style="fill:#ffaaaa;stroke:#000000;stroke-width:0.2"
id="rect3885"
width="58.208332"
height="7.9375"
x="21.166666"
y="46.302082" />
<rect
style="fill:#deaa87;stroke:#000000;stroke-width:0.2"
id="rect3887"
width="58.208332"
height="7.9375"
x="21.166666"
y="54.239582" />
<rect
style="fill:#eee8d5;stroke:#000000;stroke-width:0.2"
id="rect3889"
width="58.208332"
height="7.9375"
x="21.166666"
y="62.177082" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="34.193466"
y="35.369072"
id="text3645"><tspan
sodipodi:role="line"
id="tspan3643"
style="stroke-width:0.264583"
x="34.193466"
y="35.369072">Creating new task</tspan></text>
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="32.009281"
y="43.306568"
id="text3649"><tspan
sodipodi:role="line"
id="tspan3647"
style="stroke-width:0.264583"
x="32.009281"
y="43.306568">Unknown (app code)</tspan></text>
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="33.635365"
y="51.244068"
id="text3653"><tspan
sodipodi:role="line"
id="tspan3651"
style="stroke-width:0.264583"
x="33.635365"
y="51.244068">Running task Body</tspan></text>
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="39.037262"
y="59.181568"
id="text3657"><tspan
sodipodi:role="line"
style="stroke-width:0.264583"
x="39.037262"
y="59.181568"
id="tspan3659">Worker Body</tspan></text>
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="28.103415"
y="27.431572"
id="text3715"><tspan
sodipodi:role="line"
id="tspan3713"
style="stroke-width:0.264583"
x="28.103415"
y="27.431572">Unknown (memory alloc)</tspan></text>
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="36.400909"
y="67.460991"
id="text3893"><tspan
sodipodi:role="line"
id="tspan3891"
style="stroke-width:0.264583"
x="36.400909"
y="67.460991">Other frames ...</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2)"
d="m 79.747761,34.198069 c 9.27107,-0.479269 18.184197,3.203946 18.339362,26.014504"
id="path4008"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="84.488319"
y="67.429054"
id="text4012"><tspan
sodipodi:role="line"
id="tspan4010"
style="stroke-width:0.264583"
x="84.488319"
y="67.429054">Subsystem=Creating new task</tspan></text>
<text
xml:space="preserve"
style="font-size:3.52777px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="38.870174"
y="75.927666"
id="text4234"><tspan
sodipodi:role="line"
id="tspan4232"
style="stroke-width:0.264583"
x="38.870174"
y="75.927666">Thread stack</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB