OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [common/] [v2_0/] [src/] [thread-packets.c] - Blame information for rev 174

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.