]>
Commit | Line | Data |
---|---|---|
be17aa82 | 1 | /* |
5b74111a | 2 | * Copyright (C) 1996-2018 The Squid Software Foundation and contributors |
be17aa82 | 3 | * |
bbc27441 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
be17aa82 AR |
7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 54 Interprocess Communication */ |
10 | ||
f7f3304a | 11 | #include "squid.h" |
be17aa82 AR |
12 | |
13 | #include "base/TextException.h" | |
383ff927 | 14 | #include "Debug.h" |
68353d5a | 15 | #include "ipc/mem/Page.h" |
be17aa82 AR |
16 | #include "ipc/mem/PageStack.h" |
17 | ||
18 | /// used to mark a stack slot available for storing free page offsets | |
19 | const Ipc::Mem::PageStack::Value Writable = 0; | |
20 | ||
68353d5a | 21 | Ipc::Mem::PageStack::PageStack(const uint32_t aPoolId, const unsigned int aCapacity, const size_t aPageSize): |
f53969cc SM |
22 | thePoolId(aPoolId), theCapacity(aCapacity), thePageSize(aPageSize), |
23 | theSize(theCapacity), | |
24 | theLastReadable(prev(theSize)), theFirstWritable(next(theLastReadable)), | |
25 | theItems(aCapacity) | |
c011f9bc | 26 | { |
68353d5a DK |
27 | // initially, all pages are free |
28 | for (Offset i = 0; i < theSize; ++i) | |
29 | theItems[i] = i + 1; // skip page number zero to keep numbers positive | |
2cde0303 FC |
30 | } |
31 | ||
be17aa82 AR |
32 | /* |
33 | * TODO: We currently rely on the theLastReadable hint during each | |
34 | * loop iteration. We could also use hint just for the start position: | |
35 | * (const Offset start = theLastReadable) and then scan the stack | |
36 | * sequentially regardless of theLastReadable changes by others. Which | |
37 | * approach is better? Same for push(). | |
38 | */ | |
39 | bool | |
68353d5a | 40 | Ipc::Mem::PageStack::pop(PageId &page) |
be17aa82 | 41 | { |
8ed94021 DK |
42 | Must(!page); |
43 | ||
be17aa82 | 44 | // we may fail to dequeue, but be conservative to prevent long searches |
68353d5a | 45 | --theSize; |
be17aa82 AR |
46 | |
47 | // find a Readable slot, starting with theLastReadable and going left | |
68353d5a | 48 | while (theSize >= 0) { |
2253ee0b | 49 | Offset idx = theLastReadable; |
be17aa82 | 50 | // mark the slot at ids Writable while extracting its current value |
2253ee0b | 51 | const Value value = theItems[idx].fetch_and(0); // works if Writable is 0 |
be17aa82 AR |
52 | const bool popped = value != Writable; |
53 | // theItems[idx] is probably not Readable [any more] | |
03055efe AR |
54 | |
55 | // Whether we popped a Readable value or not, we should try going left | |
56 | // to maintain the index (and make progress). | |
57 | // We may fail if others already updated the index, but that is OK. | |
2253ee0b | 58 | theLastReadable.compare_exchange_weak(idx, prev(idx)); // may fail or lie |
03055efe | 59 | |
be17aa82 AR |
60 | if (popped) { |
61 | // the slot we emptied may already be filled, but that is OK | |
68353d5a DK |
62 | theFirstWritable = idx; // may lie |
63 | page.pool = thePoolId; | |
64 | page.number = value; | |
383ff927 | 65 | debugs(54, 9, page << " at " << idx << " size: " << theSize); |
be17aa82 AR |
66 | return true; |
67 | } | |
68 | // TODO: report suspiciously long loops | |
69 | } | |
70 | ||
68353d5a | 71 | ++theSize; |
be17aa82 AR |
72 | return false; |
73 | } | |
74 | ||
75 | void | |
68353d5a | 76 | Ipc::Mem::PageStack::push(PageId &page) |
be17aa82 | 77 | { |
383ff927 AR |
78 | debugs(54, 9, page); |
79 | ||
8ed94021 DK |
80 | if (!page) |
81 | return; | |
82 | ||
68353d5a | 83 | Must(pageIdIsValid(page)); |
be17aa82 | 84 | // find a Writable slot, starting with theFirstWritable and going right |
68353d5a | 85 | while (theSize < theCapacity) { |
2253ee0b AJ |
86 | Offset idx = theFirstWritable; |
87 | auto isWritable = Writable; | |
88 | const bool pushed = theItems[idx].compare_exchange_strong(isWritable, page.number); | |
be17aa82 | 89 | // theItems[idx] is probably not Writable [any more]; |
03055efe | 90 | |
68353d5a | 91 | // Whether we pushed the page number or not, we should try going right |
03055efe AR |
92 | // to maintain the index (and make progress). |
93 | // We may fail if others already updated the index, but that is OK. | |
2253ee0b | 94 | theFirstWritable.compare_exchange_weak(idx, next(idx)); // may fail or lie |
03055efe | 95 | |
be17aa82 AR |
96 | if (pushed) { |
97 | // the enqueued value may already by gone, but that is OK | |
68353d5a DK |
98 | theLastReadable = idx; // may lie |
99 | ++theSize; | |
383ff927 | 100 | debugs(54, 9, page << " at " << idx << " size: " << theSize); |
68353d5a | 101 | page = PageId(); |
be17aa82 AR |
102 | return; |
103 | } | |
104 | // TODO: report suspiciously long loops | |
105 | } | |
106 | Must(false); // the number of pages cannot exceed theCapacity | |
107 | } | |
108 | ||
68353d5a DK |
109 | bool |
110 | Ipc::Mem::PageStack::pageIdIsValid(const PageId &page) const | |
be17aa82 | 111 | { |
68353d5a | 112 | return page.pool == thePoolId && page.number != Writable && |
9199139f | 113 | page.number <= capacity(); |
68353d5a DK |
114 | } |
115 | ||
116 | size_t | |
117 | Ipc::Mem::PageStack::sharedMemorySize() const | |
118 | { | |
119 | return SharedMemorySize(thePoolId, theCapacity, thePageSize); | |
be17aa82 | 120 | } |
2d0647fb DK |
121 | |
122 | size_t | |
68353d5a | 123 | Ipc::Mem::PageStack::SharedMemorySize(const uint32_t, const unsigned int capacity, const size_t pageSize) |
2d0647fb | 124 | { |
2253ee0b | 125 | const size_t levelsSize = PageId::maxPurpose * sizeof(std::atomic<Ipc::Mem::PageStack::Value>); |
551f8a18 DK |
126 | const size_t pagesDataSize = capacity * pageSize; |
127 | return StackSize(capacity) + pagesDataSize + levelsSize; | |
128 | } | |
129 | ||
130 | size_t | |
131 | Ipc::Mem::PageStack::StackSize(const unsigned int capacity) | |
132 | { | |
133 | return sizeof(PageStack) + capacity * sizeof(Item); | |
134 | } | |
135 | ||
136 | size_t | |
137 | Ipc::Mem::PageStack::stackSize() const | |
138 | { | |
139 | return StackSize(theCapacity); | |
2d0647fb | 140 | } |
f53969cc | 141 |