[CRIU] [PATCH 07/22] parasite: Use thread state hash for fast lookup over thread state areas

Andrey Vagin avagin at openvz.org
Wed May 8 09:28:34 EDT 2013


From: Cyrill Gorcunov <gorcunov at openvz.org>

We lookup for threads state via hash map, which makes fini
sequence to provide @real for parasite code.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 include/parasite.h |  1 +
 parasite-syscall.c | 17 ++++++++++++++++-
 pie/parasite.c     | 46 ++++++++++++++++++++++++++++------------------
 3 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/include/parasite.h b/include/parasite.h
index becee67..72a4b40 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -110,6 +110,7 @@ struct parasite_dump_creds {
 
 struct parasite_dump_thread {
 	unsigned int		*tid_addr;
+	pid_t			real;
 	pid_t			tid;
 	k_rtsigset_t		blocked;
 	u32			tls;
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 505c264..7ae89f3 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -362,6 +362,7 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, struct pid *tid,
 	int ret;
 
 	args = parasite_args(ctl, struct parasite_dump_thread);
+	args->real = tid->real;
 
 	ret = parasite_execute_trap_by_pid(PARASITE_CMD_DUMP_THREAD, ctl, tid->real);
 
@@ -563,12 +564,16 @@ int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
 
 int parasite_fini_threads_seized(struct parasite_ctl *ctl, struct pstree_item *item)
 {
+	struct parasite_init_args *args;
 	int ret = 0, i;
 
+	args = parasite_args(ctl, struct parasite_init_args);
+
 	for (i = 0; i < item->nr_threads; i++) {
 		if (item->pid.real == item->threads[i].real)
 			continue;
 
+		args->real = item->threads[i].real;
 		ret = parasite_execute_trap_by_pid(PARASITE_CMD_FINI_THREAD, ctl,
 					      item->threads[i].real);
 		/*
@@ -593,6 +598,16 @@ int parasite_fini_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
 	return ret;
 }
 
+static int parasite_fini_seized(struct parasite_ctl *ctl)
+{
+	struct parasite_init_args *args;
+
+	args = parasite_args(ctl, struct parasite_init_args);
+	args->real = ctl->pid.real;
+
+	return parasite_execute_trap(PARASITE_CMD_FINI, ctl);
+}
+
 int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item)
 {
 	int ret = 0;
@@ -602,7 +617,7 @@ int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item)
 	if (ctl->parasite_ip) {
 		ctl->signals_blocked = 0;
 		parasite_fini_threads_seized(ctl, item);
-		parasite_execute_trap(PARASITE_CMD_FINI, ctl);
+		parasite_fini_seized(ctl);
 	}
 
 	if (ctl->remote_map) {
diff --git a/pie/parasite.c b/pie/parasite.c
index 93260fe..82a4c3d 100644
--- a/pie/parasite.c
+++ b/pie/parasite.c
@@ -21,6 +21,7 @@ static struct tid_state_s {
 	pid_t		tid;
 	bool		use_sig_blocked;
 	k_rtsigset_t	sig_blocked;
+	void		*next;
 	unsigned char	stack[PARASITE_STACK_SIZE] __aligned(8);
 } *tid_state;
 
@@ -36,6 +37,8 @@ static unsigned int next_tid_state;
 #define SPLICE_F_GIFT	0x08
 #endif
 
+static struct tid_state_s *tid_table[512];
+
 static int mprotect_vmas(struct parasite_mprotect_args *args)
 {
 	struct parasite_vma_entry *vma;
@@ -170,18 +173,23 @@ static int drain_fds(struct parasite_drain_fd *args)
 	return ret;
 }
 
-static struct tid_state_s *find_thread_state(pid_t tid)
+static void hash_thread_state(struct tid_state_s *s)
+{
+	unsigned int pos = s->real % ARRAY_SIZE(tid_table);
+	struct tid_state_s *next = tid_table[pos];
+
+	tid_table[pos] = s;
+	s->next = next;
+}
+
+static struct tid_state_s *find_thread_state(pid_t real)
 {
-	unsigned int i;
-
-	/*
-	 * FIXME
-	 *
-	 * We need a hash here rather
-	 */
-	for (i = 0; i < next_tid_state; i++) {
-		if (tid_state[i].tid == tid)
-			return &tid_state[i];
+	unsigned int pos = real % ARRAY_SIZE(tid_table);
+	struct tid_state_s *s;
+
+	for (s = tid_table[pos]; s; s = s->next) {
+		if (s->real == real)
+			return s;
 	}
 
 	return NULL;
@@ -193,7 +201,7 @@ static int dump_thread(struct parasite_dump_thread *args)
 	struct tid_state_s *s;
 	int ret;
 
-	s = find_thread_state(tid);
+	s = find_thread_state(args->real);
 	if (!s)
 		return -ENOENT;
 
@@ -228,16 +236,18 @@ static int init_thread(struct parasite_init_args *args)
 	tid_state[next_tid_state].tid = sys_gettid();
 	tid_state[next_tid_state].real = args->real;
 
+	hash_thread_state(&tid_state[next_tid_state]);
+
 	next_tid_state++;
 
 	return ret;
 }
 
-static int fini_thread(void)
+static int fini_thread(struct parasite_init_args *args)
 {
 	struct tid_state_s *s;
 
-	s = find_thread_state(sys_gettid());
+	s = find_thread_state(args->real);
 	if (!s)
 		return -ENOENT;
 
@@ -415,11 +425,11 @@ static int parasite_cfg_log(struct parasite_log_args *args)
 	return ret;
 }
 
-static int fini(void)
+static int fini(struct parasite_init_args *args)
 {
 	int ret;
 
-	ret = fini_thread();
+	ret = fini_thread(args);
 
 	sys_munmap(tid_state, TID_STATE_SIZE(nr_tid_state));
 	log_set_fd(-1);
@@ -438,9 +448,9 @@ int __used parasite_service(unsigned int cmd, void *args)
 	case PARASITE_CMD_INIT_THREAD:
 		return init_thread(args);
 	case PARASITE_CMD_FINI:
-		return fini();
+		return fini(args);
 	case PARASITE_CMD_FINI_THREAD:
-		return fini_thread();
+		return fini_thread(args);
 	case PARASITE_CMD_CFG_LOG:
 		return parasite_cfg_log(args);
 	case PARASITE_CMD_DUMPPAGES:
-- 
1.8.2



More information about the CRIU mailing list