2015-11-16 10 views
3

Можно ли просыпать поток, ожидающий блокировки futex? Я попытался использовать , используя механизм сигнала, но он не работает. Есть ли какие-либо другие вопросы Я мог бы попробовать? Ниже я добавил в примере, который может быть похож на то, что я пытаюсь достичь .Причинение ожидающего потока для возврата в пользовательское пространство

  1. У меня есть поток А, приобретающее futex замок «Лока» следующим образом: - ret = syscall(__NR_futex, &lockA, FUTEX_LOCK_PI, 1, 0, NULL, 0);

  2. У меня есть поток B, который пытается приобрести futex замок «Лока», и блоки ядро, , как нить А, приобрела замок. ret = syscall(__NR_futex, &lockA, FUTEX_LOCK_PI, 1, 0, NULL, 0);

  3. Если нить B не приобрела lockA, другой поток, нить C будет знать об этом. Если нить B не получает блокировку, нить C хотела бы, чтобы нить B остановилась, ожидая блокировки, а сделайте что-нибудь еще.

Так в основном, на данный момент я пытаюсь выяснить, если я могу сделать «сигнал» нить C нить B так, что она не будет блокировать в ядре больше. Для того, чтобы сделать это, я установил обработчик сигнала в нити B следующим образом: -

struct sigaction act; 

act.sa_handler = handler; 
sigemptyset(&act.sa_mask); 
act.sa_flags = 0; 
act.sa_restorer = NULL; 
sigaction(SIGSYS, &act, NULL); 

... 
... 

void handler() { 
    fprintf(stderr, "Inside the handler, outta the kernel\n"); 
} 

Из потока C Я стараюсь, чтобы послать сигнал, как: - pthread_kill(tid_of_B, SIGSYS);

Что я делаю неправильно? Может ли поток B проснуться вообще? Если да, следует ли использовать другой подход?

[EDIT] На основании приведенного ниже комментария я попытался проверить возвращаемое значение pthread_kill и понял, что вызов не возвращается.

+0

В теории, посылая ему сигнал должен работать, я думаю. Если вы делаете ожидание потока занятым или 'sleep()', то отправляете сигнал, вызван ли ваш обработчик? – abligh

+0

@abligh Спасибо за ваш ответ. Вы имеете в виду, что нить B должна спать? –

+4

Я бы рекомендовал не вызывать async-unsafe-функции в обработчике сигналов даже для отладки. Если вы действительно хотите записать вызов вашего обработчика сигнала, 'write()' в 'STDERR_FILENO'. – EOF

ответ

0

Несколько вещей.

Вы используете FUTEX_LOCK_PI который не на странице руководства. Я только что посмотрел на исходный код ядра и документ, и кажется, что эта версия предназначена только для ядра самого. Он используется для реализации «мьютекса PI» в качестве замены ядра spinlock.

Если вы используете futex, вы должны реализовать семантику данных в указанном адресе.

Вот грубый, псевдокод, и, возможно,/вероятно, неправильно пример:

int mysem = 1; 

void 
lock(void) 
{ 

    // atomic_dec returns new value 
    while (1) { 
     if (atomic_dec(&mysem) == 0) 
      break; 
     futex(&mysem,FUTEX_WAIT,...) 
    } 
} 

void 
unlock(void) 
{ 

    // non_atomic_swap returns old value 
    if (non_atomic_swap(&mysem,1) != 0) 
     futex(&mysem,FUTEX_WAKE,...) 
}