2828#include " PreservationTable.h"
2929#include " Stripe.h"
3030
31+ #include " iocore/eventsystem/Event.h"
3132#include " tscore/hugepages.h"
3233#include " tscore/Random.h"
3334#include " ts/ats_probe.h"
35+ #include " tsutil/Bravo.h"
36+ #include < mutex>
3437
3538#ifdef LOOP_CHECK_MODE
3639#define DIR_LOOP_THRESHOLD 1000
@@ -46,6 +49,7 @@ DbgCtl dbg_ctl_dir_clean{"dir_clean"};
4649#ifdef DEBUG
4750
4851DbgCtl dbg_ctl_cache_stats{" cache_stats" };
52+ DbgCtl dbg_ctl_cache_open_dir{" cache_open_dir" };
4953DbgCtl dbg_ctl_dir_probe_hit{" dir_probe_hit" };
5054DbgCtl dbg_ctl_dir_probe_tag{" dir_probe_tag" };
5155DbgCtl dbg_ctl_dir_probe_miss{" dir_probe_miss" };
@@ -78,10 +82,11 @@ OpenDir::OpenDir()
7882int
7983OpenDir::open_write (CacheVC *cont, int allow_if_writers, int max_writers)
8084{
81- ink_assert (cont->stripe ->mutex ->thread_holding == this_ethread ());
85+ std::lock_guard lock (_shared_mutex);
86+
8287 unsigned int h = cont->first_key .slice32 (0 );
8388 int b = h % OPEN_DIR_BUCKETS;
84- for (OpenDirEntry *d = bucket [b].head ; d; d = d->link .next ) {
89+ for (OpenDirEntry *d = _bucket [b].head ; d; d = d->link .next ) {
8590 if (!(d->writers .head ->first_key == cont->first_key )) {
8691 continue ;
8792 }
@@ -107,17 +112,27 @@ OpenDir::open_write(CacheVC *cont, int allow_if_writers, int max_writers)
107112 dir_clear (&od->first_dir );
108113 cont->od = od;
109114 cont->write_vector = &od->vector ;
110- bucket [b].push (od);
115+ _bucket [b].push (od);
111116 return 1 ;
112117}
113118
119+ /* *
120+ This event handler is called in two cases:
121+
122+ 1. Direct call from OpenDir::close_write - writer lock is already acquired
123+ 2. Self retry through event system - need to acquire writer lock
124+ */
114125int
115- OpenDir::signal_readers (int /* event ATS_UNUSED */ , Event * /* e ATS_UNUSED */ )
126+ OpenDir::signal_readers (int event, Event * /* ATS UNUSED */ )
116127{
128+ if (event == CACHE_EVENT_OPEN_DIR_RETRY) {
129+ _shared_mutex.lock ();
130+ }
131+
117132 Queue<CacheVC, Link_CacheVC_opendir_link> newly_delayed_readers;
118133 EThread *t = mutex->thread_holding ;
119134 CacheVC *c = nullptr ;
120- while ((c = delayed_readers .dequeue ())) {
135+ while ((c = _delayed_readers .dequeue ())) {
121136 CACHE_TRY_LOCK (lock, c->mutex , t);
122137 if (lock.is_locked ()) {
123138 c->f .open_read_timeout = 0 ;
@@ -127,28 +142,34 @@ OpenDir::signal_readers(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */)
127142 newly_delayed_readers.push (c);
128143 }
129144 if (newly_delayed_readers.head ) {
130- delayed_readers = newly_delayed_readers;
131- EThread *t1 = newly_delayed_readers.head ->mutex ->thread_holding ;
145+ _delayed_readers = newly_delayed_readers;
146+ EThread *t1 = newly_delayed_readers.head ->mutex ->thread_holding ;
132147 if (!t1) {
133148 t1 = mutex->thread_holding ;
134149 }
135- t1->schedule_in (this , HRTIME_MSECONDS (cache_config_mutex_retry_delay));
150+ t1->schedule_in (this , HRTIME_MSECONDS (cache_config_mutex_retry_delay), CACHE_EVENT_OPEN_DIR_RETRY );
136151 }
137- return 0 ;
152+
153+ if (event == CACHE_EVENT_OPEN_DIR_RETRY) {
154+ _shared_mutex.unlock ();
155+ }
156+
157+ return EVENT_DONE;
138158}
139159
140160int
141161OpenDir::close_write (CacheVC *cont)
142162{
143- ink_assert (cont->stripe ->mutex ->thread_holding == this_ethread ());
163+ std::lock_guard lock (_shared_mutex);
164+
144165 cont->od ->writers .remove (cont);
145166 cont->od ->num_writers --;
146167 if (!cont->od ->writers .head ) {
147168 unsigned int h = cont->first_key .slice32 (0 );
148169 int b = h % OPEN_DIR_BUCKETS;
149- bucket [b].remove (cont->od );
150- delayed_readers .append (cont->od ->readers );
151- signal_readers (0 , nullptr );
170+ _bucket [b].remove (cont->od );
171+ _delayed_readers .append (cont->od ->readers );
172+ signal_readers (EVENT_CALL , nullptr );
152173 cont->od ->vector .clear ();
153174 THREAD_FREE (cont->od , openDirEntryAllocator, cont->mutex ->thread_holding );
154175 }
@@ -159,9 +180,11 @@ OpenDir::close_write(CacheVC *cont)
159180OpenDirEntry *
160181OpenDir::open_read (const CryptoHash *key) const
161182{
183+ ts::bravo::shared_lock lock (_shared_mutex);
184+
162185 unsigned int h = key->slice32 (0 );
163186 int b = h % OPEN_DIR_BUCKETS;
164- for (OpenDirEntry *d = bucket [b].head ; d; d = d->link .next ) {
187+ for (OpenDirEntry *d = _bucket [b].head ; d; d = d->link .next ) {
165188 if (d->writers .head ->first_key == *key) {
166189 return d;
167190 }
0 commit comments