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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [common/] [current/] [src/] [thread-packets.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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