target: provide container_of()
authorDavid Brownell <dbrownell@users.sourceforge.net>
Fri, 6 Nov 2009 05:59:39 +0000 (21:59 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Fri, 6 Nov 2009 05:59:39 +0000 (21:59 -0800)
Provide a cleaner way to handle single inheritance of targets
in C, using the same model Linux does:  structs containing other
structs, un-nested via calls to a "container_of()" macro that
are packaged in typesafe inline functions.

Targets already use this containment idiom, but make it much
more complicated because they un-nest using embedded "void *"
pointers ... in chains of up to five per target, which is all
pure needless complication.  (Example: arm92x core, arm9tdmi,
arm7_9, armv4_5 ... on top of the base "target" class.)

Applying this scheme consistently simplifies things, and gets
rid of many error-prone untyped pointers.  It won't change any
part of the type model though -- it just simplifies things.
(And facilitates more cleanup later on.)

Rule of thumb:  where there's an X->arch_info void* pointer,
access to that pointer can and should be removed.  It may be
convenient to set up pointers to some of the embedded structs;
and shrink their current "*_common" names (annoyingly long).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
12 files changed:
src/target/arm720t.h
src/target/arm7_9_common.h
src/target/arm920t.h
src/target/arm926ejs.h
src/target/arm966e.h
src/target/armv4_5.h
src/target/armv7a.h
src/target/armv7m.h
src/target/cortex_a8.h
src/target/cortex_m3.h
src/target/target.h
src/target/xscale.h

index c7696266c81169123a1359549752e9d1711c1471..0689e4442157a4097bd999086ac833a8d7154d5c 100644 (file)
@@ -35,4 +35,11 @@ typedef struct arm720t_common_s
        uint32_t far_reg;
 } arm720t_common_t;
 
+static inline struct arm720t_common_s *
+target_to_arm720(struct target_s *target)
+{
+       return container_of(target->arch_info, struct arm720t_common_s,
+                       arm7tdmi_common.arm7_9_common.armv4_5_common);
+}
+
 #endif /* ARM720T_H */
index 80f8fc74807d10812fed7e4b22dddc8d58b96cec..d86ac24dc92a50d7dc9602d59f185bbc5b6ada42 100644 (file)
@@ -112,6 +112,13 @@ typedef struct arm7_9_common_s
 
 } arm7_9_common_t;
 
+static inline struct arm7_9_common_s *
+target_to_arm7_9(struct target_s *target)
+{
+       return container_of(target->arch_info, struct arm7_9_common_s,
+                       armv4_5_common);
+}
+
 int arm7_9_register_commands(struct command_context_s *cmd_ctx);
 
 int arm7_9_poll(target_t *target);
index ed851a9385513c861cb3af0972227dc0cc2575be..eb66eaa81135e81a27521c93aac513d1880c513d 100644 (file)
@@ -38,6 +38,13 @@ typedef struct arm920t_common_s
        int preserve_cache;
 } arm920t_common_t;
 
+static inline struct arm920t_common_s *
+target_to_arm920(struct target_s *target)
+{
+       return container_of(target->arch_info, struct arm920t_common_s,
+                       arm9tdmi_common.arm7_9_common.armv4_5_common);
+}
+
 typedef struct arm920t_cache_line_s
 {
        uint32_t cam;
index 7adbf1fbd311f9c665f5c35806c7268b97bc5b61..ff811e3f26c8667050b68a2f4ab40e2ead78e197 100644 (file)
@@ -38,6 +38,14 @@ typedef struct arm926ejs_common_s
        uint32_t d_far;
 } arm926ejs_common_t;
 
+static inline struct arm926ejs_common_s *
+target_to_arm926(struct target_s *target)
+{
+       return container_of(target->arch_info, struct arm926ejs_common_s,
+               arm9tdmi_common.arm7_9_common.armv4_5_common);
+}
+
+
 extern int arm926ejs_init_arch_info(target_t *target, arm926ejs_common_t *arm926ejs, jtag_tap_t *tap);
 extern int arm926ejs_register_commands(struct command_context_s *cmd_ctx);
 extern int arm926ejs_arch_state(struct target_s *target);
index 21dee1e5453c760d92eb36c3e13bd2328fe28055..710f2071661d47b5f67f54fe51a0e7dc9b1a69d7 100644 (file)
@@ -34,6 +34,13 @@ typedef struct arm966e_common_s
        uint32_t cp15_control_reg;
 } arm966e_common_t;
 
