1 /* Inferior process information for the remote server for GDB. 2 Copyright (C) 2002, 2005, 2011 3 Free Software Foundation, Inc. 4 5 Contributed by MontaVista Software. 6 7 This file is part of GDB. 8 It has been modified to integrate it in valgrind 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 Boston, MA 02110-1301, USA. */ 24 25 #include "server.h" 26 27 struct thread_info 28 { 29 struct inferior_list_entry entry; 30 void *target_data; 31 void *regcache_data; 32 unsigned int gdb_id; 33 }; 34 35 struct inferior_list all_threads; 36 37 struct thread_info *current_inferior; 38 39 #define get_thread(inf) ((struct thread_info *)(inf)) 40 41 void add_inferior_to_list (struct inferior_list *list, 42 struct inferior_list_entry *new_inferior) 43 { 44 new_inferior->next = NULL; 45 if (list->tail != NULL) 46 list->tail->next = new_inferior; 47 else 48 list->head = new_inferior; 49 list->tail = new_inferior; 50 } 51 52 void for_each_inferior (struct inferior_list *list, 53 void (*action) (struct inferior_list_entry *)) 54 { 55 struct inferior_list_entry *cur = list->head, *next; 56 57 while (cur != NULL) { 58 next = cur->next; 59 (*action) (cur); 60 cur = next; 61 } 62 } 63 64 void change_inferior_id (struct inferior_list *list, 65 unsigned long new_id) 66 { 67 if (list->head != list->tail) 68 error ("tried to change thread ID after multiple threads are created\n"); 69 70 list->head->id = new_id; 71 } 72 73 void remove_inferior (struct inferior_list *list, 74 struct inferior_list_entry *entry) 75 { 76 struct inferior_list_entry **cur; 77 78 if (list->head == entry) { 79 list->head = entry->next; 80 if (list->tail == entry) 81 list->tail = list->head; 82 return; 83 } 84 85 cur = &list->head; 86 while (*cur && (*cur)->next != entry) 87 cur = &(*cur)->next; 88 89 if (*cur == NULL) 90 return; 91 92 (*cur)->next = entry->next; 93 94 if (list->tail == entry) 95 list->tail = *cur; 96 } 97 98 void add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id) 99 { 100 struct thread_info *new_thread 101 = (struct thread_info *) malloc (sizeof (*new_thread)); 102 103 VG_(memset) (new_thread, 0, sizeof (*new_thread)); 104 105 new_thread->entry.id = thread_id; 106 107 add_inferior_to_list (&all_threads, & new_thread->entry); 108 109 if (current_inferior == NULL) 110 current_inferior = new_thread; 111 112 new_thread->target_data = target_data; 113 set_inferior_regcache_data (new_thread, new_register_cache ()); 114 new_thread->gdb_id = gdb_id; 115 } 116 117 unsigned int thread_id_to_gdb_id (unsigned long thread_id) 118 { 119 struct inferior_list_entry *inf = all_threads.head; 120 121 while (inf != NULL) { 122 struct thread_info *thread = get_thread (inf); 123 if (inf->id == thread_id) 124 return thread->gdb_id; 125 inf = inf->next; 126 } 127 128 return 0; 129 } 130 131 unsigned int thread_to_gdb_id (struct thread_info *thread) 132 { 133 return thread->gdb_id; 134 } 135 136 struct thread_info * gdb_id_to_thread (unsigned int gdb_id) 137 { 138 struct inferior_list_entry *inf = all_threads.head; 139 140 while (inf != NULL) { 141 struct thread_info *thread = get_thread (inf); 142 if (thread->gdb_id == gdb_id) 143 return thread; 144 inf = inf->next; 145 } 146 147 return NULL; 148 } 149 150 unsigned long gdb_id_to_thread_id (unsigned int gdb_id) 151 { 152 struct thread_info *thread = gdb_id_to_thread (gdb_id); 153 154 return thread ? thread->entry.id : 0; 155 } 156 157 static 158 void free_one_thread (struct inferior_list_entry *inf) 159 { 160 struct thread_info *thread = get_thread (inf); 161 free_register_cache (inferior_regcache_data (thread)); 162 free (thread); 163 } 164 165 void remove_thread (struct thread_info *thread) 166 { 167 remove_inferior (&all_threads, (struct inferior_list_entry *) thread); 168 free_one_thread (&thread->entry); 169 } 170 171 void clear_inferiors (void) 172 { 173 for_each_inferior (&all_threads, free_one_thread); 174 175 all_threads.head = all_threads.tail = NULL; 176 } 177 178 struct inferior_list_entry * find_inferior (struct inferior_list *list, 179 int (*func) 180 (struct inferior_list_entry *, 181 void *), 182 void *arg) 183 { 184 struct inferior_list_entry *inf = list->head; 185 186 while (inf != NULL) { 187 if ((*func) (inf, arg)) 188 return inf; 189 inf = inf->next; 190 } 191 192 return NULL; 193 } 194 195 struct inferior_list_entry * find_inferior_id (struct inferior_list *list, 196 unsigned long id) 197 { 198 struct inferior_list_entry *inf = list->head; 199 200 while (inf != NULL) { 201 if (inf->id == id) 202 return inf; 203 inf = inf->next; 204 } 205 206 return NULL; 207 } 208 209 void * inferior_target_data (struct thread_info *inferior) 210 { 211 return inferior->target_data; 212 } 213 214 void set_inferior_target_data (struct thread_info *inferior, void *data) 215 { 216 inferior->target_data = data; 217 } 218 219 void * inferior_regcache_data (struct thread_info *inferior) 220 { 221 return inferior->regcache_data; 222 } 223 224 void set_inferior_regcache_data (struct thread_info *inferior, void *data) 225 { 226 inferior->regcache_data = data; 227 } 228