Здравствуйте! У меня проблема с работой siglongjmp (многопоточность) и настройкой sigaction для обработки обработчика SIGVTALRM.
Я настроил с sigsetjmp 2 новых потока: 1. env [0] с P C on fun c f 2. env [1] с P C on fun c g
Я настроил обработчик для сигнала SIGVTALRM, чтобы переключаться между двумя потоками.
Я установил itimer_virtual для вызова забавного c, называемого "switchThreads", который переключается между потоками.
Я протестировал 2 случая:
Настройка таймер и вызов бесконечного l oop, он вызывает сигнал только один раз, а затем после siglongjmp прекращает вызывать обработчик.
Установка таймера и вызов после него значения f, а не Вызываю хотя бы один раз к обработчику.
Вот мой код:
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#define SECOND 1000000
#define STACK_SIZE 4096
char stack1[STACK_SIZE];
char stack2[STACK_SIZE];
sigjmp_buf env[2];
#ifdef __x86_64__
/* code for 64 bit Intel arch */
typedef unsigned long address_t;
#define JB_SP 6
#define JB_PC 7
/* A translation is required when using an address of a variable.
Use this as a black box in your code. */
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%fs:0x30,%0\n"
"rol $0x11,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
#else
/* code for 32 bit Intel arch */
typedef unsigned int address_t;
#define JB_SP 4
#define JB_PC 5
/* A translation is required when using an address of a variable.
Use this as a black box in your code. */
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%gs:0x18,%0\n"
"rol $0x9,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
#endif
static struct sigaction sa;
static struct itimerval timer;
static int currentThread = 0;
static void switchThreads(int sig)
{
int ret_val = sigsetjmp(env[currentThread], 1);
printf("SWITCH: ret_val=%d\n", ret_val);
if (ret_val == 1)
{
return;
}
currentThread = 1 - currentThread;
if (setitimer(ITIMER_VIRTUAL, &timer, NULL))
{
printf("setitimer error.");
}
siglongjmp(env[currentThread], 1);
}
void f(void)
{
int i = 0;
while (1)
{
++i;
printf("in f (%d)\n", i);
usleep(SECOND);
}
}
void g(void)
{
int i = 0;
while (1)
{
++i;
printf("in g (%d)\n", i);
usleep(SECOND);
}
}
void setup(void)
{
address_t sp, pc;
sp = (address_t) stack1 + STACK_SIZE - sizeof(address_t);
pc = (address_t) f;
sigsetjmp(env[0], 1);
(env[0]->__jmpbuf)[JB_SP] = translate_address(sp);
(env[0]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&env[0]->__saved_mask);
sp = (address_t) stack2 + STACK_SIZE - sizeof(address_t);
pc = (address_t) g;
sigsetjmp(env[1], 1);
(env[1]->__jmpbuf)[JB_SP] = translate_address(sp);
(env[1]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&env[1]->__saved_mask);
}
int main(void)
{
printf("Starting...");
// Install timer_handler as the signal handler for SIGVTALRM.
sa.sa_handler = &switchThreads;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGVTALRM, &sa, NULL) < 0)
{
printf("sigaction error.");
}
// Configure the timer to expire after 1 sec... */
timer.it_value.tv_sec = 3;
timer.it_value.tv_usec = 0;
// configure the timer to expire every 1 sec after that.
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 0;
// Start a virtual timer. It counts down whenever this process is executing.
if (setitimer(ITIMER_VIRTUAL, &timer, NULL))
{
printf("setitimer error.");
}
setup();
// for(;;){}
f();
}
Я также выполнил 2 вызова:
Первое (встречается только один раз):
rt_sigaction(SIGVTALRM, {sa_handler=0x563ff48db82d, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f22c0f72f20}, NULL, 8) = 0
setitimer(ITIMER_VIRTUAL, {it_interval={tv_sec=1, tv_usec=0}, it_value={tv_sec=3, tv_usec=0}}, NULL) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
--- SIGVTALRM {si_signo=SIGVTALRM, si_code=SI_KERNEL} ---
rt_sigprocmask(SIG_BLOCK, NULL, [VTALRM], 8) = 0
write(1, "Starting...SWITCH: ret_val=0\n", 29Starting...SWITCH: ret_val=0
) = 29
setitimer(ITIMER_VIRTUAL, {it_interval={tv_sec=1, tv_usec=0}, it_value={tv_sec=3, tv_usec=0}}, NULL) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
write(1, "in g (1)\n", 9in g (1)
) = 9
nanosleep({tv_sec=1, tv_nsec=0}, NULL) = 0
write(1, "in g (2)\n", 9in g (2)
) = 9
nanosleep({tv_sec=1, tv_nsec=0}, NULL) = 0
write(1, "in g (3)\n", 9in g (3)
) = 9
Второе (не встречается ни разу):
rt_sigaction(SIGVTALRM, {sa_handler=0x55dc7274e82d, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fe6e3768f20}, NULL, 8) = 0
setitimer(ITIMER_VIRTUAL, {it_interval={tv_sec=1, tv_usec=0}, it_value={tv_sec=3, tv_usec=0}}, NULL) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
write(1, "Starting...in f (1)\n", 20Starting...in f (1)
) = 20
nanosleep({tv_sec=1, tv_nsec=0}, NULL) = 0
write(1, "in f (2)\n", 9in f (2)
) = 9
nanosleep({tv_sec=1, tv_nsec=0}, NULL) = 0
write(1, "in f (3)\n", 9in f (3)
) = 9
nanosleep({tv_sec=1, tv_nsec=0}, NULL) = 0
write(1, "in f (4)\n", 9in f (4)
) = 9
nanosleep({tv_sec=1, tv_nsec=0}, NULL) = 0
write(1, "in f (5)\n", 9in f (5)
) = 9
Заранее спасибо! !