+static inline struct arm966e_common_s *
+target_to_arm966(struct target_s *target)
+{
+       return container_of(target->arch_info, struct arm966e_common_s,
+                       arm9tdmi_common.arm7_9_common.armv4_5_common);
+}
+
 extern int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, jtag_tap_t *tap);
 extern int arm966e_register_commands(struct command_context_s *cmd_ctx);
 extern int arm966e_write_cp15(target_t *target, int reg_addr, uint32_t value);
index 80f28db395263193fe96c70bad6dad76de8d4ea8..fb7926b6646e6d3995a2037475d7e8daea3a57c3 100644 (file)
@@ -86,6 +86,12 @@ typedef struct armv4_5_common_s
        void *arch_info;
 } armv4_5_common_t;
 
+static inline struct armv4_5_common_s *
+target_to_armv4_5(struct target_s *target)
+{
+       return target->arch_info;
+}
+
 typedef struct armv4_5_algorithm_s
 {
        int common_magic;
index c5e3257be2f60ad933afd14367a28f0529870c40..3fc97f1fe36abbb689d2a8e8c65b4ad39fe8dbd7 100644 (file)
@@ -127,6 +127,13 @@ typedef struct armv7a_common_s
 
 } armv7a_common_t;
 
+static inline struct armv7a_common_s *
+target_to_armv7a(struct target_s *target)
+{
+       return container_of(target->arch_info, struct armv7a_common_s,
+                       armv4_5_common);
+}
+
 typedef struct armv7a_algorithm_s
 {
        int common_magic;
index d9c62a8d44e8e5f9c616aa8a9794695357041158..487d6fde59f8c94dd16d49724c0d47d2e0d27a73 100644 (file)
@@ -116,6 +116,12 @@ typedef struct armv7m_common_s
        void *arch_info;
 } armv7m_common_t;
 
+static inline struct armv7m_common_s *
+target_to_armv7m(struct target_s *target)
+{
+       return target->arch_info;
+}
+
 typedef struct armv7m_algorithm_s
 {
        int common_magic;
index 369569642bc46e9e4f445d866fc8ef8ce3d95b35..b98a7de1ce088fc0993398413fcf63d5a3a7e33a 100644 (file)
@@ -137,6 +137,13 @@ typedef struct cortex_a8_common_s
        void *arch_info;
 } cortex_a8_common_t;
 
+static inline struct cortex_a8_common_s *
+target_to_cortex_a8(struct target_s *target)
+{
+       return container_of(target->arch_info, struct cortex_a8_common_s,
+                       armv7a_common.armv4_5_common);
+}
+
 extern int cortex_a8_init_arch_info(target_t *target, cortex_a8_common_t *cortex_a8, jtag_tap_t *tap);
 int cortex_a8_read_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
 int cortex_a8_write_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
index 1dd724c8c8769ed342a4dbcb752ce7c335905764..629db8e114a1699c10d3c040db541f47e2539eaa 100644 (file)
@@ -164,4 +164,11 @@ typedef struct cortex_m3_common_s
        void *arch_info;
 } cortex_m3_common_t;
 
+static inline struct cortex_m3_common_s *
+target_to_cm3(struct target_s *target)
+{
+       return container_of(target->arch_info,
+                       struct cortex_m3_common_s, armv7m);
+}
+
 #endif /* CORTEX_M3_H */
index c971f18bd64f7a6cb744d88b679c54313de5e866..1bbf40f0cd3d3c67892f9fd40f1348c29230ca42 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef TARGET_H
 #define TARGET_H
 
+#include <stddef.h>
+
 #include "breakpoints.h"
 #include "algorithm.h"
 #include "command.h"
@@ -34,6 +36,19 @@ struct reg_s;
 struct trace_s;
 struct command_context_s;
 
+
+/**
+ * Cast a member of a structure out to the containing structure.
+ * @param ptr The pointer to the member.
+ * @param type The type of the container struct this is embedded in.
+ * @param member The name of the member within the struct.
+ *
+ * This is a mechanism which is used throughout the Linux kernel.
+ */
+#define container_of(ptr, type, member) ({                     \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+
 /*
  * TARGET_UNKNOWN = 0: we don't know anything about the target yet
  * TARGET_RUNNING = 1: the target is executing user code
index 4b34cf88b72ebf5506a11a7ac39e145ba915c6e8..a1f3d463428aa0fa06294a2bfc95377dbb73d6ea 100644 (file)
@@ -134,6 +134,13 @@ typedef struct xscale_common_s
        int fast_memory_access;
 } xscale_common_t;
 
+static inline struct xscale_common_s *
+target_to_xscale(struct target_s *target)
+{
+       return container_of(target->arch_info, struct xscale_common_s,
+                       armv4_5_common);
+}
+
 typedef struct xscale_reg_s
 {
        int dbg_handler_number;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)