criu/test/testee-threads.c
Cyrill Gorcunov 1e7bbd35de restore: Add threads restoration
Now threads restortion (and TLS as well) works.
Threads test reports the following

    2775 (main): Counter value:    3 tls_data =    1
    2775 (main): ( 0) fsgs_base 7f9597aa46f0
    2775 (main): ( 0) fsgs_base        0
    2775 (thr3): Counter value:    4 tls_data =    4
    2775 (thr3): ( 0) fsgs_base 42c57940
    2775 (thr3): ( 0) fsgs_base        0
    2775 (thr2): Counter value:    3 tls_data =    2
    2775 (thr2): ( 0) fsgs_base 42456940
    2775 (thr2): ( 0) fsgs_base        0
    2775 (thr1): Counter value:    4 tls_data =    3
    2775 (thr1): ( 0) fsgs_base 40c62940
    2775 (thr1): ( 0) fsgs_base        0
    2775 (main): Counter value:    4 tls_data =    1
    2775 (main): ( 0) fsgs_base 7f9597aa46f0
    2775 (main): ( 0) fsgs_base        0
    2775 (thr1): Counter value:    5 tls_data =    3
    2775 (thr1): ( 0) fsgs_base 40c62940
    2775 (thr1): ( 0) fsgs_base        0

as expected.

This commits merges all preliminary commits into
the final one (sigreturn branch was always experimental
and forced update).

Still some problems remain:

1) While creating threads with clone() the
   flags are to be revisited. We use some predefined
   set here but it's not really correct.

2) No setup of pids in PCB thread zone.

3) No restore of FPU.

But at least on some basic tasks restore works well.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
2011-11-12 19:26:40 +04:00

176 lines
3.3 KiB
C

/*
* A simple testee program with threads
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#define __NR_arch_prctl 158
#define ARCH_SET_GS 0x1001
#define ARCH_SET_FS 0x1002
#define ARCH_GET_FS 0x1003
#define ARCH_GET_GS 0x1004
static long syscall2(int nr, unsigned long arg0, unsigned long arg1)
{
long ret;
asm volatile(
"movl %1, %%eax \t\n"
"movq %2, %%rdi \t\n"
"movq %3, %%rsi \t\n"
"syscall \t\n"
"movq %%rax, %0 \t\n"
: "=r"(ret)
: "g" ((int)nr), "g" (arg0), "g" (arg1)
: "rax", "rdi", "rsi", "memory");
return ret;
}
static long sys_arch_prctl(int code, void *addr)
{
return syscall2(__NR_arch_prctl, code, (unsigned long)addr);
}
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static int counter;
static int thread_counter = 1;
static __thread int tls_data;
static void pr_fsgs_base(char *name)
{
unsigned long fsgs_base = -1ul;
int ret;
ret = sys_arch_prctl(ARCH_GET_FS, &fsgs_base);
printf("%8d (%4s): (%2d) fsgs_base %8lx\n",
getpid(), name, ret, fsgs_base);
ret = sys_arch_prctl(ARCH_GET_GS, &fsgs_base);
printf("%8d (%4s): (%2d) fsgs_base %8lx\n",
getpid(), name, ret, fsgs_base);
}
static void *ff1(void *arg)
{
void *map_unreadable = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
(void)map_unreadable;
tls_data = thread_counter++;
pr_fsgs_base("thr3");
while (1) {
pthread_mutex_lock(&mtx);
counter++;
printf("%8d (thr3): Counter value: %4d tls_data = %4d\n",
getpid(), counter, tls_data);
pthread_mutex_unlock(&mtx);
sleep(5);
}
return NULL;
}
static void *f1(void *arg)
{
const char name[] = "f1-file";
pthread_t th;
int fd;
void *map_unreadable = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
(void)map_unreadable;
unlink(name);
fd = open(name, O_CREAT, 0644);
if (fd >= 0)
write(fd, name, sizeof(name));
if (pthread_create(&th, NULL, &ff1, NULL))
perror("Cant create thread");
tls_data = thread_counter++;
pr_fsgs_base("thr1");
while (1) {
pthread_mutex_lock(&mtx);
counter++;
printf("%8d (thr1): Counter value: %4d tls_data = %4d\n",
getpid(), counter, tls_data);
pthread_mutex_unlock(&mtx);
sleep(2);
}
return NULL;
}
static void *f2(void *arg)
{
void *map_unreadable = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
(void)map_unreadable;
tls_data = thread_counter++;
pr_fsgs_base("thr2");
while (1) {
pthread_mutex_lock(&mtx);
counter--;
printf("%8d (thr2): Counter value: %4d tls_data = %4d\n",
getpid(), counter, tls_data);
pthread_mutex_unlock(&mtx);
sleep(3);
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t th1, th2;
int rc1, rc2;
printf("%s pid %d\n", argv[0], getpid());
tls_data = thread_counter++;
pr_fsgs_base("main");
printf("%8d (main): Counter value: %4d tls_data = %4d\n",
getpid(), counter, tls_data);
rc1 = pthread_create(&th1, NULL, &f1, NULL);
rc2 = pthread_create(&th2, NULL, &f2, NULL);
if (rc1 | rc2)
exit(1);
while (1) {
printf("%8d (main): Counter value: %4d tls_data = %4d\n",
getpid(), counter, tls_data);
sleep(2);
}
pthread_join(th1, NULL);
pthread_join(th2, NULL);
exit(0);
}