2011-04-20 5 views
3

Я пытаюсь перенести реальное время Thread_Metric из ExpressLogic в POSIX, чтобы сравнить PREEMPT_RT исправления для Linux, Xenomai и RTAI для моей диссертации. Они обеспечивают исходный C-файл со следующими функциями, которые вы должны реализовать для того, чтобы в тесте на работу:Функция, которая принимает pthread как входной сигнал и приостанавливает его

void tm_initialize(void (*test_initialization_function)(void)); 
int tm_thread_create(int thread_id, int priority, void (*entry_function)(void)); 
int tm_thread_resume(int thread_id); 
int tm_thread_suspend(int thread_id); 
void tm_thread_relinquish(void); 
void tm_thread_sleep(int seconds); 
int tm_queue_create(int queue_id); 
int tm_queue_send(int queue_id, unsigned long *message_ptr); 
int tm_queue_receive(int queue_id, unsigned long *message_ptr); 
int tm_semaphore_create(int semaphore_id); 
int tm_semaphore_get(int semaphore_id); 
int tm_semaphore_put(int semaphore_id); 
int tm_memory_pool_create(int pool_id); 
int tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr); 
int tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr); 

Сейчас я пытаюсь реализовать tm_thread_suspend и tm_thread_resume функции, которые принимают в качестве PTHREAD вход. Я знаю, что вы можете приостановить pthread с помощью pthread_mutex_lock и pthread_cond_wait, но вы должны вызывать их из потока start_function. Я новичок в таких вещах, и я нахожусь в моей голове. Любая помощь приветствуется.

ответ

1

Некоторые реализации pthreads имеют эти функции. http://www.unix.com/man-page/all/3t/pthread_suspend/ Но ваше ядро ​​linux может не поддерживать их.

+0

'pthread_suspend' не является функцией pthread, это некоторое расширение поставщика. –

+0

'pthread_suspend() и pthread_continue() были разработаны X/Open.' – bmargulies

+0

И все же не включены в стандарт. Вероятно, вы можете прочесть обоснованные документы и найти достаточно вескую причину. –

3

pthread_suspend действительно похоже на путь, если он доступен. Это решение может быть более грязным, чем это стоит. Для каждого потока держите semaphore. Сделайте каждую нить прослушивать сигналы. В обработчике сигнала просто выполните down на соответствующем семафоре.

Итак, если вы хотите, чтобы нить, просто отправьте ему сигнал (возможно, с использованием сигнала в реальном времени было бы лучше), и он остановится в обработчике. Обработчик маскирует себя по умолчанию (то есть он не будет вызываться снова, если тот же сигнал будет получен до его завершения). Когда вы хотите перезапустить поток, просто сделайте up на семафоре.

Оговорка:

  • Используйте то, что @bmargulies предложил, это лучше (безопаснее, чище, более эффективным), если вы можете
  • Вы можете также использовать семафор вместо семафора
  • Dealing с сигналами - неприятная работа. Прежде чем приступить убедитесь, что вы (повторно) прочитать о
    • асинхронного сигнала безопасности
    • темы и сигналы
    • прерывание и перезапуск системных вызовов (SA_RESTART)
  • Я уверен sem_wait(3) ISN 't async-signal безопасен, но это безопасно, пока вы не используете SA_NODEFER (не то, что у вас были бы причины)

К сожалению, я не могу найти действительно бесплатную документацию по этой системе. Тем не менее, звездный или нет, есть много бесплатной документации.

Редактировать

Как было предложено @R .. есть async-signal-safe функции, которые блокируют, что вы могли бы использовать (вместо небезопасных sem_wait). Вот a list of functions you may safely use.

+0

У вас есть правильный подход, но в сигнальном обработчике нужны функции безопасности, такие как синхронизация сигналов. Мой ответ набросает некоторые идеи. –

+0

@R .. Это отличная идея. Я вижу, что 'SUSv3' задает' pselect (2) 'как безопасный для асинхронного сигнала, который бы разрешил проблемы с этим подходом. – cnicutar

1

Вы можете сделать это полностью переносимым (избегая все проблемы с асинхронным-сигналом небезопасных функциями) с использованием двух сигналов:

«нить приостановлению» обработчик сигнала будет использовать pselect атомарно разблокирование второго сигнала и спать на неопределенное время. Второй сигнал завершит pselect и заставит обработчик сигнала вернуться.

Также существует множество других решений, использующих интерфейсы с поддержкой асинхронного сигнала - в основном все, что касается дескрипторов файлов и блокировки на них, а не на примитивах синхронизации пользовательского пространства. Например, работа с сигнальным обработчиком read из трубы и запись одного байта в трубу для возобновления потока будут работать.

0

Как вы это делаете, используйте sigwait() и pthread_kill.

// глобальная переменная

int _fSigSet; 

Перед вызовом pthread_create мы устанавливаем маску сигнала. Каждый поток наследует маску. Вы можете установить маску в функции потока, я полагаю. Вот код, который мы используем:

sigemptyset(&_fSigSet); 
sigaddset(&_fSigSet, SIGUSR1); 
sigaddset(&_fSigSet, SIGSEGV); 
pthread_sigmask(SIG_BLOCK, &_fSigSet, NULL); 
... 
pthread_create(&Thread, NULL, ThreadProc, NULL); 
... 

Для ПРИОСТАНОВИТЬ:

int nSig; // signal you get if you care. 
sigwait(&_fSigSet, &nSig); // thread is suspended here waiting for signal. 

Для ПРОДОЛЖИТЬ:

pthread_kill(&Thread, SIGUSR1); 

Если вы не можете использовать SIGUSR1 по какой-то причине, следует помнить, что не все сигналы работают для нас. Мы можем делать что-то неправильно, но SIGCONT не работает.

У нас есть эталонные так называемые паузы, и этот метод был в 5 раз быстрее, чем использование мьютексов и переменных условий.

Вот некоторые code, который использует эту технику.

Смежные вопросы