void cpu_idle (void)
{
/* endless idle loop with no priority at all */
while (1) {
void (*idle)(void) = pm_idle;
if (!idle)
idle = default_idle;
if (!current->need_resched)
idle();
schedule();
check_pgt_cache();
}
}
this code existed in : "arch/i386/kernel/process.c" related to linux 2.4.18-14
this code is responsable of the ( cpu idle loop ).
the question is : can I change the while(1) loop with bust wait ?
The loop here properly schedules processes so the system continues to run properly. Switching to a pure busy wait would lock up the system when the cpu goes idle, meaning other processes would cease to be scheduled. You definitely do not want that.
Related
I am starting a bunch of joinable worker threads and main() waits for them to completed with pthread_join(). However, a user may hit CTRL+C on the terminal before the worker threads have completed their task. My understanding is that any thread could get the signal so all my worker threads call pthread_sigmask() on start up and block SIGINT (the CTRL+C signal). This causes the signal to be copied to other threads and main(). This way I know that at least main() will get definitely the signal.
I have defined a signal handler function on main() so that main() gets the signal and can kill all the worker threads and free their resources from one place. The problem is that this happens asynchronously. I call pthread_kill() from main() and then try to free() resources the worker thread is using and it's still running because the signal is dispatched asynchronously.
If I call pthread_kill(SIGTERM, ...) from main() to kill the thread main() gets killed too and do_thread_cleanup(i) is never called:
int main () {
signal (SIGINT, signal_handler);
for (i = 0; i < num_thd; i++) {
pthread_create(thread_init, ...);
}
for (i = 0; i < num_thd; i++) {
pthread_join(...);
}
return 0;
}
void signal_handler(int signal) {
for (i = 0; i < num_thd; i++) {
pthread_kill(pthread_t, SIGINT);
pthread_join(pthread_t, ...);
do_thread_cleanup(i); // Calls functions like free() and close()
}
}
void thread_init() {
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
do_stuff_in_a_loop();
}
How can I send SIGKILL to a thread without main() receiving that signal and killing itself? Alternatively, how can I wait for the thread to exit?
Having read the other SO posts the talk about using pthread_cleanup_push() and pthread_cleanup_pop() but that doesn't allow me to check form one central place that all threads are killed and their resources released.
The short answer is that you can’t; but you can do something close.
Free(), malloc() and thus all paths leading to them are not signal safe; so you can’t call them from a signal handler. It is rare that these functions would notice the signal (re)entry, so unpredictable behaviour is the likely result.
A good pattern is to have the main thread notice signals have occurred, and perform the processing for them within it. You can do this, safely, by having the main thread employ a pthread_cond_t,pthread_mutex_t pair to watch a counter, and have the signal handler use the same pair to update the counter and notify the change.
Thus the main thread can treat signals as simple inputs to transition between states, such as Normal/SIGINT -> Quitting, Quitting/SIGALRM -> HardStop.
Free() is probably a bit heavy-handed, as it can cause your program to make sporadic memory references, which may be exploitable as an attack surface.
I have N threads performing various task and these threads must be regularly synchronized with a thread barrier as illustrated below with 3 thread and 8 tasks. The || indicates the temporal barrier, all threads have to wait until the completion of 8 tasks before starting again.
Thread#1 |----task1--|---task6---|---wait-----||-taskB--| ...
Thread#2 |--task2--|---task5--|-------taskE---||----taskA--| ...
Thread#3 |-task3-|---task4--|-taskG--|--wait--||-taskC-|---taskD ...
I couldn’t find a workable solution, thought the little book of Semaphores http://greenteapress.com/semaphores/index.html was inspiring. I came up with a solution using std::atomic shown below which “seems” to be working using three std::atomic.
I am worried about my code breaking down on corner cases hence the quoted verb. So can you share advise on verification of such code? Do you have a simpler fool proof code available?
std::atomic<int> barrier1(0);
std::atomic<int> barrier2(0);
std::atomic<int> barrier3(0);
void my_thread()
{
while(1) {
// pop task from queue
...
// and execute task
switch(task.id()) {
case TaskID::Barrier:
barrier2.store(0);
barrier1++;
while (barrier1.load() != NUM_THREAD) {
std::this_thread::yield();
}
barrier3.store(0);
barrier2++;
while (barrier2.load() != NUM_THREAD) {
std::this_thread::yield();
}
barrier1.store(0);
barrier3++;
while (barrier3.load() != NUM_THREAD) {
std::this_thread::yield();
}
break;
case TaskID::Task1:
...
}
}
}
Boost offers a barrier implementation as an extension to the C++11 standard thread library. If using Boost is an option, you should look no further than that.
If you have to rely on standard library facilities, you can roll your own implementation based on std::mutex and std::condition_variable without too much of a hassle.
class Barrier {
int wait_count;
int const target_wait_count;
std::mutex mtx;
std::condition_variable cond_var;
Barrier(int threads_to_wait_for)
: wait_count(0), target_wait_count(threads_to_wait_for) {}
void wait() {
std::unique_lock<std::mutex> lk(mtx);
++wait_count;
if(wait_count != target_wait_count) {
// not all threads have arrived yet; go to sleep until they do
cond_var.wait(lk,
[this]() { return wait_count == target_wait_count; });
} else {
// we are the last thread to arrive; wake the others and go on
cond_var.notify_all();
}
// note that if you want to reuse the barrier, you will have to
// reset wait_count to 0 now before calling wait again
// if you do this, be aware that the reset must be synchronized with
// threads that are still stuck in the wait
}
};
This implementation has the advantage over your atomics-based solution that threads waiting in condition_variable::wait should get send to sleep by your operating system's scheduler, so you don't block CPU cores by having waiting threads spin on the barrier.
A few words on resetting the barrier: The simplest solution is to just have a separate reset() method and have the user ensure that reset and wait are never invoked concurrently. But in many use cases, this is not easy to achieve for the user.
For a self-resetting barrier, you have to consider races on the wait count: If the wait count is reset before the last thread returned from wait, some threads might get stuck in the barrier. A clever solution here is to not have the terminating condition depend on the wait count variable itself. Instead you introduce a second counter, that is only increased by the thread calling the notify. The other threads then observe that counter for changes to determine whether to exit the wait:
void wait() {
std::unique_lock<std::mutex> lk(mtx);
unsigned int const current_wait_cycle = m_inter_wait_count;
++wait_count;
if(wait_count != target_wait_count) {
// wait condition must not depend on wait_count
cond_var.wait(lk,
[this, current_wait_cycle]() {
return m_inter_wait_count != current_wait_cycle;
});
} else {
// increasing the second counter allows waiting threads to exit
++m_inter_wait_count;
cond_var.notify_all();
}
}
This solution is correct under the (very reasonable) assumption that all threads leave the wait before the inter_wait_count overflows.
With atomic variables, using three of them for a barrier is simply overkill that only serves to complicate the issue. You know the number of threads, so you can simply atomically increment a single counter every time a thread enters the barrier, and then spin until the counter becomes greater or equal to N. Something like this:
void barrier(int N) {
static std::atomic<unsigned int> gCounter = 0;
gCounter++;
while((int)(gCounter - N) < 0) std::this_thread::yield();
}
If you don't have more threads than CPU cores and a short expected waiting time, you might want to remove the call to std::this_thread::yield(). This call is likely to be really expensive (more than a microsecond, I'd wager, but I haven't measured it). Depending on the size of your tasks, this may be significant.
If you want to do repeated barriers, just increment the N as you go:
unsigned int lastBarrier = 0;
while(1) {
switch(task.id()) {
case TaskID::Barrier:
barrier(lastBarrier += processCount);
break;
}
}
I would like to point out that in the solution given by #ComicSansMS ,
wait_count should be reset to 0 before executing cond_var.notify_all();
This is because when the barrier is called a second time the if condition will always fail, if wait_count is not reset to 0.
In a linux kernel driver, I would like to repeat indefinitely the following sequence:
at time T, a hardware IRQ is enabled
between time T and T + "around" 15ms, the IRQ callback can be reached if the IRQ is triggered. I say around because I'm not using an RT kernel and if it's 14 or 16ms, it's fine. In the IRQ callback, I need to write down get cpu_clock(0) and call wake_up_interruptible. The timeout needs to be killed. The whole process needs to be started again within 5ms.
if by T + "around" 15ms, the IRQ has not been triggered, I need to execute some other code. The IRQ should be disabled then. The whole process needs to be started again within 5ms.
Therefore, by T + "around" 20ms, in worst case, the whole process needs to be started again.
Note that if the IRQ is physically triggered at 18ms, too bad, "I missed the train". I will catch another hardware trigger at the next sequence.
While testing, I was doing something along the following pseudo-code:
INIT_DELAYED_WORK(&priv->work, driver_work);
INIT_DELAYED_WORK(&priv->timeout, driver_timeout);
request_irq(priv->irq, driver_interrupt, IRQF_TRIGGER_RISING, "my_irq", priv);
then:
queue_delayed_work(priv->workq, &priv->work, 0ms);
static void driver_work(struct work_struct *work) {
queue_delayed_work(priv->workq, &priv->timeout, 15ms);
priv->interruptCalled = 0;
enable_irq(priv->irq);
}
Then:
static irqreturn_t driver_interrupt(int irq, void *_priv) {
disable_irq_nosync(priv->irq);
priv->interruptCalled = 1;
cancel_delayed_work(&priv->timeout);
priv->stamp = cpu_clock(0);
wake_up_interruptible(&driver_wait);
queue_delayed_work(priv->workq, &priv->work, 5ms);
return IRQ_HANDLED;
}
And:
static void driver_timeout(struct work_struct *work) {
if (priv->interruptCalled == 0) {
disable_irq_nosync(priv->irq);
//Do other small cleanup
queue_delayed_work(priv->workq, &priv->work, 5ms);
}
}
I'm trying to write a robust but simple driver. Is this a proper implementation? How can I improve this implementation?
Answering my own question: the problem is that queue_delayed_work is based on jiffies. Or 5ms is not possible as HZ=100 (1 jiffy = 10ms). HR timer brought a good solution.
Is it possible to pause a different task than the one on behalf of which the kernel is currently executing? To stop the current task, one can just set it to inactive and call schedule, but what about a different one?
What I have currently:
void disable_thread(struct task_struct *tsk) {
if (tsk->state == TASK_RUNNING) {
/*
* A running task - mark it stopped and wait for it to be descheduled
*/
tsk->state = TASK_INTERRUPTIBLE;
wait_task_inactive(tsk, TASK_INTERRUPTIBLE);
} else if (tsk->state == TASK_INTERRUPTIBLE || tsk->state == TASK_UNINTERRUPTIBLE) {
/*
* // TODO: what to do with tasks already waiting for something else?
*/
} else {
/*
* This task's state seems to indicate that it's dead, no need to disable it anymore.
*/
}
}
Stopping a running thread seems to work this way, but what can we do if the thread is already waiting for something else (e.g. waiting to acquire a lock), to prevent it from restarting even if it would get the lock?
I'm implementing a security feature, and can give more context if needed.
Thanks in advance.
I used one of the minimise to tray VC++ examples to create a program that would pop up a message at intervals to remind me to rest my eyes.
The program goes like this:
startTime = time(0);
g_hInstance=hInstance;
HWND hWnd=CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DialogProc);
if(hWnd)
{
MSG msg;
_beginthread(&checkEyeRestTime, 0, 0);
while(GetMessage(&msg,hWnd,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
and the checkEyeRestTime function:
void checkEyeRestTime(void* ptr)
{
while( true )
{
//logic to check time and display message
}//while
_endthread();
}
But this program takes up 50% CPU on a two core processor. How can I reduce the load on the processor?
Or insert Sleep(0) in the thread. This allows other threads to get some time.
If this does not help, you can increase sleep time.
Use a timer event instead of the polling loop.