Skip to content

Commit e016dc0

Browse files
authored
Merge pull request #98 from LinuxCNC/jepler/master/halcmd-cplusplus
Improve the 'halcmd loadusr' message when component is failing to load
2 parents 2c302c2 + 9b390cd commit e016dc0

7 files changed

Lines changed: 271 additions & 171 deletions

File tree

src/hal/hal_priv.h

Lines changed: 144 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,89 @@
9494

9595
#include <rtapi.h>
9696
#include <rtapi_mutex.h>
97+
98+
/* IMPORTANT: If any of the structures in this file are changed, the
99+
version code (HAL_VER) must be incremented, to ensure that
100+
incompatible utilities, etc, aren't used to manipulate data in
101+
shared memory.
102+
*/
103+
104+
/* Historical note: in versions 2.0.0 and 2.0.1 of EMC, the key was
105+
0x48414C21, and instead of the structure starting with a version
106+
number, it started with a fixed magic number. Mixing binaries or
107+
kernel modules from those releases with newer versions will result
108+
in two shmem regions being open, and really strange results (but
109+
should _not_ result in segfaults or other crash type problems).
110+
This is unfortunate, but I can't retroactively make the old code
111+
detect version mismatches. The alternative is worse: if the new
112+
code used the same shmem key, the result would be segfaults or
113+
kernel oopses.
114+
115+
The use of version codes means that any subsequent changes to
116+
the structs will be fully protected, with a clean shutdown and
117+
meaningfull error messages in case of a mismatch.
118+
*/
119+
120+
#define HAL_KEY 0x48414C32 /* key used to open HAL shared memory */
121+
#define HAL_VER 0x00000010 /* version code */
122+
#define HAL_SIZE (256*4096)
123+
#define HAL_PSEUDO_COMP_PREFIX "__" /* prefix to identify a pseudo component */
124+
125+
/* These pointers are set by hal_init() to point to the shmem block
126+
and to the master data structure. All access should use these
127+
pointers, they takes into account the mapping of shared memory
128+
into either kernel or user space. (The HAL kernel module and
129+
each HAL user process have their own copy of these vars,
130+
initialized to match that process's memory mapping.)
131+
*/
132+
97133
RTAPI_BEGIN_DECLS
134+
extern char *hal_shmem_base;
135+
extern struct hal_data_t *hal_data;
136+
RTAPI_END_DECLS
137+
138+
#ifdef __cplusplus
139+
template<class T>
140+
bool hal_shmchk(T *t) {
141+
char *c = (char*)t;
142+
return c > hal_shmem_base && c < hal_shmem_base + HAL_SIZE;
143+
}
144+
145+
template<class T>
146+
int hal_shmoff(T *t) { return t ? (char*)t - hal_shmem_base : 0; }
147+
148+
template<class T>
149+
T *hal_shmptr(int p) { return p ? (T*)(hal_shmem_base + p) : nullptr; }
150+
151+
template<class T>
152+
class hal_shmfield {
153+
public:
154+
hal_shmfield() : off{} {}
155+
hal_shmfield(T *t) : off{hal_shmoff(t)} {}
156+
hal_shmfield &operator=(T *t) { off = hal_shmoff(t); }
157+
T *get() { return hal_shmptr<T>(off); }
158+
const T *get() const { return hal_shmptr<T>(off); }
159+
T *operator *() { return get(); }
160+
const T *operator *() const { return get(); }
161+
T *operator ->() { return get(); }
162+
const T *operator ->() const { return get(); }
163+
operator bool() const { return off; }
164+
private:
165+
rtapi_intptr_t off;
166+
};
167+
168+
template<class T>
169+
hal_shmfield<T> hal_make_shmfield(T *t) {
170+
return hal_shmfield<T>(t);
171+
}
172+
173+
static_assert(sizeof(hal_shmfield<void>) == sizeof(rtapi_intptr_t), "hal_shmfield size matches");
174+
175+
#define SHMFIELD(type) hal_shmfield<type>
176+
#define SHMPTR(arg) ((arg).get())
177+
#define SHMOFF(ptr) (hal_make_shmfield(ptr))
178+
#else
179+
#define SHMFIELD(type) rtapi_intptr_t
98180

99181
/* SHMPTR(offset) converts 'offset' to a void pointer. */
100182
#define SHMPTR(offset) ( (void *)( hal_shmem_base + (offset) ) )
@@ -109,6 +191,7 @@ RTAPI_BEGIN_DECLS
109191
false by design */
110192
#define SHMCHK(ptr) ( ((char *)(ptr)) > (hal_shmem_base) && \
111193
((char *)(ptr)) < (hal_shmem_base + HAL_SIZE) )
194+
#endif
112195

