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 27struct thread_info 28{ 29 struct inferior_list_entry entry; 30 void *target_data; 31 void *regcache_data; 32 unsigned int gdb_id; 33}; 34 35struct inferior_list all_threads; 36 37struct thread_info *current_inferior; 38 39#define get_thread(inf) ((struct thread_info *)(inf)) 40 41void 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 52void 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 64void 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 73void 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 98void 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 117unsigned 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 131unsigned int thread_to_gdb_id (struct thread_info *thread) 132{ 133 return thread->gdb_id; 134} 135 136struct 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 150unsigned 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 157static 158void 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 165void 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 171void clear_inferiors (void) 172{ 173 for_each_inferior (&all_threads, free_one_thread); 174 175 all_threads.head = all_threads.tail = NULL; 176} 177 178struct 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 195struct 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 209void * inferior_target_data (struct thread_info *inferior) 210{ 211 return inferior->target_data; 212} 213 214void set_inferior_target_data (struct thread_info *inferior, void *data) 215{ 216 inferior->target_data = data; 217} 218 219void * inferior_regcache_data (struct thread_info *inferior) 220{ 221 return inferior->regcache_data; 222} 223 224void set_inferior_regcache_data (struct thread_info *inferior, void *data) 225{ 226 inferior->regcache_data = data; 227} 228