Skip to content

Commit cf74f22

Browse files
Nicolas Pitrecfriedt
Nicolas Pitre
authored andcommitted
posix: semaphore: optimize named semaphore implementation a bit
- Regroup refcount decrement and semaphore destruction by making the linked state into a counted reference for it. This allows for simplifying the code and cleanly adding a few assertions in a common location. - Remove redundant initialization to NULL on memory about to be freed and local pointer in nsem_cleanup(). Signed-off-by: Nicolas Pitre <[email protected]>
1 parent b8662b9 commit cf74f22

File tree

2 files changed

+16
-22
lines changed

2 files changed

+16
-22
lines changed

lib/posix/semaphore.c

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
struct nsem_obj {
1616
sys_snode_t snode;
1717
sem_t sem;
18-
unsigned int ref_count;
18+
int ref_count;
1919
char *name;
2020
};
2121

@@ -53,17 +53,20 @@ static void nsem_cleanup(struct nsem_obj *nsem)
5353
if (nsem != NULL) {
5454
if (nsem->name != NULL) {
5555
k_free(nsem->name);
56-
nsem->name = NULL;
5756
}
5857
k_free(nsem);
59-
nsem = NULL;
6058
}
6159
}
6260

6361
/* Remove a named semaphore if it isn't unsed */
64-
static void nsem_remove_if_unused(struct nsem_obj *nsem)
62+
static void nsem_unref(struct nsem_obj *nsem)
6563
{
64+
nsem->ref_count -= 1;
65+
__ASSERT(nsem->ref_count >= 0, "ref_count may not be negative");
66+
6667
if (nsem->ref_count == 0) {
68+
__ASSERT(nsem->name == NULL, "ref_count is 0 but sem is not unlinked");
69+
6770
sys_slist_find_and_remove(&nsem_list, (sys_snode_t *) nsem);
6871

6972
/* Free nsem */
@@ -255,7 +258,7 @@ sem_t *sem_open(const char *name, int oflags, ...)
255258
goto error_unlock;
256259
}
257260

258-
__ASSERT_NO_MSG(nsem->ref_count != UINT_MAX);
261+
__ASSERT_NO_MSG(nsem->ref_count != INT_MAX);
259262
nsem->ref_count++;
260263
goto unlock;
261264
}
@@ -282,7 +285,9 @@ sem_t *sem_open(const char *name, int oflags, ...)
282285
}
283286

284287
strcpy(nsem->name, name);
285-
nsem->ref_count = 1;
288+
289+
/* 1 for this open instance, +1 for the linked name */
290+
nsem->ref_count = 2;
286291

287292
(void)k_sem_init(&nsem->sem, value, CONFIG_SEM_VALUE_MAX);
288293

@@ -328,8 +333,7 @@ int sem_unlink(const char *name)
328333

329334
k_free(nsem->name);
330335
nsem->name = NULL;
331-
332-
nsem_remove_if_unused(nsem);
336+
nsem_unref(nsem);
333337

334338
unlock:
335339
nsem_list_unlock();
@@ -345,28 +349,18 @@ int sem_close(sem_t *sem)
345349
return -1;
346350
}
347351

348-
__ASSERT_NO_MSG(nsem != NULL);
349-
350352
nsem_list_lock();
351-
352-
__ASSERT_NO_MSG(nsem->ref_count != 0);
353-
nsem->ref_count--;
354-
355-
/* remove sem if marked for unlink */
356-
if (nsem->name == NULL) {
357-
nsem_remove_if_unused(nsem);
358-
}
359-
353+
nsem_unref(nsem);
360354
nsem_list_unlock();
361355
return 0;
362356
}
363357

364358
#ifdef CONFIG_ZTEST
365359
/* Used by ztest to get the ref count of a named semaphore */
366-
unsigned int nsem_get_ref_count(sem_t *sem)
360+
int nsem_get_ref_count(sem_t *sem)
367361
{
368362
struct nsem_obj *nsem = CONTAINER_OF(sem, struct nsem_obj, sem);
369-
unsigned int ref_count;
363+
int ref_count;
370364

371365
__ASSERT_NO_MSG(sem != NULL);
372366
__ASSERT_NO_MSG(nsem != NULL);

tests/posix/common/src/semaphore.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ ZTEST(posix_apis, test_semaphore)
107107
semaphore_test(&sema);
108108
}
109109

110-
unsigned int nsem_get_ref_count(sem_t *sem);
110+
int nsem_get_ref_count(sem_t *sem);
111111
size_t nsem_get_list_len(void);
112112
#define N_LOOPS 999
113113

0 commit comments

Comments
 (0)