On Wed, May 13, 2009 at 3:48 AM, Eric Day <[email protected]> wrote: > On Tue, May 12, 2009 at 05:31:23PM +0800, Biping MENG wrote: > > Well, maybe not everywhere. Initially doing it on socket I/O would > > be a big win, and then eventually on disk I/O. We may need to on the > > mutexes to prevent deadlocks (depending on the lock), but most > mutexes > > should be pretty short lived, so we may want to always switch on > those. > > Oops, this should have been "so we may _not_ want..." > > > Actually one user level thread corresponds to one session and many > user > > level threads may run on one kernel thread. > > So if we switch between user-level threads, mutexes shared by > > sessions(equal to user-level threads) may cause a deadlock by invoking > > yield(). Brain also reminded me of this on the IRC. I'm thinking about > the > > relation of these two levels of threads and locks on these two levels. > I > > thought a simple way of avoiding deadlock is to alway require locks > > sequentially. To keep this principle is an easy way to avoid deadlock. > I > > may need some time to check through the locks and build up a sequence > on > > them. > > In theory, yes, but we don't always have that control. Storage engines > can manage their own locking, and we can't depend on them to follow > a particular locking protocol (they manage deadlocks in their own > way). We need to make sure any user-level thread scheduler we create > doesn't create special requirements such as this, and should work > like any other threading libraries. > > > I guess we have to set up a strategy to arrange user-level threads > onto > > kernel thread. I'm thinking of these done in the following ways: > > A. All kernel threads share one pair of queues of sessions(mixed up > with > > newly connected sessions and switched out sessions by calling > yield()). > > Sessions that have just called yield() must have been blocked for some > > reason, so should be pushed back into the queue, and may wait for long > > enough to be swapped in. > > B. Each kernel thread have its own pair of queues of sessions. The > main > > thread is responsible for assigning newly connected sessions to these > > queues so as to keep the number of sessions in the queues as even as > > possible. This may avoid some lock races on access to the queue > between > > kernel threads. > > Just as in the current implementation, sessions are separated into two > > groups, that is need_processing and wait_for_io, so queues are always > in > > pairs. Maybe sessions_wait_for_io would rather be sessions_blocked. We > can > > monitor FDs by using libevent when they are ready to read or write. > But > > how could we monitor on mutexes to tell when they are unlocked? > > You can't, really, unless you do some expensive tracking. You need > to just try to run threads when they may potentially be unlocked. For > example, a thread blocks because some other thread holds the lock. What > is the other thread waiting for? Another lock or I/O. Anytime a thread > complete the I/O wait or ends up running, the other threads that may > potentially be waiting for a lock the running thread held need to be > run to see if they can proceed. This gets complicated and busy for > the threads, but the goal is to try to eliminate thread contention > to minimize the cases. > > So, we've been going down the path of own userland thread context > switching here, but there is still the option of trying to make the > execution engine stateful for non-blocking I/O and non-blocking event > triggers (for wrapping locks). To be honest I'm not sure which is > easier, but the non-blocking execution engine will most likely be more > portable, easier to debug, and can be done incrementally. Just wanted > to point out we have at least two directions we could go in here.
Good timing of reminding. It rather seems more natural to make the execution engine fully stateful, since we already had a partially stateful engine with which we can tell state by monitoring the socket FDs. I guess we have to do a similar work of transferring to non-blocking socket I/Os. Besides, we also need a new state_changed call back entry so that session could notify the scheduler when its state has changed. It's not a so advanced task to add state to the execution process, but takes effort really. I've got a question here. As the scheduler detected a state change of some session, say, the currently running session is blocked on socket I/O, thus its state changed into BLOCKED, how could we let its host thread to stop severing it suddenly and choose another session to process? I mean, I guess we may need much more info to describe the state of session rather than a single flag like BLOCKED so that we can successfully restore the session when it gets ready to go. Besides how do we do stop severing at some point of the code path suddenly? It seems not so easy as content switch does. -- Cheers. Biping MENG Natural Language Processing(NLP) Lab Dept. of Computer Science and Technology Nanjing University
_______________________________________________ Mailing list: https://launchpad.net/~drizzle-discuss Post to : [email protected] Unsubscribe : https://launchpad.net/~drizzle-discuss More help : https://help.launchpad.net/ListHelp

