Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can c/c++ do preemeptive multitasking in a single thread? [closed]

Preemptive multitasking in C/C++: can a running thread be interrupted by some timer and switch between tasks?

Many VMs and other language runtimes using green-threading and such are implemented in these terms; can C/C++ apps do the same?

If so, how?

This is going to be platform dependent, so please discuss this in terms of the support particular platforms have for this; e.g. if there's some magic you can do in a SIGALRM handler on Linux to swap some kind of internal stack (perhaps using longjmp?), that'd be great!


I ask because I am curious.

I have been working for several years making async IO loops. When writing async IO loops I have to be very careful not to put expensive to compute computation into the loop as it will DOS the loop.

I therefore have an interest in the various ways an async IO loop can be made to recover or even fully support some kind of green threading or such approach. For example, sampling the active task and the number of loop iterations in a SIGALRM, and then if a task is detected to be blocking, move the whole of everything else to a new thread, or some cunning variation on this with the desired result.

There was some complaints about node.js in this regard recently, and elsewhere I've seen tantalizing comments about other runtimes such as Go and Haskell. But lets not go too far away from the basic question of whether you can do preemptive multitasking in a single thread in C/C++

like image 537
Will Avatar asked Oct 30 '11 08:10

Will


2 Answers

Windows has fibers that are user-scheduled units of execution sharing the same thread. http://msdn.microsoft.com/en-us/library/windows/desktop/ms682661%28v=vs.85%29.aspx

UPD: More information about user-scheduled context switching can be found in LuaJIT sources, it supports coroutines for different platforms, so looking at the sources can be useful even if you are not using lua at all. Here is the summary: http://coco.luajit.org/portability.html,

like image 122
Denis K Avatar answered Sep 23 '22 12:09

Denis K


As far as i understand you are mixing things that are usually not mixed:

  • Asynchrounous Singals
    A signal is usually delivered to the program (thus in your description one thread) on the same stack that is currently running and runs the registered signal handler... in BSD unix there is an option to let the handler run on a separate so-called "signal stack".

  • Threads and Stacks
    The ability to run a thread on its own stack requires the ability to allocate stack space and save and restore state information (that includes all registers...) - otherwise clean "context switch" between threads/processes etc. is impossible. Usually this is implemented in the kernel and very often using some form of assembler since that is a very low-level and very time-sensitive operation.

  • Scheduler
    AFAIK every system capable of running threads has some sort of scheduler... which is basically a piece of code running with the highest privileges. Often it has subscribed to some HW signal (clock or whatever) and makes sure that no other code ever registers directly (only indirectly) to that same signal. The scheduler has thus the ability to preemt anything on that system. Main conern is usually to give the threads enough CPU cycles on the available cores to do their job. Implementation usually includes some sort of queues (often more than one), priority handling and several other stuff. Kernel-side threads usually have a higher priority than anything else.

  • Modern CPUs
    On modern CPUs the implementation is rather complicated since involves dealing with several cores and even some "special threads" (i.e. hyperthreads)... since modern CPUs usually have several levels of Cache etc. it is very important to deal with these appropriately to achieve high performance.

All the above means that your thread can and most probably will be preempted by OS on a regular basis.

In C you can register signal handlers which in turn preempt your thread on the same stack... BEWARE that singal handlers are problematic if reentered... you can either put the processing into the signal handler or fill some structure (for example a queue) and have that queue content consumed by your thread...

Regarding setjmp/longjmp you need to be aware that they are prone to several problems when used with C++.

For Linux there is/was a "full preemption patch" available which allows you to tell the scheduler to run your thread(s) with even higher priority than kernel thread (disk I/O...) get!

For some references see

  • http://www.kernel.org/doc/Documentation/scheduler/sched-rt-group.txt
  • http://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt
  • http://www.kernel.org/doc/Documentation/scheduler/
  • http://www.kernel.org/doc/Documentation/rt-mutex.txt
  • http://www.kernel.org/doc/Documentation/rt-mutex-design.txt
  • http://www.kernel.org/doc/Documentation/IRQ.txt
  • http://www.kernel.org/doc/Documentation/IRQ-affinity.txt
  • http://www.kernel.org/doc/Documentation/preempt-locking.txt
  • http://tldp.org/LDP/LG/issue89/vinayak2.html
  • http://lxr.linux.no/#linux+v3.1/kernel/sched.c#L3566
  • Can my thread help the OS decide when to context switch it out?
  • https://www.osadl.org/Realtime-Preempt-Kernel.kernel-rt.0.html
  • http://www.rtlinuxfree.com/
  • C++: Safe to use longjmp and setjmp?
  • Use of setjmp and longjmp in C when linking to C++ libraries
  • http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html

For seeing an acutal implementation of a scheduler etc. checkout the linux serouce code at https://kernel.org .

Since your question isn't very specific I am not sure whether this is a real answer but I suspect it has enough information to get you started.

REMARK:

I am not sure why you might want to implement something already present in the OS... if it for a higher performance on some async I/O then there are several options with maximum performance usually available on the kernel-level (i.e. write kernel-mode code)... perhaps you can clarify so that a more specific answer is possible.

like image 45
Yahia Avatar answered Sep 23 '22 12:09

Yahia