This commit is contained in:
ridethepig 2023-04-12 21:43:34 +08:00
parent 6172227724
commit 083bb41b59
8 changed files with 2279 additions and 134 deletions

View File

@ -2191,5 +2191,650 @@
:height 1382.4}), :height 1382.4}),
:page 412}, :page 412},
:content {:text "Implementing Zemaphores With Locks And CVs"}, :content {:text "Implementing Zemaphores With Locks And CVs"},
:properties {:color "yellow"}}
{:id #uuid "64361e4c-62eb-4599-9809-0f77f9ce1cd0",
:page 420,
:position {:bounding {:x1 0,
:y1 156.57144165039062,
:x2 608.1144943237305,
:y2 438.83038330078125,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 0,
:y1 156.57144165039062,
:x2 0,
:y2 179.42858505249023,
:width 806.3999999999999,
:height 1209.6}
{:x1 115.01848602294922,
:y1 403.6607360839844,
:x2 608.1144943237305,
:y2 420.23216247558594,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714530944824,
:y1 422.2589569091797,
:x2 315.529935836792,
:y2 438.83038330078125,
:width 806.3999999999999,
:height 1209.6}),
:page 420},
:content {:text " large fraction (97%) of non-deadlock bugs studied by Lu et al. are either atomicity or order violations."},
:properties {:color "yellow"}}
{:id #uuid "64361fb7-5aa6-45cd-8b1e-aa0d0c300ad2",
:page 420,
:position {:bounding {:x1 108.35714912414551,
:y1 626.1071624755859,
:x2 202.0477237701416,
:y2 646.6785888671875,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 108.35714912414551,
:y1 626.1071624755859,
:x2 202.0477237701416,
:y2 646.6785888671875,
:width 806.3999999999999,
:height 1209.6}),
:page 420},
:content {:text "Deadlock "},
:properties {:color "yellow"}}
{:id #uuid "64361fd1-49ff-4023-8493-840ac423086a",
:page 422,
:position {:bounding {:x1 108.35714721679688,
:y1 356.9196548461914,
:x2 319.1251525878906,
:y2 381.49108123779297,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 108.35714721679688,
:y1 356.9196548461914,
:x2 319.1251525878906,
:y2 381.49108123779297,
:width 806.3999999999999,
:height 1209.6}),
:page 422},
:content {:text "Conditions for Deadlock"},
:properties {:color "yellow"}}
{:id #uuid "643620d9-cdb6-4073-89f4-f9f8ac223073",
:page 422,
:position {:bounding {:x1 108.35714340209961,
:y1 720.6875305175781,
:x2 201.34223556518555,
:y2 745.2589721679688,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 108.35714340209961,
:y1 720.6875305175781,
:x2 201.34223556518555,
:y2 745.2589721679688,
:width 806.3999999999999,
:height 1209.6}),
:page 422},
:content {:text "Prevention"},
:properties {:color "yellow"}}
{:id #uuid "643620fb-edc6-43b2-b4b2-43b010cfc46e",
:page 422,
:position {:bounding {:x1 108.35714340209961,
:y1 752.3482360839844,
:x2 209.8732566833496,
:y2 774.6339569091797,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 108.35714340209961,
:y1 752.3482360839844,
:x2 209.8732566833496,
:y2 774.6339569091797,
:width 806.3999999999999,
:height 1209.6}),
:page 422},
:content {:text "Circular Wait"},
:properties {:color "yellow"}}
{:id #uuid "64362497-58cd-45da-8ab5-84f96e899e16",
:page 423,
:position {:bounding {:x1 267.0553894042969,
:y1 182.01786041259766,
:x2 620.5501251220703,
:y2 198.58929443359375,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 267.0553894042969,
:y1 182.01786041259766,
:x2 620.5501251220703,
:y2 198.58929443359375,
:width 806.3999999999999,
:height 1209.6}),
:page 423},
:content {:text " ENFORCE LOCK ORDERING BY LOCK ADDRESS"},
:properties {:color "yellow"}}
{:id #uuid "643625fe-423c-4b18-8c22-32d38720c5d0",
:page 423,
:position {:bounding {:x1 160.4375,
:y1 835.7947082519531,
:x2 272.9983215332031,
:y2 858.0804290771484,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 160.4375,
:y1 835.7947082519531,
:x2 272.9983215332031,
:y2 858.0804290771484,
:width 806.3999999999999,
:height 1209.6}),
:page 423},
:content {:text "Hold-and-wait"},
:properties {:color "yellow"}}
{:id #uuid "64362632-50e8-41dd-a1bc-bbf3d4312b0f",
:page 424,
:position {:bounding {:x1 108.35714721679688,
:y1 433.40181732177734,
:x2 225.13265228271484,
:y2 455.6875305175781,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 108.35714721679688,
:y1 433.40181732177734,
:x2 225.13265228271484,
:y2 455.6875305175781,
:width 806.3999999999999,
:height 1209.6}),
:page 424},
:content {:text "No Preemption"},
:properties {:color "yellow"}}
{:id #uuid "6436281f-4fdc-4586-83fb-b686cec3b76b",
:page 424,
:position {:bounding {:x1 480.5625305175781,
:y1 782.1875152587891,
:x2 541.9588623046875,
:y2 804.4732208251953,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 480.5625305175781,
:y1 782.1875152587891,
:x2 541.9588623046875,
:y2 804.4732208251953,
:width 806.3999999999999,
:height 1209.6}),
:page 424},
:content {:text "livelock"},
:properties {:color "yellow"}}
{:id #uuid "643629ba-e746-41a6-b073-1199b3db3691",
:page 425,
:position {:bounding {:x1 160.43750953674316,
:y1 403.1428909301758,
:x2 295.75261878967285,
:y2 425.42859649658203,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 160.43750953674316,
:y1 403.1428909301758,
:x2 295.75261878967285,
:y2 425.42859649658203,
:width 806.3999999999999,
:height 1209.6}),
:page 425},
:content {:text "Mutual Exclusion"},
:properties {:color "yellow"}}
{:id #uuid "64362af4-9b35-4e27-8ba2-0f5f8817526a",
:page 427,
:position {:bounding {:x1 160.4375114440918,
:y1 380.5535888671875,
:x2 468.5610466003418,
:y2 405.12501525878906,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 160.4375114440918,
:y1 380.5535888671875,
:x2 468.5610466003418,
:y2 405.12501525878906,
:width 806.3999999999999,
:height 1209.6}),
:page 427},
:content {:text "Deadlock Avoidance via Scheduling"},
:properties {:color "yellow"}}
{:id #uuid "64362b38-6dfb-4c00-8aa6-b756e8983de4",
:page 428,
:position {:bounding {:x1 349.3137512207031,
:y1 238.16070556640625,
:x2 413.10858154296875,
:y2 254.73214721679688,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 349.3137512207031,
:y1 238.16070556640625,
:x2 413.10858154296875,
:y2 254.73214721679688,
:width 806.3999999999999,
:height 1209.6}),
:page 428},
:content {:text "terrific "},
:properties {:color "green"}}
{:id #uuid "64362b40-5f07-418f-83f3-c83eb5927c94",
:page 428,
:position {:bounding {:x1 498.1431884765625,
:y1 238.16070556640625,
:x2 533.5830993652344,
:y2 254.73214721679688,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 498.1431884765625,
:y1 238.16070556640625,
:x2 533.5830993652344,
:y2 254.73214721679688,
:width 806.3999999999999,
:height 1209.6}),
:page 428},
:content {:text "maxim"},
:properties {:color "green"}}
{:id #uuid "64362c62-3a12-4bcb-95ae-baf1ca69312e",
:page 428,
:position {:bounding {:x1 108.35715103149414,
:y1 973.8839721679688,
:x2 272.61272048950195,
:y2 998.4554138183594,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 108.35715103149414,
:y1 973.8839721679688,
:x2 272.61272048950195,
:y2 998.4554138183594,
:width 806.3999999999999,
:height 1209.6}),
:page 428},
:content {:text "Detect and Recover"},
:properties {:color "yellow"}}
{:id #uuid "64364569-01b4-45e1-83f8-ac1bd8af5850",
:page 432,
:position {:bounding {:x1 175.8877182006836,
:y1 630.8661041259766,
:x2 216.41903686523438,
:y2 647.4375152587891,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 175.8877182006836,
:y1 630.8661041259766,
:x2 216.41903686523438,
:y2 647.4375152587891,
:width 806.3999999999999,
:height 1209.6}),
:page 432},
:content {:text "nasty "},
:properties {:color "green"}}
{:id #uuid "64364585-ace4-4920-87fe-87aad004dffd",
:page 432,
:position {:bounding {:x1 193.21429443359375,
:y1 321.7768096923828,
:x2 501.472412109375,
:y2 357.20538330078125,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 193.21429443359375,
:y1 321.7768096923828,
:x2 501.472412109375,
:y2 357.20538330078125,
:width 806.3999999999999,
:height 1209.6}),
:page 432},
:content {:text "Event-based Concurrency"},
:properties {:color "yellow"}}
{:id #uuid "643658f3-4761-4d0c-b044-4cadcfea27aa",
:page 433,
:position {:bounding {:x1 372.4933624267578,
:y1 263.21429443359375,
:x2 449.53944396972656,
:y2 279.7857208251953,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 372.4933624267578,
:y1 263.21429443359375,
:x2 449.53944396972656,
:y2 279.7857208251953,
:width 806.3999999999999,
:height 1209.6}),
:page 433},
:content {:text "event loop"},
:properties {:color "yellow"}}
{:id #uuid "643658f9-5eee-4d1a-a3d6-4f8eb9ed3d7b",
:page 433,
:position {:bounding {:x1 281.8482208251953,
:y1 475.42857360839844,
:x2 381.6801300048828,
:y2 492.00001525878906,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 281.8482208251953,
:y1 475.42857360839844,
:x2 381.6801300048828,
:y2 492.00001525878906,
:width 806.3999999999999,
:height 1209.6}),
:page 433},
:content {:text "event handler"},
:properties {:color "yellow"}}
{:id #uuid "64365db8-a249-46bc-bd9c-237251c544b5",
:page 433,
:position {:bounding {:x1 335.05357360839844,
:y1 669.3125305175781,
:x2 408.33917236328125,
:y2 689.8839721679688,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 335.05357360839844,
:y1 669.3125305175781,
:x2 408.33917236328125,
:y2 689.8839721679688,
:width 806.3999999999999,
:height 1209.6}),
:page 433},
:content {:text "select"},
:properties {:color "yellow"}}
{:id #uuid "64365eb6-5310-4893-9d11-5e332ef84c4a",
:page 434,
:position {:bounding {:x1 0,
:y1 188.57144165039062,
:x2 631.6998062133789,
:y2 500.85716247558594,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 0,
:y1 188.57144165039062,
:x2 0,
:y2 211.42858123779297,
:width 806.3999999999999,
:height 1209.6}
{:x1 0,
:y1 204.57144165039062,
:x2 0,
:y2 227.42858123779297,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 447.0893096923828,
:x2 608.0915832519531,
:y2 463.66075134277344,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 465.68751525878906,
:x2 409.7574157714844,
:y2 482.42860412597656,
:width 806.3999999999999,
:height 1209.6}
{:x1 432.49109649658203,
:y1 465.68751525878906,
:x2 631.6998062133789,
:y2 482.42860412597656,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 484.28575134277344,
:x2 236.34325408935547,
:y2 500.85716247558594,
:width 806.3999999999999,
:height 1209.6}),
:page 434},
:content {:text "if some of their descriptors are ready for reading, are ready for writing, or have an exceptional condition pending, respectively. The first nfds descriptors are checked in each set, "},
:properties {:color "yellow"}}
{:id #uuid "64365ef8-3c62-4d78-8bc6-d0a4b2c81d49",
:page 434,
:position {:bounding {:x1 0,
:y1 236.571439743042,
:x2 617.7018737792969,
:y2 556.6428661346436,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 0,
:y1 236.571439743042,
:x2 0,
:y2 259.42858695983887,
:width 806.3999999999999,
:height 1209.6}
{:x1 0,
:y1 252.571439743042,
:x2 0,
:y2 275.42858695983887,
:width 806.3999999999999,
:height 1209.6}
{:x1 384.0608825683594,
:y1 502.88395500183105,
:x2 617.7018737792969,
:y2 519.4553661346436,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714912414551,
:y1 521.4732494354248,
:x2 608.120454788208,
:y2 538.2143383026123,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714912414551,
:y1 540.071455001831,
:x2 527.1530780792236,
:y2 556.6428661346436,
:width 806.3999999999999,
:height 1209.6}),
:page 434},
:content {:text "places the given descriptor sets with subsets consisting of those descriptors that are ready for the requested operation. select() returns the total number of ready descriptors in all the sets."},
:properties {:color "yellow"}}
{:id #uuid "643693db-d363-46ee-b0d6-910b30408946",
:page 437,
:position {:bounding {:x1 250.9367218017578,
:y1 155.14285278320312,
:x2 408.5350036621094,
:y2 174,
:width 748.8000000000001,
:height 1123.2},
:rects ({:x1 250.9367218017578,
:y1 155.14285278320312,
:x2 408.5350036621094,
:y2 174,
:width 748.8000000000001,
:height 1123.2}),
:page 437},
:content {:text " Asynchronous I/O"},
:properties {:color "yellow"}}
{:id #uuid "64369701-8a39-4aa4-9985-129572c04f53",
:page 437,
:position {:bounding {:x1 0,
:y1 76.5714111328125,
:x2 633.5952548980713,
:y2 291.6964111328125,
:width 748.8000000000001,
:height 1123.2},
:rects ({:x1 0,
:y1 76.5714111328125,
:x2 0,
:y2 99.42855834960938,
:width 748.8000000000001,
:height 1123.2}
{:x1 0,
:y1 92.5714111328125,
:x2 0,
:y2 115.42855834960938,
:width 748.8000000000001,
:height 1123.2}
{:x1 168.88722610473633,
:y1 241.72320556640625,
:x2 633.5932807922363,
:y2 257.15179443359375,
:width 748.8000000000001,
:height 1123.2}
{:x1 148.9732151031494,
:y1 259,
:x2 633.5952548980713,
:y2 274.54461669921875,
:width 748.8000000000001,
:height 1123.2}
{:x1 148.9732151031494,
:y1 276.26788330078125,
:x2 480.4746799468994,
:y2 291.6964111328125,
:width 748.8000000000001,
:height 1123.2}),
:page 437},
:content {:text "issue an I/O request and return control immediately to the caller, before the I/O has completed; additional interfaces enable an application to determine whether various I/Os have completed."},
:properties {:color "yellow"}}
{:id #uuid "6436a3d9-ee29-4378-af79-4efc770cc209",
:page 438,
:position {:bounding {:x1 0,
:y1 300.5714454650879,
:x2 608.117431640625,
:y2 641.8750305175781,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 0,
:y1 300.5714454650879,
:x2 0,
:y2 323.4285888671875,
:width 806.3999999999999,
:height 1209.6}
{:x1 0,
:y1 316.5714454650879,
:x2 0,
:y2 339.4285888671875,
:width 806.3999999999999,
:height 1209.6}
{:x1 0,
:y1 332.57144601643085,
:x2 0,
:y2 355.4285913258791,
:width 806.3999999999999,
:height 1209.6}
{:x1 0,
:y1 348.5714473724365,
:x2 0,
:y2 371.4285888671875,
:width 806.3999999999999,
:height 1209.6}
{:x1 256.16650390625,
:y1 550.9107360839844,
:x2 608.1167907714844,
:y2 567.482177734375,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 569.5089569091797,
:x2 608.1011047363281,
:y2 586.2500305175781,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 588.107177734375,
:x2 608.117431640625,
:y2 604.8482360839844,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 606.7053833007812,
:x2 608.1163024902344,
:y2 623.4464721679688,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 625.3035888671875,
:x2 196.1043930053711,
:y2 641.8750305175781,
:width 806.3999999999999,
:height 1209.6}),
:page 438},
:content {:text " when an event handler issues an asynchronous I/O, it must package up some program state for the next event handler to use when the I/O finally completes; this additional work is not needed in thread-based programs, as the state the program needs is on the stack of the thread. A"},
:properties {:color "yellow"}}
{:id #uuid "6436a40a-121f-4fab-b428-b278e4cb65d3",
:page 440,
:position {:bounding {:x1 0,
:y1 44.571434020996094,
:x2 635.1374206542969,
:y2 279.7857131958008,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 0,
:y1 44.571434020996094,
:x2 0,
:y2 67.42858123779297,
:width 806.3999999999999,
:height 1209.6}
{:x1 0,
:y1 60.571434020996094,
:x2 0,
:y2 83.42858123779297,
:width 806.3999999999999,
:height 1209.6}
{:x1 0,
:y1 76.5714340209961,
:x2 0,
:y2 99.42858123779297,
:width 806.3999999999999,
:height 1209.6}
{:x1 567.6942443847656,
:y1 207.4196548461914,
:x2 635.1374206542969,
:y2 223.9910659790039,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 226.01786041259766,
:x2 608.1121215820312,
:y2 242.75894927978516,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 244.61609649658203,
:x2 608.1152648925781,
:y2 261.3571548461914,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 263.2143020629883,
:x2 449.3890686035156,
:y2 279.7857131958008,
:width 806.3999999999999,
:height 1209.6}),
:page 440},
:content {:text "record the needed information to finish processing this event in some data structure; when the event happens (i.e., when the disk I/O completes), look up the needed information and process the event."},
:properties {:color "yellow"}}
{:id #uuid "6436a46c-f845-4c7b-8bb1-97da71589c67",
:page 440,
:position {:bounding {:x1 434.5769805908203,
:y1 537.232177734375,
:x2 608.1061859130859,
:y2 553.8035888671875,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 434.5769805908203,
:y1 537.232177734375,
:x2 608.1061859130859,
:y2 553.8035888671875,
:width 806.3999999999999,
:height 1209.6}),
:page 440},
:content {:text "tilize more than one CPU,"},
:properties {:color "yellow"}}
{:id #uuid "6436a485-7a70-4974-93d2-9e11b010a948",
:page 440,
:position {:bounding {:x1 0,
:y1 444.5714569091797,
:x2 642.1258239746094,
:y2 760.0268249511719,
:width 806.3999999999999,
:height 1209.6},
:rects ({:x1 0,
:y1 444.5714569091797,
:x2 0,
:y2 467.42860412597656,
:width 806.3999999999999,
:height 1209.6}
{:x1 593.419677734375,
:y1 724.857177734375,
:x2 642.1258239746094,
:y2 741.4286193847656,
:width 806.3999999999999,
:height 1209.6}
{:x1 108.35714721679688,
:y1 743.4553833007812,
:x2 171.71078491210938,
:y2 760.0268249511719,
:width 806.3999999999999,
:height 1209.6}),
:page 440},
:content {:text "implicit blocking "},
:properties {:color "yellow"}}], :properties {:color "yellow"}}],
:extra {:page 416}} :extra {:page 351}}

