Message ID | 20230112171043.1159787-1-legouguec@adacore.com |
---|---|
State | New |
Headers |
Return-Path: <gdb-patches-bounces+patchwork=sourceware.org@sourceware.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 78B8B3858C74 for <patchwork@sourceware.org>; Thu, 12 Jan 2023 17:12:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 78B8B3858C74 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1673543567; bh=ndTKYnra4ULx5w6fVx8M4+Xd9U+FaipEL2p2iY1clYc=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=a/euYYdz8qjMDpEojk+HCUjsrXq8SaIK2WRk/68Bl761TO/eLCT+zO3mhtWr9D4TA IxPX4IIbRk9MXF+FepUQyekbbCKck9hPgPNTYcQ5smcqMSy9CaR2nak6HYmM9aNt2c +aDc6FihpAmaBa/urD0k+Hb2w6AiE87SGhJKA4hw= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by sourceware.org (Postfix) with ESMTPS id 7E5353858D35 for <gdb-patches@sourceware.org>; Thu, 12 Jan 2023 17:12:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7E5353858D35 Received: by mail-wm1-x32e.google.com with SMTP id ja17so13676934wmb.3 for <gdb-patches@sourceware.org>; Thu, 12 Jan 2023 09:12:20 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=ndTKYnra4ULx5w6fVx8M4+Xd9U+FaipEL2p2iY1clYc=; b=JY8akMgmpzjxV+3oUhiUSjoANRhQvNAJbxSG5pAyr2+Fg6ETTAwgoPwUEnJVAvuv/6 CajWaeokWU1Vp/wTM+YigYcoaOPzqQ8Vkbc2+hB4+0GGtKZb2QxJ5rA+kx1twaT7Q+Su bR6XX+u7CFRQkV/pIfR2551DZnwnLLT7yKFLMYscl8rVJIFxi7GZQZGXT0OzRKATjbJE VwOrUEYzZQq40N5m9/PXpB5j70a3Jswy9DFpszZbrxSEfQjwt1WtaL2d3MnJPmpb/st/ 0xUbURouWV7XjLxOCfT1/oW/C0bRipyehc3289ed3BsVeiaBmeqSAtHXpXfRRXuVn5oM OpMw== X-Gm-Message-State: AFqh2kqgVcXfQFbKB3BluxGoW69gq/FnS03FWnMhLnguZTcYEeJiVLqd ZW46hcqGbILHEVCwUjq7d266pclWjfH/mQHh X-Google-Smtp-Source: AMrXdXsbyF4MbR64UHt3pOIn9di/ivN/X/wAf7RCfWWzFwN24B4Yg+dyEq8MOP4GWzsdIIiaUIpYag== X-Received: by 2002:a05:600c:3b1c:b0:3d9:f0da:542c with SMTP id m28-20020a05600c3b1c00b003d9f0da542cmr12204338wms.28.1673543538998; Thu, 12 Jan 2023 09:12:18 -0800 (PST) Received: from localhost.localdomain ([37.58.245.230]) by smtp.gmail.com with ESMTPSA id g14-20020a05600c310e00b003cf5ec79bf9sm24714973wmo.40.2023.01.12.09.12.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Jan 2023 09:12:18 -0800 (PST) To: gdb-patches@sourceware.org Cc: =?utf-8?q?K=C3=A9vin_Le_Gouguec?= <legouguec@adacore.com> Subject: [PATCH] Fix Ada tasking for baremetal targets using Ravenscar threads Date: Thu, 12 Jan 2023 18:10:43 +0100 Message-Id: <20230112171043.1159787-1-legouguec@adacore.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list <gdb-patches.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/gdb-patches>, <mailto:gdb-patches-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/gdb-patches/> List-Post: <mailto:gdb-patches@sourceware.org> List-Help: <mailto:gdb-patches-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/gdb-patches>, <mailto:gdb-patches-request@sourceware.org?subject=subscribe> From: =?utf-8?q?K=C3=A9vin_Le_Gouguec_via_Gdb-patches?= <gdb-patches@sourceware.org> Reply-To: =?utf-8?q?K=C3=A9vin_Le_Gouguec?= <legouguec@adacore.com> Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" <gdb-patches-bounces+patchwork=sourceware.org@sourceware.org> |
Series |
Fix Ada tasking for baremetal targets using Ravenscar threads
|
|
Commit Message
Kévin Le Gouguec
Jan. 12, 2023, 5:10 p.m. UTC
For some boards, the Ada tasking runtime defines a __gnat_gdb_cpu_first_id symbol to let GDB map the ATCB's "Base_CPU" indices (ranging from 1 to System.Multiprocessors.CPU) onto the CPU numbers that we read from the remote stub and record in our ptids. In other words, this symbol lets GDB translate "Ada CPUs" into "target CPUs". For example, for the Microchip PolarFire board, the runtime defines this offset as: package System.BB.Board_Parameters is -- [...] GDB_First_CPU_Id : constant Interfaces.Unsigned_32 := 1; pragma Export (C, GDB_First_CPU_Id, "__gnat_gdb_cpu_first_id"); This is because on this board, CPU#1 is the "monitor" CPU; CPUs #2-5 are the "application" CPUs that run user code. So while the ATCB shows Base_CPUs equal to 1, QEMU reports that our code is running on CPU #2. We convert the ATCB's Base_CPUs into "target" CPUs before recording them in struct ada_task_info.base_cpu; this is what we need in most of ravenscar-thread.c, except in one specific spot: when reading the active thread from __gnat_running_thread_table, which is defined as: package System.BB.Threads.Queues is -- [...] Running_Thread_Table : array (System.Multiprocessors.CPU) of Thread_Id On baremetal targets, System.Multiprocessors.CPU is defined as: package System.Multiprocessors is -- [...] type CPU_Range is range 0 .. System.BB.Parameters.Max_Number_Of_CPUs; subtype CPU is CPU_Range range 1 .. CPU_Range'Last; Not_A_Specific_CPU : constant CPU_Range := 0; Thus __gnat_running_thread_table has Max_Number_Of_CPUs elements; for the Microchip PolarFire board, the runtime define this as: package System.BB.Parameters is -- [...] Max_Number_Of_CPUs : constant := 1; So the table has just one element, but ravenscar-thread.c attempts to index it using the "target" CPU ID, i.e. 2. This remained undetected because as luck would have it, with the specific compiler we were using, *(__gnat_running_thread_table+8) happened to contain exactly the same content as *__gnat_running_thread_table. After bumping the compiler, the layout of the tasking runtime changed, and so did the content of *(__gnat_running_thread_table+8). This commit introduces a new function to let GDB convert a "target" CPU back to an "Ada" CPU. Tested on x86_64-linux and riscv64-elf with AdaCore's internal testsuite, which has more extensive coverage of Ada tasking and "Ravenscar thread" features. --- gdb/ada-lang.h | 8 +++++++- gdb/ada-tasks.c | 14 ++++++++++++++ gdb/ravenscar-thread.c | 8 +++++++- 3 files changed, 28 insertions(+), 2 deletions(-)
Comments
On 1/12/23 12:10, Kévin Le Gouguec via Gdb-patches wrote: > For some boards, the Ada tasking runtime defines a __gnat_gdb_cpu_first_id > symbol to let GDB map the ATCB's "Base_CPU" indices (ranging from 1 to > System.Multiprocessors.CPU) onto the CPU numbers that we read from the > remote stub and record in our ptids. > > In other words, this symbol lets GDB translate "Ada CPUs" into "target > CPUs". For example, for the Microchip PolarFire board, the runtime defines > this offset as: > > package System.BB.Board_Parameters is > -- [...] > GDB_First_CPU_Id : constant Interfaces.Unsigned_32 := 1; > pragma Export (C, GDB_First_CPU_Id, "__gnat_gdb_cpu_first_id"); > > This is because on this board, CPU#1 is the "monitor" CPU; CPUs #2-5 are the > "application" CPUs that run user code. So while the ATCB shows Base_CPUs > equal to 1, QEMU reports that our code is running on CPU #2. > > We convert the ATCB's Base_CPUs into "target" CPUs before recording them in > struct ada_task_info.base_cpu; this is what we need in most of > ravenscar-thread.c, except in one specific spot: when reading the active > thread from __gnat_running_thread_table, which is defined as: > > package System.BB.Threads.Queues is > -- [...] > Running_Thread_Table : array (System.Multiprocessors.CPU) of Thread_Id > > On baremetal targets, System.Multiprocessors.CPU is defined as: > > package System.Multiprocessors is > -- [...] > type CPU_Range is range 0 .. System.BB.Parameters.Max_Number_Of_CPUs; > > subtype CPU is CPU_Range range 1 .. CPU_Range'Last; > > Not_A_Specific_CPU : constant CPU_Range := 0; > > Thus __gnat_running_thread_table has Max_Number_Of_CPUs elements; for the > Microchip PolarFire board, the runtime define this as: > > package System.BB.Parameters is > -- [...] > Max_Number_Of_CPUs : constant := 1; > > So the table has just one element, but ravenscar-thread.c attempts to index > it using the "target" CPU ID, i.e. 2. > > This remained undetected because as luck would have it, with the specific > compiler we were using, *(__gnat_running_thread_table+8) happened to contain > exactly the same content as *__gnat_running_thread_table. After bumping the > compiler, the layout of the tasking runtime changed, and so did the content > of *(__gnat_running_thread_table+8). > > This commit introduces a new function to let GDB convert a "target" CPU back > to an "Ada" CPU. > > Tested on x86_64-linux and riscv64-elf with AdaCore's internal testsuite, > which has more extensive coverage of Ada tasking and "Ravenscar thread" > features. Hi Kevin, I can't speak about the Ada-specific bits, but at least the commit message makes it like you know what you're doing, so that's convincing :). > --- > gdb/ada-lang.h | 8 +++++++- > gdb/ada-tasks.c | 14 ++++++++++++++ > gdb/ravenscar-thread.c | 8 +++++++- > 3 files changed, 28 insertions(+), 2 deletions(-) > > diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h > index 9fb7ac7f384..bca0deea67f 100644 > --- a/gdb/ada-lang.h > +++ b/gdb/ada-lang.h > @@ -145,7 +145,11 @@ struct ada_task_info > /* The CPU on which the task is running. This is dependent on > the runtime actually providing that info, which is not always > the case. Normally, we should be able to count on it on > - bare-metal targets. */ > + bare-metal targets. > + > + NB: This CPU number has been normalized to match the IDs reported by the > + target, as recorded in the LWP field of PTIDs. It may not map directly to > + the Base_CPU recorded in the ATCB; see ada_get_runtime_cpu_index. */ > int base_cpu; > }; > > @@ -374,6 +378,8 @@ extern struct ada_task_info *ada_get_task_info_from_ptid (ptid_t ptid); > > extern int ada_get_task_number (thread_info *thread); > > +extern int ada_get_runtime_cpu_index (int target_cpu); To conform with the current standards, please move the function doc here. > + > typedef gdb::function_view<void (struct ada_task_info *task)> > ada_task_list_iterator_ftype; > extern void iterate_over_live_ada_tasks > diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c > index a3a28063daa..1e5605f9b62 100644 > --- a/gdb/ada-tasks.c > +++ b/gdb/ada-tasks.c > @@ -346,6 +346,20 @@ ada_get_task_number (thread_info *thread) > return 0; /* No matching task found. */ > } > > +/* Translate a "target" CPU index into a "runtime" index suitable for addressing > + arrays dimensioned with System.Multiprocessors.CPU. */ And here, put: /* See ada-lang.h. */ (Ideally there would be an ada-tasks.h to match ada-tasks.c.) > + > +int > +ada_get_runtime_cpu_index (int target_cpu) > +{ > + const struct ada_tasks_pspace_data *pspace_data > + = get_ada_tasks_pspace_data (current_program_space); I would prefer if you added either a `program_space *` or `ada_tasks_pspace_data *` to this function, and pushed the reference to the global state to the caller. My life goal is to reduce the number of places that reference the global state in GDB. Or, maybe, make this a method of ada_tasks_pspace_data? The caller would then to: const ada_tasks_pspace_data *pspace_data = get_ada_tasks_pspace_data (current_program_space); cpu = pspace_data->get_runtime_cpu_index (cpu); Simon
Hey Simon, thanks for the review! Simon Marchi <simark@simark.ca> writes: > I can't speak about the Ada-specific bits, but at least the commit > message makes it like you know what you're doing, so that's convincing > :). (I've slowly come to believe I know what I am doing, but if not, hopefully this commit message will be enough to trigger Cunningham's Law) >> diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h >> index 9fb7ac7f384..bca0deea67f 100644 >> --- a/gdb/ada-lang.h >> +++ b/gdb/ada-lang.h >> @@ -145,7 +145,11 @@ struct ada_task_info >> /* The CPU on which the task is running. This is dependent on >> the runtime actually providing that info, which is not always >> the case. Normally, we should be able to count on it on >> - bare-metal targets. */ >> + bare-metal targets. >> + >> + NB: This CPU number has been normalized to match the IDs reported by the >> + target, as recorded in the LWP field of PTIDs. It may not map directly to >> + the Base_CPU recorded in the ATCB; see ada_get_runtime_cpu_index. */ >> int base_cpu; >> }; >> >> @@ -374,6 +378,8 @@ extern struct ada_task_info *ada_get_task_info_from_ptid (ptid_t ptid); >> >> extern int ada_get_task_number (thread_info *thread); >> >> +extern int ada_get_runtime_cpu_index (int target_cpu); > > To conform with the current standards, please move the function doc > here. ACK, traced back to https://sourceware.org/gdb/wiki/Internals GDB-C-Coding-Standards#Document_Every_Subprogram Will give this a re-read before submitting v2. >> + >> typedef gdb::function_view<void (struct ada_task_info *task)> >> ada_task_list_iterator_ftype; >> extern void iterate_over_live_ada_tasks >> diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c >> index a3a28063daa..1e5605f9b62 100644 >> --- a/gdb/ada-tasks.c >> +++ b/gdb/ada-tasks.c >> @@ -346,6 +346,20 @@ ada_get_task_number (thread_info *thread) >> return 0; /* No matching task found. */ >> } >> >> +/* Translate a "target" CPU index into a "runtime" index suitable for addressing >> + arrays dimensioned with System.Multiprocessors.CPU. */ > > > And here, put: > > /* See ada-lang.h. */ > > (Ideally there would be an ada-tasks.h to match ada-tasks.c.) Agreed, might explore that in a preliminary commit for v2. >> + >> +int >> +ada_get_runtime_cpu_index (int target_cpu) >> +{ >> + const struct ada_tasks_pspace_data *pspace_data >> + = get_ada_tasks_pspace_data (current_program_space); > > I would prefer if you added either a `program_space *` or > `ada_tasks_pspace_data *` to this function, and pushed the reference to > the global state to the caller. My life goal is to reduce the number of > places that reference the global state in GDB. > > Or, maybe, make this a method of ada_tasks_pspace_data? The caller > would then to: > > const ada_tasks_pspace_data *pspace_data > = get_ada_tasks_pspace_data (current_program_space); > cpu = pspace_data->get_runtime_cpu_index (cpu); I like the idea, although right now ada_tasks_pspace_data is completely internal to ada-tasks.c. ravenscar-thread.c only has access to ada_task_info instances; we could stick the CPU offset in there, but conceptually it's not really a property of the task. AFAICT this patch follows the current pattern of ravenscar-thread.c letting ada-tasks.c access globals: ada-tasks.c currently has 18 accesses to current_\(program_space\|inferior\), vs 3 calls to current_inferior in ravenscar-thread.c, which does not even include progspace.h. So by my reckoning: (a) this v1 is no worse than the status quo in terms of accessing globals, (b) naively pushing current_program_space to the caller would mean making ravenscar-thread.c aware of current_program_space, so a net loss according to the "reduce the number of references to global state in GDB" metric, (c) publishing struct ada_tasks_pspace_data and get_ada_tasks_pspace_data wouldn't be much better (ravenscar-thread.c would still need to learn about current_program_space), but it does feel like a step in the right direction? I.e. it would then "just" be a matter of… (d) … somehow adding a struct ada_tasks_pspace_data member to ravenscar_thread_target. That would allow ravenscar_thread_target::active_task to call m_pspace_data->get_runtime_cpu_index (cpu). So, with utmost consideration for your life goal, it seems to me that the solutions, ranked by decreasing order of preference, would be (c)+(d) > (a) > (b) Does that make sense? If so, I'd like to advocate for (a) (+ the doc fixes you noted), and write "figure out how to pass an ada_tasks_pspace_data instance to ravenscar_thread_target" on a post-it and stick it to my monitor, in order to unblock (d). Let me know if you'd rather I go with (b), or if I've misread the situation. Again, thanks for the review!
On 1/13/23 07:32, Kévin Le Gouguec wrote: > Hey Simon, thanks for the review! > > Simon Marchi <simark@simark.ca> writes: > >> I can't speak about the Ada-specific bits, but at least the commit >> message makes it like you know what you're doing, so that's convincing >> :). > > (I've slowly come to believe I know what I am doing, but if not, > hopefully this commit message will be enough to trigger Cunningham's > Law) > >>> diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h >>> index 9fb7ac7f384..bca0deea67f 100644 >>> --- a/gdb/ada-lang.h >>> +++ b/gdb/ada-lang.h >>> @@ -145,7 +145,11 @@ struct ada_task_info >>> /* The CPU on which the task is running. This is dependent on >>> the runtime actually providing that info, which is not always >>> the case. Normally, we should be able to count on it on >>> - bare-metal targets. */ >>> + bare-metal targets. >>> + >>> + NB: This CPU number has been normalized to match the IDs reported by the >>> + target, as recorded in the LWP field of PTIDs. It may not map directly to >>> + the Base_CPU recorded in the ATCB; see ada_get_runtime_cpu_index. */ >>> int base_cpu; >>> }; >>> >>> @@ -374,6 +378,8 @@ extern struct ada_task_info *ada_get_task_info_from_ptid (ptid_t ptid); >>> >>> extern int ada_get_task_number (thread_info *thread); >>> >>> +extern int ada_get_runtime_cpu_index (int target_cpu); >> >> To conform with the current standards, please move the function doc >> here. > > ACK, traced back to > > https://sourceware.org/gdb/wiki/Internals GDB-C-Coding-Standards#Document_Every_Subprogram > > Will give this a re-read before submitting v2. > >>> + >>> typedef gdb::function_view<void (struct ada_task_info *task)> >>> ada_task_list_iterator_ftype; >>> extern void iterate_over_live_ada_tasks >>> diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c >>> index a3a28063daa..1e5605f9b62 100644 >>> --- a/gdb/ada-tasks.c >>> +++ b/gdb/ada-tasks.c >>> @@ -346,6 +346,20 @@ ada_get_task_number (thread_info *thread) >>> return 0; /* No matching task found. */ >>> } >>> >>> +/* Translate a "target" CPU index into a "runtime" index suitable for addressing >>> + arrays dimensioned with System.Multiprocessors.CPU. */ >> >> >> And here, put: >> >> /* See ada-lang.h. */ >> >> (Ideally there would be an ada-tasks.h to match ada-tasks.c.) > > Agreed, might explore that in a preliminary commit for v2. > >>> + >>> +int >>> +ada_get_runtime_cpu_index (int target_cpu) >>> +{ >>> + const struct ada_tasks_pspace_data *pspace_data >>> + = get_ada_tasks_pspace_data (current_program_space); >> >> I would prefer if you added either a `program_space *` or >> `ada_tasks_pspace_data *` to this function, and pushed the reference to >> the global state to the caller. My life goal is to reduce the number of >> places that reference the global state in GDB. >> >> Or, maybe, make this a method of ada_tasks_pspace_data? The caller >> would then to: >> >> const ada_tasks_pspace_data *pspace_data >> = get_ada_tasks_pspace_data (current_program_space); >> cpu = pspace_data->get_runtime_cpu_index (cpu); > > I like the idea, although right now ada_tasks_pspace_data is completely > internal to ada-tasks.c. ravenscar-thread.c only has access to > ada_task_info instances; we could stick the CPU offset in there, but > conceptually it's not really a property of the task. Indeed. > AFAICT this patch follows the current pattern of ravenscar-thread.c > letting ada-tasks.c access globals: ada-tasks.c currently has 18 > accesses to current_\(program_space\|inferior\), vs 3 calls to > current_inferior in ravenscar-thread.c, which does not even include > progspace.h. > > So by my reckoning: > > (a) this v1 is no worse than the status quo in terms of accessing > globals, That's true. > (b) naively pushing current_program_space to the caller would mean > making ravenscar-thread.c aware of current_program_space, so a net loss > according to the "reduce the number of references to global state in > GDB" metric, ravenscar-thread.c is already implicitly aware of the current program space and global state in general, since it calls functions that are dependent on the global state. And as you add a new function dependent on the global state, that's one more function dependent on the global state in GDB, so I would consider that a "net loss". When possible, I try to change leaf functions to make them "pure", receiving the context as parameters rather than using the global context. And slowly progress up the call tree like this, making incremental progress. It's true that the absolute number of literal "current_program_space" reference can increase. Like if I change a function to accept a program_space parameter, rather than using "current_program_space" directly, and inline "current_program_space" in all its callers. But that's a necessary step towards the end goal. > > (c) publishing struct ada_tasks_pspace_data and > get_ada_tasks_pspace_data wouldn't be much better (ravenscar-thread.c > would still need to learn about current_program_space), but it does feel > like a step in the right direction? I.e. it would then "just" be a > matter of… Whether we have a ada_get_runtime_cpu_index free function or we expose ada_tasks_pspace_data and add a get_runtime_cpu_index method does not change anything w.r.t. references to global state. > > (d) … somehow adding a struct ada_tasks_pspace_data member to > ravenscar_thread_target. That would allow > ravenscar_thread_target::active_task to call > m_pspace_data->get_runtime_cpu_index (cpu). I don't think that makes sense, we don't want to create intances of ada_tasks_pspace_data not managed by ada_tasks_pspace_data_handle. > > So, with utmost consideration for your life goal, it seems to me that > the solutions, ranked by decreasing order of preference, would be > > (c)+(d) > (a) > (b) I disagree, I don't think (d) is right. > Does that make sense? If so, I'd like to advocate for (a) (+ the doc > fixes you noted), and write "figure out how to pass an > ada_tasks_pspace_data instance to ravenscar_thread_target" on a post-it > and stick it to my monitor, in order to unblock (d). I'm fine with doing (a) if you prefer, it doesn't change much in the grand scheme of things. However, I might just notice that function in the future being a good candidate for becoming "pure", and change it to push the global state reference up the call tree :). Simon
Simon Marchi <simark@simark.ca> writes: >> (b) naively pushing current_program_space to the caller would mean >> making ravenscar-thread.c aware of current_program_space, so a net loss >> according to the "reduce the number of references to global state in >> GDB" metric, > > ravenscar-thread.c is already implicitly aware of the current program > space and global state in general, since it calls functions that are > dependent on the global state. And as you add a new function dependent > on the global state, that's one more function dependent on the global > state in GDB, so I would consider that a "net loss". > > When possible, I try to change leaf functions to make them "pure", > receiving the context as parameters rather than using the global > context. And slowly progress up the call tree like this, making > incremental progress. It's true that the absolute number of literal > "current_program_space" reference can increase. Like if I change a > function to accept a program_space parameter, rather than using > "current_program_space" directly, and inline "current_program_space" in > all its callers. But that's a necessary step towards the end goal. OK, I see the value of endeavoring to keep newly introduced leaf functions pure, and "revealing" the implicit dependencies by pushing references to global state up to the callers. >> (d) … somehow adding a struct ada_tasks_pspace_data member to >> ravenscar_thread_target. That would allow >> ravenscar_thread_target::active_task to call >> m_pspace_data->get_runtime_cpu_index (cpu). > > I don't think that makes sense, we don't want to create intances of > ada_tasks_pspace_data not managed by ada_tasks_pspace_data_handle. ACK; naively I assumed that ravenscar_thread_target holding a reference to an ada_tasks_pspace_data would be fine as long as the latter outlived the former, but I had no reason to believe that this condition holds when I wrote that. >> Does that make sense? If so, I'd like to advocate for (a) (+ the doc >> fixes you noted), and write "figure out how to pass an >> ada_tasks_pspace_data instance to ravenscar_thread_target" on a post-it >> and stick it to my monitor, in order to unblock (d). > > I'm fine with doing (a) if you prefer, it doesn't change much in the > grand scheme of things. However, I might just notice that function in > the future being a good candidate for becoming "pure", and change it to > push the global state reference up the call tree :). I'm game for keeping this new function (ada_get_runtime_cpu_index) pure from the get go. So my current plan for v2 (taking the other remarks into account) is thus to… 1. introduce ada-tasks.h and move stuff defined in ada-tasks.c there, 2. make ada_tasks_pspace_data and its getter public, 3. introduce a get_runtime_cpu_index method, 4. rebase v1 on top of that, … on the hunch that exposing ada_tasks_pspace_data will encourage giving it pure(r) methods and keeping references to global state confined to its callers. Not sure what I'm basing this hunch on though, so let me know if this sounds like overkill, and I should just leave it at: diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c index a9c45ab6b9c..e9a52937966 100644 --- a/gdb/ada-tasks.c +++ b/gdb/ada-tasks.c @@ -350,10 +350,10 @@ ada_get_task_number (thread_info *thread) arrays dimensioned with System.Multiprocessors.CPU. */ int -ada_get_runtime_cpu_index (int target_cpu) +ada_get_runtime_cpu_index (struct program_space *pspace, int target_cpu) { const struct ada_tasks_pspace_data *pspace_data - = get_ada_tasks_pspace_data (current_program_space); + = get_ada_tasks_pspace_data (pspace); gdb_assert (pspace_data->initialized_p); Thanks for your patience.
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h index 9fb7ac7f384..bca0deea67f 100644 --- a/gdb/ada-lang.h +++ b/gdb/ada-lang.h @@ -145,7 +145,11 @@ struct ada_task_info /* The CPU on which the task is running. This is dependent on the runtime actually providing that info, which is not always the case. Normally, we should be able to count on it on - bare-metal targets. */ + bare-metal targets. + + NB: This CPU number has been normalized to match the IDs reported by the + target, as recorded in the LWP field of PTIDs. It may not map directly to + the Base_CPU recorded in the ATCB; see ada_get_runtime_cpu_index. */ int base_cpu; }; @@ -374,6 +378,8 @@ extern struct ada_task_info *ada_get_task_info_from_ptid (ptid_t ptid); extern int ada_get_task_number (thread_info *thread); +extern int ada_get_runtime_cpu_index (int target_cpu); + typedef gdb::function_view<void (struct ada_task_info *task)> ada_task_list_iterator_ftype; extern void iterate_over_live_ada_tasks diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c index a3a28063daa..1e5605f9b62 100644 --- a/gdb/ada-tasks.c +++ b/gdb/ada-tasks.c @@ -346,6 +346,20 @@ ada_get_task_number (thread_info *thread) return 0; /* No matching task found. */ } +/* Translate a "target" CPU index into a "runtime" index suitable for addressing + arrays dimensioned with System.Multiprocessors.CPU. */ + +int +ada_get_runtime_cpu_index (int target_cpu) +{ + const struct ada_tasks_pspace_data *pspace_data + = get_ada_tasks_pspace_data (current_program_space); + + gdb_assert (pspace_data->initialized_p); + + return target_cpu - pspace_data->cpu_id_offset; +} + /* Return the task number of the task running in inferior INF which matches TASK_ID , or zero if the task could not be found. */ diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c index 22fbdbe9662..52908eb2bb5 100644 --- a/gdb/ravenscar-thread.c +++ b/gdb/ravenscar-thread.c @@ -193,7 +193,11 @@ struct ravenscar_thread_target final : public target_ops /* This maps a TID to the CPU on which it was running. This is needed because sometimes the runtime will report an active task that hasn't yet been put on the list of tasks that is read by - ada-tasks.c. */ + ada-tasks.c. + + NB: These CPU numbers correspond to those reported by the target, + which may differ from the numbers recorded in the ATCB. See + ada_get_runtime_cpu_index. */ std::unordered_map<ULONGEST, int> m_cpu_map; }; @@ -377,6 +381,8 @@ ravenscar_thread_target::runtime_initialized () static CORE_ADDR get_running_thread_id (int cpu) { + cpu = ada_get_runtime_cpu_index (cpu); + struct bound_minimal_symbol object_msym = get_running_thread_msymbol (); int object_size; int buf_size;