From 6172227724b04721095d3c3b48b0d1ee288b9e83 Mon Sep 17 00:00:00 2001 From: ridethepig Date: Wed, 12 Apr 2023 01:01:51 +0800 Subject: [PATCH] OSTEP Chapter 31 --- assets/ostep_1681115599584_0.edn | 381 +++++++++++++++++- journals/2023_04_11.md | 1 + .../2023-04-11T13_46_14.704Z.Desktop.md | 133 ++++++ pages/hls__ostep_1681115599584_0.md | 193 ++++++++- 4 files changed, 704 insertions(+), 4 deletions(-) create mode 100644 journals/2023_04_11.md create mode 100644 logseq/bak/pages/hls__ostep_1681115599584_0/2023-04-11T13_46_14.704Z.Desktop.md diff --git a/assets/ostep_1681115599584_0.edn b/assets/ostep_1681115599584_0.edn index 0ac733e..27edb8f 100644 --- a/assets/ostep_1681115599584_0.edn +++ b/assets/ostep_1681115599584_0.edn @@ -1812,5 +1812,384 @@ :height 1296}), :page 390}, :content {:text "spurious wakeups"}, + :properties {:color "yellow"}} + {:id #uuid "64356d96-cce8-48ad-80f1-e3e02a1a4684", + :page 396, + :position {:bounding {:x1 131.578125, + :y1 921.546875, + :x2 249.6654510498047, + :y2 945.546875, + :width 979.1999999999999, + :height 1468.8}, + :rects ({:x1 131.578125, + :y1 921.546875, + :x2 249.6654510498047, + :y2 945.546875, + :width 979.1999999999999, + :height 1468.8}), + :page 396}, + :content {:text "Semaphores"}, + :properties {:color "yellow"}} + {:id #uuid "64356dba-48b4-49b8-8182-c962f12f03a5", + :page 396, + :position {:bounding {:x1 0, + :y1 301, + :x2 784.2239990234375, + :y2 1009.59375, + :width 979.1999999999999, + :height 1468.8}, + :rects ({:x1 0, + :y1 301, + :x2 0, + :y2 323, + :width 979.1999999999999, + :height 1468.8} + {:x1 158.6875, + :y1 967, + :x2 784.2239990234375, + :y2 987, + :width 979.1999999999999, + :height 1468.8} + {:x1 131.578125, + :y1 989.59375, + :x2 290.9900207519531, + :y2 1009.59375, + :width 979.1999999999999, + :height 1468.8}), + :page 396}, + :content {:text "A semaphore is an object with an integer value that we can manipulate with two routines;"}, + :properties {:color "yellow"}} + {:id #uuid "64357404-d348-42b3-96a3-ba28575baa66", + :page 397, + :position {:bounding {:x1 402.39794921875, + :y1 611.3125, + :x2 466.92041015625, + :y2 630.3125, + :width 921.6, + :height 1382.4}, + :rects ({:x1 402.39794921875, + :y1 611.3125, + :x2 466.92041015625, + :y2 630.3125, + :width 921.6, + :height 1382.4}), + :page 397}, + :content {:text "salient "}, + :properties {:color "green"}} + {:id #uuid "6435744b-a300-40ad-ba91-157666d8cd2a", + :page 397, + :position {:bounding {:x1 359.15777587890625, + :y1 1154.46875, + :x2 725.4879150390625, + :y2 1179.46875, + :width 921.6, + :height 1382.4}, + :rects ({:x1 359.171875, + :y1 1154.46875, + :x2 725.4879150390625, + :y2 1179.46875, + :width 921.6, + :height 1382.4} + {:x1 359.15777587890625, + :y1 1156.1875, + :x2 359.16748046875, + :y2 1175.1875, + :width 921.6, + :height 1382.4}), + :page 397}, + :content {:text "Semaphore: Definitions Of Wait And Post"}, + :properties {:color "yellow"}} + {:id #uuid "64357512-e25b-4226-961a-caec367fc8a3", + :page 397, + :position {:bounding {:x1 0, + :y1 477, + :x2 797.5911254882812, + :y2 864.109375, + :width 921.6, + :height 1382.4}, + :rects ({:x1 0, + :y1 477, + :x2 0, + :y2 499, + :width 921.6, + :height 1382.4} + {:x1 208.84375, + :y1 823.859375, + :x2 797.5911254882812, + :y2 842.859375, + :width 921.6, + :height 1382.4} + {:x1 183.359375, + :y1 845.109375, + :x2 379.579833984375, + :y2 864.109375, + :width 921.6, + :height 1382.4}), + :page 397}, + :content {:text "Third, the value of the semaphore, when negative, is equal to the number of waiting threads "}, + :properties {:color "yellow"}} + {:id #uuid "6435753a-65b5-4e46-82bc-54c11c1cd533", + :page 398, + :position {:bounding {:x1 123.828125, + :y1 461.921875, + :x2 404.9288024902344, + :y2 484.921875, + :width 921.6, + :height 1382.4}, + :rects ({:x1 123.828125, + :y1 461.921875, + :x2 404.9288024902344, + :y2 484.921875, + :width 921.6, + :height 1382.4}), + :page 398}, + :content {:text "Binary Semaphores (Locks)"}, + :properties {:color "yellow"}} + {:id #uuid "64357930-2d96-4867-bc3d-2fe89990ce5f", + :page 399, + :position {:bounding {:x1 183.359375, + :y1 1122.015625, + :x2 450.3201599121094, + :y2 1145.015625, + :width 921.6, + :height 1382.4}, + :rects ({:x1 183.359375, + :y1 1122.015625, + :x2 450.3201599121094, + :y2 1145.015625, + :width 921.6, + :height 1382.4}), + :page 399}, + :content {:text "Semaphores For Ordering"}, + :properties {:color "yellow"}} + {:id #uuid "64357c6d-381e-492e-b901-095454f5315e", + :page 401, + :position {:bounding {:x1 183.33059692382812, + :y1 1062.84375, + :x2 721.8597412109375, + :y2 1085.84375, + :width 921.6, + :height 1382.4}, + :rects ({:x1 183.33059692382812, + :y1 1062.84375, + :x2 721.8597412109375, + :y2 1085.84375, + :width 921.6, + :height 1382.4}), + :page 401}, + :content {:text "The Producer/Consumer (Bounded Buffer) Problem"}, + :properties {:color "yellow"}} + {:id #uuid "643583b4-26b1-4cbf-801c-11ed6e63976e", + :page 406, + :position {:bounding {:x1 123.828125, + :y1 331.78125, + :x2 335.4051513671875, + :y2 354.78125, + :width 921.6, + :height 1382.4}, + :rects ({:x1 123.828125, + :y1 331.78125, + :x2 335.4051513671875, + :y2 354.78125, + :width 921.6, + :height 1382.4}), + :page 406}, + :content {:text "Reader-Writer Locks"}, + :properties {:color "yellow"}} + {:id #uuid "64358755-1fae-4ea2-93a3-8c9d3d3e11c3", + :page 411, + :position {:bounding {:x1 726.3629150390625, + :y1 422.703125, + :x2 761.9802856445312, + :y2 441.703125, + :width 921.6, + :height 1382.4}, + :rects ({:x1 726.3629150390625, + :y1 422.703125, + :x2 761.9802856445312, + :y2 441.703125, + :width 921.6, + :height 1382.4}), + :page 411}, + :content {:text " bog"}, + :properties {:color "green"}} + {:id #uuid "64358758-cb9c-4e8d-aaa4-f8e50457db88", + :page 411, + :position {:bounding {:x1 259.0669860839844, + :y1 334.59375, + :x2 367.23944091796875, + :y2 357.59375, + :width 921.6, + :height 1382.4}, + :rects ({:x1 259.0669860839844, + :y1 334.59375, + :x2 367.23944091796875, + :y2 357.59375, + :width 921.6, + :height 1382.4}), + :page 411}, + :content {:text "Throttling"}, + :properties {:color "green"}} + {:id #uuid "643587a7-ade4-4f09-be50-aea233ff02c0", + :page 408, + :position {:bounding {:x1 123.81153106689453, + :y1 539.671875, + :x2 380.1902160644531, + :y2 562.671875, + :width 921.6, + :height 1382.4}, + :rects ({:x1 123.81153106689453, + :y1 539.671875, + :x2 380.1902160644531, + :y2 562.671875, + :width 921.6, + :height 1382.4}), + :page 408}, + :content {:text "The Dining Philosophers"}, + :properties {:color "yellow"}} + {:id #uuid "64358802-3b22-46ed-a0e2-71cc9df69a7b", + :page 408, + :position {:bounding {:x1 513.1211547851562, + :y1 882.953125, + :x2 556.3884887695312, + :y2 901.953125, + :width 921.6, + :height 1382.4}, + :rects ({:x1 513.1211547851562, + :y1 882.953125, + :x2 556.3884887695312, + :y2 901.953125, + :width 921.6, + :height 1382.4}), + :page 408}, + :content {:text "ensue"}, + :properties {:color "green"}} + {:id #uuid "6435889f-1375-4b94-8630-b3d0d7bdfa56", + :page 408, + :position {:bounding {:x1 0, + :y1 381, + :x2 738.0819091796875, + :y2 901.953125, + :width 921.6, + :height 1382.4}, + :rects ({:x1 0, + :y1 381, + :x2 0, + :y2 403, + :width 921.6, + :height 1382.4} + {:x1 0, + :y1 397, + :x2 0, + :y2 419, + :width 921.6, + :height 1382.4} + {:x1 0, + :y1 413, + :x2 0, + :y2 435, + :width 921.6, + :height 1382.4} + {:x1 0, + :y1 429, + :x2 0, + :y2 451, + :width 921.6, + :height 1382.4} + {:x1 0, + :y1 445, + :x2 0, + :y2 467, + :width 921.6, + :height 1382.4} + {:x1 174.31170654296875, + :y1 776.6875, + :x2 738.0610961914062, + :y2 795.6875, + :width 921.6, + :height 1382.4} + {:x1 123.828125, + :y1 797.9375, + :x2 738.0778198242188, + :y2 817.0625, + :width 921.6, + :height 1382.4} + {:x1 123.828125, + :y1 819.1875, + :x2 738.0721435546875, + :y2 838.3125, + :width 921.6, + :height 1382.4} + {:x1 123.828125, + :y1 840.4375, + :x2 738.0819091796875, + :y2 859.5625, + :width 921.6, + :height 1382.4} + {:x1 123.828125, + :y1 861.703125, + :x2 738.0709838867188, + :y2 880.828125, + :width 921.6, + :height 1382.4} + {:x1 123.828125, + :y1 882.953125, + :x2 175.7489471435547, + :y2 901.953125, + :width 921.6, + :height 1382.4}), + :page 408}, + :content {:text "here are five “philosophers” sitting around a table. Between each pair of philosophers is a single fork (and thus, five total). The philosophers each have times where they think, and don’t need any forks, and times where they eat. In order to eat, a philosopher needs two forks, both the one on their left and the one on their right. The contention for these forks,"}, + :properties {:color "yellow"}} + {:id #uuid "643589a6-31e6-4603-9259-999e9c8860f7", + :page 411, + :position {:bounding {:x1 269.5417785644531, + :y1 887.1875, + :x2 515.8197631835938, + :y2 910.1875, + :width 921.6, + :height 1382.4}, + :rects ({:x1 269.5417785644531, + :y1 887.1875, + :x2 515.8197631835938, + :y2 910.1875, + :width 921.6, + :height 1382.4}), + :page 411}, + :content {:text "Implement Semaphores"}, + :properties {:color "yellow"}} + {:id #uuid "64358b0c-e441-4d0a-852d-ecfde369306c", + :page 410, + :position {:bounding {:x1 627.167236328125, + :y1 1150.953125, + :x2 738.0892333984375, + :y2 1169.953125, + :width 921.6, + :height 1382.4}, + :rects ({:x1 627.167236328125, + :y1 1150.953125, + :x2 738.0892333984375, + :y2 1169.953125, + :width 921.6, + :height 1382.4}), + :page 410}, + :content {:text "ramifications"}, + :properties {:color "green"}} + {:id #uuid "64358de1-f418-44fd-8a77-bc0faa368059", + :page 412, + :position {:bounding {:x1 274.109375, + :y1 773.328125, + :x2 701.076904296875, + :y2 798.328125, + :width 921.6, + :height 1382.4}, + :rects ({:x1 274.109375, + :y1 773.328125, + :x2 701.076904296875, + :y2 798.328125, + :width 921.6, + :height 1382.4}), + :page 412}, + :content {:text "Implementing Zemaphores With Locks And CVs"}, :properties {:color "yellow"}}], - :extra {:page 396}} + :extra {:page 416}} diff --git a/journals/2023_04_11.md b/journals/2023_04_11.md new file mode 100644 index 0000000..4697855 --- /dev/null +++ b/journals/2023_04_11.md @@ -0,0 +1 @@ +- 大概了解了一下体系结构方向的东西 \ No newline at end of file diff --git a/logseq/bak/pages/hls__ostep_1681115599584_0/2023-04-11T13_46_14.704Z.Desktop.md b/logseq/bak/pages/hls__ostep_1681115599584_0/2023-04-11T13_46_14.704Z.Desktop.md new file mode 100644 index 0000000..248a0eb --- /dev/null +++ b/logseq/bak/pages/hls__ostep_1681115599584_0/2023-04-11T13_46_14.704Z.Desktop.md @@ -0,0 +1,133 @@ +file:: [ostep_1681115599584_0.pdf](../assets/ostep_1681115599584_0.pdf) +file-path:: ../assets/ostep_1681115599584_0.pdf + +- # Part II +- thread + ls-type:: annotation + hl-page:: 311 + hl-color:: yellow + id:: 6433ca28-1bdf-433d-8ed9-0d54bf5ba940 + - share the same address space and thus can access the same data + - context switch: the address space remains the same + hl-page:: 311 + ls-type:: annotation + id:: 6433cb70-d168-4863-8268-1e969df6ce06 + hl-color:: yellow + - thread control blocks + ls-type:: annotation + hl-page:: 311 + hl-color:: yellow + id:: 6433cb56-fbef-46da-83c2-13fa2dba2967 + - thread-local storage: one stack per thread in the address space + hl-page:: 312 + ls-type:: annotation + id:: 6433cba2-61bd-4549-a29f-2ad85b3e30cd + hl-color:: yellow + - Why thread? + - possible speedup through parallelization + - enable overlap of IO in a single program + - Though these could be done through multi-processing, threading makes share data easier +- KEY CONCURRENCY TERMS + ls-type:: annotation + hl-page:: 323 + hl-color:: yellow + id:: 6433eabf-48d6-4776-b66f-a5f7804d1ddc + - **indeterminate**: the results depend on the timing execution of the code. + - race condition + ls-type:: annotation + hl-page:: 320 + hl-color:: yellow + id:: 6433e4cc-69e4-4057-8cc6-1766240d82f4 + - A **critical section** is a piece of code that accesses a shared variable (or resource) and must not be concurrently executed by more than one thread. + hl-page:: 320 + ls-type:: annotation + id:: 6433e52b-1f38-4f7c-b168-0aed624f9bdf + hl-color:: yellow + - **mutual exclusion**: This property guarantees that if one thread is executing within the *critical section*, the others will be prevented from doing so. + hl-page:: 320 + ls-type:: annotation + id:: 6433e566-e6ef-45b3-84b1-eba981be914a + hl-color:: yellow + - Atomicity: *as a unit*, or, *all or none* + hl-page:: 321 + ls-type:: annotation + id:: 6433e6a1-407c-4936-b184-dee868ef4107 + hl-color:: yellow + - synchronization primitives + ls-type:: annotation + hl-page:: 322 + hl-color:: yellow + id:: 6433e729-7043-453b-8d60-6e6c41560543 +- sane 精神健全的;神志正常的;明智的;理智的 + ls-type:: annotation + hl-page:: 322 + hl-color:: green + id:: 6433e6e7-d995-4b69-96b3-261b79f94c1d +- Thread API + hl-page:: 327 + ls-type:: annotation + id:: 6433f35b-403b-4b25-b9f9-076e9e34777e + hl-color:: yellow + - `pthread_create` `pthread_join` `pthread_mutex_lock` `pthread_cond_*` +- Locks + ls-type:: annotation + hl-page:: 339 + hl-color:: yellow + id:: 6433f45b-0345-4790-8379-3d1a94e57ef5 + - A lock is just a variable + hl-page:: 339 + ls-type:: annotation + id:: 6433f4ba-f2e4-4743-a536-e2b7747433b7 + hl-color:: yellow + - **lock variable**: some type of variable, which holds the *state* of the lock(and maybe additional data such as its holder or a queue for acquisition) + - **lock state**: available (or unlocked or free); acquired (or locked or held) + - **lock routines**: + - `lock()` tries to acquire the lock. If no other thread holds the lock, the thread will acquire the lock and enter the critical section(become the owner of the lock). Otherwise, it will not return while the lock is held by another thread. + - `unlock()` : The owner of the lock calls `unlock()`, then it is *available* again. If there are waiting threads, one of them will (eventually) notice (or be informed of) this change of the lock's state, acquire the lock, and enter the critical section. + - Locks help transform the chaos that is traditional OS scheduling into a more controlled activity + hl-page:: 340 + ls-type:: annotation + id:: 6433f5e6-bc06-42a9-866e-e9a3053f528f + hl-color:: yellow + - Controlling Interrupts + ls-type:: annotation + hl-page:: 342 + hl-color:: yellow + id:: 6433fbfd-a1bf-4fd9-a54d-e15189c77b15 + - For *single-processor* systems, **disable interrupts** for critical sections. + - Problems + - disable interrupts is privileged. In the worst case, the OS may never regain control when the interrupt isn't going to be enabled. + - does NOT work on multi-processor systems, each CPU has its own interrupt state + - importance interrupts may get lost + - inefficient + - Just Using Loads/Stores(Fail) + hl-page:: 343 + ls-type:: annotation + id:: 6433fe7e-2221-41ee-ad6b-7deaa4459aa5 + hl-color:: yellow + - use a simple variable (flag) to indicate whether some thread has possession of a lock + hl-page:: 343 + ls-type:: annotation + id:: 6433ff4a-856d-4e4b-af30-6cb600aefeb5 + hl-color:: yellow + - On acquisition, load, test the flag. If free, set the flag; If not free, spin-wait(loop load and test). + - On releasing, clear the flag. + - Problem + - When interrupted between load and test, *mutual exclusion* is broken. + - Low efficiency because of spin-waiting. + - Spin Locks with Test-And-Set + ls-type:: annotation + hl-page:: 344 + hl-color:: yellow + id:: 64340154-807c-4a7a-b783-045d5d6d3927 + - **test-and-set (or atomic exchange) instruction** + hl-page:: 344 + ls-type:: annotation + id:: 643401e0-fcec-41d3-9898-d5c4175ac464 + hl-color:: yellow + - +- efficacy + ls-type:: annotation + hl-page:: 341 + hl-color:: green + id:: 6433fb69-1425-46b4-996f-f91da5d3e8d0 \ No newline at end of file diff --git a/pages/hls__ostep_1681115599584_0.md b/pages/hls__ostep_1681115599584_0.md index 523653b..da2a900 100644 --- a/pages/hls__ostep_1681115599584_0.md +++ b/pages/hls__ostep_1681115599584_0.md @@ -499,11 +499,12 @@ file-path:: ../assets/ostep_1681115599584_0.pdf hl-page:: 380 hl-color:: yellow id:: 643547c5-1613-49e9-899e-0e86f59a1462 -- stem - ls-type:: annotation +- stem (花草的)茎;(花或叶的)梗,柄;阻止;封堵;遏止; hl-page:: 379 - hl-color:: green + ls-type:: annotation id:: 64353eb8-8ed8-4680-a3c0-91608b429408 + hl-color:: green + - **stem from sth ** 是…的结果;起源于;根源是 - **producer/consumer problem** hl-page:: 382 ls-type:: annotation @@ -583,4 +584,190 @@ file-path:: ../assets/ostep_1681115599584_0.pdf hl-page:: 390 ls-type:: annotation id:: 643554f4-75a7-48fa-9366-87058ee723fb + hl-color:: green +- Semaphores + ls-type:: annotation + hl-page:: 396 + hl-color:: yellow + id:: 64356d96-cce8-48ad-80f1-e3e02a1a4684 + - A semaphore is an ==object with an integer value== that we can manipulate with two routines `sem_wait()` and `sem_post()`. The initial value determines its behavior, so we need to give it an initial value through `sem_init()` + hl-page:: 396 + ls-type:: annotation + id:: 64356dba-48b4-49b8-8182-c962f12f03a5 + hl-color:: yellow + - Semaphore: Definitions Of **Wait And Post** + ls-type:: annotation + hl-page:: 397 + hl-color:: yellow + id:: 6435744b-a300-40ad-ba91-157666d8cd2a + collapsed:: true + - `sem_wait(sem_t *s)`: First decrement the value of the semaphore by one. Then wait if the value of semaphore is negative + - `sem_post(sem_t*s)`: First increment the value of the semaphore by one. If there is any thread waiting, wait up one of them + - The value of the semaphore, *when negative*, is equal to the ==number of waiting threads== + hl-page:: 397 + ls-type:: annotation + id:: 64357512-e25b-4226-961a-caec367fc8a3 + hl-color:: yellow + - **Binary Semaphores (Locks)** + ls-type:: annotation + hl-page:: 398 + hl-color:: yellow + id:: 6435753a-65b5-4e46-82bc-54c11c1cd533 + collapsed:: true + - Initialize semaphore to 1, indicating we only have one piece of resource (the critical section). + - Wrap the critical section with `sem_wait` and `sem_post` + - When the lock is acquired, the semaphore is 0. On another acquisition request, the value goes to -1, which makes the caller sleep. When the lock is free, the value is decreased to 0 on acquisition, which will not get stuck. + - **Semaphores For Ordering (Condition Variable, or Ordering Primitive)** + hl-page:: 399 + ls-type:: annotation + id:: 64357930-2d96-4867-bc3d-2fe89990ce5f + hl-color:: yellow + collapsed:: true + - Initialize the semaphore to 0 + - Consider the *join* operation. The parent calls `sem_wait`and the child calls `sem_post`. In either case, no matter which thread is scheduled first, the semaphore guarantees the desired result. + - **The Producer/Consumer (Bounded Buffer) Problem (Again)** + hl-page:: 401 + ls-type:: annotation + id:: 64357c6d-381e-492e-b901-095454f5315e + hl-color:: yellow + collapsed:: true + - 2 semaphores `empty` and `full` for coordination between consumer and producer, and 1 semaphore for lock + - Initialize `empty <- MAX`, and `full <- 0` + - Consumer waits for `full` and posts `empty` and conversely, produce waits for `empty` and posts `full` + - Special case for `MAX=1` + - When only one slot is available in the buffer, we don't even need a lock! Actually, it is binary semaphore which not only controls the buffer entry but also works as a lock. + - Otherwise, there will be a ==data race== inside the `put/get` operation due to potential multi-thread access to these procedures (when `MAX > 1`, the `sem_wait(&empty)` may allow in more than one thread). + - Deadlock avoidance + - If the lock semaphore is the outmost semaphore, deadlock occurs (the thread may sleep in `sem_wait(&empty)` with `mutex` unrelease). Therefore, put the lock inside the `empty/full` semaphore pair. + - Implement + ```C + int empty = MAX, full = 0, mutex = 1; + void *producer() { + for (int i = 0; i < loops; ++ i) { + sem_wait(&empty); + sem_wait(&mutex); + put(i); + sem_post(&mutex); + sem_post(&full); + } + } + void *consumer() { + for (int i = 0; i < loops; ++ i) { + sem_wait(&full); + sem_wait(&mutex); + int tmp = get(); + sem_post(&mutex); + sem_post(&empty); + printf("%d\n", tmp); + } + } + ``` + - **Reader-Writer Locks** + ls-type:: annotation + hl-page:: 406 + hl-color:: yellow + id:: 643583b4-26b1-4cbf-801c-11ed6e63976e + - Either allow ==multiple readers to read== concurrently, or allow ==only one writer to write==. + - Two sets of operation + - `rwlock_acquire/release_writelock()`: simply `wait/post` the `writelock` + - `rwlock_acquire/release_readlock()`: acquire `writelock` when the ==first reader acquires==, and release it when the ==last reader releases== + - Implement + ```C + typedef struct _rwlock_t { + sem_t guard; // binary semaphore (basic lock) + sem_t writelock; // allow ONE writer/MANY readers + int readers; // #readers in critical section + } rwlock_t; + void rwlock_acquire_readlock(rwlock_t *rw) { + sem_wait(&rw->guard); + if (++rw->readers == 1) sem_wait(&rw->writelock); + sem_post(&rw->guard); + } + void rwlock_release_readlock(rwlock_t *rw) { + sem_wait(&rw->guard); + if (--rw->readers == 0) sem_post(&rw->writelock); + sem_post(&rw->guard); + } + void rwlock_acquire_writelock(rwlock_t *rw) { sem_wait(&rw->writelock); } + void rwlock_release_writelock(rwlock_t *rw) { sem_post(&rw->writelock); } + ``` + - Problem: More overhead; Unfairness, writer is much more likely to starve. + - To tackle the writer starvation problem, we may manually wake up the writers (if ever suspended) on read lock release. [Wiki](https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock) + - **The Dining Philosophers** + hl-page:: 408 + ls-type:: annotation + id:: 643587a7-ade4-4f09-be50-aea233ff02c0 + hl-color:: yellow + - Background setting + hl-page:: 408 + ls-type:: annotation + id:: 6435889f-1375-4b94-8630-b3d0d7bdfa56 + hl-color:: yellow + - 5 "philosophers" around a table. + Between each pair of philosophers is a single fork (and thus, 5 total). + The philosophers each have times where they think (don’t need forks), and times where they eat. + In order to eat, a philosopher needs two forks (left and right). + The contention for these forks is our synchronization problem. + - Solution + - A semaphore per fork, and helper function `left/right(p)` which is the fork on philosopher `p`'s left/right. + - Deadlock: if each philosopher tries to grab the fork on their left first, there will be a deadlock. When all of them get their left-side forks, all of the forks are locked and no one could get their right-side fork. + - Non-deadlock: force one philosopher to try to grab the right-side fork first + - Implement + ```C + void put_forks(int p) { + sem_post(&forks[left(p)]); + sem_post(&forks[right(p)]); + } + void get_forks(int p) { + if (p == 4) { + sem_wait(&forks[right(p)]); + sem_wait(&forks[left(p)]); + } else { + sem_wait(&forks[left(p)]); + sem_wait(&forks[right(p)]); + } + } + void philosopher() { + while (1) { + think(); + get_forks(p); + eat(); + put_forks(p); + } + } + ``` + - Implement Semaphores + ls-type:: annotation + hl-page:: 411 + hl-color:: yellow + id:: 643589a6-31e6-4603-9259-999e9c8860f7 + - Implementing Zemaphores With One Lock And One CV: the book authors provide us a simple implement for semaphore, though somewhat different from its definition. + hl-page:: 412 + ls-type:: annotation + id:: 64358de1-f418-44fd-8a77-bc0faa368059 + hl-color:: yellow +- salient 最重要的;显着的;突出的: + ls-type:: annotation + hl-page:: 397 + hl-color:: green + id:: 64357404-d348-42b3-96a3-ba28575baa66 +- ensue 跟着发生,接着发生; + ls-type:: annotation + hl-page:: 408 + hl-color:: green + id:: 64358802-3b22-46ed-a0e2-71cc9df69a7b +- Throttle 节流阀;风门;喉咙;使窒息;使节流; + hl-page:: 411 + ls-type:: annotation + id:: 64358758-cb9c-4e8d-aaa4-f8e50457db88 + hl-color:: green +- bog 沼泽;泥塘;使陷于泥沼;使动弹不得 + hl-page:: 411 + ls-type:: annotation + id:: 64358755-1fae-4ea2-93a3-8c9d3d3e11c3 + hl-color:: green +- ramification (众多复杂而又难以预料的)结果,后果 + hl-page:: 410 + ls-type:: annotation + id:: 64358b0c-e441-4d0a-852d-ecfde369306c hl-color:: green \ No newline at end of file