Skip to content

Commit 8013f3b

Browse files
committed
refactor hal_struct to use a dedicated namespace
Replace the param-backed implementation with a proper struct namespace inside HAL shmem. hal_struct_newf now maintains its own linked list (struct_list_ptr / struct_free_ptr in hal_data_t), sorted by name, entirely separate from pins, signals, and parameters. hal_struct_attach increments attach_count; hal_struct_detach decrements it, making detach a meaningful operation. No hal_param_s32_new call anywhere in the new path. HAL_VER bumped to 0x11 for the hal_data_t layout change.
1 parent 970857b commit 8013f3b

3 files changed

Lines changed: 166 additions & 43 deletions

File tree

src/hal/hal.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -985,18 +985,22 @@ extern void hal_stream_wait_writable(hal_stream_t *stream, sig_atomic_t *stop);
985985

986986

987987
/** Named struct API
988+
*
989+
* Structs live in their own namespace inside HAL shmem, separate from
990+
* pins, signals, and parameters. They are not visible in halcmd show pin/
991+
* param/sig output.
988992
*
989993
* hal_struct_newf() allocates 'size' bytes in HAL shmem, optionally
990-
* initialises it from 'defval' (or zeroes if NULL), and registers a HAL_RO
991-
* s32 param named according to the printf-style format so that the data can
992-
* be found by name from any process that has HAL shmem mapped.
994+
* initialises it from 'defval' (or zeroes if NULL), and registers the blob
995+
* in the struct namespace under the printf-style name. Must be called
996+
* before hal_ready().
993997
*
994-
* hal_struct_attach() resolves a name previously registered by
995-
* hal_struct_newf() and sets *memptr to point at the data. May be called
996-
* from both RT and userspace after hal_init().
998+
* hal_struct_attach() finds an entry by name, increments its reference
999+
* count, and sets *memptr to point at the data. May be called from both
1000+
* RT and userspace after hal_init().
9971001
*
998-
* hal_struct_detach() is a no-op; HAL shmem lifetime is managed by the
999-
* creating component.
1002+
* hal_struct_detach() decrements the reference count. The data itself
1003+
* lives for the lifetime of the HAL shmem block.
10001004
*/
10011005
extern int hal_struct_newf(int comp_id, long int size, const void *defval,
10021006
const char *fmt, ...)

src/hal/hal_lib.c

Lines changed: 138 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ hal_comp_t *halpr_alloc_comp_struct(void);
128128
static hal_pin_t *alloc_pin_struct(void);
129129
static hal_sig_t *alloc_sig_struct(void);
130130
static hal_param_t *alloc_param_struct(void);
131+
static hal_struct_entry_t *alloc_struct_entry(void);
132+
static void free_struct_entry(hal_struct_entry_t *p);
131133
static hal_oldname_t *halpr_alloc_oldname_struct(void);
132134
#ifdef RTAPI
133135
static hal_funct_t *alloc_funct_struct(void);
@@ -2688,6 +2690,23 @@ hal_param_t *halpr_find_param_by_name(const char *name)
26882690
return 0;
26892691
}
26902692

2693+
hal_struct_entry_t *halpr_find_struct_by_name(const char *name)
2694+
{
2695+
int next;
2696+
hal_struct_entry_t *entry;
2697+
2698+
/* search struct list for 'name' */
2699+
next = hal_data->struct_list_ptr;
2700+
while (next != 0) {
2701+
entry = SHMPTR(next);
2702+
if (strcmp(entry->name, name) == 0) {
2703+
return entry;
2704+
}
2705+
next = entry->next_ptr;
2706+
}
2707+
return 0;
2708+
}
2709+
26912710
hal_thread_t *halpr_find_thread_by_name(const char *name)
26922711
{
26932712
int next;
@@ -3084,6 +3103,7 @@ static int init_hal_data(void)
30843103
hal_data->pin_list_ptr = 0;
30853104
hal_data->sig_list_ptr = 0;
30863105
hal_data->param_list_ptr = 0;
3106+
hal_data->struct_list_ptr = 0;
30873107
hal_data->funct_list_ptr = 0;
30883108
hal_data->thread_list_ptr = 0;
30893109
hal_data->base_period = 0;
@@ -3093,6 +3113,7 @@ static int init_hal_data(void)
30933113
hal_data->pin_free_ptr = 0;
30943114
hal_data->sig_free_ptr = 0;
30953115
hal_data->param_free_ptr = 0;
3116+
hal_data->struct_free_ptr = 0;
30963117
hal_data->funct_free_ptr = 0;
30973118
hal_data->pending_constructor = 0;
30983119
hal_data->constructor_prefix[0] = 0;
@@ -3285,6 +3306,34 @@ static hal_param_t *alloc_param_struct(void)
32853306
return p;
32863307
}
32873308

