What should C program do in idle time when running on Linux?

2.3k views Asked by At

I've written many C programs for microcontrollers but never one that runs on an OS like linux. How does linux decide how much processing time to give my application? Is there something I need to do when I have idle time to tell the OS to go do something else and come back to me later so that other processes can get time to run as well? Or does the OS just do that automatically?

Edit: Adding More Detail My c program has a task scheduler. Some tasks run every 100ms, some run every 50 ms and so on. In my main program loop i call ProcessTasks which checks if any tasks are ready to run, if none are ready it calls an idle function. The idle function does nothing but it's there so that I could toggle a GPIO pin and monitor idle time with an O'scope... or something if I so desired. So maybe I should call sched_yield() in this idle function???

3

There are 3 answers

3
cnicutar On BEST ANSWER

How does linux decide how much processing time to give my application

Each scheduler makes up its own mind. Some reward you for not using up your share, some roll dices trying to predict what you'll do etc. In my opinion you can just consider it magic. After we enter the loop, the scheduler magically decides our time is up etc.

Is there something I need to do when I have idle time to tell the OS to go do something else

You might call sched_yield. I've never called it, nor do I know of any reasons why one would want to. The manual does say it could improve performance though.

Or does the OS just do that automatically

It most certainly does. That's why they call it "preemptive" multitasking.

2
Kerrek SB On

It depends why and how you have "idle time". Any call to a blocking I/O function, waiting on a mutex or sleeping will automatically deschedule your thread and let the OS get on with something else. Only something like a busy loop would be a problem, but that shouldn't appear in your design in any case.

Your program should really only have one central "infinite loop". If there's any chance that the loop body "runs out of work", then it would be best if you could make the loop perform one of the above system functions which would make all the niceness appear automatically. For example, if your central loop is an epoll_wait and all your I/O, timers and signals are handled by epoll, call the function with a timeout of -1 to make it sleep if there's nothing to do. (By contrast, calling it with a timeout of 0 would make it busy-loop – bad!).

5
chacham15 On

The other answers IMO are going into too much detail. The simple thing to do is:

while (1){
    if (iHaveWorkToDo()){
        doWork();
    } else {
        sleep(amountOfTimeToWaitBeforeNextCheck);
    }
}

Note: this is the simple solution which is useful in a single-threaded application or like your case where you dont have anything to do for a specified amount of time; just to get something decent working. The other thing about this is that sleep will call whatever yield function the os prefers, so in that sense it is better than an os specific yield call.

If you want to go for high performance, you should be waiting on events.

If you have your own events it will be something like follows:

Lock *l;
ConditionVariable *cv;

while (1){
    l->acquire();
    if (iHaveWorkToDo()){
        doWork();
    } else {
        cv->wait(lock);
    }
    l->release();
}

In a networking type situation it will be more like:

while (1){
    int result = select(fd_max+1, &currentSocketSet, NULL, NULL, NULL);
    process_result();
}