From 17de5480057f1709b28ccebe45d7367ea6bd43d9 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 19:33:32 -0500 Subject: [PATCH 01/13] hal_priv: Introduce, use SHMFIELD Every field that is used with SHMPTR / SHMOFF should be declared as SHMFIELD(actual_type). Later, this will enable smarter type-checking when parts of hal are converted to C++. Signed-off-by: Jeff Epler --- src/hal/hal_priv.h | 72 ++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/src/hal/hal_priv.h b/src/hal/hal_priv.h index 58a2a57f763..9a146c80274 100644 --- a/src/hal/hal_priv.h +++ b/src/hal/hal_priv.h @@ -96,6 +96,8 @@ #include RTAPI_BEGIN_DECLS +#define SHMFIELD(type) int + /* SHMPTR(offset) converts 'offset' to a void pointer. */ #define SHMPTR(offset) ( (void *)( hal_shmem_base + (offset) ) ) @@ -131,8 +133,8 @@ RTAPI_BEGIN_DECLS inside a larger structure. */ typedef struct { - rtapi_intptr_t next; /* next element in list */ - rtapi_intptr_t prev; /* previous element in list */ + SHMFIELD(hal_list_t) next; /* next element in list */ + SHMFIELD(hal_list_t) prev; /* previous element in list */ } hal_list_t; /** HAL "oldname" data structure. @@ -140,7 +142,7 @@ typedef struct { store the original name. */ typedef struct { - rtapi_intptr_t next_ptr; /* next struct (used for free list only) */ + SHMFIELD(hal_oldname_t) next_ptr; /* next struct (used for free list only) */ char name[HAL_NAME_LEN + 1]; /* the original name */ } hal_oldname_t; @@ -162,24 +164,24 @@ typedef struct { /* prefix of name for new instance */ char constructor_arg[HAL_NAME_LEN+1]; /* prefix of name for new instance */ - rtapi_intptr_t shmem_bot; /* bottom of free shmem (first free byte) */ - rtapi_intptr_t shmem_top; /* top of free shmem (1 past last free) */ - rtapi_intptr_t comp_list_ptr; /* root of linked list of components */ - rtapi_intptr_t pin_list_ptr; /* root of linked list of pins */ - rtapi_intptr_t sig_list_ptr; /* root of linked list of signals */ - rtapi_intptr_t param_list_ptr; /* root of linked list of parameters */ - rtapi_intptr_t funct_list_ptr; /* root of linked list of functions */ - rtapi_intptr_t thread_list_ptr; /* root of linked list of threads */ + int shmem_bot; /* bottom of free shmem (first free byte) */ + int shmem_top; /* top of free shmem (1 past last free) */ + SHMFIELD(hal_comp_t) comp_list_ptr; /* root of linked list of components */ + SHMFIELD(hal_pin_t) pin_list_ptr; /* root of linked list of pins */ + SHMFIELD(hal_sig_t) sig_list_ptr; /* root of linked list of signals */ + SHMFIELD(hal_param_t) param_list_ptr; /* root of linked list of parameters */ + SHMFIELD(hal_funct_t) funct_list_ptr; /* root of linked list of functions */ + SHMFIELD(hal_thread_t) thread_list_ptr; /* root of linked list of threads */ long base_period; /* timer period for realtime tasks */ int threads_running; /* non-zero if threads are started */ - rtapi_intptr_t oldname_free_ptr; /* list of free oldname structs */ - rtapi_intptr_t comp_free_ptr; /* list of free component structs */ - rtapi_intptr_t pin_free_ptr; /* list of free pin structs */ - rtapi_intptr_t sig_free_ptr; /* list of free signal structs */ - rtapi_intptr_t param_free_ptr; /* list of free parameter structs */ - rtapi_intptr_t funct_free_ptr; /* list of free function structs */ + SHMFIELD(hal_oldname_t) oldname_free_ptr; /* list of free oldname structs */ + SHMFIELD(hal_comp_t) comp_free_ptr; /* list of free component structs */ + SHMFIELD(hal_pin_t) pin_free_ptr; /* list of free pin structs */ + SHMFIELD(hal_sig_t) sig_free_ptr; /* list of free signal structs */ + SHMFIELD(hal_param_t) param_free_ptr; /* list of free parameter structs */ + SHMFIELD(hal_funct_t) funct_free_ptr; /* list of free function structs */ hal_list_t funct_entry_free; /* list of free funct entry structs */ - rtapi_intptr_t thread_free_ptr; /* list of free thread structs */ + SHMFIELD(hal_thread_t) thread_free_ptr; /* list of free thread structs */ int exact_base_period; /* if set, pretend that rtapi satisfied our period request exactly */ unsigned char lock; /* hal locking, can be one of the HAL_LOCK_* types */ @@ -201,7 +203,7 @@ typedef enum { component calls hal_init(). */ typedef struct { - rtapi_intptr_t next_ptr; /* next component in the list */ + SHMFIELD(hal_comp_t) next_ptr; /* next component in the list */ int comp_id; /* component ID (RTAPI module id) */ int mem_id; /* RTAPI shmem ID used by this comp */ component_type_t type; @@ -210,19 +212,19 @@ typedef struct { void *shmem_base; /* base of shmem for this component */ char name[HAL_NAME_LEN + 1]; /* component name */ constructor make; - int insmod_args; /* args passed to insmod when loaded */ + SHMFIELD(char) insmod_args; /* args passed to insmod when loaded */ } hal_comp_t; /** HAL 'pin' data structure. This structure contains information about a 'pin' object. */ typedef struct { - rtapi_intptr_t next_ptr; /* next pin in linked list */ - int data_ptr_addr; /* address of pin data pointer */ - int owner_ptr; /* component that owns this pin */ - int signal; /* signal to which pin is linked */ + SHMFIELD(hal_pin_t) next_ptr; /* next pin in linked list */ + SHMFIELD(void*) data_ptr_addr; /* address of pin data pointer */ + SHMFIELD(hal_comp_t) owner_ptr; /* component that owns this pin */ + SHMFIELD(hal_sig_t) signal; /* signal to which pin is linked */ hal_data_u dummysig; /* if unlinked, data_ptr points here */ - int oldname; /* old name if aliased, else zero */ + SHMFIELD(hal_oldname_t) oldname; /* old name if aliased, else zero */ hal_type_t type; /* data type */ hal_pin_dir_t dir; /* pin direction */ char name[HAL_NAME_LEN + 1]; /* pin name */ @@ -232,8 +234,8 @@ typedef struct { This structure contains information about a 'signal' object. */ typedef struct { - rtapi_intptr_t next_ptr; /* next signal in linked list */ - int data_ptr; /* offset of signal value */ + SHMFIELD(hal_sig_t) next_ptr; /* next signal in linked list */ + SHMFIELD(void*) data_ptr; /* offset of signal value */ hal_type_t type; /* data type */ int readers; /* number of input pins linked */ int writers; /* number of output pins linked */ @@ -245,10 +247,10 @@ typedef struct { This structure contains information about a 'parameter' object. */ typedef struct { - rtapi_intptr_t next_ptr; /* next parameter in linked list */ - int data_ptr; /* offset of parameter value */ - int owner_ptr; /* component that owns this signal */ - int oldname; /* old name if aliased, else zero */ + SHMFIELD(hal_param_t) next_ptr; /* next parameter in linked list */ + SHMFIELD(void*) data_ptr; /* offset of parameter value */ + SHMFIELD(hal_comp_t) owner_ptr; /* component that owns this signal */ + SHMFIELD(hal_oldname_t) oldname; /* old name if aliased, else zero */ hal_type_t type; /* data type */ hal_param_dir_t dir; /* data direction */ char name[HAL_NAME_LEN + 1]; /* parameter name */ @@ -271,9 +273,9 @@ typedef struct { */ typedef struct { - rtapi_intptr_t next_ptr; /* next function in linked list */ + SHMFIELD(hal_funct_t) next_ptr; /* next function in linked list */ int uses_fp; /* floating point flag */ - int owner_ptr; /* component that added this funct */ + SHMFIELD(hal_comp_t) owner_ptr; /* component that added this funct */ int reentrant; /* non-zero if function is re-entrant */ int users; /* number of threads using function */ void *arg; /* argument for function */ @@ -288,13 +290,13 @@ typedef struct { hal_list_t links; /* linked list data */ void *arg; /* argument for function */ void (*funct) (void *, long); /* ptr to function code */ - int funct_ptr; /* pointer to function */ + SHMFIELD(hal_funct_t) funct_ptr; /* pointer to function */ } hal_funct_entry_t; #define HAL_STACKSIZE 16384 /* realtime task stacksize */ typedef struct { - rtapi_intptr_t next_ptr; /* next thread in linked list */ + SHMFIELD(hal_thread_t) next_ptr; /* next thread in linked list */ int uses_fp; /* floating point flag */ long int period; /* period of the thread, in nsec */ int priority; /* priority of the thread */ From aa2717412b0db1e6e99757c75355bf28ec34b10d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 19:35:59 -0500 Subject: [PATCH 02/13] hal_priv: Make it possible to forward-declare these structures 'typedef struct { ... } typedefame;' without a struct name is impossible to forward-declare, so use 'typedef struct T {...} T;' consistently. Signed-off-by: Jeff Epler --- src/hal/hal_priv.h | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/hal/hal_priv.h b/src/hal/hal_priv.h index 9a146c80274..dce73e14dd4 100644 --- a/src/hal/hal_priv.h +++ b/src/hal/hal_priv.h @@ -121,6 +121,16 @@ RTAPI_BEGIN_DECLS * PRIVATE HAL DATA STRUCTURES AND DECLARATIONS * ************************************************************************/ +/** HAL "data union" structure + ** This structure may hold any type of hal data +*/ +typedef union hal_data_u { + hal_bit_t b; + hal_s32_t s; + hal_u32_t u; + hal_float_t f; +} hal_data_u; + /** HAL "list element" data structure. This structure is used to implement generic double linked circular lists. Such lists have the following characteristics: @@ -132,7 +142,7 @@ RTAPI_BEGIN_DECLS This structure has no data, only links. To use it, include it inside a larger structure. */ -typedef struct { +typedef struct hal_list_t { SHMFIELD(hal_list_t) next; /* next element in list */ SHMFIELD(hal_list_t) prev; /* previous element in list */ } hal_list_t; @@ -141,7 +151,7 @@ typedef struct { When a pin or parameter gets an alias, this structure is used to store the original name. */ -typedef struct { +typedef struct hal_oldname_t { SHMFIELD(hal_oldname_t) next_ptr; /* next struct (used for free list only) */ char name[HAL_NAME_LEN + 1]; /* the original name */ } hal_oldname_t; @@ -154,7 +164,7 @@ typedef struct { in the area, as well as some housekeeping data. It is the root structure for all data in the HAL. */ -typedef struct { +typedef struct hal_data_t { int version; /* version code for structs, etc */ rtapi_mutex_t mutex; /* protection for linked lists, etc. */ hal_s32_t shmem_avail; /* amount of shmem left free */ @@ -202,7 +212,7 @@ typedef enum { An instance of this structure is added to a linked list when the component calls hal_init(). */ -typedef struct { +typedef struct hal_comp_t { SHMFIELD(hal_comp_t) next_ptr; /* next component in the list */ int comp_id; /* component ID (RTAPI module id) */ int mem_id; /* RTAPI shmem ID used by this comp */ @@ -218,7 +228,7 @@ typedef struct { /** HAL 'pin' data structure. This structure contains information about a 'pin' object. */ -typedef struct { +typedef struct hal_pin_t { SHMFIELD(hal_pin_t) next_ptr; /* next pin in linked list */ SHMFIELD(void*) data_ptr_addr; /* address of pin data pointer */ SHMFIELD(hal_comp_t) owner_ptr; /* component that owns this pin */ @@ -233,7 +243,7 @@ typedef struct { /** HAL 'signal' data structure. This structure contains information about a 'signal' object. */ -typedef struct { +typedef struct hal_sig_t { SHMFIELD(hal_sig_t) next_ptr; /* next signal in linked list */ SHMFIELD(void*) data_ptr; /* offset of signal value */ hal_type_t type; /* data type */ @@ -246,7 +256,7 @@ typedef struct { /** HAL 'parameter' data structure. This structure contains information about a 'parameter' object. */ -typedef struct { +typedef struct hal_param_t { SHMFIELD(hal_param_t) next_ptr; /* next parameter in linked list */ SHMFIELD(void*) data_ptr; /* offset of parameter value */ SHMFIELD(hal_comp_t) owner_ptr; /* component that owns this signal */ @@ -272,7 +282,7 @@ typedef struct { that identify the functions connected to that thread. */ -typedef struct { +typedef struct hal_funct_t { SHMFIELD(hal_funct_t) next_ptr; /* next function in linked list */ int uses_fp; /* floating point flag */ SHMFIELD(hal_comp_t) owner_ptr; /* component that added this funct */ @@ -286,7 +296,7 @@ typedef struct { char name[HAL_NAME_LEN + 1]; /* function name */ } hal_funct_t; -typedef struct { +typedef struct hal_funct_entry_t { hal_list_t links; /* linked list data */ void *arg; /* argument for function */ void (*funct) (void *, long); /* ptr to function code */ @@ -295,7 +305,7 @@ typedef struct { #define HAL_STACKSIZE 16384 /* realtime task stacksize */ -typedef struct { +typedef struct hal_thread_t { SHMFIELD(hal_thread_t) next_ptr; /* next thread in linked list */ int uses_fp; /* floating point flag */ long int period; /* period of the thread, in nsec */ From 8ed906b0ed7ffa9d10c4c424b56b3862b4858b2b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 19:36:37 -0500 Subject: [PATCH 03/13] hal_priv: forward-declare these types If SHMFIELD(t) will ever expand to a use of the type t, it will have to be forward-declared. Signed-off-by: Jeff Epler --- src/hal/hal_priv.h | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/hal/hal_priv.h b/src/hal/hal_priv.h index dce73e14dd4..c6cb3c480e8 100644 --- a/src/hal/hal_priv.h +++ b/src/hal/hal_priv.h @@ -156,6 +156,14 @@ typedef struct hal_oldname_t { char name[HAL_NAME_LEN + 1]; /* the original name */ } hal_oldname_t; +typedef struct hal_comp_t hal_comp_t; +typedef struct hal_pin_t hal_pin_t; +typedef struct hal_sig_t hal_sig_t; +typedef struct hal_param_t hal_param_t; +typedef struct hal_funct_t hal_funct_t; +typedef struct hal_funct_entry_t hal_funct_entry_t; +typedef struct hal_thread_t hal_thread_t; + /* Master HAL data structure There is a single instance of this structure in the machine. It resides at the base of the HAL shared memory block, where it @@ -212,7 +220,7 @@ typedef enum { An instance of this structure is added to a linked list when the component calls hal_init(). */ -typedef struct hal_comp_t { +struct hal_comp_t { SHMFIELD(hal_comp_t) next_ptr; /* next component in the list */ int comp_id; /* component ID (RTAPI module id) */ int mem_id; /* RTAPI shmem ID used by this comp */ @@ -223,12 +231,12 @@ typedef struct hal_comp_t { char name[HAL_NAME_LEN + 1]; /* component name */ constructor make; SHMFIELD(char) insmod_args; /* args passed to insmod when loaded */ -} hal_comp_t; +}; /** HAL 'pin' data structure. This structure contains information about a 'pin' object. */ -typedef struct hal_pin_t { +struct hal_pin_t { SHMFIELD(hal_pin_t) next_ptr; /* next pin in linked list */ SHMFIELD(void*) data_ptr_addr; /* address of pin data pointer */ SHMFIELD(hal_comp_t) owner_ptr; /* component that owns this pin */ @@ -238,12 +246,12 @@ typedef struct hal_pin_t { hal_type_t type; /* data type */ hal_pin_dir_t dir; /* pin direction */ char name[HAL_NAME_LEN + 1]; /* pin name */ -} hal_pin_t; +}; /** HAL 'signal' data structure. This structure contains information about a 'signal' object. */ -typedef struct hal_sig_t { +struct hal_sig_t { SHMFIELD(hal_sig_t) next_ptr; /* next signal in linked list */ SHMFIELD(void*) data_ptr; /* offset of signal value */ hal_type_t type; /* data type */ @@ -251,12 +259,12 @@ typedef struct hal_sig_t { int writers; /* number of output pins linked */ int bidirs; /* number of I/O pins linked */ char name[HAL_NAME_LEN + 1]; /* signal name */ -} hal_sig_t; +}; /** HAL 'parameter' data structure. This structure contains information about a 'parameter' object. */ -typedef struct hal_param_t { +struct hal_param_t { SHMFIELD(hal_param_t) next_ptr; /* next parameter in linked list */ SHMFIELD(void*) data_ptr; /* offset of parameter value */ SHMFIELD(hal_comp_t) owner_ptr; /* component that owns this signal */ @@ -264,7 +272,7 @@ typedef struct hal_param_t { hal_type_t type; /* data type */ hal_param_dir_t dir; /* data direction */ char name[HAL_NAME_LEN + 1]; /* parameter name */ -} hal_param_t; +}; /** the HAL uses functions and threads to handle synchronization of code. In general, most control systems need to read inputs, @@ -282,7 +290,7 @@ typedef struct hal_param_t { that identify the functions connected to that thread. */ -typedef struct hal_funct_t { +struct hal_funct_t { SHMFIELD(hal_funct_t) next_ptr; /* next function in linked list */ int uses_fp; /* floating point flag */ SHMFIELD(hal_comp_t) owner_ptr; /* component that added this funct */ @@ -294,18 +302,18 @@ typedef struct hal_funct_t { hal_s32_t maxtime; /* (param) duration of longest run, in CPU cycles */ hal_bit_t maxtime_increased; /* on last call, maxtime increased */ char name[HAL_NAME_LEN + 1]; /* function name */ -} hal_funct_t; +}; -typedef struct hal_funct_entry_t { +struct hal_funct_entry_t { hal_list_t links; /* linked list data */ void *arg; /* argument for function */ void (*funct) (void *, long); /* ptr to function code */ SHMFIELD(hal_funct_t) funct_ptr; /* pointer to function */ -} hal_funct_entry_t; +}; #define HAL_STACKSIZE 16384 /* realtime task stacksize */ -typedef struct hal_thread_t { +struct hal_thread_t { SHMFIELD(hal_thread_t) next_ptr; /* next thread in linked list */ int uses_fp; /* floating point flag */ long int period; /* period of the thread, in nsec */ @@ -316,7 +324,7 @@ typedef struct hal_thread_t { hal_list_t funct_list; /* list of functions to run */ char name[HAL_NAME_LEN + 1]; /* thread name */ int comp_id; -} hal_thread_t; +}; /* IMPORTANT: If any of the structures in this file are changed, the version code (HAL_VER) must be incremented, to ensure that From 7da442e4909afdf107cc91d0219179fb96a676f8 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 19:54:57 -0500 Subject: [PATCH 04/13] hal_priv: reorder slightly .. for the impending C++ definitions Signed-off-by: Jeff Epler --- src/hal/hal_priv.h | 79 ++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/hal/hal_priv.h b/src/hal/hal_priv.h index c6cb3c480e8..6af05b43732 100644 --- a/src/hal/hal_priv.h +++ b/src/hal/hal_priv.h @@ -94,7 +94,47 @@ #include #include + +/* IMPORTANT: If any of the structures in this file are changed, the + version code (HAL_VER) must be incremented, to ensure that + incompatible utilities, etc, aren't used to manipulate data in + shared memory. +*/ + +/* Historical note: in versions 2.0.0 and 2.0.1 of EMC, the key was + 0x48414C21, and instead of the structure starting with a version + number, it started with a fixed magic number. Mixing binaries or + kernel modules from those releases with newer versions will result + in two shmem regions being open, and really strange results (but + should _not_ result in segfaults or other crash type problems). + This is unfortunate, but I can't retroactively make the old code + detect version mismatches. The alternative is worse: if the new + code used the same shmem key, the result would be segfaults or + kernel oopses. + + The use of version codes means that any subsequent changes to + the structs will be fully protected, with a clean shutdown and + meaningfull error messages in case of a mismatch. +*/ + +#define HAL_KEY 0x48414C32 /* key used to open HAL shared memory */ +#define HAL_VER 0x00000010 /* version code */ +#define HAL_SIZE (256*4096) +#define HAL_PSEUDO_COMP_PREFIX "__" /* prefix to identify a pseudo component */ + +/* These pointers are set by hal_init() to point to the shmem block + and to the master data structure. All access should use these + pointers, they takes into account the mapping of shared memory + into either kernel or user space. (The HAL kernel module and + each HAL user process have their own copy of these vars, + initialized to match that process's memory mapping.) +*/ + RTAPI_BEGIN_DECLS +extern char *hal_shmem_base; +extern struct hal_data_t *hal_data; +RTAPI_END_DECLS + #define SHMFIELD(type) int @@ -326,48 +366,11 @@ struct hal_thread_t { int comp_id; }; -/* IMPORTANT: If any of the structures in this file are changed, the - version code (HAL_VER) must be incremented, to ensure that - incompatible utilities, etc, aren't used to manipulate data in - shared memory. -*/ - -/* Historical note: in versions 2.0.0 and 2.0.1 of EMC, the key was - 0x48414C21, and instead of the structure starting with a version - number, it started with a fixed magic number. Mixing binaries or - kernel modules from those releases with newer versions will result - in two shmem regions being open, and really strange results (but - should _not_ result in segfaults or other crash type problems). - This is unfortunate, but I can't retroactively make the old code - detect version mismatches. The alternative is worse: if the new - code used the same shmem key, the result would be segfaults or - kernel oopses. - - The use of version codes means that any subsequent changes to - the structs will be fully protected, with a clean shutdown and - meaningful error messages in case of a mismatch. -*/ - -#define HAL_KEY 0x48414C32 /* key used to open HAL shared memory */ -#define HAL_VER 0x00000010 /* version code */ -#define HAL_SIZE (256*4096) -#define HAL_PSEUDO_COMP_PREFIX "__" /* prefix to identify a pseudo component */ - -/* These pointers are set by hal_init() to point to the shmem block - and to the master data structure. All access should use these - pointers, they takes into account the mapping of shared memory - into either kernel or user space. (The HAL kernel module and - each HAL user process have their own copy of these vars, - initialized to match that process's memory mapping.) -*/ - -extern char *hal_shmem_base; -extern hal_data_t *hal_data; - /*********************************************************************** * PRIVATE HAL FUNCTIONS - NOT PART OF THE API * ************************************************************************/ +RTAPI_BEGIN_DECLS /** None of these functions get or release any mutex. They all assume that the mutex has already been obtained. Calling them without having the mutex may give incorrect results if other processes are From 02768240b3ee97734d3868b20f2484d6795dc7a9 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 19:55:59 -0500 Subject: [PATCH 05/13] halmodule: better check for HAL being initialized .. the old check, SHMPTR(0), will become a compile error soon since this file is C++ and 0 carries no type information. Signed-off-by: Jeff Epler --- src/hal/halmodule.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hal/halmodule.cc b/src/hal/halmodule.cc index 6b8eef3aa87..f5f413d3a52 100644 --- a/src/hal/halmodule.cc +++ b/src/hal/halmodule.cc @@ -773,7 +773,7 @@ static PyObject * pyhal_pin_new(halitem * pin, const char * name) { PyObject *pin_has_writer(PyObject *self, PyObject *args) { char *name; if(!PyArg_ParseTuple(args, "s", &name)) return NULL; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -797,7 +797,7 @@ PyObject *pin_has_writer(PyObject *self, PyObject *args) { PyObject *component_exists(PyObject *self, PyObject *args) { char *name; if(!PyArg_ParseTuple(args, "s", &name)) return NULL; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -809,7 +809,7 @@ PyObject *component_exists(PyObject *self, PyObject *args) { PyObject *component_is_ready(PyObject *self, PyObject *args) { char *name; if(!PyArg_ParseTuple(args, "s", &name)) return NULL; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -824,7 +824,7 @@ PyObject *new_sig(PyObject *self, PyObject *args) { char *name; int type,retval; if(!PyArg_ParseTuple(args, "si", &name,&type)) return NULL; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -853,7 +853,7 @@ PyObject *new_sig(PyObject *self, PyObject *args) { PyObject *connect(PyObject *self, PyObject *args) { char *signame,*pinname; if(!PyArg_ParseTuple(args, "ss", &pinname,&signame)) return NULL; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -941,7 +941,7 @@ PyObject *set_p(PyObject *self, PyObject *args) { void *d_ptr; if(!PyArg_ParseTuple(args, "ss", &name,&value)) return NULL; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; From cd95d06f55efd725245a932117f4baf0646d1095 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 19:56:23 -0500 Subject: [PATCH 06/13] hal_priv: Type-safe C++ for access to HAL shared memory area Signed-off-by: Jeff Epler --- src/hal/hal_priv.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/hal/hal_priv.h b/src/hal/hal_priv.h index 6af05b43732..f356cd4c3c9 100644 --- a/src/hal/hal_priv.h +++ b/src/hal/hal_priv.h @@ -135,7 +135,47 @@ extern char *hal_shmem_base; extern struct hal_data_t *hal_data; RTAPI_END_DECLS +#ifdef __cplusplus +template +bool hal_shmchk(T *t) { + char *c = (char*)t; + return c > hal_shmem_base && c < hal_shmem_base + HAL_SIZE; +} + +template +int hal_shmoff(T *t) { return t ? (char*)t - hal_shmem_base : 0; } + +template +T *hal_shmptr(int p) { return p ? (T*)(hal_shmem_base + p) : nullptr; } + +template +class hal_shmfield { +public: + hal_shmfield() : off{} {} + hal_shmfield(T *t) : off{hal_shmoff(t)} {} + hal_shmfield &operator=(T *t) { off = hal_shmoff(t); } + T *get() { return hal_shmptr(off); } + const T *get() const { return hal_shmptr(off); } + T *operator *() { return get(); } + const T *operator *() const { return get(); } + T *operator ->() { return get(); } + const T *operator ->() const { return get(); } + operator bool() const { return off; } +private: + int off; +}; + +template +hal_shmfield hal_make_shmfield(T *t) { + return hal_shmfield(t); +} + +static_assert(sizeof(hal_shmfield) == sizeof(int), "hal_shmfield size matches"); +#define SHMFIELD(type) hal_shmfield +#define SHMPTR(arg) ((arg).get()) +#define SHMOFF(ptr) (hal_make_shmfield(ptr)) +#else #define SHMFIELD(type) int /* SHMPTR(offset) converts 'offset' to a void pointer. */ @@ -151,6 +191,7 @@ RTAPI_END_DECLS false by design */ #define SHMCHK(ptr) ( ((char *)(ptr)) > (hal_shmem_base) && \ ((char *)(ptr)) < (hal_shmem_base + HAL_SIZE) ) +#endif /** The good news is that none of this linked list complexity is visible to the components that use this API. Complexity here From bd630e0a37154e42fe56b0b6b9e6358a03517ebc Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 20:16:00 -0500 Subject: [PATCH 07/13] halcmd: Make headers usable from C++ Signed-off-by: Jeff Epler --- src/hal/utils/halcmd.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/hal/utils/halcmd.h b/src/hal/utils/halcmd.h index f2fae1d40df..eedd699e491 100644 --- a/src/hal/utils/halcmd.h +++ b/src/hal/utils/halcmd.h @@ -41,6 +41,9 @@ #define HALCMD_H #include #include "hal.h" + +RTAPI_BEGIN_DECLS + extern int halcmd_startup(int quiet); extern void halcmd_shutdown(); extern int halcmd_parse_cmd(char * tokens[]); @@ -91,4 +94,6 @@ extern FILE *halcmd_inifile; #define MAX_CMD_LEN 1024 #define MAX_EXPECTED_SIGS 999 +RTAPI_END_DECLS + #endif From 6803de1995a35ccc27d44bbe0581d1fdf2601f00 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 20:29:18 -0500 Subject: [PATCH 08/13] halcmd: const-correctness fixes Signed-off-by: Jeff Epler --- src/hal/utils/halcmd.c | 6 +++--- src/hal/utils/halcmd_commands.c | 36 ++++++++++++++++----------------- src/hal/utils/halcmd_commands.h | 8 ++++---- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/hal/utils/halcmd.c b/src/hal/utils/halcmd.c index 1e4354594c8..630ed5334b9 100644 --- a/src/hal/utils/halcmd.c +++ b/src/hal/utils/halcmd.c @@ -188,7 +188,7 @@ static int compare_command(const void *namep, const void *commandp) { } -pid_t hal_systemv_nowait(char *const argv[]) { +pid_t hal_systemv_nowait(const char *const argv[]) { pid_t pid; int n; @@ -223,7 +223,7 @@ pid_t hal_systemv_nowait(char *const argv[]) { } rtapi_print_msg(RTAPI_MSG_DBG, "\n" ); /* call execv() to invoke command */ - execvp(argv[0], argv); + execvp(argv[0], (char * const *)argv); /* should never get here */ halcmd_error("execv(%s): %s\n", argv[0], strerror(errno) ); exit(1); @@ -235,7 +235,7 @@ pid_t hal_systemv_nowait(char *const argv[]) { return pid; } -int hal_systemv(char *const argv[]) { +int hal_systemv(const char *const argv[]) { pid_t pid; int status; int retval; diff --git a/src/hal/utils/halcmd_commands.c b/src/hal/utils/halcmd_commands.c index afe051d1ff1..b152eab4e07 100644 --- a/src/hal/utils/halcmd_commands.c +++ b/src/hal/utils/halcmd_commands.c @@ -83,8 +83,8 @@ static const char *pin_data_dir(int dir); static const char *param_data_dir(int dir); static const char *data_arrow1(int dir); static const char *data_arrow2(int dir); -static char *data_value(int type, void *valptr); -static char *data_value2(int type, void *valptr); +static const char *data_value(int type, void *valptr); +static const char *data_value2(int type, void *valptr); static void save_comps(FILE *dst); static void save_aliases(FILE *dst); static void save_signals(FILE *dst, int only_unlinked); @@ -1093,7 +1093,7 @@ int do_loadrt_cmd(char *mod_name, char *args[]) char arg_string[MAX_CMD_LEN+1]; int m=0, n=0, retval; hal_comp_t *comp; - char *argv[MAX_TOK+3]; + const char *argv[MAX_TOK+3]; char *cp1; #if defined(RTAPI_USPACE) argv[m++] = "-Wn"; @@ -1357,7 +1357,7 @@ int do_unloadrt_cmd(char *mod_name) static int unloadrt_comp(char *mod_name) { int retval; - char *argv[4]; + const char *argv[4]; #if defined(RTAPI_USPACE) argv[0] = EMC2_BIN_DIR "/rtapi_app"; @@ -1404,13 +1404,13 @@ int do_unload_cmd(char *mod_name) { } } -static char *guess_comp_name(char *prog_name) +static const char *guess_comp_name(const char *prog_name) { static char name[HAL_NAME_LEN+1]; - char *last_slash = strrchr(prog_name, '/'); - char *st = last_slash ? last_slash + 1 : prog_name; - char *last_dot = strrchr(st, '.'); - char *en = last_dot ? last_dot : prog_name + strlen(prog_name); + const char *last_slash = strrchr(prog_name, '/'); + const char *st = last_slash ? last_slash + 1 : prog_name; + const char *last_dot = strrchr(st, '.'); + const char *en = last_dot ? last_dot : prog_name + strlen(prog_name); size_t len = en-st; snprintf(name, sizeof(name), "%.*s", (int)len, st); @@ -1440,11 +1440,11 @@ is not fixed or has regressed by debian jessie) #endif } -int do_loadusr_cmd(char *args[]) +int do_loadusr_cmd(const char *args[]) { int wait_flag, wait_comp_flag, ignore_flag; - char *prog_name, *new_comp_name=NULL; - char *argv[MAX_TOK+1]; + const char *prog_name, *new_comp_name=NULL; + const char *argv[MAX_TOK+1]; int n, m, retval, status; pid_t pid; @@ -1464,7 +1464,7 @@ int do_loadusr_cmd(char *args[]) /* check for options (-w, -i, and/or -r) */ reset_getopt_state(); while (1) { - int c = getopt(argc, args, "+wWin:"); + int c = getopt(argc, (char * const *)args, "+wWin:"); if(c == -1) break; switch(c) { @@ -2341,9 +2341,9 @@ static const char *data_arrow2(int dir) /* Switch function to return var value for the print_*_list functions */ /* the value is printed in a 12 character wide field */ -static char *data_value(int type, void *valptr) +static const char *data_value(int type, void *valptr) { - char *value_str; + const char *value_str; static char buf[15]; switch (type) { @@ -2378,9 +2378,9 @@ static char *data_value(int type, void *valptr) /* Switch function to return var value in string form */ /* the value is printed as a packed string (no whitespace */ -static char *data_value2(int type, void *valptr) +static const char *data_value2(int type, void *valptr) { - char *value_str; + const char *value_str; static char buf[15]; switch (type) { @@ -2414,7 +2414,7 @@ static char *data_value2(int type, void *valptr) return value_str; } -int do_save_cmd(char *type, char *filename) +int do_save_cmd(const char *type, char *filename) { FILE *dst; diff --git a/src/hal/utils/halcmd_commands.h b/src/hal/utils/halcmd_commands.h index a8fc0b02bcb..63fbf44890d 100644 --- a/src/hal/utils/halcmd_commands.h +++ b/src/hal/utils/halcmd_commands.h @@ -82,13 +82,13 @@ extern int do_unlinkp_cmd(char *mod_name); extern int do_unload_cmd(char *mod_name); extern int do_unloadrt_cmd(char *mod_name); extern int do_unloadusr_cmd(char *mod_name); -extern int do_loadusr_cmd(char *args[]); +extern int do_loadusr_cmd(const char *args[]); extern int do_waitusr_cmd(char *comp_name); -extern int do_save_cmd(char *type, char *filename); +extern int do_save_cmd(const char *type, char *filename); extern int do_setexact_cmd(void); -pid_t hal_systemv_nowait(char *const argv[]); -int hal_systemv(char *const argv[]); +pid_t hal_systemv_nowait(const char *const argv[]); +int hal_systemv(const char *const argv[]); extern int scriptmode, comp_id; From 0702e669c440297edc0fbf14901b4f3c44df6bed Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 20:22:03 -0500 Subject: [PATCH 09/13] halcmd: use SHMFIELD() for next-pointers Signed-off-by: Jeff Epler --- src/hal/utils/halcmd_commands.c | 71 +++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/src/hal/utils/halcmd_commands.c b/src/hal/utils/halcmd_commands.c index b152eab4e07..7d4d432af1e 100644 --- a/src/hal/utils/halcmd_commands.c +++ b/src/hal/utils/halcmd_commands.c @@ -396,7 +396,7 @@ static int preflight_net_cmd(char *signal, hal_sig_t *sig, char *pins[]) { if(writers || bidirs) { hal_pin_t *pin; - int next; + SHMFIELD(hal_pin_t) next; for(next = hal_data->pin_list_ptr; next; next=pin->next_ptr) { pin = SHMPTR(next); @@ -1199,7 +1199,8 @@ int do_loadrt_cmd(char *mod_name, char *args[]) int do_delsig_cmd(char *mod_name) { - int next, retval, retval1, n; + SHMFIELD(hal_sig_t) next; + int retval, retval1, n; hal_sig_t *sig; char sigs[MAX_EXPECTED_SIGS][HAL_NAME_LEN+1]; @@ -1261,7 +1262,8 @@ int do_delsig_cmd(char *mod_name) int do_unloadusr_cmd(char *mod_name) { - int next, all; + SHMFIELD(hal_comp_t) next; + int all; hal_comp_t *comp; pid_t ourpid = getpid(); @@ -1292,7 +1294,8 @@ int do_unloadusr_cmd(char *mod_name) int do_unloadrt_cmd(char *mod_name) { - int next, retval, retval1, n, all; + SHMFIELD(hal_comp_t) next; + int retval, retval1, n, all; hal_comp_t *comp; char comps[64][HAL_NAME_LEN+1]; @@ -1632,7 +1635,7 @@ int do_waitusr_cmd(char *comp_name) static void print_comp_info(char **patterns) { - int next; + SHMFIELD(hal_comp_t) next; hal_comp_t *comp; if (scriptmode == 0) { @@ -1671,7 +1674,7 @@ static void print_comp_info(char **patterns) static void print_pin_info(int type, char **patterns) { - int next; + SHMFIELD(hal_pin_t) next; hal_pin_t *pin; hal_comp_t *comp; hal_sig_t *sig; @@ -1723,7 +1726,7 @@ static void print_pin_info(int type, char **patterns) static void print_pin_aliases(char **patterns) { - int next; + SHMFIELD(hal_pin_t) next; hal_oldname_t *oldname; hal_pin_t *pin; @@ -1754,7 +1757,7 @@ static void print_pin_aliases(char **patterns) static void print_sig_info(int type, char **patterns) { - int next; + SHMFIELD(hal_sig_t) next; hal_sig_t *sig; void *dptr; hal_pin_t *pin; @@ -1789,7 +1792,7 @@ static void print_sig_info(int type, char **patterns) static void print_script_sig_info(int type, char **patterns) { - int next; + SHMFIELD(hal_sig_t) next; hal_sig_t *sig; void *dptr; hal_pin_t *pin; @@ -1822,7 +1825,7 @@ static void print_script_sig_info(int type, char **patterns) static void print_param_info(int type, char **patterns) { - int next; + SHMFIELD(hal_param_t) next; hal_param_t *param; hal_comp_t *comp; @@ -1858,7 +1861,7 @@ static void print_param_info(int type, char **patterns) static void print_param_aliases(char **patterns) { - int next; + SHMFIELD(hal_param_t) next; hal_oldname_t *oldname; hal_param_t *param; @@ -1889,7 +1892,7 @@ static void print_param_aliases(char **patterns) static void print_funct_info(char **patterns) { - int next; + SHMFIELD(hal_funct_t) next; hal_funct_t *fptr; hal_comp_t *comp; @@ -1925,7 +1928,8 @@ static void print_funct_info(char **patterns) static void print_thread_info(char **patterns) { - int next_thread, n; + SHMFIELD(hal_thread_t) next_thread; + int n; hal_thread_t *tptr; hal_list_t *list_root, *list_entry; hal_funct_entry_t *fentry; @@ -2005,7 +2009,7 @@ static void print_thread_info(char **patterns) static void print_comp_names(char **patterns) { - int next; + SHMFIELD(hal_comp_t) next; hal_comp_t *comp; rtapi_mutex_get(&(hal_data->mutex)); @@ -2023,7 +2027,7 @@ static void print_comp_names(char **patterns) static void print_pin_names(char **patterns) { - int next; + SHMFIELD(hal_pin_t) next; hal_pin_t *pin; rtapi_mutex_get(&(hal_data->mutex)); @@ -2041,7 +2045,7 @@ static void print_pin_names(char **patterns) static void print_sig_names(char **patterns) { - int next; + SHMFIELD(hal_sig_t) next; hal_sig_t *sig; rtapi_mutex_get(&(hal_data->mutex)); @@ -2059,7 +2063,7 @@ static void print_sig_names(char **patterns) static void print_param_names(char **patterns) { - int next; + SHMFIELD(hal_param_t) next; hal_param_t *param; rtapi_mutex_get(&(hal_data->mutex)); @@ -2077,7 +2081,7 @@ static void print_param_names(char **patterns) static void print_funct_names(char **patterns) { - int next; + SHMFIELD(hal_funct_t) next; hal_funct_t *fptr; rtapi_mutex_get(&(hal_data->mutex)); @@ -2095,7 +2099,7 @@ static void print_funct_names(char **patterns) static void print_thread_names(char **patterns) { - int next_thread; + SHMFIELD(hal_thread_t) next_thread; hal_thread_t *tptr; rtapi_mutex_get(&(hal_data->mutex)); @@ -2149,7 +2153,7 @@ static int count_list(int list_root) static void print_mem_status() { - int active, recycled, next; + int active, recycled; hal_pin_t *pin; hal_param_t *param; @@ -2169,19 +2173,23 @@ static void print_mem_status() halcmd_output(" active/recycled parameters: %d/%d\n", active, recycled); // count aliases rtapi_mutex_get(&(hal_data->mutex)); - next = hal_data->pin_list_ptr; + { + SHMFIELD(hal_pin_t) next = hal_data->pin_list_ptr; active = 0; while (next != 0) { pin = SHMPTR(next); if ( pin->oldname != 0 ) active++; next = pin->next_ptr; } - next = hal_data->param_list_ptr; + } + { + SHMFIELD(hal_param_t) next = hal_data->param_list_ptr; while (next != 0) { param = SHMPTR(next); if ( param->oldname != 0 ) active++; next = param->next_ptr; } + } rtapi_mutex_give(&(hal_data->mutex)); recycled = count_list(hal_data->oldname_free_ptr); halcmd_output(" active/recycled aliases: %d/%d\n", active, recycled); @@ -2489,7 +2497,7 @@ int do_save_cmd(const char *type, char *filename) static void save_comps(FILE *dst) { - int next; + SHMFIELD(hal_comp_t) next; hal_comp_t *comp; fprintf(dst, "# components\n"); @@ -2543,13 +2551,14 @@ static void save_comps(FILE *dst) static void save_aliases(FILE *dst) { - int next; hal_pin_t *pin; hal_param_t *param; hal_oldname_t *oldname; fprintf(dst, "# pin aliases\n"); rtapi_mutex_get(&(hal_data->mutex)); + { + SHMFIELD(hal_pin_t) next; next = hal_data->pin_list_ptr; while (next != 0) { pin = SHMPTR(next); @@ -2560,7 +2569,10 @@ static void save_aliases(FILE *dst) } next = pin->next_ptr; } + } fprintf(dst, "# param aliases\n"); + { + SHMFIELD(hal_param_t) next; next = hal_data->param_list_ptr; while (next != 0) { param = SHMPTR(next); @@ -2571,12 +2583,13 @@ static void save_aliases(FILE *dst) } next = param->next_ptr; } + } rtapi_mutex_give(&(hal_data->mutex)); } static void save_signals(FILE *dst, int only_unlinked) { - int next; + SHMFIELD(hal_sig_t) next; hal_sig_t *sig; fprintf(dst, "# signals\n"); @@ -2592,7 +2605,7 @@ static void save_signals(FILE *dst, int only_unlinked) static void save_links(FILE *dst, int arrow) { - int next; + SHMFIELD(hal_pin_t) next; hal_pin_t *pin; hal_sig_t *sig; const char *arrow_str; @@ -2618,7 +2631,7 @@ static void save_links(FILE *dst, int arrow) static void save_nets(FILE *dst, int arrow) { - int next; + SHMFIELD(hal_sig_t) next; hal_pin_t *pin; hal_sig_t *sig; const char *arrow_str; @@ -2701,7 +2714,7 @@ static void save_nets(FILE *dst, int arrow) static void save_params(FILE *dst) { - int next; + SHMFIELD(hal_param_t) next; hal_param_t *param; fprintf(dst, "# parameter values\n"); @@ -2721,7 +2734,7 @@ static void save_params(FILE *dst) static void save_threads(FILE *dst) { - int next_thread; + SHMFIELD(hal_thread_t) next_thread; hal_thread_t *tptr; hal_list_t *list_root, *list_entry; hal_funct_entry_t *fentry; From 632fcbd3ddc67fbf55570874242cf0375ee89c3c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 20:23:20 -0500 Subject: [PATCH 10/13] halcmd: convert halcmd_commands to C++ Signed-off-by: Jeff Epler --- src/hal/utils/Submakefile | 8 ++++---- .../utils/{halcmd_commands.c => halcmd_commands.cc} | 11 ++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) rename src/hal/utils/{halcmd_commands.c => halcmd_commands.cc} (99%) diff --git a/src/hal/utils/Submakefile b/src/hal/utils/Submakefile index 2559c7ea578..b9933381d0f 100644 --- a/src/hal/utils/Submakefile +++ b/src/hal/utils/Submakefile @@ -1,5 +1,5 @@ -HALCMDSRCS := hal/utils/halcmd.c hal/utils/halcmd_commands.c hal/utils/halcmd_main.c -HALSHSRCS := hal/utils/halcmd.c hal/utils/halcmd_commands.c hal/utils/halsh.c +HALCMDSRCS := hal/utils/halcmd.c hal/utils/halcmd_commands.cc hal/utils/halcmd_main.c +HALSHSRCS := hal/utils/halcmd.c hal/utils/halcmd_commands.cc hal/utils/halsh.c ifneq ($(READLINE_LIBS),) HALCMDSRCS += hal/utils/halcmd_completion.c @@ -10,12 +10,12 @@ $(call TOOBJSDEPS, $(HALSHSRCS)) : EXTRAFLAGS = -fPIC $(call TOOBJSDEPS, hal/utils/halsh.c) : EXTRAFLAGS += $(TCL_CFLAGS) ../tcl/hal.so: $(call TOOBJS, $(HALSHSRCS)) ../lib/liblinuxcncini.so.0 ../lib/liblinuxcnchal.so.0 $(ECHO) Linking $(notdir $@) - $(Q)$(CC) $(LDFLAGS) -shared $^ $(TCL_LIBS) -o $@ + $(Q)$(CXX) $(LDFLAGS) -shared $^ $(TCL_LIBS) -o $@ TARGETS += ../tcl/hal.so ../bin/halcmd: $(call TOOBJS, $(HALCMDSRCS)) ../lib/liblinuxcncini.so.0 ../lib/liblinuxcnchal.so.0 $(ECHO) Linking $(notdir $@) - $(Q)$(CC) $(LDFLAGS) -o $@ $^ $(READLINE_LIBS) + $(Q)$(CXX) $(LDFLAGS) -o $@ $^ $(READLINE_LIBS) TARGETS += ../bin/halcmd HALRMTSRCS := hal/utils/halrmt.c diff --git a/src/hal/utils/halcmd_commands.c b/src/hal/utils/halcmd_commands.cc similarity index 99% rename from src/hal/utils/halcmd_commands.c rename to src/hal/utils/halcmd_commands.cc index 7d4d432af1e..85de58250fa 100644 --- a/src/hal/utils/halcmd_commands.c +++ b/src/hal/utils/halcmd_commands.cc @@ -75,7 +75,6 @@ static void print_param_names(char **patterns); static void print_funct_names(char **patterns); static void print_thread_names(char **patterns); static void print_lock_status(); -static int count_list(int list_root); static void print_mem_status(); static const char *data_type(int type); static const char *data_type2(int type); @@ -1173,7 +1172,7 @@ int do_loadrt_cmd(char *mod_name, char *args[]) strncat(arg_string, " ", MAX_CMD_LEN); } /* allocate HAL shmem for the string */ - cp1 = hal_malloc(strlen(arg_string)+1); + cp1 = (char*)hal_malloc(strlen(arg_string)+1); if ( cp1 == NULL ) { halcmd_error("failed to allocate memory for module args\n"); return -1; @@ -2136,16 +2135,18 @@ static void print_lock_status() halcmd_output(" HAL_LOCK_RUN - running/stopping HAL is locked\n"); } -static int count_list(int list_root) +template +int count_list(SHMFIELD(T) list_root) { - int n, next; + int n; + SHMFIELD(T) next; rtapi_mutex_get(&(hal_data->mutex)); next = list_root; n = 0; while (next != 0) { n++; - next = *((int *) SHMPTR(next)); + next = SHMPTR(next)->next_ptr; } rtapi_mutex_give(&(hal_data->mutex)); return n; From ae0b949d61fed06bba79949c95b6f3e18cc3b11b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 28 Jun 2016 20:58:07 -0500 Subject: [PATCH 11/13] halcmd: improve user feedback when loading components Now, when a component takes a long time to load, and other components load in the meantime, a diagnostic is shown on stderr of the form: While waiting for 'wrongname', component 'example' loaded. Did you specify the correct name via 'loadusr -Wn'? Signed-off-by: Jeff Epler --- src/hal/utils/halcmd_commands.cc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/hal/utils/halcmd_commands.cc b/src/hal/utils/halcmd_commands.cc index 85de58250fa..16d8c08b43d 100644 --- a/src/hal/utils/halcmd_commands.cc +++ b/src/hal/utils/halcmd_commands.cc @@ -1442,6 +1442,28 @@ is not fixed or has regressed by debian jessie) #endif } +#include +#include + +static std::set get_all_comp_names() { + std::set result; + for(auto comp = hal_data->comp_list_ptr; comp; comp=comp->next_ptr) { + result.insert(comp->name); + } + return result; +} + +static void warn_newly_loaded_comps(std::set &names, const char *newname) { + auto new_names = get_all_comp_names(); + for(const auto &name : new_names) { + if(name == newname) continue; + if(names.find(name) == names.end()) { + fprintf(stderr, "\nWhile waiting for '%s', component '%s' loaded.\nDid you specify the correct name via 'loadusr -Wn'?", newname, name.c_str()); + } + } + std::swap(new_names, names); +} + int do_loadusr_cmd(const char *args[]) { int wait_flag, wait_comp_flag, ignore_flag; @@ -1490,6 +1512,9 @@ int do_loadusr_cmd(const char *args[]) if(!new_comp_name) { new_comp_name = guess_comp_name(prog_name); } + + std::set comp_names_pre = get_all_comp_names(); + /* prepare to exec() the program */ argv[0] = prog_name; /* loop thru remaining arguments */ @@ -1539,9 +1564,11 @@ int do_loadusr_cmd(const char *args[]) if(count == 200) { fprintf(stderr, "Waiting for component '%s' to become ready.", new_comp_name); + warn_newly_loaded_comps(comp_names_pre, new_comp_name); fflush(stderr); } else if(count > 200 && count % 10 == 0) { fprintf(stderr, "."); + warn_newly_loaded_comps(comp_names_pre, new_comp_name); fflush(stderr); } } From 5d787ca38cede96c1a29ebd6be715caf1355a79e Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen Date: Fri, 15 Jul 2022 00:21:42 +0200 Subject: [PATCH 12/13] Update patch to the latest changes to master. --- src/hal/hal_priv.h | 10 ---------- src/hal/halmodule.cc | 22 +++++++++++----------- src/hal/utils/halcmd_commands.cc | 2 +- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/hal/hal_priv.h b/src/hal/hal_priv.h index f356cd4c3c9..04a9ae1fa06 100644 --- a/src/hal/hal_priv.h +++ b/src/hal/hal_priv.h @@ -202,16 +202,6 @@ static_assert(sizeof(hal_shmfield) == sizeof(int), "hal_shmfield size matc * PRIVATE HAL DATA STRUCTURES AND DECLARATIONS * ************************************************************************/ -/** HAL "data union" structure - ** This structure may hold any type of hal data -*/ -typedef union hal_data_u { - hal_bit_t b; - hal_s32_t s; - hal_u32_t u; - hal_float_t f; -} hal_data_u; - /** HAL "list element" data structure. This structure is used to implement generic double linked circular lists. Such lists have the following characteristics: diff --git a/src/hal/halmodule.cc b/src/hal/halmodule.cc index f5f413d3a52..3ad567f2bd5 100644 --- a/src/hal/halmodule.cc +++ b/src/hal/halmodule.cc @@ -865,7 +865,7 @@ PyObject *connect(PyObject *self, PyObject *args) { PyObject *disconnect(PyObject *self, PyObject *args) { char *pinname; if(!PyArg_ParseTuple(args, "s", &pinname)) return NULL; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -1008,7 +1008,7 @@ PyObject *get_value(PyObject *self, PyObject *args) { void *d_ptr; if(!PyArg_ParseTuple(args, "s", &name)) return NULL; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -1085,7 +1085,7 @@ PyObject *get_value(PyObject *self, PyObject *args) { /*######################################*/ /* Get a dict of pin info for all pins in system */ PyObject *get_info_pins(PyObject *self, PyObject *args) { - int next; + SHMFIELD(hal_pin_t) next; int type; char str_n[] = "NAME"; char str_v[] = "VALUE"; @@ -1099,7 +1099,7 @@ PyObject *get_info_pins(PyObject *self, PyObject *args) { PyObject* python_list = PyList_New(0); PyObject *obj; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -1109,7 +1109,7 @@ PyObject *get_info_pins(PyObject *self, PyObject *args) { rtapi_mutex_get(&(hal_data->mutex)); next = hal_data->pin_list_ptr; while (next != 0) { - pin = (hal_pin_t*)SHMPTR(next); + pin = SHMPTR(next); type = pin->type; if (pin->signal != 0) { sig = (hal_sig_t*)SHMPTR(pin->signal); @@ -1174,7 +1174,7 @@ PyObject *get_info_pins(PyObject *self, PyObject *args) { /*######################################*/ /* Get a dict of signal info for all signals in system */ PyObject *get_info_signals(PyObject *self, PyObject *args) { - int next; + SHMFIELD(hal_sig_t) next; int type; char str_n[] = "NAME"; char str_v[] = "VALUE"; @@ -1186,7 +1186,7 @@ PyObject *get_info_signals(PyObject *self, PyObject *args) { PyObject* python_list = PyList_New(0); PyObject *obj; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -1196,7 +1196,7 @@ PyObject *get_info_signals(PyObject *self, PyObject *args) { rtapi_mutex_get(&(hal_data->mutex)); next = hal_data->sig_list_ptr; while (next != 0) { - sig = (hal_sig_t*)SHMPTR(next); + sig = SHMPTR(next); type = sig->type; d_ptr = SHMPTR(sig->data_ptr); @@ -1259,7 +1259,7 @@ PyObject *get_info_signals(PyObject *self, PyObject *args) { /*######################################*/ /* Get a dict of parameter info for all parameters in system */ PyObject *get_info_params(PyObject *self, PyObject *args) { - int next; + SHMFIELD(hal_param_t) next; int type; char str_n[] = "NAME"; char str_v[] = "VALUE"; @@ -1269,7 +1269,7 @@ PyObject *get_info_params(PyObject *self, PyObject *args) { PyObject* python_list = PyList_New(0); PyObject *obj; - if(!SHMPTR(0)) { + if(!hal_shmem_base) { PyErr_Format(PyExc_RuntimeError, "Cannot call before creating component"); return NULL; @@ -1279,7 +1279,7 @@ PyObject *get_info_params(PyObject *self, PyObject *args) { rtapi_mutex_get(&(hal_data->mutex)); next = hal_data->param_list_ptr; while (next != 0) { - param = (hal_param_t*)SHMPTR(next); + param = SHMPTR(next); type = param->type; d_ptr = SHMPTR(param->data_ptr); diff --git a/src/hal/utils/halcmd_commands.cc b/src/hal/utils/halcmd_commands.cc index 16d8c08b43d..a7be6cd1fb8 100644 --- a/src/hal/utils/halcmd_commands.cc +++ b/src/hal/utils/halcmd_commands.cc @@ -2791,7 +2791,7 @@ static void save_unconnected_input_pin_values(FILE *dst) { hal_pin_t *pin; void *dptr; - int next; + SHMFIELD(hal_pin_t) next; fprintf(dst, "# unconnected pin values\n"); for(next = hal_data->pin_list_ptr; next; next=pin->next_ptr) { From ac4308e9827a1e71d3ac054bf1764b6397b6fa9b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 20 Jul 2022 22:02:34 -0500 Subject: [PATCH 13/13] Use correct type In the main branch, the type of these fields was updated from 'int' to 'rtapi_intptr_t'. On 64-bit systems, this led to most HAL operations crashing. --- src/hal/hal_priv.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hal/hal_priv.h b/src/hal/hal_priv.h index 04a9ae1fa06..4501567b6cb 100644 --- a/src/hal/hal_priv.h +++ b/src/hal/hal_priv.h @@ -162,7 +162,7 @@ class hal_shmfield { const T *operator ->() const { return get(); } operator bool() const { return off; } private: - int off; + rtapi_intptr_t off; }; template @@ -170,13 +170,13 @@ hal_shmfield hal_make_shmfield(T *t) { return hal_shmfield(t); } -static_assert(sizeof(hal_shmfield) == sizeof(int), "hal_shmfield size matches"); +static_assert(sizeof(hal_shmfield) == sizeof(rtapi_intptr_t), "hal_shmfield size matches"); #define SHMFIELD(type) hal_shmfield #define SHMPTR(arg) ((arg).get()) #define SHMOFF(ptr) (hal_make_shmfield(ptr)) #else -#define SHMFIELD(type) int +#define SHMFIELD(type) rtapi_intptr_t /* SHMPTR(offset) converts 'offset' to a void pointer. */ #define SHMPTR(offset) ( (void *)( hal_shmem_base + (offset) ) )