aboutsummaryrefslogtreecommitdiff
path: root/src/core/thread.c
Commit message (Collapse)AuthorAge
* fixes #352 aio lock is burning hotGarrett D'Amore2018-05-14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | fixes #326 consider nni_taskq_exec_synch() fixes #410 kqueue implementation could be smarter fixes #411 epoll_implementation could be smarter fixes #426 synchronous completion can lead to panic fixes #421 pipe close race condition/duplicate destroy This is a major refactoring of two significant parts of the code base, which are closely interrelated. First the aio and taskq framework have undergone a number of simplifications, and improvements. We have ditched a few parts of the internal API (for example tasks no longer support cancellation) that weren't terribly useful but added a lot of complexity, and we've made aio_schedule something that now checks for cancellation or other "premature" completions. The aio framework now uses the tasks more tightly, so that aio wait can devolve into just nni_task_wait(). We did have to add a "task_prep()" step to prevent race conditions. Second, the entire POSIX poller framework has been simplified, and made more robust, and more scalable. There were some fairly inherent race conditions around the shutdown/close code, where we *thought* we were synchronizing against the other thread, but weren't doing so adequately. With a cleaner design, we've been able to tighten up the implementation to remove these race conditions, while substantially reducing the chance for lock contention, thereby improving scalability. The illumos poller also got a performance boost by polling for multiple events. In highly "busy" systems, we expect to see vast reductions in lock contention, and therefore greater scalability, in addition to overall improved reliability. One area where we currently can do better is that there is still only a single poller thread run. Scaling this out is a task that has to be done differently for each poller, and carefuly to ensure that close conditions are safe on all pollers, and that no chance for deadlock/livelock waiting for pfd finalizers can occur.
* Provide versions of mutex, condvar, and aio init that never fail.Garrett D'Amore2017-08-16
| | | | | | | | | | | | | | | | | | | | | | | If the underlying platform fails (FreeBSD is the only one I'm aware of that does this!), we use a global lock or condition variable instead. This means that our lock initializers never ever fail. Probably we could eliminate most of this for Linux and Darwin, since on those platforms, mutex and condvar initialization reasonably never fails. Initial benchmarks show little difference either way -- so we can revisit (optimize) later. This removes a lot of otherwise untested code in error cases and so forth, improving coverage and resilience in the face of allocation failures. Platforms other than POSIX should follow a similar pattern if they need this. (VxWorks, I'm thinking of you.) Most sane platforms won't have an issue here, since normally these initializations do not need to allocate memory. (Reportedly, even FreeBSD has plans to "fix" this in libthr2.) While here, some bugs were fixed in initialization & teardown. The fallback code is properly tested with dedicated test cases.
* Thundering herd kills performance.Garrett D'Amore2017-08-10
| | | | | | | | | | | | | | A little benchmarking showed that we were encountering far too many wakeups, leading to severe performance degradation; we had a bunch of threads all sleeping on the same condition variable (taskqs) and this woke them all up, resulting in heavy mutex contention. Since we only need one of the threads to wake, and we don't care which one, let's just wake only one. This reduced RTT latency from about 240 us down to about 30 s. (1/8 of the former cost.) There's still a bunch of tuning to do; performance remains worse than we would like.
* Eliminate the separate wrapping structure for platform mtx and cv.Garrett D'Amore2017-07-11
|
* Give up on uncrustify; switch to clang-format.Garrett D'Amore2017-07-10
|
* Fix bug that prevents threads from starting if waited on too soon.Garrett D'Amore2017-01-26
| | | | | | | This is partly caused by a race, but also an incorrect boolean short-circuit that I had not reasoned about properly. Mostly changing the boolean order fixes the condition, so that we prefer to start than to stop, if both are set.
* Thread fini shouldl be idempotent.Garrett D'Amore2017-01-19
|
* Start of event framework.Garrett D'Amore2017-01-16
| | | | | | | | | | This compiles correctly, but doesn't actually deliver events yet. As part of this, I've made most of the initializables in nng safe to tear-down if uninitialized (or set to zero e.g. via calloc). This makes it loads easier to write the teardown on error code, since I can deinit everything, without worrying about which things have been initialized and which have not.
* Many fixes for Windows. It compiles, and some tests work.Garrett D'Amore2017-01-13
| | | | | | Windows is getting there. Needs a couple of more more hours to enable everything, especially IPC, and most of the work at this point is probably some combination of debug and tweaking things like error handling.
* Simplify locking for protocols.Garrett D'Amore2017-01-07
| | | | | | | | | In an attempt to simplify the protocol implementation, and hopefully track down a close related race, we've made it so that most protocols need not worry about locks, and can access the socket lock if they do need a lock. They also let the socket manage their workers, for the most part. (The req protocol is special, since it needs a top level work distributor, *and* a resender.)
* Bunch of copyright fixes.Garrett D'Amore2017-01-06
|
* Add nng_shutdown() for sockets to help avoid close race.Garrett D'Amore2017-01-05
| | | | Also we added a two phase shutdown for threads.
* Pipe simplifications for thread management.Garrett D'Amore2017-01-01
| | | | | | | This may also address a race in closing down pipes. Now pipes are always registered with the socket. They also always have both a sender and receiver thread. If the protocol doesn't need one or the other, the stock thread just exits early.
* New thread infrastructure -- not used anywhere yet, but tested.Garrett D'Amore2017-01-01