aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/debug
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2010-08-05 10:22:19 -0400
committerJason Wessel <jason.wessel@windriver.com>2010-08-05 10:22:19 -0400
commit84a0bd5b2830722cf80ff6ad33ef98101a947e14 (patch)
tree942f596d5a6b48bde181ed2ab063d697a0f2e73d /kernel/debug
parenta9fa20a7af1f152d2d89c44c274a310ac654e3ad (diff)
gdbstub: Optimize kgdb's "thread:" response for the gdb serial protocol
The gdb debugger understands how to parse short versions of the thread reference string as long as the bytes are paired in sets of two characters. The kgdb implementation was always sending 8 leading zeros which could be omitted, and further optimized in the case of non-negative thread numbers. The negative numbers are used to reference a specific cpu in the case of kgdb. An example of the previous i386 stop packet looks like: T05thread:00000000000003bb; New stop packet response: T05thread:03bb; The previous ThreadInfo response looks like: m00000000fffffffe,0000000000000001,0000000000000002,0000000000000003,0000000000000004,0000000000000005,0000000000000006,0000000000000007,000000000000000c,0000000000000088,000000000000008a,000000000000008b,000000000000008c,000000000000008d,000000000000008e,00000000000000d4,00000000000000d5,00000000000000dd New ThreadInfo response: mfffffffe,01,02,03,04,05,06,07,0c,88,8a,8b,8c,8d,8e,d4,d5,dd A few bytes saved means better response time when using kgdb over a serial line. Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'kernel/debug')
-rw-r--r--kernel/debug/gdbstub.c37
1 files changed, 19 insertions, 18 deletions
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c
index 3517fd71963..e117cfd7588 100644
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -367,28 +367,31 @@ static void error_packet(char *pkt, int error)
367 * remapped to negative TIDs. 367 * remapped to negative TIDs.
368 */ 368 */
369 369
370#define BUF_THREAD_ID_SIZE 16 370#define BUF_THREAD_ID_SIZE 8
371 371
372static char *pack_threadid(char *pkt, unsigned char *id) 372static char *pack_threadid(char *pkt, unsigned char *id)
373{ 373{
374 char *limit; 374 unsigned char *limit;
375 int lzero = 1;
376
377 limit = id + (BUF_THREAD_ID_SIZE / 2);
378 while (id < limit) {
379 if (!lzero || *id != 0) {
380 pkt = pack_hex_byte(pkt, *id);
381 lzero = 0;
382 }
383 id++;
384 }
375 385
376 limit = pkt + BUF_THREAD_ID_SIZE; 386 if (lzero)
377 while (pkt < limit) 387 pkt = pack_hex_byte(pkt, 0);
378 pkt = pack_hex_byte(pkt, *id++);
379 388
380 return pkt; 389 return pkt;
381} 390}
382 391
383static void int_to_threadref(unsigned char *id, int value) 392static void int_to_threadref(unsigned char *id, int value)
384{ 393{
385 unsigned char *scan; 394 put_unaligned_be32(value, id);
386 int i = 4;
387
388 scan = (unsigned char *)id;
389 while (i--)
390 *scan++ = 0;
391 put_unaligned_be32(value, scan);
392} 395}
393 396
394static struct task_struct *getthread(struct pt_regs *regs, int tid) 397static struct task_struct *getthread(struct pt_regs *regs, int tid)
@@ -601,7 +604,7 @@ static void gdb_cmd_query(struct kgdb_state *ks)
601{ 604{
602 struct task_struct *g; 605 struct task_struct *g;
603 struct task_struct *p; 606 struct task_struct *p;
604 unsigned char thref[8]; 607 unsigned char thref[BUF_THREAD_ID_SIZE];
605 char *ptr; 608 char *ptr;
606 int i; 609 int i;
607 int cpu; 610 int cpu;
@@ -621,8 +624,7 @@ static void gdb_cmd_query(struct kgdb_state *ks)
621 for_each_online_cpu(cpu) { 624 for_each_online_cpu(cpu) {
622 ks->thr_query = 0; 625 ks->thr_query = 0;
623 int_to_threadref(thref, -cpu - 2); 626 int_to_threadref(thref, -cpu - 2);
624 pack_threadid(ptr, thref); 627 ptr = pack_threadid(ptr, thref);
625 ptr += BUF_THREAD_ID_SIZE;
626 *(ptr++) = ','; 628 *(ptr++) = ',';
627 i++; 629 i++;
628 } 630 }
@@ -631,8 +633,7 @@ static void gdb_cmd_query(struct kgdb_state *ks)
631 do_each_thread(g, p) { 633 do_each_thread(g, p) {
632 if (i >= ks->thr_query && !finished) { 634 if (i >= ks->thr_query && !finished) {
633 int_to_threadref(thref, p->pid); 635 int_to_threadref(thref, p->pid);
634 pack_threadid(ptr, thref); 636 ptr = pack_threadid(ptr, thref);
635 ptr += BUF_THREAD_ID_SIZE;
636 *(ptr++) = ','; 637 *(ptr++) = ',';
637 ks->thr_query++; 638 ks->thr_query++;
638 if (ks->thr_query % KGDB_MAX_THREAD_QUERY == 0) 639 if (ks->thr_query % KGDB_MAX_THREAD_QUERY == 0)
@@ -851,7 +852,7 @@ int gdb_serial_stub(struct kgdb_state *ks)
851 memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer)); 852 memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
852 853
853 if (kgdb_connected) { 854 if (kgdb_connected) {
854 unsigned char thref[8]; 855 unsigned char thref[BUF_THREAD_ID_SIZE];
855 char *ptr; 856 char *ptr;
856 857
857 /* Reply to host that an exception has occurred */ 858 /* Reply to host that an exception has occurred */