View File

@ -0,0 +1,350 @@
{:meta/version 1
;; Currently, we support either "Markdown" or "Org".
;; This can overwrite your global preference so that
;; maybe your personal preferred format is Org but you'd
;; need to use Markdown for some projects.
;; :preferred-format ""
;; Preferred workflow style.
;; Value is either ":now" for NOW/LATER style,
;; or ":todo" for TODO/DOING style.
:preferred-workflow :now
;; The app will ignore those directories or files.
;; E.g. :hidden ["/archived" "/test.md" "../assets/archived"]
:hidden []
;; When creating the new journal page, the app will use your template if there is one.
;; You only need to input your template name here.
:default-templates
{:journals ""}
;; Set a custom date format for journal page title
;; Example:
;; :journal/page-title-format "EEE, do MMM yyyy"
;; Whether to enable hover on tooltip preview feature
;; Default is true, you can also toggle this via setting page
:ui/enable-tooltip? true
;; Show brackets around page references
;; :ui/show-brackets? true
;; Enable showing the body of blocks when referencing them.
:ui/show-full-blocks? false
;; Expand block references automatically when zoom-in
:ui/auto-expand-block-refs? true
;; Enable Block timestamp
:feature/enable-block-timestamps? false
;; Enable remove accents when searching.
;; After toggle this option, please remember to rebuild your search index by press (cmd+c cmd+s).
:feature/enable-search-remove-accents? true
;; Enable journals
;; :feature/enable-journals? true
;; Enable flashcards
;; :feature/enable-flashcards? true
;; Enable Whiteboards
;; :feature/enable-whiteboards? true
;; Disable the built-in Scheduled tasks and deadlines query
;; :feature/disable-scheduled-and-deadline-query? true
;; Specify the number of days in the future to display in the
;; scheduled tasks and deadlines query, with a default value of 0 which
;; only displays tasks for today.
;; Example usage:
;; Display all scheduled tasks and deadlines in the next 7 days
;; :scheduled/future-days 7
;; Specify the date on which the week starts.
;; Goes from 0 to 6 (Monday to Sunday), default to 6
:start-of-week 6
;; Specify a custom CSS import
;; This option take precedence over your local `logseq/custom.css` file
;; You may find a list of awesome logseq themes here:
;; https://github.com/logseq/awesome-logseq#css-themes
;; Example:
;; :custom-css-url "@import url('https://cdn.jsdelivr.net/gh/dracula/logseq@master/custom.css');"
;; Specify a custom js import
;; This option take precedence over your local `logseq/custom.js` file
;; :custom-js-url ""
;; Set a custom Arweave gateway
;; Default gateway: https://arweave.net
;; :arweave/gateway ""
;; Set Bullet indentation when exporting
;; default option: tab
;; Possible options are for `:sidebar` are
;; 1. `:eight-spaces` as eight spaces
;; 2. `:four-spaces` as four spaces
;; 3. `:two-spaces` as two spaces
;; :export/bullet-indentation :tab
;; When :all-pages-public? true, export repo would export all pages within that repo.
;; Regardless of whether you've set any page to public or not.
;; Example:
;; :publishing/all-pages-public? true
;; Specify default home page and sidebar status for Logseq
;; If not specified, Logseq default opens journals page on startup
;; value for `:page` is name of page
;; Possible options for `:sidebar` are
;; 1. `"Contents"` to open up `Contents` in sidebar by default
;; 2. `page name` to open up some page in sidebar
;; 3. Or multiple pages in an array ["Contents" "Page A" "Page B"]
;; If `:sidebar` is not set, sidebar will be hidden
;; Example:
;; 1. Setup page "Changelog" as home page and "Contents" in sidebar
;; :default-home {:page "Changelog", :sidebar "Contents"}
;; 2. Setup page "Jun 3rd, 2021" as home page without sidebar
;; :default-home {:page "Jun 3rd, 2021"}
;; 3. Setup page "home" as home page with multiple pages in sidebar
;; :default-home {:page "home" :sidebar ["page a" "page b"]}
;; Tell logseq to use a specific folder in the repo as a default location for notes
;; if not specified, notes are stored in `pages` directory
;; :pages-directory "your-directory"
;; Tell logseq to use a specific folder in the repo as a default location for journals
;; if not specified, journals are stored in `journals` directory
;; :journals-directory "your-directory"
;; Set this to true will convert
;; `[[Grant Ideas]]` to `[[file:./grant_ideas.org][Grant Ideas]]` for org-mode
;; For more, see https://github.com/logseq/logseq/issues/672
;; :org-mode/insert-file-link? true
;; Setup custom shortcuts under `:shortcuts` key
;; Syntax:
;; 1. `+` means keys pressing simultaneously. eg: `ctrl+shift+a`
;; 2. ` ` empty space between keys represents key chords. eg: `t s` means press `t` followed by `s`
;; 3. `mod` means `Ctrl` for Windows/Linux and `Command` for Mac
;; 4. use `false` to disable particular shortcut
;; 5. you can define multiple bindings for one action, eg `["ctrl+j" "down"]`
;; full list of configurable shortcuts are available below:
;; https://github.com/logseq/logseq/blob/master/src/main/frontend/modules/shortcut/config.cljs
;; Example:
;; :shortcuts
;; {:editor/new-block "enter"
;; :editor/new-line "shift+enter"
;; :editor/insert-link "mod+shift+k"
;; :editor/highlight false
;; :ui/toggle-settings "t s"
;; :editor/up ["ctrl+k" "up"]
;; :editor/down ["ctrl+j" "down"]
;; :editor/left ["ctrl+h" "left"]
;; :editor/right ["ctrl+l" "right"]}
:shortcuts {}
;; By default, pressing `Enter` in the document mode will create a new line.
;; Set this to `true` so that it's the same behaviour as the usual outliner mode.
:shortcut/doc-mode-enter-for-new-block? false
;; Block content larger than `block/content-max-length` will not be searchable
;; or editable for performance.
:block/content-max-length 10000
;; Whether to show command doc on hover
:ui/show-command-doc? true
;; Whether to show empty bullets for non-document mode (the default mode)
:ui/show-empty-bullets? false
;; Pre-defined :view function to use with advanced queries
:query/views
{:pprint
(fn [r] [:pre.code (pprint r)])}
;; Pre-defined :result-transform function for use with advanced queries
:query/result-transforms
{:sort-by-priority
(fn [result] (sort-by (fn [h] (get h :block/priority "Z")) result))}
;; The app will show those queries in today's journal page,
;; the "NOW" query asks the tasks which need to be finished "now",
;; the "NEXT" query asks the future tasks.
:default-queries
{:journals
[{:title "🔨 NOW"
:query [:find (pull ?h [*])
:in $ ?start ?today
:where
[?h :block/marker ?marker]
[(contains? #{"NOW" "DOING"} ?marker)]
[?h :block/page ?p]
[?p :block/journal? true]
[?p :block/journal-day ?d]
[(>= ?d ?start)]
[(<= ?d ?today)]]
:inputs [:14d :today]
:result-transform (fn [result]
(sort-by (fn [h]
(get h :block/priority "Z")) result))
:collapsed? false}
{:title "📅 NEXT"
:query [:find (pull ?h [*])
:in $ ?start ?next
:where
[?h :block/marker ?marker]
[(contains? #{"NOW" "LATER" "TODO"} ?marker)]
[?h :block/page ?p]
[?p :block/journal? true]
[?p :block/journal-day ?d]
[(> ?d ?start)]
[(< ?d ?next)]]
:inputs [:today :7d-after]
:collapsed? false}]}
;; Add your own commands to slash menu to speedup.
;; E.g.
;; :commands
;; [
;; ["js" "Javascript"]
;; ["md" "Markdown"]
;; ]
:commands
[]
;; By default, a block can only be collapsed if it has some children.
;; `:outliner/block-title-collapse-enabled? true` enables a block with a title
;; (multiple lines) can be collapsed too. For example:
;; - block title
;; block content
:outliner/block-title-collapse-enabled? false
;; Macros replace texts and will make you more productive.
;; For example:
;; Change the :macros value below to:
;; {"poem" "Rose is $1, violet's $2. Life's ordered: Org assists you."}
;; input "{{poem red,blue}}"
;; becomes
;; Rose is red, violet's blue. Life's ordered: Org assists you.
:macros {}
;; The default level to be opened for the linked references.
;; For example, if we have some example blocks like this:
;; - a [[page]] (level 1)
;; - b (level 2)
;; - c (level 3)
;; - d (level 4)
;;
;; With the default value of level 2, `b` will be collapsed.
;; If we set the level's value to 3, `b` will be opened and `c` will be collapsed.
:ref/default-open-blocks-level 2
:ref/linked-references-collapsed-threshold 50
;; Favorites to list on the left sidebar
:favorites []
;; any number between 0 and 1 (the greater it is the faster the changes of the next-interval of card reviews) (default 0.5)
;; :srs/learning-fraction 0.5
;; the initial interval after the first successful review of a card (default 4)
;; :srs/initial-interval 4
;; hide specific properties for blocks
;; E.g. :block-hidden-properties #{:created-at :updated-at}
;; :block-hidden-properties #{}
;; Enable all your properties to have corresponding pages
:property-pages/enabled? true
;; Properties to exclude from having property pages
;; E.g.:property-pages/excludelist #{:duration :author}
;; :property-pages/excludelist
;; By default, property value separated by commas will not be treated as
;; page references. You can add properties to enable it.
;; E.g. :property/separated-by-commas #{:alias :tags}
;; :property/separated-by-commas #{}
;; Properties that are ignored when parsing property values for references
;; :ignored-page-references-keywords #{:author :startup}
;; logbook setup
;; :logbook/settings
;; {:with-second-support? false ;limit logbook to minutes, seconds will be eliminated
;; :enabled-in-all-blocks true ;display logbook in all blocks after timetracking
;; :enabled-in-timestamped-blocks false ;don't display logbook at all
;; }
;; Mobile photo uploading setup
;; :mobile/photo
;; {:allow-editing? true
;; :quality 80}
;; Mobile features options
;; Gestures
;; :mobile
;; {:gestures/disabled-in-block-with-tags ["kanban"]}
;; Extra CodeMirror options
;; See https://codemirror.net/5/doc/manual.html#config for possible options
;; :editor/extra-codemirror-options {:keyMap "emacs" :lineWrapping true}
;; Enable logical outdenting
;; :editor/logical-outdenting? true
;; When both text and a file are in the clipboard, paste the file
;; :editor/preferred-pasting-file? true
;; Quick capture templates for receiving contents from other apps.
;; Each template contains three elements {time}, {text} and {url}, which can be auto-expanded
;; by received contents from other apps. Note: the {} cannot be omitted.
;; - {time}: capture time
;; - {date}: capture date using current date format, use `[[{date}]]` to get a page reference
;; - {text}: text that users selected before sharing.
;; - {url}: url or assets path for media files stored in Logseq.
;; You can also reorder them, or even only use one or two of them in the template.
;; You can also insert or format any text in the template as shown in the following examples.
;; :quick-capture-templates
;; {:text "[[quick capture]] **{time}**: {text} from {url}"
;; :media "[[quick capture]] **{time}**: {url}"}
;; Quick capture options
;; :quick-capture-options {:insert-today? false :redirect-page? false :default-page "my page"}
;; File sync options
;; Ignore these files when syncing, regexp is supported.
;; :file-sync/ignore-files []
;; dwim (do what I mean) for Enter key when editing.
;; Context-awareness of Enter key makes editing more easily
; :dwim/settings {
; :admonition&src? true
; :markup? false
; :block-ref? true
; :page-ref? true
; :properties? true
; :list? true
; }
;; Decide the way to escape the special characters in the page title.
;; Warning:
;; This is a dangerous operation. If you want to change the setting,
;; should access the setting `Filename format` and follow the instructions.
;; Or you have to rename all the affected files manually then re-index on all
;; clients after the files are synced. Wrong handling may cause page titles
;; containing special characters to be messy.
;; Available values:
;; :file/name-format :triple-lowbar
;; ;use triple underscore `___` for slash `/` in page title
;; ;use Percent-encoding for other invalid characters
:file/name-format :triple-lowbar
:ui/show-brackets? false
;; specify the format of the filename for journal files
;; :journal/file-name-format "yyyy_MM_dd"
}

View File

@ -0,0 +1,350 @@
{:meta/version 1
;; Currently, we support either "Markdown" or "Org".
;; This can overwrite your global preference so that
;; maybe your personal preferred format is Org but you'd
;; need to use Markdown for some projects.
;; :preferred-format ""
;; Preferred workflow style.
;; Value is either ":now" for NOW/LATER style,
;; or ":todo" for TODO/DOING style.
:preferred-workflow :now
;; The app will ignore those directories or files.
;; E.g. :hidden ["/archived" "/test.md" "../assets/archived"]
:hidden []
;; When creating the new journal page, the app will use your template if there is one.
;; You only need to input your template name here.
:default-templates
{:journals ""}
;; Set a custom date format for journal page title
;; Example:
;; :journal/page-title-format "EEE, do MMM yyyy"
;; Whether to enable hover on tooltip preview feature
;; Default is true, you can also toggle this via setting page
:ui/enable-tooltip? true
;; Show brackets around page references
;; :ui/show-brackets? true
;; Enable showing the body of blocks when referencing them.
:ui/show-full-blocks? false
;; Expand block references automatically when zoom-in
:ui/auto-expand-block-refs? false
;; Enable Block timestamp
:feature/enable-block-timestamps? false
;; Enable remove accents when searching.
;; After toggle this option, please remember to rebuild your search index by press (cmd+c cmd+s).
:feature/enable-search-remove-accents? true
;; Enable journals
;; :feature/enable-journals? true
;; Enable flashcards
;; :feature/enable-flashcards? true
;; Enable Whiteboards
;; :feature/enable-whiteboards? true
;; Disable the built-in Scheduled tasks and deadlines query
;; :feature/disable-scheduled-and-deadline-query? true
;; Specify the number of days in the future to display in the
;; scheduled tasks and deadlines query, with a default value of 0 which
;; only displays tasks for today.
;; Example usage:
;; Display all scheduled tasks and deadlines in the next 7 days
;; :scheduled/future-days 7
;; Specify the date on which the week starts.
;; Goes from 0 to 6 (Monday to Sunday), default to 6
:start-of-week 6
;; Specify a custom CSS import
;; This option take precedence over your local `logseq/custom.css` file
;; You may find a list of awesome logseq themes here:
;; https://github.com/logseq/awesome-logseq#css-themes
;; Example:
;; :custom-css-url "@import url('https://cdn.jsdelivr.net/gh/dracula/logseq@master/custom.css');"
;; Specify a custom js import
;; This option take precedence over your local `logseq/custom.js` file
;; :custom-js-url ""
;; Set a custom Arweave gateway
;; Default gateway: https://arweave.net
;; :arweave/gateway ""
;; Set Bullet indentation when exporting
;; default option: tab
;; Possible options are for `:sidebar` are
;; 1. `:eight-spaces` as eight spaces
;; 2. `:four-spaces` as four spaces
;; 3. `:two-spaces` as two spaces
;; :export/bullet-indentation :tab
;; When :all-pages-public? true, export repo would export all pages within that repo.
;; Regardless of whether you've set any page to public or not.
;; Example:
;; :publishing/all-pages-public? true
;; Specify default home page and sidebar status for Logseq
;; If not specified, Logseq default opens journals page on startup
;; value for `:page` is name of page
;; Possible options for `:sidebar` are
;; 1. `"Contents"` to open up `Contents` in sidebar by default
;; 2. `page name` to open up some page in sidebar
;; 3. Or multiple pages in an array ["Contents" "Page A" "Page B"]
;; If `:sidebar` is not set, sidebar will be hidden
;; Example:
;; 1. Setup page "Changelog" as home page and "Contents" in sidebar
;; :default-home {:page "Changelog", :sidebar "Contents"}
;; 2. Setup page "Jun 3rd, 2021" as home page without sidebar
;; :default-home {:page "Jun 3rd, 2021"}
;; 3. Setup page "home" as home page with multiple pages in sidebar
;; :default-home {:page "home" :sidebar ["page a" "page b"]}
;; Tell logseq to use a specific folder in the repo as a default location for notes
;; if not specified, notes are stored in `pages` directory
;; :pages-directory "your-directory"
;; Tell logseq to use a specific folder in the repo as a default location for journals
;; if not specified, journals are stored in `journals` directory
;; :journals-directory "your-directory"
;; Set this to true will convert
;; `[[Grant Ideas]]` to `[[file:./grant_ideas.org][Grant Ideas]]` for org-mode
;; For more, see https://github.com/logseq/logseq/issues/672
;; :org-mode/insert-file-link? true
;; Setup custom shortcuts under `:shortcuts` key
;; Syntax:
;; 1. `+` means keys pressing simultaneously. eg: `ctrl+shift+a`
;; 2. ` ` empty space between keys represents key chords. eg: `t s` means press `t` followed by `s`
;; 3. `mod` means `Ctrl` for Windows/Linux and `Command` for Mac
;; 4. use `false` to disable particular shortcut
;; 5. you can define multiple bindings for one action, eg `["ctrl+j" "down"]`
;; full list of configurable shortcuts are available below:
;; https://github.com/logseq/logseq/blob/master/src/main/frontend/modules/shortcut/config.cljs
;; Example:
;; :shortcuts
;; {:editor/new-block "enter"
;; :editor/new-line "shift+enter"
;; :editor/insert-link "mod+shift+k"
;; :editor/highlight false
;; :ui/toggle-settings "t s"
;; :editor/up ["ctrl+k" "up"]
;; :editor/down ["ctrl+j" "down"]
;; :editor/left ["ctrl+h" "left"]
;; :editor/right ["ctrl+l" "right"]}
:shortcuts {}
;; By default, pressing `Enter` in the document mode will create a new line.
;; Set this to `true` so that it's the same behaviour as the usual outliner mode.
:shortcut/doc-mode-enter-for-new-block? false
;; Block content larger than `block/content-max-length` will not be searchable
;; or editable for performance.
:block/content-max-length 10000
;; Whether to show command doc on hover
:ui/show-command-doc? true
;; Whether to show empty bullets for non-document mode (the default mode)
:ui/show-empty-bullets? false
;; Pre-defined :view function to use with advanced queries
:query/views
{:pprint
(fn [r] [:pre.code (pprint r)])}
;; Pre-defined :result-transform function for use with advanced queries
:query/result-transforms
{:sort-by-priority
(fn [result] (sort-by (fn [h] (get h :block/priority "Z")) result))}
;; The app will show those queries in today's journal page,
;; the "NOW" query asks the tasks which need to be finished "now",
;; the "NEXT" query asks the future tasks.
:default-queries
{:journals
[{:title "🔨 NOW"
:query [:find (pull ?h [*])
:in $ ?start ?today
:where
[?h :block/marker ?marker]
[(contains? #{"NOW" "DOING"} ?marker)]
[?h :block/page ?p]
[?p :block/journal? true]
[?p :block/journal-day ?d]
[(>= ?d ?start)]
[(<= ?d ?today)]]
:inputs [:14d :today]
:result-transform (fn [result]
(sort-by (fn [h]
(get h :block/priority "Z")) result))
:collapsed? false}
{:title "📅 NEXT"
:query [:find (pull ?h [*])
:in $ ?start ?next
:where
[?h :block/marker ?marker]
[(contains? #{"NOW" "LATER" "TODO"} ?marker)]
[?h :block/page ?p]
[?p :block/journal? true]
[?p :block/journal-day ?d]
[(> ?d ?start)]
[(< ?d ?next)]]
:inputs [:today :7d-after]
:collapsed? false}]}
;; Add your own commands to slash menu to speedup.
;; E.g.
;; :commands
;; [
;; ["js" "Javascript"]
;; ["md" "Markdown"]
;; ]
:commands
[]
;; By default, a block can only be collapsed if it has some children.
;; `:outliner/block-title-collapse-enabled? true` enables a block with a title
;; (multiple lines) can be collapsed too. For example:
;; - block title
;; block content
:outliner/block-title-collapse-enabled? false
;; Macros replace texts and will make you more productive.
;; For example:
;; Change the :macros value below to:
;; {"poem" "Rose is $1, violet's $2. Life's ordered: Org assists you."}
;; input "{{poem red,blue}}"
;; becomes
;; Rose is red, violet's blue. Life's ordered: Org assists you.
:macros {}
;; The default level to be opened for the linked references.
;; For example, if we have some example blocks like this:
;; - a [[page]] (level 1)
;; - b (level 2)
;; - c (level 3)
;; - d (level 4)
;;
;; With the default value of level 2, `b` will be collapsed.
;; If we set the level's value to 3, `b` will be opened and `c` will be collapsed.
:ref/default-open-blocks-level 2
:ref/linked-references-collapsed-threshold 50
;; Favorites to list on the left sidebar
:favorites []
;; any number between 0 and 1 (the greater it is the faster the changes of the next-interval of card reviews) (default 0.5)
;; :srs/learning-fraction 0.5
;; the initial interval after the first successful review of a card (default 4)
;; :srs/initial-interval 4
;; hide specific properties for blocks
;; E.g. :block-hidden-properties #{:created-at :updated-at}
;; :block-hidden-properties #{}
;; Enable all your properties to have corresponding pages
:property-pages/enabled? true
;; Properties to exclude from having property pages
;; E.g.:property-pages/excludelist #{:duration :author}
;; :property-pages/excludelist
;; By default, property value separated by commas will not be treated as
;; page references. You can add properties to enable it.
;; E.g. :property/separated-by-commas #{:alias :tags}
;; :property/separated-by-commas #{}
;; Properties that are ignored when parsing property values for references
;; :ignored-page-references-keywords #{:author :startup}
;; logbook setup
;; :logbook/settings
;; {:with-second-support? false ;limit logbook to minutes, seconds will be eliminated
;; :enabled-in-all-blocks true ;display logbook in all blocks after timetracking
;; :enabled-in-timestamped-blocks false ;don't display logbook at all
;; }
;; Mobile photo uploading setup
;; :mobile/photo
;; {:allow-editing? true
;; :quality 80}
;; Mobile features options
;; Gestures
;; :mobile
;; {:gestures/disabled-in-block-with-tags ["kanban"]}
;; Extra CodeMirror options
;; See https://codemirror.net/5/doc/manual.html#config for possible options
;; :editor/extra-codemirror-options {:keyMap "emacs" :lineWrapping true}
;; Enable logical outdenting
;; :editor/logical-outdenting? true
;; When both text and a file are in the clipboard, paste the file
;; :editor/preferred-pasting-file? true
;; Quick capture templates for receiving contents from other apps.
;; Each template contains three elements {time}, {text} and {url}, which can be auto-expanded
;; by received contents from other apps. Note: the {} cannot be omitted.
;; - {time}: capture time
;; - {date}: capture date using current date format, use `[[{date}]]` to get a page reference
;; - {text}: text that users selected before sharing.
;; - {url}: url or assets path for media files stored in Logseq.
;; You can also reorder them, or even only use one or two of them in the template.
;; You can also insert or format any text in the template as shown in the following examples.
;; :quick-capture-templates
;; {:text "[[quick capture]] **{time}**: {text} from {url}"
;; :media "[[quick capture]] **{time}**: {url}"}
;; Quick capture options
;; :quick-capture-options {:insert-today? false :redirect-page? false :default-page "my page"}
;; File sync options
;; Ignore these files when syncing, regexp is supported.
;; :file-sync/ignore-files []
;; dwim (do what I mean) for Enter key when editing.
;; Context-awareness of Enter key makes editing more easily
; :dwim/settings {
; :admonition&src? true
; :markup? false
; :block-ref? true
; :page-ref? true
; :properties? true
; :list? true
; }
;; Decide the way to escape the special characters in the page title.
;; Warning:
;; This is a dangerous operation. If you want to change the setting,
;; should access the setting `Filename format` and follow the instructions.
;; Or you have to rename all the affected files manually then re-index on all
;; clients after the files are synced. Wrong handling may cause page titles
;; containing special characters to be messy.
;; Available values:
;; :file/name-format :triple-lowbar
;; ;use triple underscore `___` for slash `/` in page title
;; ;use Percent-encoding for other invalid characters
:file/name-format :triple-lowbar
:ui/show-brackets? false
;; specify the format of the filename for journal files
;; :journal/file-name-format "yyyy_MM_dd"
}

View File

@ -0,0 +1,586 @@
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
collapsed:: true
- 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
collapsed:: true
- **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
collapsed:: true
- `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
collapsed:: true
- **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
collapsed:: true
- 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
collapsed:: true
- 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 lock**
- ```c
void lock(lock_t *lock) {
while (TestAndSet(&lock->status, 1) == 1);
}
void unlock(lock_t *lock) { lock->status = 0; }
```
- Requires a preemptive scheduler(or it may spin forever)
- No fairness guarantee
- For single processor systems, terrible performance, because the thread holding the lock cannot make any progress to release the lock until it is scheduled again and thus all other threads waiting for the lock can do nothing but spinning even they are scheduled.
- For multi-processor systems, spin lock may work well when thread B on CPU1 waits for thread A on CPU0, and the critical section is short. Because lock owner keeps making progress, spinning doesn't waste many cycles.
- **Priority Inversion**: Threads with high priority wait for locks held by threads with low priority.
hl-page:: 355
ls-type:: annotation
id:: 6435099b-0834-483e-9ef2-98a0b795cf00
hl-color:: yellow
Solution: **priority inheritance** or give up the priority?
- **Test-And-Set (Atomic Exchange)**
hl-page:: 344
ls-type:: annotation
id:: 643401e0-fcec-41d3-9898-d5c4175ac464
hl-color:: yellow
collapsed:: true
- Returns the old value pointed to by the `old_ptr`, and simultaneously updates said value to `new`.
- "test" the old value (which is what is returned) while simultaneously "set" the memory location to a new value
- ```c
int TestAndSet(int *old_ptr, int new) {
int old = *old_ptr;
*old_ptr = new;
return old;
}
```
- **Compare-And-Swap**
hl-page:: 348
ls-type:: annotation
id:: 6434f8ac-d762-40a4-abb0-2955c2c8b396
hl-color:: yellow
collapsed:: true
- Test whether the value at the address specified by `ptr` is equal to `expected`.
hl-page:: 348
ls-type:: annotation
id:: 6434fab0-08de-4f28-8d8e-f48f7e04aaaa
hl-color:: yellow
If so, update the memory location with the `new` value.
If not, do nothing.
Return the old value at the memory location.
- ```c
int CompareAndSwap(int *ptr, int expected, int new) {
int original = *ptr;
if (original == expected) *ptr = new;
return orginial
}
```
- Compare-and-swap flavor spin lock
```C
void lock(lock_t *lock) {
while (CompareAndSwap(&lock->status, 0, 1) == 1) ;
}
```
- **load-linked** and **store-conditional**
hl-page:: 349
ls-type:: annotation
id:: 6434fde1-9d19-4381-805e-f2a972875dc2
hl-color:: yellow
collapsed:: true
- The **load-linked** operates much like a typical load instruction, and simply fetches a value from memory and places it in a register.
ls-type:: annotation
hl-page:: 349
hl-color:: yellow
id:: 6434fe1c-47f3-422c-a317-be72f08d6aef
- **store-conditional** only succeeds if no intervening store to the address has taken place.
hl-page:: 349
ls-type:: annotation
id:: 6434fe62-0e92-4414-86cc-b0c37fcf51ec
hl-color:: yellow
On success, return 1 and update the value at `ptr` to value.
On failure, return 0 and the value at `ptr` is not updated.
- ```c
int LL(int *ptr) { return *ptr; }
int SC(int *ptr, int value) {
if (/*no update to *ptr since LoadLinked to this address*/) {
*ptr = value;
return 1; // success!
} else {
return 0; // failed to update
}
}
```
- LL/SC flavor spin lock: very similar to the errant Load/Store lock, but the special instructions here can detect intervening
```c
void lock(lock_t *lock) {
while (true) {
while (LL(&lock->status) == 1) ; // test
if (SC(&lock->status, 1) == 1) // set
break;
// else retry, in case lock->status is changed
}
}
```
- **Fetch-And-Add**
ls-type:: annotation
hl-page:: 350
hl-color:: yellow
id:: 64350170-c853-4080-9ed1-2777ea3a18c8
collapsed:: true
- Atomically increments a value while returning the old value at a particular address
- ```c
int FetchAndAdd(int *ptr) {
int old = *ptr;
*ptr = old + 1;
return old;
}
```
- **ticket lock**
hl-page:: 351
ls-type:: annotation
id:: 64350331-8fbb-4c41-9ac1-1a4ba852f772
hl-color:: yellow
- ```C
struct lock_t{
int ticket;
int turn;
};
void lock(lock_t *lock) {
int myturn = FetchAndAdd(&lock->ticket);
// atomically allocate a ticket as the thread's turn
while (lock->turn != myturn) ;
// wait for its turn
}
void unlock(lock_t *lock) {
lock->turn += 1;
}
```
- Ensure progress for all threads. Once a thread is assigned its ticket value, it will be scheduled at some point in the future (i.e. it will definitely get its turn as `unlock()` operations increase global `turn` value).
hl-page:: 351
ls-type:: annotation
id:: 64350420-ca8a-4cac-af2f-f4e7deb5d1be
hl-color:: yellow
In contrast, test-and-set spin lock may starve, if it is very unlucky.(never succeeds in contention)
- Simple Yield Lock
hl-page:: 353
ls-type:: annotation
id:: 64350781-6995-41db-8b8e-2de0eb84136a
hl-color:: yellow
collapsed:: true
- `yield`: a system call that moves the caller from the running state to the ready state, and thus promotes another thread to running.
hl-page:: 353
ls-type:: annotation
id:: 643507af-1153-46c1-b232-31a9a203e5df
hl-color:: yellow
- ```C
void lock(lock_t *lock) {
while (TestAndSet(&lock->status, 1) == 1)
yield();
}
```
- Problem: Starvation is still possible; Context switch overhead, though better than spinning
- Lock With Queues, Test-and-set, Yield, And Wakeup
ls-type:: annotation
hl-page:: 354
hl-color:: yellow
id:: 64350b44-dfae-4544-93f9-ff2b343fefd4
- The real problem is: We have not much control over which thread to run next and thus causes potential waste.
hl-page:: 353
ls-type:: annotation
id:: 64350b4e-9559-49d9-aa37-eda9fe425b7f
hl-color:: yellow
- `park()`: put a calling thread to sleep
hl-page:: 354
ls-type:: annotation
id:: 64350bfb-64f7-4d41-8cc2-260dbec3372d
hl-color:: yellow
- `unpark(threadID)`: wake a particular thread
hl-page:: 354
ls-type:: annotation
id:: 64350c01-39bb-4d15-b554-0287b13806ee
hl-color:: yellow
- implement
```C
struct lock_t{
int lk;
int guard; // spin lock for the whole lock
queue_t *q; // control who gets the lock next
};
void lock(lock_t *lock) {
while (TestAndSet(&m->guard, 1) == 1) ;
if (m->lk == 0) {
m->lk = 1;
m->guard = 0;
}
else {
m->q->add(get_tid());
setpark(); // newly added
m->guard = 0;
// ---- wakeup/waiting race ----
park();
}
}
void unlock(lock_t *lock) {
while (TestAndSet(&m->guard, 1) == 1) ;
if (m->q->empty())
m->flag = 0;
else
unpark(m->q->pop()); // should not clear flag here
// Wake up Only one waiting thread
m->guard = 0;
}
```
- When a thread is woken up, it will be as if it is returning from `park()`. Thus when `unpark` a thread, pass the lock directly from the thread releasing the lock to the next thread acquiring it; flag is not set to 0 in-between.
- wakeup/waiting race: If the thread is scheduled out just before it calls `park`, and then the lock owner calls `unpark` on that thread, it would sleep forever.
hl-page:: 356
ls-type:: annotation
id:: 64351ba3-d4b5-4999-bc61-7733d5e0a061
hl-color:: yellow
- One solution is to use `setpark()`: indicate the thread is about to `park`. If it happens to be interrupted and another thread calls `unpark` before `park` is actually called, the subsequent park returns immediately instead of sleeping.
- Peterson's algorithm: mutual exclusion lock for 2 threads without hardware atomic instruction. Use 2 intention flags and a turn flag.
hl-page:: 345
ls-type:: annotation
id:: 6434edd3-2a7b-4e11-af18-29854e628bc6
hl-color:: yellow
- **two-phase lock**
hl-page:: 358
ls-type:: annotation
id:: 643522a7-4b16-4998-9b2f-47a852681a16
hl-color:: yellow
- A combination of spin lock and sleep lock
- In the first phase, the lock spins for a while, hoping that it can acquire the lock.
hl-page:: 358
ls-type:: annotation
id:: 6435230e-d84a-4c91-8329-b7608b0d543a
hl-color:: yellow
- A second phase is entered if the lock is not acquired, where the caller is put to sleep, and only woken up when the lock becomes free later.
ls-type:: annotation
hl-page:: 358
hl-color:: yellow
id:: 64352344-d140-468c-987c-e8afa05c2171
- Linux System Call **futex**
hl-page:: 356
ls-type:: annotation
id:: 64351e9a-6505-4176-a6fb-ddf63f3245a8
hl-color:: yellow
- each `futex` is associated with ==a specific physical memory location==, and ==an in-kernel queue==
- `futex_wake(address)` wakes one thread that is waiting on the queue.
- `futex_wait(address, expected)` puts the calling thread to sleep, assuming the value at `address` is equal to `expected`. If it is not equal, the call returns immediately.
- Figure 28.10: Linux-based Futex Locks
ls-type:: annotation
hl-page:: 357
hl-color:: yellow
id:: 64352221-d590-4371-a5f0-29e9cfa75ccb
- efficacy 功效,效力
ls-type:: annotation
hl-page:: 341
hl-color:: green
id:: 6433fb69-1425-46b4-996f-f91da5d3e8d0
- foil
ls-type:: annotation
hl-page:: 347
hl-color:: green
id:: 6434f523-44b7-40ab-8fea-528969c5acfd
- delve 钻研;探究;挖
ls-type:: annotation
hl-page:: 349
hl-color:: green
id:: 6434fb8c-2b3b-4d80-83fb-3b34da4dcd28
- brag 吹嘘;自吹自擂
ls-type:: annotation
hl-page:: 351
hl-color:: green
id:: 643501c1-f11b-4e85-8125-d2a5a31f69b0
- scourge
- 鞭打;鞭笞;折磨;使受苦难
- Lock-based Concurrent Data Structures
ls-type:: annotation
hl-page:: 361
hl-color:: yellow
id:: 643525b0-e245-489b-877d-a2a1d63e7ea6
- **Concurrent Counters**
hl-page:: 361
ls-type:: annotation
id:: 643525e5-fb85-48d4-905a-2a88b9ac0b0d
hl-color:: yellow
collapsed:: true
- **Counter with lock**
- Wrap the all the operations with a single lock.
- Performance is bad due to lock contention and it gets worse when the number of threads increases.
- **perfect scaling**: the increase in thread number doesn't harm the performance
hl-page:: 363
ls-type:: annotation
id:: 64352751-d9bd-4d5e-a8ba-cd18f86b1a15
hl-color:: yellow
- **approximate counter**
hl-page:: 363
ls-type:: annotation
id:: 64352794-d7c8-42f9-8321-f874967cebf2
hl-color:: yellow
- represent a single logical counter via ==numerous local physical counters==(one per CPU core), as well as ==a single global counter==. Each actual counter has a ==lock==.
- To add the counter, acquire the ==local lock== and increase it, thus avoiding contention.
- To read the counter, acquire the ==global lock== and read.
- To keep the global counter up to date, the local values are periodically transferred to the global counter and reset, which requires ==global lock and local lock==. A threshold `S` determines how often this transfer happens, tuning the trade-off between scalability and precision.
- **Concurrent Linked Lists**
ls-type:: annotation
hl-page:: 367
hl-color:: yellow
id:: 643530d8-9d09-4c8a-9e92-47dfe814ef50
collapsed:: true
- Again, the simplest way to implement this is to wrap all operations on the list with a single lock.
- Assuming the `malloc` is ==thread-safe==, we can improve the code a little by narrowing critical section: only operations on global structure need to be locked.
- **hand-over-hand locking**: a lock per node.
hl-page:: 369
ls-type:: annotation
id:: 64353237-4b74-4148-b7c1-5854d83a18c7
hl-color:: yellow
- When traversing the list, the code first grabs the next node's lock and then releases the current node's lock.
- In practice, it ==doesn't work== due to prohibitive overhead
- **Concurrent Queues**
ls-type:: annotation
hl-page:: 370
hl-color:: yellow
id:: 64353353-9de2-421b-967d-dc80a597eecd
- Two locks, head and tail, for `enqueue` and `dequeue` operation.
- Add a dummy node to separate head and tail operation. Without this, `dequeue` operation needs to acquire both locks in case the queue is empty.
- **Concurrent Hash Table**
hl-page:: 372
ls-type:: annotation
id:: 6435360d-c176-494a-9d61-b1fd0107a9bd
hl-color:: yellow
- instead of having a single lock for the entire structure, it uses a lock per hash bucket
ls-type:: annotation
hl-page:: 372
hl-color:: yellow
id:: 6435363d-c697-42a6-bfd0-8a2332cef394
- ubiquitous 似乎无所不在的;十分普遍的
ls-type:: annotation
hl-page:: 372
hl-color:: green
id:: 6435365a-b5d6-46fc-a9a1-25b0d23aa529
- humble 谦逊;低声下气;虚心;贬低
ls-type:: annotation
hl-page:: 373
hl-color:: green
id:: 6435367f-dd9e-449d-b0e4-3d8c9e14f6c2
- sloppy 马虎的,草率的;(衣服)宽松肥大的;太稀的,不够稠的;
hl-page:: 376
ls-type:: annotation
id:: 643536c8-fc05-4bbe-8d1d-0f4f6d1c4fee
hl-color:: green
- gross 总的,毛的;严重的,极端的;粗鲁的;臃肿的;粗略的;
hl-page:: 378
ls-type:: annotation
id:: 643537d3-7d01-442b-b47e-59433c2aa6db
hl-color:: green
- **condition variable**
hl-page:: 378
ls-type:: annotation
id:: 643537ff-1028-4725-8d7a-c0338cc946d3
hl-color:: yellow
- A ==condition variable== is an explicit queue that threads can put themselves on when some state of execution(condition) is not as desired (by *waiting on the condition*); some other thread, when it changes said state, can then wake one (or more) of those waiting threads and thus allow them to continue (by *signaling*).
hl-page:: 378
ls-type:: annotation
id:: 64353882-7697-4c16-8e53-c8f59ea256c1
hl-color:: yellow
- Operations
- `wait()` put the caller to sleep. `pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)`
hl-page:: 378
ls-type:: annotation
id:: 643538d5-9ea3-4399-9fa2-d75fdf0e1dd4
hl-color:: yellow
- `signal()` wake up a sleeping thread waiting on this condition. `pthread_cond_signal(pthread_cond_t *c);`
hl-page:: 379
ls-type:: annotation
id:: 643538de-cc40-4dd2-8f03-9492004f209b
hl-color:: yellow
- The `wait()` also takes a mutex as a parameter; it assumes that this mutex is locked when `wait()` is called. The responsibility of `wait()` is to ==release the lock and put the calling thread to sleep== (atomically); when the thread wakes up, it must ==re-acquire the lock before returning== to the caller. The design is helpful to avoid some race conditions when trying to sleep.
- use a while loop instead of just an if statement when deciding whether to wait on the condition.
ls-type:: annotation
hl-page:: 380
hl-color:: yellow
id:: 643547c5-1613-49e9-899e-0e86f59a1462
- stem
ls-type:: annotation
hl-page:: 379
hl-color:: green
id:: 64353eb8-8ed8-4680-a3c0-91608b429408
- **producer/consumer problem**
hl-page:: 382
ls-type:: annotation
id:: 64354974-adea-4b20-90f4-a12ebe1e4d5b
hl-color:: yellow
- **Mesa semantics**: Signaling a thread only wakes them up; it is thus a hint that the state of the world has ==changed==, but there is ==no guarantee== that when the woken thread runs, the state will ==still be as desired==. (Another guy may run before the thread and change the state again)
hl-page:: 385
ls-type:: annotation
id:: 64354cc4-14c5-408d-b879-7d4d011b2b5c
hl-color:: yellow
- So, always use while loops. While loops make sure the thread wake up in the desired state of world, which tackles the ((64355502-f41f-40dd-b71f-e0abdbc76716)) and provides support for ((64355441-5a1b-4015-baa1-65917526079c))
hl-page:: 386
ls-type:: annotation
id:: 64354db0-8c74-4c14-b063-d26378a10555
hl-color:: yellow
- **Hoare semantics**: provides a stronger guarantee that the woken thread will run immediately upon being woken
hl-page:: 386
ls-type:: annotation
id:: 64354d46-4286-44fd-9e82-2ba562a50f25
hl-color:: yellow
- Incorrect Solution: single condition variable. The problem arises from the ==undirected wakeup operation==: God knows which thread is to be woken up.
- Envision multiple consumers and one producer:
1. producer `P1` increases count to 1, signals the CV and sleeps
2. consumer `C1` is awaken, reduces count to 0, signals the CV and sleeps
3. another consumer `C2` is woken up ==by accident==, finds out count is 0, sleeps
4. In this case, they all sleep and thus nobody will signal any of them
- If in step 3, the producer `P1` is woken up, everything is fine. Obviously, one solution is to ==exert control over which thread is to be woken up==. Well, wake up all threads may also solve this problem, see ((64355441-5a1b-4015-baa1-65917526079c)).
- Correct solution: 2 condition variable.
- Producer threads wait on the condition `empty`, and signals `fill`. Conversely, consumer threads wait on `fill` and signal `empty`.
- Code
```C
cond_t empty, fill;
mutex_t mutex;
void *producer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
Pthread_mutex_lock(&mutex);
while (count == MAX)
Pthread_cond_wait(&empty, &mutex);
put(i);
Pthread_cond_signal(&fill);
Pthread_mutex_unlock(&mutex);
}
}
void *consumer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
Pthread_mutex_lock(&mutex);
while (count == 0)
Pthread_cond_wait(&fill, &mutex);
int tmp = get();
Pthread_cond_signal(&empty);
Pthread_mutex_unlock(&mutex);
printf("%d\n", tmp);
}
}
```
- **spurious wakeups**
hl-page:: 390
ls-type:: annotation
id:: 64355502-f41f-40dd-b71f-e0abdbc76716
hl-color:: yellow
- In some thread packages, due to details of the implementation, it is possible that two threads get woken up though just a single signal has taken place.
- **covering condition**
hl-page:: 391
ls-type:: annotation
id:: 64355441-5a1b-4015-baa1-65917526079c
hl-color:: yellow
- covers all the cases where a thread needs to wake up, those unneeded simply wake up, re-check condition and go back to sleep
- `pthread_cond_broadcast()` wakes up all waiting threads
- albeit 尽管;虽然
ls-type:: annotation
hl-page:: 390
hl-color:: green
id:: 64354f54-b26c-48dc-a328-4ae355b680f3
- spurious 虚假的;伪造的;建立在错误的观念(或思想方法)之上的;谬误的
hl-page:: 390
ls-type:: annotation
id:: 643554f4-75a7-48fa-9366-87058ee723fb
hl-color:: green

View File

@ -9,7 +9,7 @@
;; Preferred workflow style. ;; Preferred workflow style.
;; Value is either ":now" for NOW/LATER style, ;; Value is either ":now" for NOW/LATER style,
;; or ":todo" for TODO/DOING style. ;; or ":todo" for TODO/DOING style.
:preferred-workflow :now :preferred-workflow :todo
;; The app will ignore those directories or files. ;; The app will ignore those directories or files.
;; E.g. :hidden ["/archived" "/test.md" "../assets/archived"] ;; E.g. :hidden ["/archived" "/test.md" "../assets/archived"]
@ -35,7 +35,7 @@
:ui/show-full-blocks? false :ui/show-full-blocks? false
;; Expand block references automatically when zoom-in ;; Expand block references automatically when zoom-in
:ui/auto-expand-block-refs? true :ui/auto-expand-block-refs? false
;; Enable Block timestamp ;; Enable Block timestamp
:feature/enable-block-timestamps? false :feature/enable-block-timestamps? false

View File

@ -0,0 +1,20 @@
- [Wiki](https://en.wikipedia.org/wiki/Banker%27s_algorithm) [Zhihu](https://zhuanlan.zhihu.com/p/59533950)
- It is usually quoted in EXAMs, thus still worth some time.
- 3 matrices is indexed by `[ProcessID, ResourceID]`
- Max: the maximum number of resources that will be needed during execution of each kind
- Allocated: the number resources that is already allocated to the process
- Need: the number of resources that the process still needs, i.e. `Need = Max - Allocated`
- 2 vectors indexed by `[ResourceID]`
- Total: the number of each kind of resources in the system
- Available: the number of resources that is not yet allocated by the OS, i.e. `Available = Total - sum(Allocated, axis=1)`
- Safe state: it is possible for all processes to finish executing. If we can find a possible sequence of execution, where the each process is able to acquire its maximum resources, and terminates.
- Safe sequence algorithm
- suppose we have a sequence of `P1 P2 ... Pn`
- 1. start from the current state `S[i]` which is after execution of `P[i-1]`
2. if `Available >= Need[i, :]` then `P[i]` is able to terminate; else it is not a safe sequence, return false
3. after `P[i]` terminates, `Available += Allocated[i, :]` and `i += 1`, then loop back to 2 until all process is executed
- Request
- > When the system receives a request for resources, it runs the Banker's algorithm to determine if it is safe to grant the request. The algorithm is fairly straightforward once the distinction between safe and unsafe states is understood.
1. Can the request be granted? If not, the request is impossible and must either be denied or put on a waiting list
2. Assume that the request is granted
3. Is the new state safe? If so grant the request; If not, either deny the request or put it on a waiting list

View File

@ -0,0 +1,119 @@
- Spin Lock Implement
id:: 6436aafd-c85f-414c-8aee-acdc71e9138e
- ```c
void lock(lock_t *lock) {
while (TestAndSet(&lock->status, 1) == 1);
}
void unlock(lock_t *lock) { lock->status = 0; }
```
- Test-And-Set Code Description
id:: 6436af87-3f1b-4ee8-a2c8-4de0f1961f1a
- ```c
int TestAndSet(int *old_ptr, int new) {
int old = *old_ptr;
*old_ptr = new;
return old;
}
```
- Ticket Lock Implement
id:: 6436af5c-0000-4bfb-9a27-1d7cf0a830db
- ```C
struct lock_t{
int ticket;
int turn;
};
void lock(lock_t *lock) {
int myturn = FetchAndAdd(&lock->ticket);
// atomically allocate a ticket as the thread's turn
while (lock->turn != myturn) ;
// wait for its turn
}
void unlock(lock_t *lock) {
lock->turn += 1;
}
```
- Lock with Queue Implement
id:: 6436b05f-2873-4af4-952c-86d82685b583
- ```C
struct lock_t{
int lk;
int guard; // spin lock for the whole lock
queue_t *q; // control who gets the lock next
};
void lock(lock_t *lock) {
while (TestAndSet(&m->guard, 1) == 1) ;
if (m->lk == 0) {
m->lk = 1;
m->guard = 0;
}
else {
m->q->add(get_tid());
setpark(); // newly added
m->guard = 0;
// ---- wakeup/waiting race ----
park();
}
}
void unlock(lock_t *lock) {
while (TestAndSet(&m->guard, 1) == 1) ;
if (m->q->empty())
m->flag = 0;
else
unpark(m->q->pop()); // should not clear flag here
// Wake up Only one waiting thread
m->guard = 0;
}
```
- Producer/Consumer Solution with Condition Variable
id:: 6436b07d-9279-46bb-9c6b-985eb2324df8
- ```C
cond_t empty, fill;
mutex_t mutex;
void *producer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
Pthread_mutex_lock(&mutex);
while (count == MAX)
Pthread_cond_wait(&empty, &mutex);
put(i);
Pthread_cond_signal(&fill);
Pthread_mutex_unlock(&mutex);
}
}
void *consumer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
Pthread_mutex_lock(&mutex);
while (count == 0)
Pthread_cond_wait(&fill, &mutex);
int tmp = get();
Pthread_cond_signal(&empty);
Pthread_mutex_unlock(&mutex);
printf("%d\n", tmp);
}
}
```
- Producer/Consumer Solution with Semaphore
id:: 6436b15a-98b4-49be-8cdf-abefcf7e60b1
- ```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);
}
}
```

View File

@ -7,7 +7,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
hl-page:: 311 hl-page:: 311
hl-color:: yellow hl-color:: yellow
id:: 6433ca28-1bdf-433d-8ed9-0d54bf5ba940 id:: 6433ca28-1bdf-433d-8ed9-0d54bf5ba940
collapsed:: true
- share the same address space and thus can access the same data - share the same address space and thus can access the same data
- context switch: the address space remains the same - context switch: the address space remains the same
hl-page:: 311 hl-page:: 311
@ -33,7 +32,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
hl-page:: 323 hl-page:: 323
hl-color:: yellow hl-color:: yellow
id:: 6433eabf-48d6-4776-b66f-a5f7804d1ddc id:: 6433eabf-48d6-4776-b66f-a5f7804d1ddc
collapsed:: true
- **indeterminate**: the results depend on the timing execution of the code. - **indeterminate**: the results depend on the timing execution of the code.
- race condition - race condition
ls-type:: annotation ls-type:: annotation
@ -70,7 +68,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 6433f35b-403b-4b25-b9f9-076e9e34777e id:: 6433f35b-403b-4b25-b9f9-076e9e34777e
hl-color:: yellow hl-color:: yellow
collapsed:: true
- `pthread_create` `pthread_join` `pthread_mutex_lock` `pthread_cond_*` - `pthread_create` `pthread_join` `pthread_mutex_lock` `pthread_cond_*`
- Locks - Locks
ls-type:: annotation ls-type:: annotation
@ -82,7 +79,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 6433f4ba-f2e4-4743-a536-e2b7747433b7 id:: 6433f4ba-f2e4-4743-a536-e2b7747433b7
hl-color:: yellow hl-color:: yellow
collapsed:: true
- **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 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 state**: available (or unlocked or free); acquired (or locked or held)
- **lock routines**: - **lock routines**:
@ -98,7 +94,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
hl-page:: 342 hl-page:: 342
hl-color:: yellow hl-color:: yellow
id:: 6433fbfd-a1bf-4fd9-a54d-e15189c77b15 id:: 6433fbfd-a1bf-4fd9-a54d-e15189c77b15
collapsed:: true
- For *single-processor* systems, **disable interrupts** for critical sections. - For *single-processor* systems, **disable interrupts** for critical sections.
- Problems - Problems
- disable interrupts is privileged. In the worst case, the OS may never regain control when the interrupt isn't going to be enabled. - disable interrupts is privileged. In the worst case, the OS may never regain control when the interrupt isn't going to be enabled.
@ -110,7 +105,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 6433fe7e-2221-41ee-ad6b-7deaa4459aa5 id:: 6433fe7e-2221-41ee-ad6b-7deaa4459aa5
hl-color:: yellow hl-color:: yellow
collapsed:: true
- use a simple variable (flag) to indicate whether some thread has possession of a lock - use a simple variable (flag) to indicate whether some thread has possession of a lock
hl-page:: 343 hl-page:: 343
ls-type:: annotation ls-type:: annotation
@ -122,14 +116,8 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
- When interrupted between load and test, *mutual exclusion* is broken. - When interrupted between load and test, *mutual exclusion* is broken.
- Low efficiency because of spin-waiting. - Low efficiency because of spin-waiting.
- **spin lock** - **spin lock**
- ```c - ((6436aafd-c85f-414c-8aee-acdc71e9138e))
void lock(lock_t *lock) { - Requires a preemptive scheduler(or it may spin forever) and NO fairness guarantee
while (TestAndSet(&lock->status, 1) == 1);
}
void unlock(lock_t *lock) { lock->status = 0; }
```
- Requires a preemptive scheduler(or it may spin forever)
- No fairness guarantee
- For single processor systems, terrible performance, because the thread holding the lock cannot make any progress to release the lock until it is scheduled again and thus all other threads waiting for the lock can do nothing but spinning even they are scheduled. - For single processor systems, terrible performance, because the thread holding the lock cannot make any progress to release the lock until it is scheduled again and thus all other threads waiting for the lock can do nothing but spinning even they are scheduled.
- For multi-processor systems, spin lock may work well when thread B on CPU1 waits for thread A on CPU0, and the critical section is short. Because lock owner keeps making progress, spinning doesn't waste many cycles. - For multi-processor systems, spin lock may work well when thread B on CPU1 waits for thread A on CPU0, and the critical section is short. Because lock owner keeps making progress, spinning doesn't waste many cycles.
- **Priority Inversion**: Threads with high priority wait for locks held by threads with low priority. - **Priority Inversion**: Threads with high priority wait for locks held by threads with low priority.
@ -143,22 +131,14 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 643401e0-fcec-41d3-9898-d5c4175ac464 id:: 643401e0-fcec-41d3-9898-d5c4175ac464
hl-color:: yellow hl-color:: yellow
collapsed:: true
- Returns the old value pointed to by the `old_ptr`, and simultaneously updates said value to `new`. - Returns the old value pointed to by the `old_ptr`, and simultaneously updates said value to `new`.
- "test" the old value (which is what is returned) while simultaneously "set" the memory location to a new value - "test" the old value (which is what is returned) while simultaneously "set" the memory location to a new value
- ```c - ((6436af87-3f1b-4ee8-a2c8-4de0f1961f1a))
int TestAndSet(int *old_ptr, int new) {
int old = *old_ptr;
*old_ptr = new;
return old;
}
```
- **Compare-And-Swap** - **Compare-And-Swap**
hl-page:: 348 hl-page:: 348
ls-type:: annotation ls-type:: annotation
id:: 6434f8ac-d762-40a4-abb0-2955c2c8b396 id:: 6434f8ac-d762-40a4-abb0-2955c2c8b396
hl-color:: yellow hl-color:: yellow
collapsed:: true
- Test whether the value at the address specified by `ptr` is equal to `expected`. - Test whether the value at the address specified by `ptr` is equal to `expected`.
hl-page:: 348 hl-page:: 348
ls-type:: annotation ls-type:: annotation
@ -185,7 +165,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 6434fde1-9d19-4381-805e-f2a972875dc2 id:: 6434fde1-9d19-4381-805e-f2a972875dc2
hl-color:: yellow hl-color:: yellow
collapsed:: true
- The **load-linked** operates much like a typical load instruction, and simply fetches a value from memory and places it in a register. - The **load-linked** operates much like a typical load instruction, and simply fetches a value from memory and places it in a register.
ls-type:: annotation ls-type:: annotation
hl-page:: 349 hl-page:: 349
@ -225,7 +204,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
hl-page:: 350 hl-page:: 350
hl-color:: yellow hl-color:: yellow
id:: 64350170-c853-4080-9ed1-2777ea3a18c8 id:: 64350170-c853-4080-9ed1-2777ea3a18c8
collapsed:: true
- Atomically increments a value while returning the old value at a particular address - Atomically increments a value while returning the old value at a particular address
- ```c - ```c
int FetchAndAdd(int *ptr) { int FetchAndAdd(int *ptr) {
@ -239,21 +217,7 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 64350331-8fbb-4c41-9ac1-1a4ba852f772 id:: 64350331-8fbb-4c41-9ac1-1a4ba852f772
hl-color:: yellow hl-color:: yellow
- ```C - ((6436af5c-0000-4bfb-9a27-1d7cf0a830db))
struct lock_t{
int ticket;
int turn;
};
void lock(lock_t *lock) {
int myturn = FetchAndAdd(&lock->ticket);
// atomically allocate a ticket as the thread's turn
while (lock->turn != myturn) ;
// wait for its turn
}
void unlock(lock_t *lock) {
lock->turn += 1;
}
```
- Ensure progress for all threads. Once a thread is assigned its ticket value, it will be scheduled at some point in the future (i.e. it will definitely get its turn as `unlock()` operations increase global `turn` value). - Ensure progress for all threads. Once a thread is assigned its ticket value, it will be scheduled at some point in the future (i.e. it will definitely get its turn as `unlock()` operations increase global `turn` value).
hl-page:: 351 hl-page:: 351
ls-type:: annotation ls-type:: annotation
@ -265,7 +229,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 64350781-6995-41db-8b8e-2de0eb84136a id:: 64350781-6995-41db-8b8e-2de0eb84136a
hl-color:: yellow hl-color:: yellow
collapsed:: true
- `yield`: a system call that moves the caller from the running state to the ready state, and thus promotes another thread to running. - `yield`: a system call that moves the caller from the running state to the ready state, and thus promotes another thread to running.
hl-page:: 353 hl-page:: 353
ls-type:: annotation ls-type:: annotation
@ -298,37 +261,7 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 64350c01-39bb-4d15-b554-0287b13806ee id:: 64350c01-39bb-4d15-b554-0287b13806ee
hl-color:: yellow hl-color:: yellow
- implement - ((6436b05f-2873-4af4-952c-86d82685b583))
```C
struct lock_t{
int lk;
int guard; // spin lock for the whole lock
queue_t *q; // control who gets the lock next
};
void lock(lock_t *lock) {
while (TestAndSet(&m->guard, 1) == 1) ;
if (m->lk == 0) {
m->lk = 1;
m->guard = 0;
}
else {
m->q->add(get_tid());
setpark(); // newly added
m->guard = 0;
// ---- wakeup/waiting race ----
park();
}
}
void unlock(lock_t *lock) {
while (TestAndSet(&m->guard, 1) == 1) ;
if (m->q->empty())
m->flag = 0;
else
unpark(m->q->pop()); // should not clear flag here
// Wake up Only one waiting thread
m->guard = 0;
}
```
- When a thread is woken up, it will be as if it is returning from `park()`. Thus when `unpark` a thread, pass the lock directly from the thread releasing the lock to the next thread acquiring it; flag is not set to 0 in-between. - When a thread is woken up, it will be as if it is returning from `park()`. Thus when `unpark` a thread, pass the lock directly from the thread releasing the lock to the next thread acquiring it; flag is not set to 0 in-between.
- wakeup/waiting race: If the thread is scheduled out just before it calls `park`, and then the lock owner calls `unpark` on that thread, it would sleep forever. - wakeup/waiting race: If the thread is scheduled out just before it calls `park`, and then the lock owner calls `unpark` on that thread, it would sleep forever.
hl-page:: 356 hl-page:: 356
@ -390,8 +323,7 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
hl-page:: 351 hl-page:: 351
hl-color:: green hl-color:: green
id:: 643501c1-f11b-4e85-8125-d2a5a31f69b0 id:: 643501c1-f11b-4e85-8125-d2a5a31f69b0
- scourge - scourge 鞭打;鞭笞;折磨;使受苦难
- 鞭打;鞭笞;折磨;使受苦难
- Lock-based Concurrent Data Structures - Lock-based Concurrent Data Structures
ls-type:: annotation ls-type:: annotation
hl-page:: 361 hl-page:: 361
@ -534,34 +466,7 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
- If in step 3, the producer `P1` is woken up, everything is fine. Obviously, one solution is to ==exert control over which thread is to be woken up==. Well, wake up all threads may also solve this problem, see ((64355441-5a1b-4015-baa1-65917526079c)). - If in step 3, the producer `P1` is woken up, everything is fine. Obviously, one solution is to ==exert control over which thread is to be woken up==. Well, wake up all threads may also solve this problem, see ((64355441-5a1b-4015-baa1-65917526079c)).
- Correct solution: 2 condition variable. - Correct solution: 2 condition variable.
- Producer threads wait on the condition `empty`, and signals `fill`. Conversely, consumer threads wait on `fill` and signal `empty`. - Producer threads wait on the condition `empty`, and signals `fill`. Conversely, consumer threads wait on `fill` and signal `empty`.
- Code - ((6436b07d-9279-46bb-9c6b-985eb2324df8))
```C
cond_t empty, fill;
mutex_t mutex;
void *producer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
Pthread_mutex_lock(&mutex);
while (count == MAX)
Pthread_cond_wait(&empty, &mutex);
put(i);
Pthread_cond_signal(&fill);
Pthread_mutex_unlock(&mutex);
}
}
void *consumer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
Pthread_mutex_lock(&mutex);
while (count == 0)
Pthread_cond_wait(&fill, &mutex);
int tmp = get();
Pthread_cond_signal(&empty);
Pthread_mutex_unlock(&mutex);
printf("%d\n", tmp);
}
}
```
- **spurious wakeups** - **spurious wakeups**
hl-page:: 390 hl-page:: 390
ls-type:: annotation ls-type:: annotation
@ -600,7 +505,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
hl-page:: 397 hl-page:: 397
hl-color:: yellow hl-color:: yellow
id:: 6435744b-a300-40ad-ba91-157666d8cd2a 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_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 - `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== - The value of the semaphore, *when negative*, is equal to the ==number of waiting threads==
@ -613,7 +517,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
hl-page:: 398 hl-page:: 398
hl-color:: yellow hl-color:: yellow
id:: 6435753a-65b5-4e46-82bc-54c11c1cd533 id:: 6435753a-65b5-4e46-82bc-54c11c1cd533
collapsed:: true
- Initialize semaphore to 1, indicating we only have one piece of resource (the critical section). - 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` - 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. - 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.
@ -622,7 +525,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 64357930-2d96-4867-bc3d-2fe89990ce5f id:: 64357930-2d96-4867-bc3d-2fe89990ce5f
hl-color:: yellow hl-color:: yellow
collapsed:: true
- Initialize the semaphore to 0 - 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. - 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)** - **The Producer/Consumer (Bounded Buffer) Problem (Again)**
@ -630,7 +532,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 64357c6d-381e-492e-b901-095454f5315e id:: 64357c6d-381e-492e-b901-095454f5315e
hl-color:: yellow hl-color:: yellow
collapsed:: true
- 2 semaphores `empty` and `full` for coordination between consumer and producer, and 1 semaphore for lock - 2 semaphores `empty` and `full` for coordination between consumer and producer, and 1 semaphore for lock
- Initialize `empty <- MAX`, and `full <- 0` - Initialize `empty <- MAX`, and `full <- 0`
- Consumer waits for `full` and posts `empty` and conversely, produce waits for `empty` and posts `full` - Consumer waits for `full` and posts `empty` and conversely, produce waits for `empty` and posts `full`
@ -640,28 +541,6 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
- Deadlock avoidance - 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. - 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 - 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** - **Reader-Writer Locks**
ls-type:: annotation ls-type:: annotation
hl-page:: 406 hl-page:: 406
@ -692,7 +571,7 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
void rwlock_release_writelock(rwlock_t *rw) { sem_post(&rw->writelock); } void rwlock_release_writelock(rwlock_t *rw) { sem_post(&rw->writelock); }
``` ```
- Problem: More overhead; Unfairness, writer is much more likely to starve. - 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) - To tackle the writer starvation problem, we may manually wake up the writers (if ever suspended) every time read lock releases. [Wiki](https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock)
- **The Dining Philosophers** - **The Dining Philosophers**
hl-page:: 408 hl-page:: 408
ls-type:: annotation ls-type:: annotation
@ -741,11 +620,32 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
hl-page:: 411 hl-page:: 411
hl-color:: yellow hl-color:: yellow
id:: 643589a6-31e6-4603-9259-999e9c8860f7 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. - Implementing Zemaphores With One Lock And One CV: the book authors provide us a simple implement for semaphore.
hl-page:: 412 hl-page:: 412
ls-type:: annotation ls-type:: annotation
id:: 64358de1-f418-44fd-8a77-bc0faa368059 id:: 64358de1-f418-44fd-8a77-bc0faa368059
hl-color:: yellow hl-color:: yellow
- Implement
```C
struct sem_t{
int value;
cond_t cond;
mutex_t lock;
};
void sem_wait(sem_t *sem) {
mutex_lock(&sem->lock);
while (s->value <= 0)
cond_wait(&sem->cond, &sem->lock);
s->value --;
mutex_unlock(&sem->lock);
}
void sem_post(sem_t *sem) {
mutex_lock(&sem->lock);
sem->value ++;
cond_signal(&sem->cond);
mutex_unlock(&sem->lock);
}
```
- salient 最重要的;显着的;突出的: - salient 最重要的;显着的;突出的:
ls-type:: annotation ls-type:: annotation
hl-page:: 397 hl-page:: 397
@ -771,3 +671,178 @@ file-path:: ../assets/ostep_1681115599584_0.pdf
ls-type:: annotation ls-type:: annotation
id:: 64358b0c-e441-4d0a-852d-ecfde369306c id:: 64358b0c-e441-4d0a-852d-ecfde369306c
hl-color:: green hl-color:: green
- Non-Deadlock Bugs: A large fraction (97%) of non-deadlock bugs studied by Lu et al. are either ==atomicity violations== or ==order violations==.
hl-page:: 420
ls-type:: annotation
id:: 64361e4c-62eb-4599-9809-0f77f9ce1cd0
hl-color:: yellow
- **Deadlock**
ls-type:: annotation
hl-page:: 420
hl-color:: yellow
id:: 64361fb7-5aa6-45cd-8b1e-aa0d0c300ad2
- **Conditions for Deadlock**
hl-page:: 422
ls-type:: annotation
id:: 64361fd1-49ff-4023-8493-840ac423086a
hl-color:: yellow
- If any of these four conditions are not met, deadlock cannot occur.
- **Mutual exclusion**: Threads claim exclusive control of resources that they require
- **Hold-and-wait**: Threads hold resources allocated to them while waiting for additional resources
- **No preemption**: Resources cannot be forcibly removed from threads that are holding them.
- **Circular wait**: There exists a circular chain of threads such that each thread holds one or more resources that are being requested by the next thread in the chain.
- **Prevention**: break the conditions for deadlock
hl-page:: 422
ls-type:: annotation
id:: 643620d9-cdb6-4073-89f4-f9f8ac223073
hl-color:: yellow
- **Circular Wait**: Never induce a circular wait.
hl-page:: 422
ls-type:: annotation
id:: 643620fb-edc6-43b2-b4b2-43b010cfc46e
hl-color:: yellow
- total ordering and partial ordering of lock acquisition (think about your Discrete Math, total ordering is a restricted form of partial ordering, in partial ordering, some pairs of elements are not comparable)
- Anyways, follow some kind of ordering when acquire lock in order to avoid cycles.
- ENFORCE LOCK ORDERING BY LOCK ADDRESS
ls-type:: annotation
hl-page:: 423
hl-color:: yellow
id:: 64362497-58cd-45da-8ab5-84f96e899e16
- **Hold-and-wait**: acquiring all locks at once, atomically.
hl-page:: 423
ls-type:: annotation
id:: 643625fe-423c-4b18-8c22-32d38720c5d0
hl-color:: yellow
- Not practical
- **No Preemption**
hl-page:: 424
ls-type:: annotation
id:: 64362632-50e8-41dd-a1bc-bbf3d4312b0f
hl-color:: yellow
- `trylock` either grabs the lock (if it is available) and returns success or returns an error code indicating the lock is held
- Instead of blocking at the lock call, give up all previous locks and try over again if some of the locks is not available.
- ```C
while (true) {
mutex_lock(&lock1);
if (mutex_trylock(&lock2) == 0) break;
else mutex_unlock(&lock1);
}
```
- **livelock** problem: in some special cases, two threads may keep trying and giving up locks due to each other's intervention
hl-page:: 424
ls-type:: annotation
id:: 6436281f-4fdc-4586-83fb-b686cec3b76b
hl-color:: yellow
- random delay before looping back and trying the entire thing over again
- **Mutual Exclusion**: lock-free data structures
hl-page:: 425
ls-type:: annotation
id:: 643629ba-e746-41a6-b073-1199b3db3691
hl-color:: yellow
- use atomic instructions provided by hardware
- **Avoidance**
hl-page:: 427
ls-type:: annotation
id:: 64362af4-9b35-4e27-8ba2-0f5f8817526a
hl-color:: yellow
- By careful scheduling, deadlock could be avoided.
- Limited usage: OS does not always have sufficient knowledge to make deadlock-free scheduling. Such approaches also limit concurrency.
- [[Banker's Algorithm]]
- **Detect and Recover**
ls-type:: annotation
hl-page:: 428
hl-color:: yellow
id:: 64362c62-3a12-4bcb-95ae-baf1ca69312e
- Allow deadlocks to occasionally occur, and then take some action once such a deadlock has been detected.
- terrific 极好的;绝妙的;了不起的;很大的
ls-type:: annotation
hl-page:: 428
hl-color:: green
id:: 64362b38-6dfb-4c00-8aa6-b756e8983de4
- maxim 格言;箴言;座右铭
ls-type:: annotation
hl-page:: 428
hl-color:: green
id:: 64362b40-5f07-418f-83f3-c83eb5927c94
- nasty 极差的;令人厌恶的;令人不悦的;不友好的
ls-type:: annotation
hl-page:: 432
hl-color:: green
id:: 64364569-01b4-45e1-83f8-ac1bd8af5850
- **Event-based Concurrency**
ls-type:: annotation
hl-page:: 432
hl-color:: yellow
id:: 64364585-ace4-4920-87fe-87aad004dffd
- event loop: waits for something to do and then, for each event returned, processes them, one at a time
hl-page:: 433
ls-type:: annotation
id:: 643658f3-4761-4d0c-b044-4cadcfea27aa
hl-color:: yellow
- event handler
ls-type:: annotation
hl-page:: 433
hl-color:: yellow
id:: 643658f9-5eee-4d1a-a3d6-4f8eb9ed3d7b
- `select` or `poll`
hl-page:: 433
ls-type:: annotation
id:: 64365db8-a249-46bc-bd9c-237251c544b5
hl-color:: yellow
- Check whether there is any incoming I/O that should be attended to.
- ```C
int select(
int nfds,
fd_set *restrict readfds,
fd_set *restrict writefds,
fd_set *restrict errorfds,
struct timeval *restrict timeout);
```
- Examine if some of their descriptors are ready for reading/writing or have an exceptional condition pending. The first n descriptors are checked in each set
hl-page:: 434
ls-type:: annotation
id:: 64365eb6-5310-4893-9d11-5e332ef84c4a
hl-color:: yellow
- `select` places the given descriptor sets with ==subsets of ready descriptors==. `select()` ==returns the total number of ready descriptors== in all the sets.
hl-page:: 434
ls-type:: annotation
id:: 64365ef8-3c62-4d78-8bc6-d0a4b2c81d49
hl-color:: yellow
- Block IO: NO blocking calls are allowed in event-based systems, because it will just stop the whole process.
- **Asynchronous I/O**
ls-type:: annotation
hl-page:: 437
hl-color:: yellow
id:: 643693db-d363-46ee-b0d6-910b30408946
- Issue an I/O request and return control immediately to the caller, before completion. Additional interfaces to determine whether the IOs have completed.
hl-page:: 437
ls-type:: annotation
id:: 64369701-8a39-4aa4-9985-129572c04f53
hl-color:: yellow
- AIO control block `aiocb`
- `int aio_read(struct aiocb *aiocbp);` issues an asynchronous read request
- `int aio_error(const struct aiocb *aiocbp);` checks whether the request (designated by the `aiocb`) has completed
- Checking IO completion is inefficient, perhaps we need interrupt-based approaches (e.g. UNIX signals) to inform applications when async IO completes.
- Problems
- State management
- manual stack management: when an event handler issues an asynchronous I/O, it must package up some program state for the next event handler to use when the I/O finally completes; this additional work is not needed in thread-based programs, as the state the program needs is on the stack of the thread.
hl-page:: 438
ls-type:: annotation
id:: 6436a3d9-ee29-4378-af79-4efc770cc209
hl-color:: yellow
- continuation: record the needed information to finish processing this event in some data structure; when the event happens (i.e., when the disk I/O completes), look up the needed information and process the event.
hl-page:: 440
ls-type:: annotation
id:: 6436a40a-121f-4fab-b428-b278e4cb65d3
hl-color:: yellow
- Utilizing multiple CPUs
hl-page:: 440
ls-type:: annotation
id:: 6436a46c-f845-4c7b-8bb1-97da71589c67
hl-color:: yellow
- Implicit blocking such as paging
hl-page:: 440
ls-type:: annotation
id:: 6436a485-7a70-4974-93d2-9e11b010a948
hl-color:: yellow
- Messy code base due to complicated asynchronous logic