rtos : smp support
[fw/openocd] / src / rtos / rtos.c
index d69127e5e424d26abd9650b622bfc3616e8b50a3..815025704df1168d6880027c185a628f5ea3f01b 100644 (file)
@@ -29,7 +29,6 @@
 #include "server/gdb_server.h"
 
 
-static int64_t current_threadid = -1;
 
 static void hex_to_str( char* dst, char * hex_src );
 static int str_to_hex( char* hex_dst, char* src );
@@ -38,20 +37,30 @@ static int str_to_hex( char* hex_dst, char* src );
 /* RTOSs */
 extern struct rtos_type FreeRTOS_rtos;
 extern struct rtos_type ThreadX_rtos;
+extern struct rtos_type eCos_rtos;
 
 static struct rtos_type *rtos_types[] =
 {
        &ThreadX_rtos,
        &FreeRTOS_rtos,
+       &eCos_rtos,
        NULL
 };
 
+int rtos_thread_packet(struct connection *connection, char *packet, int packet_size);
+
+int rtos_smp_init(struct target *target)
+{
+       if (target->rtos->type->smp_init)
+               return target->rtos->type->smp_init(target);
+       return ERROR_TARGET_INIT_FAILED;
+}
+
 
 int rtos_create(Jim_GetOptInfo *goi, struct target * target)
 {
        int x;
        char *cp;
-
        if (! goi->isconfigure) {
                if (goi->argc != 0) {
                        if (goi->argc != 0) {
@@ -111,9 +120,12 @@ int rtos_create(Jim_GetOptInfo *goi, struct target * target)
        /* Create it */
        target->rtos = calloc(1,sizeof(struct rtos));
        target->rtos->type = rtos_types[x];
+       target->rtos->current_threadid = -1;
        target->rtos->current_thread = 0;
        target->rtos->symbols = NULL;
        target->rtos->target = target;
+       /* put default thread handler in linux usecase it is overloaded*/
+       target->rtos->gdb_thread_packet = rtos_thread_packet;
 
        if ( 0 != strcmp( cp, "auto") )
        {
@@ -123,96 +135,22 @@ int rtos_create(Jim_GetOptInfo *goi, struct target * target)
        return JIM_OK;
 }
 
-
-
-
-int gdb_thread_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
+int gdb_thread_packet(struct connection *connection, char *packet, int packet_size)
 {
-       if (strstr(packet, "qP"))
-       {
-               #define TAG_THREADID 1          /* Echo the thread identifier */
-               #define TAG_EXISTS 2            /* Is this process defined enough to
-                                                  fetch registers and its stack */
-               #define TAG_DISPLAY 4           /* A short thing maybe to put on a window */
-               #define TAG_THREADNAME 8        /* string, maps 1-to-1 with a thread is */
-               #define TAG_MOREDISPLAY 16      /* Whatever the kernel wants to say about */
-
-                       // TODO: need to scanf the mode variable (or it with the tags), and the threadid
-
-               unsigned long mode;
-               threadid_t threadid = 0;
-               struct thread_detail* detail;
-               sscanf(packet, "qP%8lx%16" SCNx64, &mode, &threadid);
-
-
-               int found = -1;
-
-               if ((target->rtos != NULL) && (target->rtos->thread_details
-                               != NULL)) {
-                       int thread_num;
-                       for (thread_num = 0; thread_num
-                                       < target->rtos->thread_count; thread_num++) {
-                               if (target->rtos->thread_details[thread_num].threadid
-                                               == threadid) {
-                                       if (target->rtos->thread_details[thread_num].exists) {
-                                               found = thread_num;
-                                       }
-                               }
-                       }
-               }
-               if (found == -1) {
-                       gdb_put_packet(connection, "E01", 3); // thread not found
-                       return ERROR_OK;
-               }
-
-               detail = &target->rtos->thread_details[found];
-
-               if ( detail->display_str != NULL )
-               {
-                       mode &= TAG_DISPLAY;
-               }
-               if ( detail->thread_name_str != NULL )
-               {
-                       mode &= TAG_THREADNAME;
-               }
-               if ( detail->extra_info_str != NULL )
-               {
-                       mode &= TAG_MOREDISPLAY;
-               }
-
-
-               mode &= TAG_THREADID | TAG_EXISTS;
+       struct target *target = get_target_from_connection(connection);
+       if (target->rtos == NULL)
+               return rtos_thread_packet(connection, packet, packet_size); /* thread not found*/
+       return target->rtos->gdb_thread_packet(connection, packet, packet_size);
+}
 
-               char thread_str[1000];
 
-               sprintf(thread_str, "%08lx", mode);
-               sprintf(thread_str, "%016" PRIx64, threadid);
 
 
-               if (mode & TAG_THREADID) {
-                       sprintf(thread_str, "%08" PRIx32 "10%016" PRIx64, TAG_THREADID, threadid);
-               }
-               if (mode & TAG_EXISTS) {
-                       sprintf(thread_str, "%08" PRIx32 "08%08" PRIx32, TAG_EXISTS, (detail->exists==true)?1:0);
-               }
-               if (mode & TAG_DISPLAY) {
-                       sprintf(thread_str, "%08" PRIx32 "%02x%s", TAG_DISPLAY, (unsigned char)strlen(detail->display_str), detail->display_str );
-               }
-               if (mode & TAG_MOREDISPLAY) {
-                       sprintf(thread_str, "%08" PRIx32 "%02x%s", TAG_MOREDISPLAY, (unsigned char)strlen(detail->extra_info_str), detail->extra_info_str );
-               }
-               if (mode & TAG_THREADNAME) {
-                       sprintf(thread_str, "%08" PRIx32 "%02x%s", TAG_THREADNAME, (unsigned char)strlen(detail->thread_name_str), detail->thread_name_str );
-               }
-
-               //gdb_put_packet(connection, tmpstr, sizeof(tmpstr)-1);
-               gdb_put_packet(connection, thread_str, strlen(thread_str));
+int rtos_thread_packet(struct connection *connection, char *packet, int packet_size)
+{
+       struct target *target = get_target_from_connection(connection);
 
-               //                      gdb_put_packet(connection, "", 0);
-               //              gdb_put_packet(connection, "OK", 2); // all threads alive
-               return ERROR_OK;
-       }
-       else if (strstr(packet, "qThreadExtraInfo,"))
+       if (strstr(packet, "qThreadExtraInfo,"))
        {
                if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) && (target->rtos->thread_count != 0))
                {
@@ -278,6 +216,9 @@ int gdb_thread_packet(struct connection *connection, struct target *target, char
                                tmp_str_ptr += sprintf( tmp_str_ptr, " : %s", detail->extra_info_str );
                        }
 
+                       assert(strlen(tmp_str) ==
+                               (size_t) (tmp_str_ptr - tmp_str));
+
                        char * hex_str = (char*) malloc( strlen(tmp_str)*2 +1 );
                        str_to_hex( hex_str, tmp_str );
 
@@ -312,15 +253,14 @@ int gdb_thread_packet(struct connection *connection, struct target *target, char
                                int symbol_num;
 
                                char* found = strstr( packet, "qSymbol::" );
-                               int numconv;
                                if (0 == found )
                                {
-                                       numconv =sscanf(packet, "qSymbol:%" SCNx64 ":%s", &value, hex_name_str);
+                                       sscanf(packet, "qSymbol:%" SCNx64 ":%s", &value, hex_name_str);
                                }
                                else
                                {
                                        // No value returned by GDB - symbol was not found
-                                       numconv =sscanf(packet, "qSymbol::%s", hex_name_str);
+                                       sscanf(packet, "qSymbol::%s", hex_name_str);
                                }
                                name_str = (char*) malloc( 1+ strlen(hex_name_str) / 2 );
 
@@ -451,7 +391,17 @@ int gdb_thread_packet(struct connection *connection, struct target *target, char
        }
        else if (strstr(packet, "qC"))
        {
-               gdb_put_packet(connection, "QC0", 3);
+               if( target->rtos!=NULL )
+               {
+                       char buffer[15];
+                       int size;
+                       size = snprintf(buffer, 15, "QC%08X", (int)target->rtos->current_thread);
+                       gdb_put_packet(connection, buffer, size);
+               }
+               else
+               {
+                       gdb_put_packet(connection, "QC0", 3);
+               }
                return ERROR_OK;
        }
        else if ( packet[0] == 'T' ) // Is thread alive?
@@ -477,25 +427,28 @@ int gdb_thread_packet(struct connection *connection, struct target *target, char
                } else {
                        gdb_put_packet(connection, "E01", 3); // thread not found
                }
+               return ERROR_OK;
        }
        else if ( packet[0] == 'H') // Set current thread ( 'c' for step and continue, 'g' for all other operations )
        {
-               if (packet[1] == 'g')
-               {
-                       sscanf(packet, "Hg%16" SCNx64, &current_threadid);
-               }
+               if ((packet[1] == 'g') && (target->rtos != NULL))
+                       sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid);
                gdb_put_packet(connection, "OK", 2);
+               return ERROR_OK;
        }
 
        return GDB_THREAD_PACKET_NOT_CONSUMED;
 }
 
-int rtos_get_gdb_reg_list(struct connection *connection, struct target *target, struct reg **reg_list[], int *reg_list_size)
+int rtos_get_gdb_reg_list(struct connection *connection)
 {
-       if ( ( target->rtos != NULL ) &&
-                ( current_threadid != 1 ) &&
-                ( current_threadid != 0 ) &&
-                ( current_threadid != target->rtos->current_thread ) )
+       struct target *target = get_target_from_connection(connection);
+       int64_t current_threadid = target->rtos->current_threadid;
+       if ((target->rtos != NULL) &&
+                (current_threadid != -1) &&
+                (current_threadid != 0) &&
+                ((current_threadid != target->rtos->current_thread) ||
+                (target->smp))) /* in smp several current thread are possible */
        {
                char * hex_reg_list;
                target->rtos->type->get_thread_reg_list( target->rtos, current_threadid, &hex_reg_list );
@@ -554,6 +507,12 @@ int rtos_generic_stack_read( struct target * target, const struct rtos_register_
        *hex_reg_list = (char*)malloc( list_size*2 +1 );
        tmp_str_ptr = *hex_reg_list;
        new_stack_ptr = stack_ptr - stacking->stack_growth_direction * stacking->stack_registers_size;
+       if (stacking->stack_alignment != 0) {
+               /* Align new stack pointer to x byte boundary */
+               new_stack_ptr =
+                       (new_stack_ptr & (~((int64_t) stacking->stack_alignment - 1))) +
+                       ((stacking->stack_growth_direction == -1) ? stacking->stack_alignment : 0);
+       }
        for( i = 0; i < stacking->num_output_registers; i++ )
        {
                int j;