113196
/** The good news is that none of this linked list complexity is
114197
visible to the components that use this API. Complexity here
@@ -130,20 +213,28 @@ RTAPI_BEGIN_DECLS
130213
This structure has no data, only links. To use it, include it
131214
inside a larger structure.
132215
*/
133-
typedef struct {
134-
rtapi_intptr_t next; /* next element in list */
135-
rtapi_intptr_t prev; /* previous element in list */
216+
typedef struct hal_list_t {
217+
SHMFIELD(hal_list_t) next; /* next element in list */
218+
SHMFIELD(hal_list_t) prev; /* previous element in list */
136219
} hal_list_t;
137220

138221
/** HAL "oldname" data structure.
139222
When a pin or parameter gets an alias, this structure is used to
140223
store the original name.
141224
*/
142-
typedef struct {
143-
rtapi_intptr_t next_ptr; /* next struct (used for free list only) */
225+
typedef struct hal_oldname_t {
226+
SHMFIELD(hal_oldname_t) next_ptr; /* next struct (used for free list only) */
144227
char name[HAL_NAME_LEN + 1]; /* the original name */
145228
} hal_oldname_t;
146229

230+
typedef struct hal_comp_t hal_comp_t;
231+
typedef struct hal_pin_t hal_pin_t;
232+
typedef struct hal_sig_t hal_sig_t;
233+
typedef struct hal_param_t hal_param_t;
234+
typedef struct hal_funct_t hal_funct_t;
235+
typedef struct hal_funct_entry_t hal_funct_entry_t;
236+
typedef struct hal_thread_t hal_thread_t;
237+
147238
/* Master HAL data structure
148239
There is a single instance of this structure in the machine.
149240
It resides at the base of the HAL shared memory block, where it
@@ -152,7 +243,7 @@ typedef struct {
152243
in the area, as well as some housekeeping data. It is the root
153244
structure for all data in the HAL.
154245
*/
155-
typedef struct {
246+
typedef struct hal_data_t {
156247
int version; /* version code for structs, etc */
157248
rtapi_mutex_t mutex; /* protection for linked lists, etc. */
158249
hal_s32_t shmem_avail; /* amount of shmem left free */
@@ -162,24 +253,24 @@ typedef struct {
162253
/* prefix of name for new instance */
163254
char constructor_arg[HAL_NAME_LEN+1];
164255
/* prefix of name for new instance */
165-
rtapi_intptr_t shmem_bot; /* bottom of free shmem (first free byte) */
166-
rtapi_intptr_t shmem_top; /* top of free shmem (1 past last free) */
167-
rtapi_intptr_t comp_list_ptr; /* root of linked list of components */
168-
rtapi_intptr_t pin_list_ptr; /* root of linked list of pins */
169-
rtapi_intptr_t sig_list_ptr; /* root of linked list of signals */
170-
rtapi_intptr_t param_list_ptr; /* root of linked list of parameters */
171-
rtapi_intptr_t funct_list_ptr; /* root of linked list of functions */
172-
rtapi_intptr_t thread_list_ptr; /* root of linked list of threads */
256+
int shmem_bot; /* bottom of free shmem (first free byte) */
257+
int shmem_top; /* top of free shmem (1 past last free) */
258+
SHMFIELD(hal_comp_t) comp_list_ptr; /* root of linked list of components */
259+
SHMFIELD(hal_pin_t) pin_list_ptr; /* root of linked list of pins */
260+
SHMFIELD(hal_sig_t) sig_list_ptr; /* root of linked list of signals */
261+
SHMFIELD(hal_param_t) param_list_ptr; /* root of linked list of parameters */
262+
SHMFIELD(hal_funct_t) funct_list_ptr; /* root of linked list of functions */
263+
SHMFIELD(hal_thread_t) thread_list_ptr; /* root of linked list of threads */
173264
long base_period; /* timer period for realtime tasks */
174265
int threads_running; /* non-zero if threads are started */
175-
rtapi_intptr_t oldname_free_ptr; /* list of free oldname structs */
176-
rtapi_intptr_t comp_free_ptr; /* list of free component structs */
177-
rtapi_intptr_t pin_free_ptr; /* list of free pin structs */
178-
rtapi_intptr_t sig_free_ptr; /* list of free signal structs */
179-
rtapi_intptr_t param_free_ptr; /* list of free parameter structs */
180-
rtapi_intptr_t funct_free_ptr; /* list of free function structs */
266+
SHMFIELD(hal_oldname_t) oldname_free_ptr; /* list of free oldname structs */
267+
SHMFIELD(hal_comp_t) comp_free_ptr; /* list of free component structs */
268+
SHMFIELD(hal_pin_t) pin_free_ptr; /* list of free pin structs */
269+
SHMFIELD(hal_sig_t) sig_free_ptr; /* list of free signal structs */
270+
SHMFIELD(hal_param_t) param_free_ptr; /* list of free parameter structs */
271+
SHMFIELD(hal_funct_t) funct_free_ptr; /* list of free function structs */
181272
hal_list_t funct_entry_free; /* list of free funct entry structs */
182-
rtapi_intptr_t thread_free_ptr; /* list of free thread structs */
273+
SHMFIELD(hal_thread_t) thread_free_ptr; /* list of free thread structs */
183274
int exact_base_period; /* if set, pretend that rtapi satisfied our
184275
period request exactly */
185276
unsigned char lock; /* hal locking, can be one of the HAL_LOCK_* types */
@@ -200,8 +291,8 @@ typedef enum {
200291
An instance of this structure is added to a linked list when the
201292
component calls hal_init().
202293
*/
203-
typedef struct {
204-
rtapi_intptr_t next_ptr; /* next component in the list */
294+
struct hal_comp_t {
295+
SHMFIELD(hal_comp_t) next_ptr; /* next component in the list */
205296
int comp_id; /* component ID (RTAPI module id) */
206297
int mem_id; /* RTAPI shmem ID used by this comp */
207298
component_type_t type;
@@ -210,49 +301,49 @@ typedef struct {
210301
void *shmem_base; /* base of shmem for this component */
211302
char name[HAL_NAME_LEN + 1]; /* component name */
212303
constructor make;
213-
int insmod_args; /* args passed to insmod when loaded */
214-
} hal_comp_t;
304+
SHMFIELD(char) insmod_args; /* args passed to insmod when loaded */
305+
};
215306

216307
/** HAL 'pin' data structure.
217308
This structure contains information about a 'pin' object.
218309
*/
219-
typedef struct {
220-
rtapi_intptr_t next_ptr; /* next pin in linked list */
221-
int data_ptr_addr; /* address of pin data pointer */
222-
int owner_ptr; /* component that owns this pin */
223-
int signal; /* signal to which pin is linked */
310+
struct hal_pin_t {
311+
SHMFIELD(hal_pin_t) next_ptr; /* next pin in linked list */
312+
SHMFIELD(void*) data_ptr_addr; /* address of pin data pointer */
313+
SHMFIELD(hal_comp_t) owner_ptr; /* component that owns this pin */
314+
SHMFIELD(hal_sig_t) signal; /* signal to which pin is linked */
224315
hal_data_u dummysig; /* if unlinked, data_ptr points here */
225-
int oldname; /* old name if aliased, else zero */
316+
SHMFIELD(hal_oldname_t) oldname; /* old name if aliased, else zero */
226317
hal_type_t type; /* data type */
227318
hal_pin_dir_t dir; /* pin direction */
228319
char name[HAL_NAME_LEN + 1]; /* pin name */
229-
} hal_pin_t;
320+
};
230321

231322
/** HAL 'signal' data structure.
232323
This structure contains information about a 'signal' object.
233324
*/
234-
typedef struct {
235-
rtapi_intptr_t next_ptr; /* next signal in linked list */
236-
int data_ptr; /* offset of signal value */
325+
struct hal_sig_t {
326+
SHMFIELD(hal_sig_t) next_ptr; /* next signal in linked list */
327+
SHMFIELD(void*) data_ptr; /* offset of signal value */
237328
hal_type_t type; /* data type */
238329
int readers; /* number of input pins linked */
239330
int writers; /* number of output pins linked */
240331
int bidirs; /* number of I/O pins linked */
241332
char name[HAL_NAME_LEN + 1]; /* signal name */
242-
} hal_sig_t;
333+
};
243334

244335
/** HAL 'parameter' data structure.
245336
This structure contains information about a 'parameter' object.
246337
*/
247-
typedef struct {
248-
rtapi_intptr_t next_ptr; /* next parameter in linked list */
249-
int data_ptr; /* offset of parameter value */
250-
int owner_ptr; /* component that owns this signal */
251-
int oldname; /* old name if aliased, else zero */
338+
struct hal_param_t {
339+
SHMFIELD(hal_param_t) next_ptr; /* next parameter in linked list */
340+
SHMFIELD(void*) data_ptr; /* offset of parameter value */
341+
SHMFIELD(hal_comp_t) owner_ptr; /* component that owns this signal */
342+
SHMFIELD(hal_oldname_t) oldname; /* old name if aliased, else zero */
252343
hal_type_t type; /* data type */
253344
hal_param_dir_t dir; /* data direction */
254345
char name[HAL_NAME_LEN + 1]; /* parameter name */
255-
} hal_param_t;
346+
};
256347

257348
/** the HAL uses functions and threads to handle synchronization of
258349
code. In general, most control systems need to read inputs,
@@ -270,10 +361,10 @@ typedef struct {
270361
that identify the functions connected to that thread.
271362
*/
272363

273-
typedef struct {
274-
rtapi_intptr_t next_ptr; /* next function in linked list */
364+
struct hal_funct_t {
365+
SHMFIELD(hal_funct_t) next_ptr; /* next function in linked list */
275366
int uses_fp; /* floating point flag */
276-
int owner_ptr; /* component that added this funct */
367+
SHMFIELD(hal_comp_t) owner_ptr; /* component that added this funct */
277368
int reentrant; /* non-zero if function is re-entrant */
278369
int users; /* number of threads using function */
279370
void *arg; /* argument for function */
@@ -282,19 +373,19 @@ typedef struct {
282373
hal_s32_t maxtime; /* (param) duration of longest run, in CPU cycles */
283374
hal_bit_t maxtime_increased; /* on last call, maxtime increased */
284375
char name[HAL_NAME_LEN + 1]; /* function name */
285-
} hal_funct_t;
376+
};
286377

287-
typedef struct {
378+
struct hal_funct_entry_t {
288379
hal_list_t links; /* linked list data */
289380
void *arg; /* argument for function */
290381
void (*funct) (void *, long); /* ptr to function code */
291-
int funct_ptr; /* pointer to function */
292-
} hal_funct_entry_t;
382+
SHMFIELD(hal_funct_t) funct_ptr; /* pointer to function */
383+
};
293384

294385
#define HAL_STACKSIZE 16384 /* realtime task stacksize */
295386

296-
typedef struct {
297-
rtapi_intptr_t next_ptr; /* next thread in linked list */
387+
struct hal_thread_t {
388+
SHMFIELD(hal_thread_t) next_ptr; /* next thread in linked list */
298389
int uses_fp; /* floating point flag */
299390
long int period; /* period of the thread, in nsec */
300391
int priority; /* priority of the thread */
@@ -304,50 +395,13 @@ typedef struct {
304395
hal_list_t funct_list; /* list of functions to run */
305396
char name[HAL_NAME_LEN + 1]; /* thread name */
306397
int comp_id;
307-
} hal_thread_t;
308-
309-
/* IMPORTANT: If any of the structures in this file are changed, the
310-
version code (HAL_VER) must be incremented, to ensure that
311-
incompatible utilities, etc, aren't used to manipulate data in
312-
shared memory.
313-
*/
314-
315-
/* Historical note: in versions 2.0.0 and 2.0.1 of EMC, the key was
316-
0x48414C21, and instead of the structure starting with a version
317-
number, it started with a fixed magic number. Mixing binaries or
318-
kernel modules from those releases with newer versions will result
319-
in two shmem regions being open, and really strange results (but
320-
should _not_ result in segfaults or other crash type problems).
321-
This is unfortunate, but I can't retroactively make the old code
322-
detect version mismatches. The alternative is worse: if the new
323-
code used the same shmem key, the result would be segfaults or
324-
kernel oopses.
325-
326-
The use of version codes means that any subsequent changes to
327-
the structs will be fully protected, with a clean shutdown and
328-
meaningful error messages in case of a mismatch.
329-
*/
330-
331-
#define HAL_KEY 0x48414C32 /* key used to open HAL shared memory */
332-
#define HAL_VER 0x00000010 /* version code */
333-
#define HAL_SIZE (256*4096)
334-
#define HAL_PSEUDO_COMP_PREFIX "__" /* prefix to identify a pseudo component */
335-
336-
/* These pointers are set by hal_init() to point to the shmem block
337-
and to the master data structure. All access should use these
338-
pointers, they takes into account the mapping of shared memory
339-
into either kernel or user space. (The HAL kernel module and
340-
each HAL user process have their own copy of these vars,
341-
initialized to match that process's memory mapping.)
342-
*/
343-
344-
extern char *hal_shmem_base;
345-
extern hal_data_t *hal_data;
398+
};
346399

347400
/***********************************************************************
348401
* PRIVATE HAL FUNCTIONS - NOT PART OF THE API *
349402
************************************************************************/
350403

404+
RTAPI_BEGIN_DECLS
351405
/** None of these functions get or release any mutex. They all assume
352406
that the mutex has already been obtained. Calling them without
353407
having the mutex may give incorrect results if other processes are

0 commit comments

Comments
 (0)