I thought the purpose of the different threads in ATS was pretty clear. There are many threads to handle requests (1.5x the number of HT cores). 8 threads to handle disk I/O (cache). 2-3 threads to do miscellaneous tasks. 2-3 threads to handle logging. One thread for each port which you want to listen on.
Are you running into some perf issue with locking/contention etc? On Wed, Oct 10, 2018 at 10:31 AM Walt Karas <wka...@oath.com.invalid> wrote: > It seems like ATS does not have a coherent strategy for threading and > mutexes. > > One pure strategy is event driven with one thread per core (processing > an event queue). Share data structures are owned by a particular core > (also helps with NUMA), and events that want to access the data > structure are queued on the thread for that core. Few if any mutexes > are needed. > > The other strategy (non event driven) is to figure that threads are > low-overhead compared to processes, so don't worry about creating gobs > of them, or the mutex overhead. Most programmers find this approach > to be more straightforward, and it jives better with the API of Unix > and most other OSes. > > ATS has static threads, but many more than one per core. The > purpose(s) of the large number and various types of threads is > unclear. Our discussion of mutexes quickly turned into blah blah blah > mumble mumble. > On Wed, Oct 10, 2018 at 11:38 AM Pushkar Pradhan > <pprad...@oath.com.invalid> wrote: > > > > I think Alan is referring to the below code. > > It's a try lock, so if it doesn't succeed it's just rescheduled for > later. > > > > void > > EThread::process_event(Event *e, int calling_code) > > { > > ink_assert((!e->in_the_prot_queue && !e->in_the_priority_queue)); > > MUTEX_TRY_LOCK_FOR(lock, e->mutex, this, e->continuation); > > if (!lock.is_locked()) { > > e->timeout_at = cur_time + DELAY_FOR_RETRY; > > EventQueueExternal.enqueue_local(e); > > } else { > > if (e->cancelled) { > > free_event(e); > > return; > > } > > Continuation *c_temp = e->continuation; > > // Make sure that the contination is locked before calling the > handler > > //set_cont_flags(e->continuation->control_flags); > > e->continuation->handleEvent(calling_code, e); > > > > On Tue, Oct 9, 2018 at 2:04 PM Walt Karas <wka...@oath.com.invalid> > wrote: > > > > > To what "explicit continuation locking" do you refer? > > > > > > How does this address the issue that using TSMutexLock() or MutexLock > > > in a currently running continuation function (unnecessarily) blocks > > > all other events waiting in a thread event queue? Whereas the > > > inability to lock a continuation mutex cause the continuation to be > > > requeued at the end of the thread event queue, thus allowing > > > succeeding events in the thread's queue to be handled. > > > On Tue, Oct 9, 2018 at 3:44 PM Alan Carroll > > > <solidwallofc...@oath.com.invalid> wrote: > > > > > > > > It's a bit more complex than that. One key thing is that if you > schedule > > > an > > > > event for a continuation, when the event handler is called the > > > continuation > > > > mutex will be locked. Therefore it's rarely the case a plugin needs > to > > > lock > > > > its continuations explicitly. For that reason, simply scheduling > handles > > > > lock contention without thread blocking. > > > > > > > > In the core, there is a class, MutexLock, which does the RAII style > > > locking. > > > > > > > > On Tue, Oct 9, 2018 at 2:26 PM Walt Karas <wka...@oath.com.invalid> > > > wrote: > > > > > > > > > In TS, is it important to favor use of continuation mutexes to > avoid > > > > > thread blocking. For example, should code like this: > > > > > > > > > > before(); > > > > > TSMutexLock(mutex); > > > > > critical_section(); > > > > > TSMutexUnlock(mutex); > > > > > after(); > > > > > > > > > > be replaced with code like: > > > > > > > > > > int contf_after(TSCont, TSEvent, void *) > > > > > { > > > > > after(); > > > > > > > > > > return 0; > > > > > } > > > > > > > > > > int contf_critical_section(TSCont, TSEvent, void *) > > > > > { > > > > > critical_section(); > > > > > > > > > > static TSCont cont_after = TSContCreate(contf_after, nullptr); > > > > > > > > > > TSContSchedule(cont_after, 0, TS_THREAD_POOL_DEFAULT); > > > > > > > > > > return 0; > > > > > } > > > > > > > > > > // ... > > > > > > > > > > before(); > > > > > > > > > > static TSCont cont_critical_section = > > > > > TSContCreate(contf_critical_section, mutex); > > > > > > > > > > TSContSchedule(cont_critical_section, 0, TS_THREAD_POOL_DEFAULT); > > > > > > > > > > // ... > > > > > > > > > > (This is plugin code but I assume the same principle would apply to > > > core > > > > > code.) > > > > > > > > > > > > > > > > > -- > > > > *Beware the fisherman who's casting out his line in to a dried up > > > riverbed.* > > > > *Oh don't try to tell him 'cause he won't believe. Throw some bread > to > > > the > > > > ducks instead.* > > > > *It's easier that way. *- Genesis : Duke : VI 25-28 > > > > > > > > > -- > > pushkar > -- pushkar