mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-23 10:09:57 +00:00
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>
176 lines
3.3 KiB
C
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);
|
|
}
|