3309+
static hal_struct_entry_t *alloc_struct_entry(void)
3310+
{
3311+
hal_struct_entry_t *p;
3312+
3313+
/* check the free list */
3314+
if (hal_data->struct_free_ptr != 0) {
3315+
p = SHMPTR(hal_data->struct_free_ptr);
3316+
hal_data->struct_free_ptr = p->next_ptr;
3317+
p->next_ptr = 0;
3318+
} else {
3319+
p = shmalloc_dn(sizeof(hal_struct_entry_t));
3320+
}
3321+
if (p) {
3322+
p->next_ptr = 0;
3323+
p->owner_ptr = 0;
3324+
p->data_ptr = 0;
3325+
p->attach_count = 0;
3326+
p->name[0] = '\0';
3327+
}
3328+
return p;
3329+
}
3330+
3331+
static void free_struct_entry(hal_struct_entry_t *p)
3332+
{
3333+
p->next_ptr = hal_data->struct_free_ptr;
3334+
hal_data->struct_free_ptr = SHMOFF(p);
3335+
}
3336+
32883337
static hal_oldname_t *halpr_alloc_oldname_struct(void)
32893338
{
32903339
hal_oldname_t *p;
@@ -4356,19 +4405,20 @@ int hal_stream_num_underruns(hal_stream_t *stream) {
43564405
}
43574406

43584407
/* ========================================================================
4359-
* Named struct API — allocates an opaque blob in HAL shmem and makes it
4360-
* discoverable by name. The blob is registered as a HAL_RO s32 param
4361-
* whose value is the shmem offset of the data; hal_struct_attach() resolves
4362-
* that offset back to a pointer. No new shmem segment is created — the
4363-
* allocation lives inside the existing HAL shmem block.
4408+
* Named struct API — allocates an opaque blob in HAL shmem and registers
4409+
* it in a dedicated struct namespace, separate from pins, signals, and
4410+
* parameters. The struct list in hal_data tracks all entries by name and
4411+
* maintains a reference count so hal_struct_detach() is meaningful.
43644412
* ======================================================================== */
43654413

43664414
int hal_struct_newf(int comp_id, long int size, const void *defval,
43674415
const char *fmt, ...)
43684416
{
43694417
char name[HAL_NAME_LEN + 1];
4370-
int sz;
4371-
hal_s32_t *offset_holder;
4418+
int sz, cmp;
4419+
hal_comp_t *comp;
4420+
hal_struct_entry_t *new_entry, *ptr;
4421+
rtapi_intptr_t *prev, next;
43724422
void *data;
43734423
va_list ap;
43744424

@@ -4380,18 +4430,36 @@ int hal_struct_newf(int comp_id, long int size, const void *defval,
43804430
"HAL: hal_struct_newf: name too long\n");
43814431
return -ENOMEM;
43824432
}
4433+
if (hal_data == 0) {
4434+
rtapi_print_msg(RTAPI_MSG_ERR,
4435+
"HAL: hal_struct_newf called before init\n");
4436+
return -EINVAL;
4437+
}
4438+
4439+
rtapi_mutex_get(&(hal_data->mutex));
4440+
4441+
comp = halpr_find_comp_by_id(comp_id);
4442+
if (!comp) {
4443+
rtapi_mutex_give(&(hal_data->mutex));
4444+
rtapi_print_msg(RTAPI_MSG_ERR,
4445+
"HAL: hal_struct_newf: component %d not found\n", comp_id);
4446+
return -EINVAL;
4447+
}
43834448

4384-
/* Allocate s32 to hold the shmem offset of the data */
4385-
offset_holder = (hal_s32_t *)hal_malloc(sizeof(hal_s32_t));
4386-
if (!offset_holder) {
4449+
/* Allocate the entry metadata (from shmalloc_dn, no extra mutex needed) */
4450+
new_entry = alloc_struct_entry();
4451+
if (!new_entry) {
4452+
rtapi_mutex_give(&(hal_data->mutex));
43874453
rtapi_print_msg(RTAPI_MSG_ERR,
4388-
"HAL: hal_struct_newf: can't allocate offset holder\n");
4454+
"HAL: hal_struct_newf: insufficient memory for entry '%s'\n", name);
43894455
return -ENOMEM;
43904456
}
43914457

4392-
/* Allocate the struct data — hal_malloc aligns by size */
4393-
data = hal_malloc(size);
4458+
/* Allocate the data blob (shmalloc_up, mutex already held) */
4459+
data = shmalloc_up(size);
43944460
if (!data) {
4461+
free_struct_entry(new_entry);
4462+
rtapi_mutex_give(&(hal_data->mutex));
43954463
rtapi_print_msg(RTAPI_MSG_ERR,
43964464
"HAL: hal_struct_newf: can't allocate %ld bytes for '%s'\n",
43974465
size, name);
@@ -4403,18 +4471,45 @@ int hal_struct_newf(int comp_id, long int size, const void *defval,
44034471
else
44044472
memset(data, 0, (size_t)size);
44054473

4406-
/* Store offset so hal_struct_attach can find the data */
4407-
*offset_holder = (hal_s32_t)(((char *)data) - hal_shmem_base);
4474+
/* Fill in the entry */
4475+
new_entry->owner_ptr = SHMOFF(comp);
4476+
new_entry->data_ptr = SHMOFF(data);
4477+
new_entry->attach_count = 0;
4478+
rtapi_snprintf(new_entry->name, sizeof(new_entry->name), "%s", name);
44084479

4409-
/* Register as a HAL param so the name is in the HAL namespace */
4410-
return hal_param_s32_new(name, HAL_RO, offset_holder, comp_id);
4480+
/* Insert into struct list, sorted by name */
4481+
prev = &(hal_data->struct_list_ptr);
4482+
next = *prev;
4483+
while (1) {
4484+
if (next == 0) {
4485+
new_entry->next_ptr = next;
4486+
*prev = SHMOFF(new_entry);
4487+
rtapi_mutex_give(&(hal_data->mutex));
4488+
return 0;
4489+
}
4490+
ptr = SHMPTR(next);
4491+
cmp = strcmp(ptr->name, new_entry->name);
4492+
if (cmp > 0) {
4493+
new_entry->next_ptr = next;
4494+
*prev = SHMOFF(new_entry);
4495+
rtapi_mutex_give(&(hal_data->mutex));
4496+
return 0;
4497+
}
4498+
if (cmp == 0) {
4499+
free_struct_entry(new_entry);
4500+
rtapi_mutex_give(&(hal_data->mutex));
4501+
rtapi_print_msg(RTAPI_MSG_ERR,
4502+
"HAL: hal_struct_newf: duplicate name '%s'\n", name);
4503+
return -EINVAL;
4504+
}
4505+
prev = &(ptr->next_ptr);
4506+
next = *prev;
4507+
}
44114508
}
44124509

44134510
int hal_struct_attach(const char *name, void **memptr)
44144511
{
4415-
hal_param_t *param;
4416-
void *dptr;
4417-
hal_s32_t offset;
4512+
hal_struct_entry_t *entry;
44184513

44194514
if (hal_data == 0) {
44204515
rtapi_print_msg(RTAPI_MSG_ERR,
@@ -4425,31 +4520,40 @@ int hal_struct_attach(const char *name, void **memptr)
44254520
return -EINVAL;
44264521

44274522
rtapi_mutex_get(&(hal_data->mutex));
4428-
param = halpr_find_param_by_name(name);
4429-
if (param == 0) {
4523+
entry = halpr_find_struct_by_name(name);
4524+
if (entry == 0) {
44304525
rtapi_mutex_give(&(hal_data->mutex));
44314526
rtapi_print_msg(RTAPI_MSG_ERR,
44324527
"HAL: hal_struct_attach: '%s' not found\n", name);
44334528
return -ENOENT;
44344529
}
4435-
if (param->type != HAL_S32) {
4436-
rtapi_mutex_give(&(hal_data->mutex));
4437-
rtapi_print_msg(RTAPI_MSG_ERR,
4438-
"HAL: hal_struct_attach: '%s' is not a struct param\n", name);
4439-
return -EINVAL;
4440-
}
4441-
dptr = SHMPTR(param->data_ptr);
4442-
offset = *(hal_s32_t *)dptr;
4530+
entry->attach_count++;
4531+
*memptr = SHMPTR(entry->data_ptr);
44434532
rtapi_mutex_give(&(hal_data->mutex));
4444-
4445-
*memptr = hal_shmem_base + offset;
44464533
return 0;
44474534
}
44484535

44494536
int hal_struct_detach(const char *name)
44504537
{
4451-
(void)name;
4452-
return 0; /* no-op: HAL shmem lifetime managed by creating component */
4538+
hal_struct_entry_t *entry;
4539+
4540+
if (hal_data == 0)
4541+
return -EINVAL;
4542+
if (!name)
4543+
return -EINVAL;
4544+
4545+
rtapi_mutex_get(&(hal_data->mutex));
4546+
entry = halpr_find_struct_by_name(name);
4547+
if (entry == 0) {
4548+
rtapi_mutex_give(&(hal_data->mutex));
4549+
rtapi_print_msg(RTAPI_MSG_ERR,
4550+
"HAL: hal_struct_detach: '%s' not found\n", name);
4551+
return -ENOENT;
4552+
}
4553+
if (entry->attach_count > 0)
4554+
entry->attach_count--;
4555+
rtapi_mutex_give(&(hal_data->mutex));
4556+
return 0;
44534557
}
44544558

44554559
#ifdef RTAPI

src/hal/hal_priv.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
*/
119119

120120
#define HAL_KEY 0x48414C32 /* key used to open HAL shared memory */
121-
#define HAL_VER 0x00000010 /* version code */
121+
#define HAL_VER 0x00000011 /* version code — bumped for hal_struct namespace */
122122
#define HAL_SIZE (256*4096)
123123
#define HAL_PSEUDO_COMP_PREFIX "__" /* prefix to identify a pseudo component */
124124

@@ -233,6 +233,7 @@ typedef struct hal_comp_t hal_comp_t;
233233
typedef struct hal_pin_t hal_pin_t;
234234
typedef struct hal_sig_t hal_sig_t;
235235
typedef struct hal_param_t hal_param_t;
236+
typedef struct hal_struct_entry_t hal_struct_entry_t;
236237
typedef struct hal_funct_t hal_funct_t;
237238
typedef struct hal_funct_entry_t hal_funct_entry_t;
238239
typedef struct hal_thread_t hal_thread_t;
@@ -261,6 +262,7 @@ typedef struct hal_data_t {
261262
SHMFIELD(hal_pin_t) pin_list_ptr; /* root of linked list of pins */
262263
SHMFIELD(hal_sig_t) sig_list_ptr; /* root of linked list of signals */
263264
SHMFIELD(hal_param_t) param_list_ptr; /* root of linked list of parameters */
265+
SHMFIELD(hal_struct_entry_t) struct_list_ptr; /* root of linked list of struct entries */
264266
SHMFIELD(hal_funct_t) funct_list_ptr; /* root of linked list of functions */
265267
SHMFIELD(hal_thread_t) thread_list_ptr; /* root of linked list of threads */
266268
long base_period; /* timer period for realtime tasks */
@@ -270,6 +272,7 @@ typedef struct hal_data_t {
270272
SHMFIELD(hal_pin_t) pin_free_ptr; /* list of free pin structs */
271273
SHMFIELD(hal_sig_t) sig_free_ptr; /* list of free signal structs */
272274
SHMFIELD(hal_param_t) param_free_ptr; /* list of free parameter structs */
275+
SHMFIELD(hal_struct_entry_t) struct_free_ptr; /* list of free struct entry structs */
273276
SHMFIELD(hal_funct_t) funct_free_ptr; /* list of free function structs */
274277
hal_list_t funct_entry_free; /* list of free funct entry structs */
275278
SHMFIELD(hal_thread_t) thread_free_ptr; /* list of free thread structs */
@@ -347,6 +350,17 @@ struct hal_param_t {
347350
char name[HAL_NAME_LEN + 1]; /* parameter name */
348351
};
349352

353+
/** HAL 'struct entry' — a named, ref-counted opaque blob in HAL shmem.
354+
Lives in its own namespace, separate from pins, signals, and parameters.
355+
*/
356+
struct hal_struct_entry_t {
357+
SHMFIELD(hal_struct_entry_t) next_ptr; /* next entry in list */
358+
SHMFIELD(hal_comp_t) owner_ptr; /* component that created this entry */
359+
SHMFIELD(void*) data_ptr; /* offset of data in shmem */
360+
int attach_count; /* number of active attachments */
361+
char name[HAL_NAME_LEN + 1]; /* entry name */
362+
};
363+
350364
/** the HAL uses functions and threads to handle synchronization of
351365
code. In general, most control systems need to read inputs,
352366
perform control calculations, and write outputs, in that order.
@@ -449,6 +463,7 @@ extern hal_comp_t *halpr_find_comp_by_name(const char *name);
449463
extern hal_pin_t *halpr_find_pin_by_name(const char *name);
450464
extern hal_sig_t *halpr_find_sig_by_name(const char *name);
451465
extern hal_param_t *halpr_find_param_by_name(const char *name);
466+
extern hal_struct_entry_t *halpr_find_struct_by_name(const char *name);
452467
extern hal_thread_t *halpr_find_thread_by_name(const char *name);
453468
extern hal_funct_t *halpr_find_funct_by_name(const char *name);
454469

0 commit comments

Comments
 (0)