Skip to content

Commit

Permalink
Fix \secref{} and \fig{}
Browse files Browse the repository at this point in the history
\sescref{} and \fig{} are replaced with corresponding anchors in HTML. 
Proper IDs are added to SVGs for reference.
  • Loading branch information
idoleat committed May 26, 2024
1 parent 1aafc98 commit e9e1615
Show file tree
Hide file tree
Showing 11 changed files with 15 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/atomic_operation_as_building_blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ In the second, subsequent sensor inputs could be missed if the <small>ISR</small
Lockless algorithms are not inherently superior or quicker than blocking ones;
they serve different purposes with their own design philosophies.
Additionally, the mere use of atomic operations does not render algorithms lock-free.
For example, our basic spinlock discussed in \secref{spinlock} is still considered a blocking algorithm even though it eschews <small>OS</small>-specific syscalls for making the blocked thread sleep.
For example, our basic spinlock discussed in [test and set](/read-modify-write/test_and_set.html#test-and-set) is still considered a blocking algorithm even though it eschews <small>OS</small>-specific syscalls for making the blocked thread sleep.
Putting a blocked thread to sleep is often an optimization,
allowing the operating system's scheduler to allocate <small>CPU</small> resources to active threads until the blocked one is revived.
Some concurrency libraries even introduce hybrid locks that combine brief spinning with sleeping to balance <small>CPU</small> usage and context-switching overheads.
Expand Down
8 changes: 4 additions & 4 deletions src/background.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ Furthermore, calculations might be performed speculatively ahead of a branch dec
Even without compiler alterations,
we would face challenges because our hardware complicates matters further!
Modern <small>CPU</small>s operate in a fashion far more complex than what traditional pipelined methods,
like those depicted in \fig{pipeline}<!--FIXME-->, suggest.
like those depicted in the figure below, suggest.
They are equipped with multiple data paths tailored for various instruction types and schedulers that reorder and direct instructions through these paths.

{{#include images/pipeline.svg}}
> *A traditional five-stage <small>CPU</small> pipeline with fetch, decode, execute, memory access, and write-back stages. Modern designs are much more complicated, often reordering instructions on the fly.*
It is quite common to form oversimplified views about memory operations.
Picturing a multi-core processor setup might lead us to envision a model similar to \fig{ideal-machine}, <!--FIXME-->
Picturing a multi-core processor setup might lead us to envision a model similar to the figure below,
wherein each core alternately accesses and manipulates the system's memory.

{{#include images/ideal-machine.svg}}
Expand All @@ -83,12 +83,12 @@ Establishing some semblance of order among threads requires a concerted effort i
compiler, programming language, and your application.
Let's delve into our options and the tools necessary for this endeavor.

[^a]: Most <small>CPU</small> architectures execute segments of multiple instructions concurrently to improve throughput (refer to \fig{pipeline}).<!--FIXME-->
[^a]: Most <small>CPU</small> architectures execute segments of multiple instructions concurrently to improve throughput (refer to the [pipeline figure](#pipeline)).
A stall, or suspension of forward progress, occurs when an instruction awaits the outcome of a preceding one in the pipeline until the necessary result becomes available.

[^b]: <small>RAM</small> accesses data not byte by byte, but in larger units known as *cache lines*.
Grouping frequently used variables on the same cache line means they are processed together,
significantly boosting performance. However, as discussed in \secref{false-sharing}, <!--FIXME-->
significantly boosting performance. However, as discussed in [false-sharing](/cache_effect_and_false_sharing.html) chapter,
this strategy can lead to complications when cache lines are shared across cores.

[^c]: Profile-guided optimization (PGO) often employs this strategy.
2 changes: 1 addition & 1 deletion src/do_we_always_need_seq-cst.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ But as you might expect, these barriers can have a noticeable impact on performa
After all, they inhibit optimizations that your compiler and hardware would otherwise make.

What if we could avoid some of this slowdown?
Consider a simple case like the spinlock from \secref{spinlock}. <!--FIXME-->
Consider a simple case like the spinlock from [test and set](/read-modify-write/test_and_set.html#test-and-set).
Between the `lock()` and `unlock()` calls, we have a *critical section* where we can safely modify shared state protected by the lock.
Outside this critical section, we only read and write to things that are not shared with other threads.
```cpp
Expand Down
2 changes: 1 addition & 1 deletion src/images/ideal-machine.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/images/mp-cache.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/images/pipeline.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/memory_ordering/acq_and_rel.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Acquire and release

We have just examined the acquire and release operations in the context of the lock example from \secref{lock-example}.<!--FIXME-->
We have just examined the acquire and release operations in the context of the lock example from [last chapter](/do_we_always_need_seq-cst.html).
You can think of them as "one-way" barriers: an acquire operation permits other reads and writes to move past it,
but only in a \\(before\to after\\) direction.
A release works the opposite manner, allowing actions to move in an \\(after\to before\\) direction.
Expand Down Expand Up @@ -50,7 +50,7 @@ if thread *W* stores a value with release semantics,
and thread *R* loads that value with acquire semantics,
then all writes made by *W* before its store-release are observable to *R* after its load-acquire.
If this sounds familiar, it is exactly what we were trying to achieve in
\secref{background} and \secref{seqcst}: <!--FIXME-->
chapter [background](/background.html) and [enforcing law and order](/enforcing_law_and_order.html):
```cpp
int v;
std::atomic_bool v_ready(false);
Expand Down
2 changes: 1 addition & 1 deletion src/memory_ordering/relaxed.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Relaxed atomic operations are useful for variables shared between threads where *no specific order* of operations is needed.
Although it may seem like a niche requirement, such scenarios are quite common.

Refer back to our discussions on \secref{atomicity} and \secref{rmw} operations, <!--FIXME-->
Refer back to our discussions on chapter [Atomicity](/atomicity.html) and [read-modify-write operations](/read-modify-write.html),
where a worker thread increments a counter that a <small>UI</small> thread then reads.
In this case, the counter can be incremented using `fetch_add(1, memory_order_relaxed)` because the only requirement is atomicity;
the counter itself does not coordinate synchronization.
Expand Down
3 changes: 1 addition & 2 deletions src/read-modify-write/compare_and_swap.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ bool atomic<T>::compare_exchange_strong(
```

The `compare_exchange_strong` suffix may leave you wondering if there is a corresponding "weak" <small>CAS</small>.
Indeed, there is. However, we will delve into that topic later in \secref{spurious-llsc-failures}.<!--FIXME-->

Indeed, there is. However, we will delve into that topic later in chapter [Spurious LL/SC failures](/spurious_ll-sc_failures.html).
Let's say we have some long-running task that we might want to cancel.
We'll give it three states: *idle*, *running*, and *cancelled*, and write a loop that exits when it is cancelled.

Expand Down
2 changes: 1 addition & 1 deletion src/read-modify-write/exchange.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The simplest atomic <small>RMW</small> operation is an *exchange*:
the current value is read and replaced with a new one.
To see where this might be useful,
let's tweak our example from \secref{atomicity}:
let's tweak our example from chapter [Atomicity](/atomicity.html):
instead of displaying the total number of processed files,
the <small>UI</small> might want to show how many were processed per second.
We could implement this by having the <small>UI</small> thread read the counter then zero it each second.
Expand Down
2 changes: 1 addition & 1 deletion src/volatile.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Before we go, we should lay a common misconception surrounding the `volatile` ke
Perhaps because of how it worked in older compilers and hardware,
or due to its different meaning in languages like Java and C#,\punckern<small>footnote</small>[^a]
some believe that the keyword is useful for building concurrency tools.
Except for one specific case (see \secref{fusing}<!--FIXME-->), this is false.
Except for one specific case (see [Atomic fusion](/atomic_fusion.html) chapter), this is false.

The purpose of `volatile` is to inform the compiler that a value can be changed by something besides the program we are executing.
This is useful for memory-mapped <small>IO</small> (<small>MMIO</small>),
Expand Down

0 comments on commit e9e1615

Please sign in to comment.