@@ -128,6 +128,8 @@ hal_comp_t *halpr_alloc_comp_struct(void);
128128static hal_pin_t * alloc_pin_struct (void );
129129static hal_sig_t * alloc_sig_struct (void );
130130static 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 );
131133static hal_oldname_t * halpr_alloc_oldname_struct (void );
132134#ifdef RTAPI
133135static 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+
26912710hal_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+
32883337static 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
43664414int 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
44134510int 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
44494536int 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
0 commit comments