@@ -84,6 +84,8 @@ struct vregion {
8484 uint8_t * base ; /* base address of entire region */
8585 size_t size ; /* size of whole region in bytes */
8686 unsigned int pages ; /* size of whole region in pages */
87+ struct k_mutex lock ; /* protect vregion heaps and use-count */
88+ unsigned int use_count ;
8789
8890 /* interim heap */
8991 struct interim_heap interim ; /* interim heap */
@@ -152,6 +154,10 @@ struct vregion *vregion_create(size_t lifetime_size, size_t interim_size)
152154 /* init interim heaps */
153155 k_heap_init (& vr -> interim .heap , vr -> interim .heap .heap .init_mem , interim_size );
154156
157+ k_mutex_init (& vr -> lock );
158+ /* The creator is the first user */
159+ vr -> use_count = 1 ;
160+
155161 /* log the new vregion */
156162 LOG_INF ("new at base %p size %#zx pages %u struct embedded at %p" ,
157163 (void * )vr -> base , total_size , pages , (void * )vr );
@@ -161,20 +167,46 @@ struct vregion *vregion_create(size_t lifetime_size, size_t interim_size)
161167 return vr ;
162168}
163169
170+ struct vregion * vregion_get (struct vregion * vr )
171+ {
172+ if (!vr )
173+ return NULL ;
174+
175+ k_mutex_lock (& vr -> lock , K_FOREVER );
176+ vr -> use_count ++ ;
177+ k_mutex_unlock (& vr -> lock );
178+
179+ return vr ;
180+ }
181+
164182/**
165- * @brief Destroy a virtual region instance .
183+ * @brief Decrement virtual region's user count or destroy it .
166184 *
167- * @param[in] vr Pointer to the virtual region instance to destroy.
185+ * @param[in] vr Pointer to the virtual region instance to release.
186+ * @return struct vregion* Pointer to the virtual region instance or NULL if it has been destroyed.
168187 */
169- void vregion_destroy (struct vregion * vr )
188+ struct vregion * vregion_put (struct vregion * vr )
170189{
190+ unsigned int use_count ;
191+
171192 if (!vr )
172- return ;
193+ return NULL ;
194+
195+ k_mutex_lock (& vr -> lock , K_FOREVER );
196+ use_count = -- vr -> use_count ;
197+ k_mutex_unlock (& vr -> lock );
198+
199+ if (use_count )
200+ return vr ;
201+
202+ /* Last user: nobody else can access the instance. */
173203
174204 /* log the vregion being destroyed */
175205 LOG_DBG ("destroy %p size %#zx pages %u" , (void * )vr -> base , vr -> size , vr -> pages );
176206 LOG_DBG (" lifetime used %zu free count %d" , vr -> lifetime .used , vr -> lifetime .free_count );
177207 vpage_free (vr -> base );
208+
209+ return NULL ;
178210}
179211
180212/**
@@ -275,25 +307,24 @@ void vregion_free(struct vregion *vr, void *ptr)
275307 if (!vr || !ptr )
276308 return ;
277309
310+ k_mutex_lock (& vr -> lock , K_FOREVER );
311+
278312 if (sys_cache_is_ptr_uncached (ptr ))
279313 ptr = sys_cache_cached_ptr_get (ptr );
280314
281- /* check if pointer is in interim heap */
282315 if (ptr >= (void * )vr -> interim .heap .heap .init_mem &&
283316 ptr < (void * )((uint8_t * )vr -> interim .heap .heap .init_mem +
284- vr -> interim .heap .heap .init_bytes )) {
317+ vr -> interim .heap .heap .init_bytes ))
318+ /* pointer is in interim heap */
285319 interim_free (& vr -> interim , ptr );
286- return ;
287- }
288-
289- /* check if pointer is in lifetime heap */
290- if (ptr >= (void * )vr -> lifetime .base &&
291- ptr < (void * )(vr -> lifetime .base + vr -> lifetime .size )) {
320+ else if (ptr >= (void * )vr -> lifetime .base &&
321+ ptr < (void * )(vr -> lifetime .base + vr -> lifetime .size ))
322+ /* pointer is in lifetime heap */
292323 lifetime_free (& vr -> lifetime , ptr );
293- return ;
294- }
324+ else
325+ LOG_ERR ( "error: vregion free invalid pointer %p" , ptr );
295326
296- LOG_ERR ( "error: vregion free invalid pointer %p" , ptr );
327+ k_mutex_unlock ( & vr -> lock );
297328}
298329EXPORT_SYMBOL (vregion_free );
299330
@@ -310,21 +341,31 @@ EXPORT_SYMBOL(vregion_free);
310341void * vregion_alloc_align (struct vregion * vr , enum vregion_mem_type type ,
311342 size_t size , size_t alignment )
312343{
344+ void * p ;
345+
313346 if (!vr || !size )
314347 return NULL ;
315348
316349 if (alignment < PLATFORM_DCACHE_ALIGN )
317350 alignment = PLATFORM_DCACHE_ALIGN ;
318351
352+ k_mutex_lock (& vr -> lock , K_FOREVER );
353+
319354 switch (type ) {
320355 case VREGION_MEM_TYPE_INTERIM :
321- return interim_alloc (& vr -> interim , size , alignment );
356+ p = interim_alloc (& vr -> interim , size , alignment );
357+ break ;
322358 case VREGION_MEM_TYPE_LIFETIME :
323- return lifetime_alloc (& vr -> lifetime , size , alignment );
359+ p = lifetime_alloc (& vr -> lifetime , size , alignment );
360+ break ;
324361 default :
325362 LOG_ERR ("error: invalid memory type %d" , type );
326- return NULL ;
363+ p = NULL ;
327364 }
365+
366+ k_mutex_unlock (& vr -> lock );
367+
368+ return p ;
328369}
329370EXPORT_SYMBOL (vregion_alloc_align );
330371
0 commit comments