Mercurial > ecos
annotate packages/hal/common/current/src/thread-packets.c @ 2595:3ea2b2f69262
* src/thread-packets.c (threadmatch): Silence pointer signedness
warning.
(threadref_to_int): Ditto.
* src/generic-stub.c (__mem2hex): Ditto.
(__mem2hex_safe): Ditto.
(__hex2mem): Ditto.
(__hex2mem_safe): Ditto.
* src/hal_if.c (delay_us): Ditto.
* include/hal_stub.h (CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION):
Instead of using a local variable to avoid compiler reordering
when taking the address of a label, instead call an external function.
(NB making the variable volatile isn't sufficient).
* cdl/hal.cdl: Work around problem with current ARM EABI tools by
using /dev/null as linker script. Should be safe with other tools.
* src/hal_if.c (delay_us): use HAL_DELAY_US() rather than the
fancy implementation if the port cannot provide HAL_CLOCK_READ()
* cdl/common.cdl: Add CYGBLD_HAL_LINKER_GROUPED_LIBS to allow
CDL setting of libraries used for GROUP() directive in linker
script.
| author | jlarmour |
|---|---|
| date | Tue, 11 Nov 2008 04:28:57 +0000 |
| parents | d2c90368aeef |
| children | 74dbf4c3f2e1 |
| rev | line source |
|---|---|
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
1 //======================================================================== |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
2 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
3 // thread-packets.c |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
4 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
5 // Provides multi-threaded debug support |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
6 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
7 //======================================================================== |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
8 //####ECOSGPLCOPYRIGHTBEGIN#### |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
9 // ------------------------------------------- |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
10 // This file is part of eCos, the Embedded Configurable Operating System. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
|
2595
3ea2b2f69262
* src/thread-packets.c (threadmatch): Silence pointer signedness
jlarmour
parents:
210
diff
changeset
|
12 // Copyright (C) 2008 eCosCentric Limited. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
13 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
14 // eCos is free software; you can redistribute it and/or modify it under |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
15 // the terms of the GNU General Public License as published by the Free |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
16 // Software Foundation; either version 2 or (at your option) any later version. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
17 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
21 // for more details. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
22 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
23 // You should have received a copy of the GNU General Public License along |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
24 // with eCos; if not, write to the Free Software Foundation, Inc., |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
26 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
27 // As a special exception, if other files instantiate templates or use macros |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
28 // or inline functions from this file, or you compile this file and link it |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
29 // with other works to produce a work based on this file, this file does not |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
30 // by itself cause the resulting work to be covered by the GNU General Public |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
31 // License. However the source code for this file must still be made available |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
32 // in accordance with section (3) of the GNU General Public License. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
33 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
34 // This exception does not invalidate any other reasons why a work based on |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
35 // this file might be covered by the GNU General Public License. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
36 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
|
210
d2c90368aeef
Merge from eCos master repository on 2002-05-23-21:39:14-BST
jlarmour
parents:
208
diff
changeset
|
38 // at http://sources.redhat.com/ecos/ecos-license/ |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
39 // ------------------------------------------- |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
191
diff
changeset
|
40 //####ECOSGPLCOPYRIGHTEND#### |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
41 //======================================================================== |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
42 //#####DESCRIPTIONBEGIN#### |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
43 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
44 // Author(s): Red Hat, nickg |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
45 // Contributors: Red Hat, nickg |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
46 // Date: 1998-08-25 |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
47 // Purpose: |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
48 // Description: Provides multi-threaded debug support |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
49 // Usage: |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
50 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
51 //####DESCRIPTIONEND#### |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
52 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
53 //======================================================================== |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
46
diff
changeset
|
54 |
| 2 | 55 // Define __ECOS__; allows all eCos specific additions to be easily identified. |
| 56 #define __ECOS__ | |
| 0 | 57 |
| 58 | |
| 2 | 59 // #ifdef __ECOS__ |
| 0 | 60 #include <pkgconf/hal.h> |
| 61 | |
| 62 #if defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT) \ | |
| 63 && defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) | |
| 2 | 64 // #endif // __ECOS__ |
| 0 | 65 |
| 66 /* FIXME: Scan this module for correct sizes of fields in packets */ | |
| 2 | 67 |
| 68 #ifdef __ECOS__ | |
| 69 #include <cyg/hal/dbg-threads-api.h> | |
| 70 #else // __ECOS__ | |
| 71 #include "dbg-threads-api.h" | |
| 72 #endif // __ECOS__ | |
| 0 | 73 |
| 74 /* This file should ALWAYS define debug thread support */ | |
| 75 /* Dont include the object in the link if you dont need the support */ | |
| 76 /* This is NOT the internal unit debug flag, it is a feature control */ | |
| 77 #if defined(DEBUG_THREADS) | |
| 78 #undef DEBUG_THREADS | |
| 79 #endif | |
| 80 | |
| 2 | 81 #define DEBUG_THREADS 1 |
| 82 #define UNIT_TEST 0 | |
| 83 #define GDB_MOCKUP 0 | |
| 0 | 84 |
| 85 | |
| 86 #define STUB_BUF_MAX 300 /* for range checking of packet lengths */ | |
| 87 | |
| 88 #include "thread-pkts.h" | |
| 89 | |
| 2 | 90 #ifdef __ECOS__ |
| 0 | 91 // Use HAL rather than board.h in eCos |
| 92 #include <cyg/hal/hal_stub.h> | |
| 2 | 93 #else // __ECOS__ |
| 94 #include "board.h" | |
| 95 #endif // __ECOS__ | |
| 96 | |
| 97 /* | |
| 98 * Export the continue and "general" (context) thread IDs from GDB. | |
| 99 */ | |
| 100 int _gdb_cont_thread ; | |
| 101 int _gdb_general_thread ; | |
| 0 | 102 |
| 103 #if !defined(PKT_DEBUG) | |
| 104 #define PKT_DEBUG 0 | |
| 105 #endif | |
| 106 extern void output_string(char * message) ; | |
| 107 | |
| 108 #if PKT_DEBUG | |
| 109 void output_threadid(char * title,threadref * ref) ; | |
| 110 #warning "PKT_DEBUG macros engaged" | |
| 111 #define PKT_TRACE(title,packet) \ | |
| 112 { output_string(title) ; output_string(packet) ; output_string("\n") ;} | |
| 113 #else | |
| 114 #define PKT_TRACE(title,packet) {} | |
| 115 #endif | |
| 116 | |
| 117 | |
| 118 /* This is going to be irregular because the various implementations | |
| 119 have adopted different names for registers. | |
| 120 It would be nice to fix them to have a common convention | |
| 121 _stub_registers | |
| 122 stub_registers | |
| 123 alt_stub_registers | |
| 124 */ | |
| 125 | |
| 126 extern target_register_t * _registers ; | |
| 127 /* A pointer to the current set of registers */ | |
|
191
678094f34118
Merge from eCos master repository on 2001-10-19-06:43:02-BST
jlarmour
parents:
76
diff
changeset
|
128 extern target_register_t registers[]; /* The current saved registers */ |
|
678094f34118
Merge from eCos master repository on 2001-10-19-06:43:02-BST
jlarmour
parents:
76
diff
changeset
|
129 extern target_register_t alt_registers[] ; |
| 0 | 130 /* Thread or saved process state */ |
| 131 | |
| 132 | |
| 2 | 133 static void stub_copy_registers( |
| 134 target_register_t * dest, | |
| 135 target_register_t *src | |
| 136 ) | |
| 0 | 137 { |
| 138 target_register_t * limit ; | |
| 139 limit = dest + NUMREGS ; | |
| 140 | |
| 141 while (dest < limit) *dest++ = *src++ ; | |
| 142 } | |
| 143 | |
| 2 | 144 #ifdef __ECOS__ |
| 145 void __stub_copy_registers(target_register_t * dest, | |
| 146 target_register_t *src) | |
| 147 { | |
| 148 stub_copy_registers(dest, src); | |
| 149 } | |
| 150 #endif // __ECOS__ | |
| 151 | |
| 0 | 152 extern int stubhex(char ch) ; |
| 153 | |
| 154 /* ----- STUB_PACK_NAK ----------------------------------- */ | |
| 155 /* Pack an error response into the response packet */ | |
| 156 | |
| 157 char * stub_pack_nak(char * outbuf) | |
| 158 { | |
| 159 *outbuf++ = 'E' ; | |
| 160 *outbuf++ = '0' ; | |
| 161 *outbuf++ = '2' ; | |
| 162 return outbuf ; | |
| 163 } /* stub_pack_nak */ | |
| 164 | |
| 165 /* ----- STUB_PACK_ACK -------------------------- */ | |
| 166 /* Pack an OK achnowledgement */ | |
| 167 char * stub_pack_ack(char * outbuf) | |
| 168 { | |
| 169 *outbuf++ = 'O' ; | |
| 170 *outbuf++ = 'K' ; | |
| 171 return outbuf ; | |
| 172 } /* stub_pack_ack */ | |
| 173 | |
| 174 /* ------- STUB_UNPACK_INT ------------------------------- */ | |
| 175 /* Unpack a few bytes and return its integer value */ | |
| 176 /* This is where I wish functions could return several values | |
| 177 I would also advance the buffer pointer */ | |
| 178 | |
| 179 int stub_unpack_int(char * buff,int fieldlength) | |
| 180 { | |
| 181 int retval = 0 ; | |
| 182 int nibble ; | |
| 183 while (fieldlength) | |
| 184 { nibble = stubhex(*buff++) ; | |
| 185 retval |= nibble ; | |
| 186 fieldlength-- ; | |
| 187 if (fieldlength) retval = retval << 4 ; | |
| 188 } | |
| 189 return retval ; | |
| 190 } /* stub_unpack_int */ | |
| 191 | |
| 192 static char * unpack_byte(char * buf, int * value) | |
| 193 { | |
| 194 *value = stub_unpack_int(buf,2) ; | |
| 195 return buf + 2 ; | |
| 196 } | |
| 197 | |
| 198 static char * unpack_int(char * buf, int * value) | |
| 199 { | |
| 200 *value = stub_unpack_int(buf,8) ; | |
| 201 return buf + 8 ; | |
| 202 } | |
| 203 | |
|
38
e7ba79f6d3a8
Merge from eCos master repository on 1999-09-23-20:10:25-BST
jlarmour
parents:
2
diff
changeset
|
204 /* We are NOT depending upon extensive libraries */ |
| 0 | 205 static int ishex(char ch,int *val) |
| 206 { | |
| 207 if ((ch >= 'a') && (ch <= 'f')) | |
| 208 { *val =ch - 'a' + 10 ; return 1 ; } | |
| 209 if ((ch >= 'A') && (ch <= 'F')) | |
| 210 { *val = ch - 'A' + 10 ; return 1 ;} | |
| 211 if ((ch >= '0') && (ch <= '9')) | |
| 212 { *val = ch - '0' ; return 1 ; } | |
| 213 return 0 ; | |
| 214 } /* ishex */ | |
| 215 | |
| 216 static char * unpack_nibble(char * buf,int * val) | |
| 217 { | |
| 218 ishex(*buf++,val) ; | |
| 219 return buf ; | |
| 220 } | |
| 221 | |
| 222 | |
| 223 static const char hexchars[] = "0123456789abcdef"; | |
| 224 | |
| 225 static char * pack_hex_byte(char * pkt, unsigned char byte) | |
| 226 { | |
| 227 *pkt++ = hexchars[(byte >> 4) & 0xf] ; | |
| 228 *pkt++ = hexchars[(byte & 0xf)] ; | |
| 229 return pkt ; | |
| 230 } /* pack_hex_byte */ | |
| 231 | |
| 2 | 232 #ifndef __ECOS__ |
| 0 | 233 /* ---- STUB_PACK_VARLEN_HEX ------------------------------------- */ |
| 234 /* Format a variable length stream of hex bytes */ | |
| 235 | |
| 236 static char * pack_varlen_hex( | |
| 2 | 237 char * pkt, |
| 238 unsigned int value) | |
| 0 | 239 { |
| 240 int i ; | |
| 241 static unsigned char n[8] ; | |
| 242 if (value == 0) | |
| 243 { | |
| 244 *pkt++ = '0' ; | |
| 245 return pkt ; | |
| 246 } | |
| 247 else | |
| 248 { | |
| 249 i = 8 ; | |
| 250 while (i-- >= 0 ) /* unpack nibbles into a char array */ | |
| 2 | 251 { |
| 252 n[i] = value & 0x0f ; | |
| 253 value = value >> 4 ; | |
| 254 } | |
|
38
e7ba79f6d3a8
Merge from eCos master repository on 1999-09-23-20:10:25-BST
jlarmour
parents:
2
diff
changeset
|
255 i = 0 ; /* we had decrmented it to -1 */ |
| 0 | 256 while (n[i] == 0 ) i++ ; /* drop leading zeroes */ |
| 257 while (i++ < 8) *pkt++ = hexchars[n[i]] ; /* pack the number */ | |
| 258 } | |
| 259 return pkt ; | |
| 260 } /* pack_varlen_hex */ | |
| 2 | 261 #endif // !__ECOS__ |
| 262 | |
| 0 | 263 |
| 264 /* ------ STUB_UNPACK_VARLEN_HEX -------------------------------- */ | |
| 265 /* Parse a stream of hex bytes which may be of variable length */ | |
| 266 /* return the pointer to the next char */ | |
| 267 /* modify a varparm containing the result */ | |
| 268 /* A failure would look like a non-increment of the buffer pointer */ | |
| 269 | |
| 270 /* This unpacks hex strings that may have been packed using sprintf(%x) */ | |
| 271 /* We assume some non-hex delimits them */ | |
| 272 | |
| 273 char * unpack_varlen_hex( | |
| 2 | 274 char * buff, /* packet to parse */ |
| 275 int * result) | |
| 0 | 276 { |
| 277 int nibble ; | |
| 278 int retval ; | |
| 279 retval = 0 ; | |
| 280 | |
| 281 while (ishex(*buff,&nibble)) | |
| 282 { | |
| 283 buff++ ; | |
| 284 retval = retval << 4 ; | |
| 285 retval |= nibble & 0x0f ; | |
| 286 } | |
| 287 *result = retval ; | |
| 288 return buff ; | |
| 289 } /* stub_unpack_varlen_int */ | |
| 290 | |
| 291 | |
| 292 /* ------ UNPACK_THREADID ------------------------------- */ | |
| 293 /* A threadid is a 64 bit quantity */ | |
| 294 | |
| 295 #define BUFTHREADIDSIZ 16 /* encode 64 bits in 16 chars of hex */ | |
| 296 | |
| 297 static char * unpack_threadid(char * inbuf, threadref * id) | |
| 298 { | |
| 299 char * altref ; | |
| 300 char * limit = inbuf + BUFTHREADIDSIZ ; | |
| 301 int x,y ; | |
| 302 altref = (char *) id ; | |
| 303 | |
| 304 while (inbuf < limit) | |
| 305 { | |
| 306 x = stubhex(*inbuf++) ; | |
| 307 y = stubhex(*inbuf++) ; | |
| 308 *altref++ = (x << 4) | y ; | |
| 309 } | |
| 310 return inbuf ; | |
| 311 } /* unpack_threadid */ | |
| 312 | |
| 313 | |
| 314 | |
| 315 /* Pack an integer use leading zeroes */ | |
| 316 static char * pack_int(char * buf,int value) | |
| 317 { | |
| 318 buf = pack_hex_byte(buf,(value>> 24)& 0xff) ; | |
| 319 buf = pack_hex_byte(buf,(value >>16)& 0xff) ; | |
| 320 buf = pack_hex_byte(buf,(value >>8) & 0x0ff) ; | |
| 321 buf = pack_hex_byte(buf,(value & 0xff)) ; | |
| 322 return buf ; | |
| 323 } /* pack_int */ | |
| 324 | |
| 325 | |
| 326 /* -------- PACK_STRING ---------------------------------------------- */ | |
| 327 /* This stupid string better not contain any funny characters */ | |
| 328 /* Also, the GDB protocol will not cope with NULLs in the | |
| 329 string or at the end of it. | |
| 330 While is is posable to encapsulate the protocol in ays that | |
| 331 preclude filtering for # I am assuming this is a constraint. | |
| 332 */ | |
| 333 | |
| 334 static char * pack_raw_string(char * pkt,char * string) | |
| 335 { | |
| 336 char ch ; | |
| 337 while (0 != (ch = *string++)) *pkt++ = ch ; | |
| 338 return pkt ; | |
| 339 } | |
| 340 | |
| 341 static char * pack_string( | |
| 2 | 342 char * pkt, |
| 343 char * string) | |
| 0 | 344 { |
| 345 char ch ; | |
| 2 | 346 #ifdef __ECOS__ |
| 0 | 347 int len = 0; |
| 348 char *s = string; | |
| 349 while( *s++ ) len++; | |
| 2 | 350 #else // __ECOS__ |
| 351 int len ; | |
| 352 len = strlen(string) ; | |
| 353 #endif // __ECOS | |
| 0 | 354 if (len > 200 ) len = 200 ; /* Bigger than most GDB packets, junk??? */ |
| 355 pkt = pack_hex_byte(pkt,len) ; | |
| 356 while (len-- > 0) | |
| 357 { | |
| 358 ch = *string++ ; | |
| 359 if ((ch == '\0') || (ch == '#')) ch = '*' ; /* Protect encapsulation */ | |
| 360 *pkt++ = ch ; | |
| 361 } | |
| 362 return pkt ; | |
| 363 } /* pack_string */ | |
| 364 | |
| 365 | |
| 366 /* ----- STUB_PACK_THREADID --------------------------------------------- */ | |
| 367 /* Convert a binary 64 bit threadid and pack it into a xmit buffer */ | |
| 368 /* Return the advanced buffer pointer */ | |
| 369 | |
| 370 static char * pack_threadid(char * pkt, threadref * id) | |
| 371 { | |
| 372 char * limit ; | |
| 373 unsigned char * altid ; | |
| 374 altid = (unsigned char *) id ; | |
| 375 limit = pkt + BUFTHREADIDSIZ ; | |
| 376 while (pkt < limit) pkt = pack_hex_byte(pkt,*altid++) ; | |
| 377 return pkt ; | |
| 378 } /* stub_pack_threadid */ | |
| 379 | |
|
38
e7ba79f6d3a8
Merge from eCos master repository on 1999-09-23-20:10:25-BST
jlarmour
parents:
2
diff
changeset
|
380 /* UNFORTUNATELY, not all of the extended debugging system has yet been |
|
e7ba79f6d3a8
Merge from eCos master repository on 1999-09-23-20:10:25-BST
jlarmour
parents:
2
diff
changeset
|
381 converted to 64 but thread references and process identifiers. |
| 0 | 382 These routines do the conversion. |
| 383 An array of bytes is the correct treatment of an opaque identifier. | |
| 384 ints have endian issues. | |
| 385 */ | |
| 386 | |
| 387 static void int_to_threadref(threadref * id, int value) | |
| 388 { | |
| 389 unsigned char * scan ; | |
| 390 scan = (unsigned char *) id ; | |
| 391 { | |
| 392 int i = 4 ; | |
| 393 while (i--) *scan++ = 0 ; | |
| 394 } | |
| 395 *scan++ = (value >> 24) & 0xff ; | |
| 396 *scan++ = (value >> 16) & 0xff ; | |
| 397 *scan++ = (value >> 8) & 0xff ; | |
| 398 *scan++ = (value & 0xff) ; | |
| 399 } | |
| 400 | |
| 401 static int threadref_to_int(threadref * ref) | |
| 402 { | |
| 403 int value = 0 ; | |
| 404 unsigned char * scan ; | |
| 405 int i ; | |
| 406 | |
|
2595
3ea2b2f69262
* src/thread-packets.c (threadmatch): Silence pointer signedness
jlarmour
parents:
210
diff
changeset
|
407 scan = (unsigned char *) ref ; |
| 0 | 408 scan += 4 ; |
| 409 i = 4 ; | |
| 410 while (i-- > 0) value = (value << 8) | ((*scan++) & 0xff) ; | |
| 411 return value ; | |
| 412 } /* threadref_to_int */ | |
| 413 | |
| 414 void copy_threadref(threadref * dest, threadref * src) | |
| 415 { | |
| 416 int i ; | |
| 417 unsigned char * csrc, * cdest ; | |
| 418 csrc = (unsigned char *) src ; | |
| 419 cdest = (unsigned char *) dest ; | |
| 420 i = 8 ; | |
| 421 while (i--) *cdest++ = *csrc++ ; | |
| 422 } | |
| 423 | |
| 424 | |
| 425 int threadmatch( | |
| 2 | 426 threadref * dest , |
| 427 threadref * src | |
| 428 ) | |
| 0 | 429 { |
| 430 unsigned char * srcp, * destp ; | |
| 431 int i , result ; | |
|
2595
3ea2b2f69262
* src/thread-packets.c (threadmatch): Silence pointer signedness
jlarmour
parents:
210
diff
changeset
|
432 srcp = (unsigned char *) src ; |
|
3ea2b2f69262
* src/thread-packets.c (threadmatch): Silence pointer signedness
jlarmour
parents:
210
diff
changeset
|
433 destp = (unsigned char *) dest ; |
| 0 | 434 i = 8 ; |
| 435 result = 1 ; | |
| 436 while (i-- > 0 ) result &= (*srcp++ == *destp++) ? 1 : 0 ; | |
| 437 return result ; | |
| 2 | 438 } /* threadmatch */ |
| 0 | 439 |
| 440 | |
| 441 | |
| 442 static char * Tpkt_threadtag = "thread:" ; | |
| 443 | |
| 444 /* ----- STUB_PACK_TPKT_THREADID ------------------------------------ */ | |
| 445 /* retreive, tag and insert a thread identifier into a T packet. */ | |
| 446 /* Insert nothing if the thread identifier is not available */ | |
| 447 | |
| 448 char * stub_pack_Tpkt_threadid(char * pkt) | |
| 449 { | |
| 450 static threadref thread ; | |
| 451 int fmt = 0 ; /* old format */ | |
| 452 PKT_TRACE("Tpkt-id","---") ; | |
| 453 if (dbg_currthread(&thread)) | |
| 454 { | |
| 455 pkt = pack_raw_string(pkt,Tpkt_threadtag) ; | |
| 456 if (fmt) | |
| 2 | 457 pkt = pack_threadid(pkt,&thread) ; |
| 0 | 458 else |
| 2 | 459 /* Until GDB lengthens its thread ids, we have to MASH |
| 460 the threadid into somthing shorter. PLEASE FIX GDB */ | |
| 461 pkt = pack_int(pkt,threadref_to_int(&thread)) ; | |
| 0 | 462 *pkt++ = ';' ; /* terminate variable length int */ |
| 463 *pkt = '\0' ; /* Null terminate to allow string to be printed, no++ */ | |
| 464 } | |
| 465 PKT_TRACE("packedTpkt","--") ; | |
| 466 return pkt ; | |
| 467 } /* stub_pack_Tpkt_threadid */ | |
| 468 | |
| 2 | 469 long stub_get_currthread (void) |
| 470 { | |
| 471 threadref thread ; | |
| 472 | |
| 473 if (dbg_currthread(&thread)) | |
| 474 return threadref_to_int(&thread) ; | |
| 475 else | |
| 476 return 0 ; | |
| 477 } | |
| 0 | 478 |
| 479 void stub_pkt_currthread( | |
| 2 | 480 char * inbuf, |
| 481 char * outbuf, | |
| 482 int bufmax) | |
| 0 | 483 { |
| 484 threadref thread ; | |
| 485 char * base_out ; | |
| 486 base_out = outbuf ; | |
| 487 | |
| 488 if (dbg_currthread(&thread)) | |
| 489 { | |
| 2 | 490 *outbuf++ = 'Q' ; |
|
46
797268ecc331
Merge from eCos master repository on 1999-10-19-18:55:31-BST
jlarmour
parents:
38
diff
changeset
|
491 *outbuf++ = 'C' ; /* FIXME: Is this a reasonable code */ |
| 2 | 492 outbuf = pack_int(outbuf, threadref_to_int(&thread)) ; /* Short form */ |
| 0 | 493 } |
| 494 else outbuf = stub_pack_nak(outbuf) ; | |
| 495 *outbuf = '\0' ; /* terminate response packet */ | |
| 496 PKT_TRACE("stub_pkt_currthread(resp) ",base_out) ; | |
| 497 } /* stub_pkt_currthread */ | |
| 498 | |
| 499 /* ----- STUB_PKT_THREAD_ALIVE --------------------------------- */ | |
| 500 /* Answer the thread alive query */ | |
| 501 | |
| 2 | 502 static int thread_alive (int id) |
| 503 { | |
| 504 threadref thread ; | |
| 505 struct cygmon_thread_debug_info info ; | |
| 506 | |
| 507 int_to_threadref(&thread, id) ; | |
| 508 if (dbg_threadinfo(&thread, &info) && | |
| 509 info.context_exists) | |
| 510 return 1 ; | |
| 511 else | |
| 512 return 0 ; | |
| 513 } | |
| 514 | |
| 0 | 515 void stub_pkt_thread_alive(char * inbuf, |
| 2 | 516 char * outbuf, |
| 517 int bufmax) | |
| 0 | 518 { |
| 519 char * prebuf = inbuf ; | |
| 520 int result ; | |
| 521 | |
| 522 if (prebuf != (inbuf = unpack_varlen_hex(inbuf,&result))) | |
| 523 { | |
| 2 | 524 if (thread_alive(result)) |
| 525 { | |
| 526 outbuf = stub_pack_ack(outbuf) ; | |
| 527 *outbuf = '\0' ; | |
| 528 return ; | |
| 529 } | |
| 0 | 530 } |
| 531 outbuf = stub_pack_nak(outbuf) ; | |
| 532 *outbuf = '\0' ; /* terminate the response message */ | |
| 533 } /* stub_pkt_thread_alive */ | |
| 534 | |
| 535 | |
| 536 | |
| 537 /* ----- STUB_PKT_CHANGETHREAD ------------------------------- */ | |
| 538 /* Switch the display of registers to that of a saved context */ | |
| 539 | |
| 540 /* Changing the context makes NO sense, although the packets define the | |
| 541 capability. Therefore, the option to change the context back does | |
| 542 call the function to change registers. Also, there is no | |
| 543 forced context switch. | |
| 544 'p' - New format, long long threadid, no special cases | |
| 2 | 545 'c' - Old format, id for continue, 32 bit threadid max, possably less |
| 546 -1 means continue all threads | |
| 0 | 547 'g' - Old Format, id for general use (other than continue) |
| 548 | |
| 549 replies: | |
| 550 OK for success | |
| 2 | 551 ENN for error |
| 0 | 552 */ |
| 553 | |
| 554 void stub_pkt_changethread( | |
| 2 | 555 char * inbuf, |
| 556 char * outbuf, | |
| 557 int bufmax) | |
| 0 | 558 { |
| 559 threadref id ; | |
| 560 int idefined = -1 ; | |
| 561 char ch ; | |
| 562 PKT_TRACE("setthread-pkt ",inbuf) ; | |
| 563 | |
| 564 /* Parse the incoming packet for a thread identifier */ | |
| 565 switch (ch = *inbuf++ ) /* handle various packet formats */ | |
| 566 { | |
| 567 case 'p' : /* New format: mode:8,threadid:64 */ | |
| 568 inbuf = unpack_nibble(inbuf,&idefined) ; | |
| 569 inbuf = unpack_threadid(inbuf,&id) ; /* even if startflag */ | |
| 570 break ; | |
| 571 case 'c' : /* old format , specify thread for continue */ | |
| 2 | 572 if (inbuf[0] == '-' && inbuf[1] == '1') /* Hc-1 */ |
| 573 _gdb_cont_thread = 0 ; | |
| 574 else | |
| 575 inbuf = unpack_varlen_hex(inbuf, &_gdb_cont_thread) ; | |
| 576 | |
| 577 if (_gdb_cont_thread == 0 || /* revert to any old thread */ | |
| 578 thread_alive(_gdb_cont_thread)) /* specified thread is alive */ | |
| 579 outbuf = stub_pack_ack(outbuf) ; | |
| 580 else | |
| 581 outbuf = stub_pack_nak(outbuf) ; | |
| 582 break ; | |
| 0 | 583 case 'g' : /* old format, specify thread for general operations */ |
| 584 /* OLD format: parse a variable length hex string */ | |
| 585 /* OLD format consider special thread ids */ | |
| 586 { | |
| 2 | 587 inbuf = unpack_varlen_hex(inbuf, &_gdb_general_thread) ; |
| 588 int_to_threadref(&id, _gdb_general_thread) ; | |
| 589 switch (_gdb_general_thread) | |
| 590 { | |
| 591 case 0 : /* pick a thread, any thread */ | |
| 592 idefined = 2 ; /* select original interrupted context */ | |
| 593 break ; | |
| 594 case -1 : /* all threads */ | |
| 595 idefined = 2 ; | |
| 596 break ; | |
| 597 default : | |
| 598 idefined = 1 ; /* select the specified thread */ | |
| 599 break ; | |
| 600 } | |
| 0 | 601 } |
| 602 break ; | |
| 603 default: | |
| 604 outbuf = stub_pack_nak(outbuf) ; | |
| 605 break ; | |
| 606 } /* handle various packet formats */ | |
| 607 | |
| 608 switch (idefined) | |
| 609 { | |
| 610 case -1 : | |
| 611 /* Packet not supported, already NAKed, no further action */ | |
| 612 break ; | |
| 613 case 0 : | |
| 614 /* Switch back to interrupted context */ | |
| 615 _registers = ®isters[0] ; | |
| 616 break ; | |
| 617 case 1 : | |
| 618 /* copy the saved registers into the backup registers */ | |
| 2 | 619 stub_copy_registers(alt_registers,registers) ; |
| 0 | 620 /* The OS will now update the values it has in a saved process context*/ |
| 621 if (dbg_getthreadreg(&id,NUMREGS,&alt_registers[0])) | |
| 2 | 622 { |
| 623 /* switch the registers pointer */ | |
| 624 _registers = &alt_registers[0] ; | |
| 625 outbuf = stub_pack_ack(outbuf) ; | |
| 626 } | |
| 0 | 627 else |
| 2 | 628 outbuf = stub_pack_nak(outbuf) ; |
| 0 | 629 break ; |
| 2 | 630 case 2 : |
| 631 /* switch to interrupted context */ | |
| 632 outbuf = stub_pack_ack(outbuf) ; | |
| 633 break ; | |
| 0 | 634 default: |
| 635 outbuf = stub_pack_nak(outbuf) ; | |
| 636 break ; | |
| 637 } | |
| 638 *outbuf = '\0' ; /* Terminate response pkt */ | |
| 2 | 639 } /* stub_pkt_changethread */ |
| 0 | 640 |
| 641 | |
| 642 /* ---- STUB_PKT_GETTHREADLIST ------------------------------- */ | |
| 643 /* Get a portion of the threadlist or process list */ | |
| 644 /* This may be part of a multipacket transaction */ | |
| 645 /* It would be hard to tell in the response packet the difference | |
| 646 between the end of list and an error in threadid encoding. | |
| 647 */ | |
| 648 | |
| 649 void stub_pkt_getthreadlist(char * inbuf, | |
| 2 | 650 char * outbuf, |
| 651 int bufmax) | |
| 0 | 652 { |
| 653 char * count_ptr ; | |
| 654 char * done_ptr ; | |
| 655 char * limit ; | |
| 656 int start_flag , batchsize , result , count ; | |
| 657 static threadref lastthread, nextthread ; | |
| 658 | |
| 659 #if PKT_DEBUG | |
| 660 char * r_base = outbuf ; | |
| 661 #endif | |
| 662 PKT_TRACE("pkt_getthreadlist: ",inbuf) ; | |
| 663 | |
| 664 count = 0 ; | |
| 665 inbuf = unpack_nibble(inbuf,&start_flag) ; | |
| 666 inbuf = unpack_byte(inbuf,&batchsize) ; | |
| 667 inbuf = unpack_threadid(inbuf,&lastthread) ; /* even if startflag */ | |
| 668 | |
| 669 /* Start building response packet */ | |
| 670 limit = outbuf + (bufmax - BUFTHREADIDSIZ - 10) ; /* id output packing limit */ | |
| 671 *outbuf++ = 'Q' ; | |
| 672 *outbuf++ = 'M' ; | |
| 673 | |
| 674 /* Default values for count and done fields, save ptr to repatch */ | |
| 675 count_ptr = outbuf ; /* save to repatch count */ | |
| 676 outbuf = pack_hex_byte(outbuf,0) ; | |
| 677 done_ptr = outbuf ; /* Backpatched later */ | |
| 678 *outbuf++ = '0' ; /* Done = 0 by default */ | |
| 679 outbuf = pack_threadid(outbuf,&lastthread) ; | |
| 680 | |
| 681 /* Loop through the threadid packing */ | |
| 682 while ((outbuf < limit) && (count < batchsize)) | |
| 683 { | |
| 684 result = dbg_threadlist(start_flag,&lastthread,&nextthread) ; | |
|
76
435cced73e2f
eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
jlarmour
parents:
66
diff
changeset
|
685 start_flag = 0 ; /* redundant but effective */ |
| 0 | 686 if (!result) |
| 2 | 687 { *done_ptr = '1' ; /* pack the done flag */ |
| 688 break ; | |
| 689 } | |
| 0 | 690 #if 0 /* DEBUG */ |
| 691 if (threadmatch(&lastthread,&nextthread)) | |
| 2 | 692 { |
| 693 output_string("FAIL: Threadlist, not incrementing\n") ; | |
| 694 *done_ptr = '1' ; | |
| 695 break ; | |
| 696 } | |
| 0 | 697 #endif |
| 698 count++ ; | |
| 699 outbuf = pack_threadid(outbuf,&nextthread) ; | |
| 700 copy_threadref(&lastthread,&nextthread) ; | |
| 701 } | |
| 702 pack_hex_byte(count_ptr,count) ;/* backpatch, Pack the count field */ | |
| 703 *outbuf = '\0' ; | |
| 704 PKT_TRACE("pkt_getthreadlist(resp) ",r_base) ; | |
| 705 } /* pkt_getthreadlist */ | |
| 706 | |
| 707 | |
| 708 | |
| 709 | |
| 710 /* ----- STUB_PKT_GETTHREADINFO ---------------------------------------- */ | |
| 711 /* Get the detailed information about a specific thread or process */ | |
| 712 | |
| 713 /* | |
| 714 Encoding: | |
| 715 'Q':8,'P':8,mask:16 | |
| 716 | |
| 717 Mask Fields | |
| 2 | 718 threadid:1, # always request threadid |
| 719 context_exists:2, | |
| 720 display:4, | |
| 721 unique_name:8, | |
| 722 more_display:16 | |
| 0 | 723 */ |
| 724 | |
| 725 void stub_pkt_getthreadinfo( | |
| 2 | 726 char * inbuf, |
| 727 char * outbuf, | |
| 728 int bufmax) | |
| 0 | 729 { |
| 730 int mask ; | |
| 731 int result ; | |
| 732 threadref thread ; | |
| 733 struct cygmon_thread_debug_info info ; | |
| 734 | |
| 735 info.context_exists = 0 ; | |
| 736 info.thread_display = 0 ; | |
| 737 info.unique_thread_name = 0 ; | |
| 738 info.more_display = 0 ; | |
| 739 | |
| 740 /* Assume the packet identification chars have already been | |
| 741 discarded by the packet demultiples routines */ | |
| 742 PKT_TRACE("PKT getthreadinfo",inbuf) ; | |
| 743 | |
| 744 inbuf = unpack_int(inbuf,&mask) ; | |
| 745 inbuf = unpack_threadid(inbuf,&thread) ; | |
| 746 | |
| 747 result = dbg_threadinfo(&thread,&info) ; /* Make system call */ | |
| 748 | |
| 749 if (result) | |
| 750 { | |
| 751 *outbuf++ = 'q' ; | |
| 752 *outbuf++ = 'p' ; | |
| 753 outbuf = pack_int(outbuf,mask) ; | |
| 754 outbuf = pack_threadid(outbuf,&info.thread_id) ; /* echo threadid */ | |
| 755 if (mask & 2) /* context-exists */ | |
| 2 | 756 { |
| 757 outbuf = pack_int(outbuf,2) ; /* tag */ | |
| 758 outbuf = pack_hex_byte(outbuf,2) ; /* length */ | |
| 759 outbuf = pack_hex_byte(outbuf,info.context_exists) ; | |
| 760 } | |
| 0 | 761 if ((mask & 4) && info.thread_display)/* display */ |
| 2 | 762 { |
| 763 outbuf = pack_int(outbuf,4) ; /* tag */ | |
| 764 outbuf = pack_string(outbuf,info.thread_display) ; | |
| 765 } | |
| 0 | 766 if ((mask & 8) && info.unique_thread_name) /* unique_name */ |
| 2 | 767 { |
| 768 outbuf = pack_int(outbuf,8) ; | |
| 769 outbuf = pack_string(outbuf,info.unique_thread_name) ; | |
| 770 } | |
| 0 | 771 if ((mask & 16) && info.more_display) /* more display */ |
| 2 | 772 { |
| 773 outbuf = pack_int(outbuf,16) ; /* tag 16 */ | |
| 774 outbuf = pack_string(outbuf,info.more_display) ; | |
| 775 } | |
| 0 | 776 } |
| 777 else | |
| 778 { | |
| 779 PKT_TRACE("FAIL: dbg_threadinfo\n", "") ; | |
| 780 outbuf = stub_pack_nak(outbuf) ; | |
| 781 } | |
| 782 *outbuf = '\0' ; | |
| 783 } /* stub_pkt_getthreadinfo */ | |
| 784 | |
| 2 | 785 int stub_lock_scheduler(int lock, /* 0 to unlock, 1 to lock */ |
| 786 int mode, /* 0 for step, 1 for continue */ | |
| 787 long id) /* current thread */ | |
| 788 { | |
| 789 threadref thread; | |
| 0 | 790 |
| 2 | 791 int_to_threadref(&thread, id) ; |
| 792 return dbg_scheduler(&thread, lock, mode) ; | |
| 793 } | |
| 0 | 794 |
| 795 | |
| 796 #if GDB_MOCKUP | |
| 797 /* ------ MATCHED GDB SIDE PACKET ENCODING AND PARSING ----------------- */ | |
| 798 | |
| 799 char * pack_nibble(char * buf, int nibble) | |
| 800 { | |
| 801 *buf++ = hexchars[(nibble & 0x0f)] ; | |
| 802 return buf ; | |
| 803 } /* pack_nibble */ | |
| 804 | |
| 805 #if 0 | |
| 806 static char * unpack_short(char * buf,int * value) | |
| 807 { | |
| 808 *value = stub_unpack_int(buf,4) ; | |
| 809 return buf + 4 ; | |
| 810 } | |
| 811 | |
| 812 static char * pack_short( | |
| 2 | 813 char * buf, |
| 814 unsigned int value) | |
| 0 | 815 { |
| 816 buf = pack_hex_byte(buf,(value >> 8) & 0xff) ; | |
| 817 buf = pack_hex_byte(buf,(value & 0xff)) ; | |
| 818 return buf ; | |
| 819 } /* pack_short */ | |
| 820 #endif | |
| 821 | |
| 822 | |
| 823 /* Generally, I dont bury xmit and receive calls inside packet formatters | |
| 824 and parsers | |
| 825 */ | |
| 826 | |
| 827 | |
| 828 | |
| 829 | |
| 830 /* ----- PACK_SETTHREAD_REQUEST ------------------------------------- */ | |
| 2 | 831 /* Encoding: ??? decode gdb/remote.c |
| 832 'Q':8,'p':8,idefined:8,threadid:32 ; | |
| 833 */ | |
| 0 | 834 |
| 835 char * pack_setthread_request( | |
| 2 | 836 char * buf, |
| 837 char fmt, /* c,g or, p */ | |
| 838 int idformat , | |
| 839 threadref * threadid ) | |
| 0 | 840 { |
| 841 *buf++ = fmt ; | |
| 842 | |
| 843 if (fmt == 'p') | |
| 844 { /* pack the long form */ | |
| 845 buf = pack_nibble(buf,idformat) ; | |
| 846 buf = pack_threadid(buf,threadid) ; | |
| 847 } | |
| 848 else | |
| 849 { /* pack the shorter form - Serious truncation */ | |
| 850 /* There are reserved identifieds 0 , -1 */ | |
| 851 int quickref = threadref_to_int(threadid) ; | |
| 852 buf = pack_varlen_hex(buf,quickref) ; | |
| 853 } | |
| 854 *buf++ = '\0' ; /* end_of_packet */ | |
| 855 return buf ; | |
| 856 } /* pack_setthread_request */ | |
| 857 | |
| 858 | |
| 859 | |
| 860 /* -------- PACK_THREADLIST-REQUEST --------------------------------- */ | |
| 861 /* Format: i'Q':8,i"L":8,initflag:8,batchsize:16,lastthreadid:32 */ | |
| 862 | |
| 863 | |
| 864 char * pack_threadlist_request( | |
| 2 | 865 char * pkt, |
| 866 int startflag, | |
| 867 int threadcount, | |
| 868 threadref * nextthread | |
| 869 ) | |
| 0 | 870 { |
| 871 *pkt++ = 'q' ; | |
| 872 *pkt++ = 'L' ; | |
| 873 pkt = pack_nibble(pkt,startflag) ; /* initflag 1 bytes */ | |
| 874 pkt = pack_hex_byte(pkt,threadcount) ; /* threadcount 2 bytes */ | |
| 875 pkt = pack_threadid(pkt,nextthread) ; /* 64 bit thread identifier */ | |
| 876 *pkt = '\0' ; | |
| 877 return pkt ; | |
| 878 } /* remote_threadlist_request */ | |
| 879 | |
| 880 | |
| 881 | |
| 882 | |
| 883 /* ---------- PARSE_THREADLIST_RESPONSE ------------------------------------ */ | |
| 884 /* Encoding: 'q':8,'M':8,count:16,done:8,argthreadid:64,(threadid:64)* */ | |
| 885 | |
| 886 int parse_threadlist_response( | |
| 2 | 887 char * pkt, |
| 888 threadref * original_echo, | |
| 889 threadref * resultlist, | |
| 890 int * doneflag) | |
| 0 | 891 { |
| 892 char * limit ; | |
| 893 int count, resultcount , done ; | |
| 894 resultcount = 0 ; | |
| 895 | |
| 896 /* assume the 'q' and 'M chars have been stripped */ | |
| 897 PKT_TRACE("parse-threadlist-response ",pkt) ; | |
| 898 limit = pkt + (STUB_BUF_MAX - BUFTHREADIDSIZ) ; /* done parse past here */ | |
| 2 | 899 pkt = unpack_byte(pkt,&count) ; /* count field */ |
| 0 | 900 pkt = unpack_nibble(pkt,&done) ; |
| 901 /* The first threadid is the argument threadid */ | |
| 902 pkt = unpack_threadid(pkt,original_echo) ; /* should match query packet */ | |
| 903 while ((count-- > 0) && (pkt < limit)) | |
| 904 { | |
| 905 pkt = unpack_threadid(pkt,resultlist++) ; | |
| 906 resultcount++ ; | |
| 907 } | |
| 908 if (doneflag) *doneflag = done ; | |
| 909 return resultcount ; /* successvalue */ | |
| 910 } /* parse_threadlist_response */ | |
| 911 | |
| 912 struct gdb_ext_thread_info | |
| 913 { | |
| 914 threadref threadid ; | |
| 915 int active ; | |
| 916 char display[256] ; | |
| 917 char shortname[32] ; | |
| 918 char more_display[256] ; | |
| 919 } ; | |
| 920 | |
| 921 | |
| 922 /* ----- PACK_THREAD_INFO_REQUEST -------------------------------- */ | |
| 923 | |
| 924 /* | |
| 925 threadid:1, # always request threadid | |
| 926 context_exists:2, | |
| 927 display:4, | |
| 928 unique_name:8, | |
| 929 more_display:16 | |
| 930 */ | |
| 931 | |
| 932 /* Encoding: 'Q':8,'P':8,mask:32,threadid:64 */ | |
| 933 | |
| 934 char * pack_threadinfo_request(char * pkt, | |
| 2 | 935 int mode, |
| 936 threadref * id | |
| 937 ) | |
| 0 | 938 { |
| 939 *pkt++ = 'Q' ; | |
| 940 *pkt++ = 'P' ; | |
| 941 pkt = pack_int(pkt,mode) ; /* mode */ | |
| 942 pkt = pack_threadid(pkt,id) ; /* threadid */ | |
| 943 *pkt = '\0' ; /* terminate */ | |
| 944 return pkt ; | |
| 945 } /* pack_thread_info_request */ | |
| 946 | |
| 947 | |
| 948 | |
| 949 static char * unpack_string( | |
| 2 | 950 char * src, |
| 951 char * dest, | |
| 952 int length) | |
| 0 | 953 { |
| 954 while (length--) *dest++ = *src++ ; | |
| 955 *dest = '\0' ; | |
| 956 return src ; | |
| 957 } /* unpack_string */ | |
| 958 | |
| 959 | |
| 960 void output_threadid(char * title,threadref * ref) | |
| 961 { | |
| 962 char hexid[20] ; | |
| 963 pack_threadid(&hexid[0],ref) ; /* Convert threead id into hex */ | |
| 964 hexid[16] = 0 ; | |
| 2 | 965 output_string(title) ; |
| 966 output_string(&hexid[0]) ; | |
| 967 output_string("\n") ; | |
| 0 | 968 } |
| 969 | |
| 970 /* ------ REMOTE_UPK_THREAD_INFO_RESPONSE ------------------------------- */ | |
| 971 /* Unpack the response of a detailed thread info packet */ | |
| 972 /* Encoding: i'Q':8,i'R':8,argmask:16,threadid:64,(tag:8,length:16,data:x)* */ | |
| 973 | |
| 974 #define TAG_THREADID 1 | |
| 975 #define TAG_EXISTS 2 | |
| 976 #define TAG_DISPLAY 4 | |
| 977 #define TAG_THREADNAME 8 | |
| 978 #define TAG_MOREDISPLAY 16 | |
| 979 | |
| 980 | |
| 981 int remote_upk_thread_info_response( | |
| 2 | 982 char * pkt, |
| 983 threadref * expectedref , | |
| 984 struct gdb_ext_thread_info * info) | |
| 0 | 985 { |
| 986 int mask, length ; | |
| 987 unsigned int tag ; | |
| 988 threadref ref ; | |
| 989 char * limit = pkt + 500 ; /* plausable parsing limit */ | |
| 990 int retval = 1 ; | |
| 991 | |
| 992 PKT_TRACE("upk-threadinfo ",pkt) ; | |
| 993 | |
| 994 /* info->threadid = 0 ; FIXME: implement zero_threadref */ | |
| 995 info->active = 0 ; | |
| 996 info->display[0] = '\0' ; | |
| 997 info->shortname[0] = '\0' ; | |
| 998 info->more_display[0] = '\0' ; | |
| 999 | |
| 1000 /* Assume the characters indicating the packet type have been stripped */ | |
| 1001 pkt = unpack_int(pkt,&mask) ; /* arg mask */ | |
| 1002 pkt = unpack_threadid(pkt , &ref) ; | |
| 1003 | |
| 1004 if (! threadmatch(&ref,expectedref)) | |
| 1005 { /* This is an answer to a different request */ | |
| 1006 output_string("FAIL Thread mismatch\n") ; | |
| 1007 output_threadid("ref ",&ref) ; | |
| 1008 output_threadid("expected ",expectedref) ; | |
| 1009 return 0 ; | |
| 1010 } | |
| 1011 copy_threadref(&info->threadid,&ref) ; | |
| 1012 | |
| 1013 /* Loop on tagged fields , try to bail if somthing goes wrong */ | |
| 1014 if (mask==0) output_string("OOPS NO MASK \n") ; | |
| 1015 | |
| 1016 while ((pkt < limit) && mask && *pkt) /* packets are terminated with nulls */ | |
| 1017 { | |
| 1018 pkt = unpack_int(pkt,&tag) ; /* tag */ | |
| 1019 pkt = unpack_byte(pkt,&length) ; /* length */ | |
| 1020 if (! (tag & mask)) /* tags out of synch with mask */ | |
| 2 | 1021 { |
| 1022 output_string("FAIL: threadinfo tag mismatch\n") ; | |
| 1023 retval = 0 ; | |
| 1024 break ; | |
| 1025 } | |
| 0 | 1026 if (tag == TAG_THREADID) |
| 2 | 1027 { |
| 1028 output_string("unpack THREADID\n") ; | |
| 1029 if (length != 16) | |
| 1030 { | |
| 1031 output_string("FAIL: length of threadid is not 16\n") ; | |
| 1032 retval = 0 ; | |
| 1033 break ; | |
| 1034 } | |
| 1035 pkt = unpack_threadid(pkt,&ref) ; | |
| 1036 mask = mask & ~ TAG_THREADID ; | |
| 1037 continue ; | |
| 1038 } | |
| 0 | 1039 if (tag == TAG_EXISTS) |
| 2 | 1040 { |
| 1041 info->active = stub_unpack_int(pkt,length) ; | |
| 1042 pkt += length ; | |
| 1043 mask = mask & ~(TAG_EXISTS) ; | |
| 1044 if (length > 8) | |
| 1045 { | |
| 1046 output_string("FAIL: 'exists' length too long\n") ; | |
| 1047 retval = 0 ; | |
| 1048 break ; | |
| 1049 } | |
| 1050 continue ; | |
| 1051 } | |
| 0 | 1052 if (tag == TAG_THREADNAME) |
| 2 | 1053 { |
| 1054 pkt = unpack_string(pkt,&info->shortname[0],length) ; | |
| 1055 mask = mask & ~TAG_THREADNAME ; | |
| 1056 continue ; | |
| 1057 } | |
| 0 | 1058 if (tag == TAG_DISPLAY) |
| 2 | 1059 { |
| 1060 pkt = unpack_string(pkt,&info->display[0],length) ; | |
| 1061 mask = mask & ~TAG_DISPLAY ; | |
| 1062 continue ; | |
| 1063 } | |
| 0 | 1064 if (tag == TAG_MOREDISPLAY) |
| 2 | 1065 { |
| 1066 pkt = unpack_string(pkt,&info->more_display[0],length) ; | |
| 1067 mask = mask & ~TAG_MOREDISPLAY ; | |
| 1068 continue ; | |
| 1069 } | |
| 0 | 1070 output_string("FAIL: unknown info tag\n") ; |
| 1071 break ; /* Not a tag we know about */ | |
| 1072 } | |
| 1073 return retval ; | |
| 1074 } /* parse-thread_info_response */ | |
| 1075 | |
| 1076 | |
| 2 | 1077 /* ---- REMOTE_PACK_CURRTHREAD_REQUEST ---------------------------- */ |
| 0 | 1078 /* This is a request to emit the T packet */ |
| 1079 | |
| 1080 /* FORMAT: 'q':8,'C' */ | |
| 1081 | |
| 1082 char * remote_pack_currthread_request(char * pkt ) | |
| 1083 { | |
| 1084 *pkt++ = 'q' ; | |
| 1085 *pkt++ = 'C' ; | |
| 1086 *pkt = '\0' ; | |
| 1087 return pkt ; | |
| 2 | 1088 } /* remote_pack_currthread_request */ |
| 0 | 1089 |
| 1090 | |
| 1091 /* ------- REMOTE_UPK_CURTHREAD_RESPONSE ----------------------- */ | |
| 1092 /* Unpack the interesting part of a T packet */ | |
| 1093 | |
| 1094 | |
| 1095 int remote_upk_currthread_response( | |
| 2 | 1096 char * pkt, |
| 1097 int *thr ) /* Parse a T packet */ | |
| 0 | 1098 { |
| 1099 int retval = 0 ; | |
| 1100 PKT_TRACE("upk-currthreadresp ",pkt) ; | |
| 1101 | |
| 1102 #if 0 | |
| 1103 { | |
| 1104 static char threadtag[8] = "thread" ; | |
| 1105 int retval = 0 ; | |
| 1106 int i , found ; | |
| 1107 char ch ; | |
| 1108 int quickid ; | |
| 1109 | |
| 1110 /* Unpack as a t packet */ | |
| 1111 while (((ch = *pkt++) != ':') /* scan for : thread */ | |
| 2 | 1112 && (ch != '\0')) /* stop at end of packet */ |
| 0 | 1113 |
| 1114 { | |
| 1115 found = 0 ; | |
| 1116 i = 0 ; | |
| 1117 while ((ch = *pkt++) == threadtag[i++]) ; | |
| 1118 if (i == 8) /* string match "thread" */ | |
| 2 | 1119 { |
| 1120 pkt = unpack_varlen_hex(pkt,&quickid) ; | |
| 1121 retval = 1; | |
| 1122 break ; | |
| 1123 } | |
| 0 | 1124 retval = 0 ; |
| 1125 } | |
| 1126 } | |
| 1127 #else | |
| 2 | 1128 pkt = unpack_threadid(pkt, thr) ; |
| 0 | 1129 retval = 1 ; |
| 1130 #endif | |
| 1131 return retval ; | |
| 1132 } /* remote_upk_currthread_response */ | |
| 1133 | |
| 1134 | |
| 1135 /* -------- REMOTE_UPK-SIMPLE_ACK --------------------------------- */ | |
| 1136 /* Decode a response which is eother "OK" or "Enn" | |
| 1137 fillin error code, fillin pkfag-1== undef, 0==nak, 1 == ack ; | |
| 1138 return advanced packet pointer */ | |
| 1139 | |
| 1140 | |
| 1141 char * remote_upk_simple_ack( | |
| 2 | 1142 char * buf, |
| 1143 int * pkflag, | |
| 1144 int * errcode) | |
| 0 | 1145 { |
| 1146 int lclerr = 0 ; | |
| 1147 char ch = *buf++ ; | |
| 1148 int retval = -1 ; /* Undefined ACK , a protocol error */ | |
| 1149 if (ch == 'E') /* NAK */ | |
| 1150 { | |
| 1151 buf = unpack_byte(buf,&lclerr) ; | |
| 1152 retval = 0 ; /* transaction failed, explicitly */ | |
| 1153 } | |
| 1154 else | |
| 1155 if ((ch == 'O') && (*buf++ == 'K')) /* ACK */ | |
| 1156 retval = 1 ; /* transaction succeeded */ | |
| 1157 *pkflag = retval ; | |
| 1158 *errcode = lclerr ; | |
| 1159 return buf ; | |
| 1160 } /* remote-upk_simple_ack */ | |
| 1161 | |
| 1162 | |
| 1163 /* -------- PACK_THREADALIVE_REQUEST ------------------------------- */ | |
| 1164 | |
| 1165 char * pack_threadalive_request( | |
| 2 | 1166 char * buf, |
| 1167 threadref * threadid) | |
| 0 | 1168 { |
| 1169 *buf++ = 'T' ; | |
| 1170 buf = pack_threadid(buf,threadid) ; | |
| 1171 *buf = '\0' ; | |
| 1172 return buf ; | |
| 1173 } /* pack_threadalive_request */ | |
| 1174 | |
| 1175 #endif /* GDB_MOCKUP */ | |
| 1176 | |
| 1177 /* ---------------------------------------------------------------------- */ | |
| 1178 /* UNIT_TESTS SUBSECTION */ | |
| 1179 /* ---------------------------------------------------------------------- */ | |
| 1180 | |
| 1181 | |
| 1182 #if UNIT_TEST | |
| 1183 extern void output_string(char * message) ; | |
| 1184 static char test_req[400] ; | |
| 1185 static char t_response[400] ; | |
| 1186 | |
| 1187 | |
| 1188 | |
| 1189 /* ----- DISPLAY_THREAD_INFO ---------------------------------------------- */ | |
| 1190 /* Use local cygmon string output utiities */ | |
| 1191 | |
| 1192 void display_thread_info(struct gdb_ext_thread_info * info) | |
| 1193 { | |
| 1194 | |
| 1195 output_threadid("Threadid: ",&info->threadid) ; | |
| 1196 /* short name */ | |
| 1197 output_string("Name: ") ; output_string(info->shortname) ; output_string("\n"); | |
| 1198 /* format display state */ | |
| 1199 output_string("State: ") ; output_string(info->display) ; output_string("\n") ; | |
| 1200 /* additional data */ | |
| 1201 output_string("other: ");output_string(info->more_display); | |
| 1202 output_string("\n\n"); | |
| 1203 } /* display_thread_info */ | |
| 1204 | |
| 1205 | |
| 1206 /* --- CURRTHREAD-TEST -------------------------------------------- */ | |
| 1207 static int currthread_test(threadref * thread) | |
| 1208 { | |
| 1209 int result ; | |
| 2 | 1210 int threadid ; |
| 0 | 1211 output_string("TEST: currthread\n") ; |
| 1212 remote_pack_currthread_request(test_req) ; | |
| 1213 stub_pkt_currthread(test_req+2,t_response,STUB_BUF_MAX) ; | |
| 2 | 1214 result = remote_upk_currthread_response(t_response+2, &threadid) ; |
| 0 | 1215 if (result) |
| 1216 { | |
| 1217 output_string("PASS getcurthread\n") ; | |
| 1218 /* FIXME: print the thread */ | |
| 1219 } | |
| 1220 else | |
| 1221 output_string("FAIL getcurrthread\n") ; | |
| 1222 return result ; | |
| 1223 } /* currthread_test */ | |
| 1224 | |
| 1225 /* ------ SETTHREAD_TEST ------------------------------------------- */ | |
| 1226 /* use a known thread from previous test */ | |
| 1227 | |
| 1228 static int setthread_test(threadref * thread) | |
| 1229 { | |
| 1230 int result, errcode ; | |
| 1231 output_string("TEST: setthread\n") ; | |
| 1232 | |
| 1233 pack_setthread_request(test_req,'p',1,thread) ; | |
| 1234 stub_pkt_changethread(test_req,t_response,STUB_BUF_MAX) ; | |
| 1235 remote_upk_simple_ack(t_response,&result,&errcode) ; | |
| 1236 switch (result) | |
| 1237 { | |
| 1238 case 0 : | |
| 1239 output_string("FAIL setthread\n") ; | |
| 1240 break ; | |
| 1241 case 1 : | |
| 1242 output_string("PASS setthread\n") ; | |
| 1243 break ; | |
| 1244 default : | |
| 1245 output_string("FAIL setthread -unrecognized response\n") ; | |
| 1246 break ; | |
| 1247 } | |
| 1248 return result ; | |
| 1249 } /* setthread_test */ | |
| 1250 | |
| 1251 | |
| 1252 /* ------ THREADACTIVE_TEST ---------------------- */ | |
| 1253 /* use known thread */ | |
| 1254 /* pack threadactive packet */ | |
| 1255 /* process threadactive packet */ | |
| 1256 /* parse threadactive response */ | |
| 1257 /* check results */ | |
| 1258 | |
| 1259 | |
| 1260 int threadactive_test(threadref * thread) | |
| 1261 { | |
| 1262 int result ; | |
| 1263 int errcode ; | |
| 1264 output_string("TEST: threadactive\n") ; | |
| 1265 pack_threadalive_request(test_req,thread) ; | |
| 1266 stub_pkt_thread_alive(test_req+1,t_response,STUB_BUF_MAX); | |
| 1267 remote_upk_simple_ack(t_response,&result,&errcode) ; | |
| 1268 switch (result) | |
| 1269 { | |
| 1270 case 0 : | |
| 1271 output_string("FAIL threadalive\n") ; | |
| 1272 break ; | |
| 1273 case 1 : | |
| 1274 output_string("PASS threadalive\n") ; | |
| 1275 break ; | |
| 1276 default : | |
| 1277 output_string("FAIL threadalive -unrecognized response\n") ; | |
| 1278 break ; | |
| 1279 } | |
| 1280 return result ; | |
| 1281 } /* threadactive_test */ | |
| 1282 | |
| 1283 /* ------ REMOTE_GET_THREADINFO -------------------------------------- */ | |
| 1284 int remote_get_threadinfo( | |
| 1285 threadref * threadid, | |
| 1286 int fieldset , /* TAG mask */ | |
| 1287 struct gdb_ext_thread_info * info | |
| 1288 ) | |
| 1289 { | |
| 1290 int result ; | |
| 1291 pack_threadinfo_request(test_req,fieldset,threadid) ; | |
| 1292 stub_pkt_getthreadinfo(test_req+2,t_response,STUB_BUF_MAX) ; | |
| 1293 result = remote_upk_thread_info_response(t_response+2,threadid,info) ; | |
| 1294 return result ; | |
| 1295 } /* remote_get-thrreadinfo */ | |
| 1296 | |
| 1297 | |
| 1298 static struct gdb_ext_thread_info test_info ; | |
| 1299 | |
| 1300 static int get_and_display_threadinfo(threadref * thread) | |
| 1301 { | |
| 1302 int mode ; | |
| 1303 int result ; | |
| 1304 /* output_string("TEST: get and display threadinfo\n") ; */ | |
| 1305 | |
| 1306 mode = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME | |
| 1307 | TAG_MOREDISPLAY | TAG_DISPLAY ; | |
| 1308 result = remote_get_threadinfo(thread,mode,&test_info) ; | |
| 1309 if (result) display_thread_info(&test_info) ; | |
| 1310 #if 0 /* silent subtest */ | |
| 1311 if (result) | |
| 1312 output_string("PASS: get_and_display threadinfo\n") ; | |
| 1313 else | |
| 1314 output_string("FAIL: get_and_display threadinfo\n") ; | |
| 1315 #endif | |
| 1316 return result ; | |
| 1317 } /* get-and-display-threadinfo */ | |
| 1318 | |
| 1319 | |
| 1320 | |
| 1321 /* ----- THREADLIST_TEST ------------------------------------------ */ | |
| 1322 #define TESTLISTSIZE 16 | |
| 1323 #define TLRSIZ 2 | |
| 1324 static threadref test_threadlist[TESTLISTSIZE] ; | |
| 1325 | |
| 1326 static int threadlist_test(void) | |
| 1327 { | |
| 1328 int done, i , result_count ; | |
| 1329 int startflag = 1 ; | |
| 1330 int result = 1 ; | |
| 1331 int loopcount = 0 ; | |
| 1332 static threadref nextthread ; | |
| 1333 static threadref echo_nextthread ; | |
| 1334 | |
| 1335 output_string("TEST: threadlist\n") ; | |
| 1336 | |
| 1337 done = 0 ; | |
| 1338 while (! done) | |
| 1339 { | |
| 1340 if (loopcount++ > 10) | |
| 2 | 1341 { |
| 1342 result = 0 ; | |
| 1343 output_string("FAIL: Threadlist test -infinite loop-\n") ; | |
| 1344 break ; | |
| 1345 } | |
| 0 | 1346 pack_threadlist_request(test_req,startflag,TLRSIZ,&nextthread) ; |
| 1347 startflag = 0 ; /* clear for later iterations */ | |
| 1348 stub_pkt_getthreadlist(test_req+2,t_response,STUB_BUF_MAX); | |
| 1349 result_count = parse_threadlist_response(t_response+2, | |
| 2 | 1350 &echo_nextthread, |
| 1351 &test_threadlist[0],&done) ; | |
| 0 | 1352 if (! threadmatch(&echo_nextthread,&nextthread)) |
| 2 | 1353 { |
| 1354 output_string("FAIL: threadlist did not echo arg thread\n"); | |
| 1355 result = 0 ; | |
| 1356 break ; | |
| 1357 } | |
| 0 | 1358 if (result_count <= 0) |
| 2 | 1359 { |
| 1360 if (done != 0) | |
| 1361 { output_string("FAIL threadlist_test, failed to get list"); | |
| 1362 result = 0 ; | |
| 1363 } | |
| 1364 break ; | |
| 1365 } | |
| 0 | 1366 if (result_count > TLRSIZ) |
| 2 | 1367 { |
| 1368 output_string("FAIL: threadlist response longer than requested\n") ; | |
| 1369 result = 0 ; | |
| 1370 break ; | |
| 1371 } | |
| 0 | 1372 /* Setup to resume next batch of thread references , set nestthread */ |
| 1373 copy_threadref(&nextthread,&test_threadlist[result_count-1]) ; | |
| 1374 /* output_threadid("last-of-batch",&nextthread) ; */ | |
| 1375 i = 0 ; | |
| 1376 while (result_count--) | |
| 2 | 1377 { |
| 1378 if (0) /* two display alternatives */ | |
| 1379 output_threadid("truncatedisplay",&test_threadlist[i++]) ; | |
| 1380 else | |
| 1381 get_and_display_threadinfo(&test_threadlist[i++]) ; | |
| 1382 } | |
| 0 | 1383 |
| 1384 } | |
| 1385 if (!result) | |
| 1386 output_string("FAIL: threadlist test\n") ; | |
| 1387 else output_string("PASS: Threadlist test\n") ; | |
| 1388 return result ; | |
| 1389 } /* threadlist_test */ | |
| 1390 | |
| 1391 | |
| 1392 static threadref testthread ; | |
| 1393 | |
| 1394 | |
| 1395 int test_thread_support(void) | |
| 1396 { | |
| 1397 int result = 1 ; | |
| 1398 output_string("TESTING Thread support infrastructure\n") ; | |
| 1399 stub_pack_Tpkt_threadid(test_req) ; | |
| 1400 PKT_TRACE("packing the threadid -> ",test_req) ; | |
| 1401 result &= currthread_test(&testthread) ; | |
| 1402 result &= get_and_display_threadinfo(&testthread) ; | |
| 1403 result &= threadlist_test() ; | |
| 1404 result &= setthread_test(&testthread) ; | |
| 1405 if (result) | |
| 1406 output_string("PASS: UNITTEST Thread support\n") ; | |
| 1407 else | |
| 1408 output_string("FAIL: UNITTEST Thread support\n") ; | |
| 1409 return result ; | |
| 1410 } /* test-thread_support */ | |
| 1411 #endif /* UNIT_TEST */ | |
| 1412 | |
| 2 | 1413 // #ifdef __ECOS__ |
| 0 | 1414 #endif // ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT... |
| 2 | 1415 // #endif // __ECOS__ |
