Skip to content

Commit 64e9463

Browse files
committed
Add event pools, allocate and free
1 parent a0ae6bc commit 64e9463

File tree

4 files changed

+258
-5
lines changed

4 files changed

+258
-5
lines changed

libs/event/event.c

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) Adel Mamin
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
/**
26+
* @file
27+
*
28+
* Event API implementation.
29+
*/
30+
31+
#include <string.h>
32+
33+
#include "common/compiler.h" /* IWYU pragma: keep */
34+
#include "common/macros.h"
35+
#include "onesize/onesize.h"
36+
#include "blk/blk.h"
37+
#include "pal/pal.h"
38+
#include "event.h"
39+
40+
#define AM_EVENT_IS_STATIC(event) (0 == (event)->pool_index)
41+
42+
/** Event internal state. */
43+
struct am_event_state {
44+
/** user defined event memory pools */
45+
struct am_onesize pool[AM_EVENT_POOL_NUM_MAX];
46+
/** the number of user defined event memory pools */
47+
int npool;
48+
};
49+
50+
static struct am_event_state am_event_state_;
51+
52+
void am_event_add_pool(void *pool, int size, int block_size, int alignment) {
53+
struct am_event_state *me = &am_event_state_;
54+
AM_ASSERT(me->npool < AM_EVENT_POOL_NUM_MAX);
55+
if (me->npool > 0) {
56+
int prev_size = am_onesize_get_block_size(&me->pool[me->npool - 1]);
57+
AM_ASSERT(block_size > prev_size);
58+
}
59+
60+
struct am_blk blk;
61+
memset(&blk, 0, sizeof(blk));
62+
blk.ptr = pool;
63+
blk.size = size;
64+
am_onesize_init(&me->pool[me->npool], &blk, block_size, alignment);
65+
66+
++me->npool;
67+
}
68+
69+
struct am_event *am_event_allocate(int id, int size, int margin) {
70+
struct am_event_state *me = &am_event_state_;
71+
AM_ASSERT(size > 0);
72+
AM_ASSERT(me->npool);
73+
AM_ASSERT(size <= am_onesize_get_block_size(&me->pool[me->npool - 1]));
74+
AM_ASSERT(id >= AM_EVT_USER);
75+
AM_ASSERT(margin >= 0);
76+
77+
for (int i = 0; i < me->npool; i++) {
78+
struct am_onesize *osz = &me->pool[i];
79+
if (size > am_onesize_get_block_size(osz)) {
80+
continue;
81+
}
82+
83+
am_pal_crit_enter();
84+
85+
int nfree = am_onesize_get_nfree(osz);
86+
if (margin && (nfree <= margin)) {
87+
am_pal_crit_exit();
88+
break;
89+
}
90+
if (!nfree) {
91+
am_pal_crit_exit();
92+
continue;
93+
}
94+
struct am_event *event =
95+
(struct am_event *)am_onesize_allocate(osz, size);
96+
am_pal_crit_exit();
97+
98+
AM_ASSERT(event);
99+
100+
/* event pointer is guaranteeed to be non-NULL here */
101+
AM_DISABLE_WARNING(AM_W_NULL_DEREFERENCE);
102+
memset(event, 0, sizeof(*event));
103+
event->id = id;
104+
event->pool_index =
105+
(unsigned)i & ((1U << AM_EVENT_POOL_INDEX_BITS) - 1);
106+
AM_ENABLE_WARNING(AM_W_NULL_DEREFERENCE);
107+
108+
return event;
109+
}
110+
111+
AM_ASSERT(margin);
112+
113+
return NULL;
114+
}
115+
116+
void am_event_free(const struct am_event *event) {
117+
if (NULL == event) {
118+
return;
119+
}
120+
if (AM_EVENT_IS_STATIC(event)) {
121+
return; /* the event is statically allocated */
122+
}
123+
124+
am_pal_crit_enter();
125+
126+
if (event->ref_counter > 1) {
127+
--AM_CAST(struct am_event *, event)->ref_counter;
128+
am_pal_crit_exit();
129+
return;
130+
}
131+
132+
AM_ASSERT(event->pool_index <= AM_EVENT_POOL_NUM_MAX);
133+
am_onesize_free(&am_event_state_.pool[event->pool_index - 1], event);
134+
135+
am_pal_crit_exit();
136+
}
137+
138+
int am_event_get_pool_min_nfree(int index) {
139+
struct am_event_state *me = &am_event_state_;
140+
AM_ASSERT(index >= 0);
141+
AM_ASSERT(index < me->npool);
142+
return am_onesize_get_min_nfree(&me->pool[index]);
143+
}
144+
145+
int am_event_get_pool_nfree_now(int index) {
146+
struct am_event_state *me = &am_event_state_;
147+
AM_ASSERT(index >= 0);
148+
AM_ASSERT(index < me->npool);
149+
return am_onesize_get_nfree(&me->pool[index]);
150+
}
151+
152+
int am_event_get_pool_nblocks(int index) {
153+
struct am_event_state *me = &am_event_state_;
154+
AM_ASSERT(index >= 0);
155+
AM_ASSERT(index < me->npool);
156+
return am_onesize_get_nblocks(&me->pool[index]);
157+
}
158+
159+
int am_event_get_pools_num(void) { return am_event_state_.npool; }

libs/event/event.h

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
/*
22
* The MIT License (MIT)
33
*
4-
* Copyright (c) 2020-2024 Adel Mamin
5-
* Copyright (c) 2019 Ryan Hartlage (documentation)
4+
* Copyright (c) Adel Mamin
65
*
76
* Permission is hereby granted, free of charge, to any person obtaining a copy
87
* of this software and associated documentation files (the "Software"), to deal
@@ -38,20 +37,26 @@
3837
*/
3938
#define AM_EVT_USER 5
4039

40+
#ifndef AM_EVENT_POOL_NUM_MAX
41+
#define AM_EVENT_POOL_NUM_MAX 3
42+
#endif
43+
4144
/**
4245
* Check if event has a valid user event ID
4346
* @param event event to check
4447
* @retval true the event has user event ID
4548
* @retval false the event does not have user event ID
4649
*/
4750
#define AM_EVENT_HAS_USER_ID(event) \
48-
(((const struct am_event*)(event))->id >= AM_EVT_USER)
51+
(((const struct am_event *)(event))->id >= AM_EVT_USER)
4952

5053
#define AM_EVENT_TICK_DOMAIN_BITS 3
5154
#define AM_EVENT_TICK_DOMAIN_MASK ((1U << AM_EVENT_TICK_DOMAIN_BITS) - 1U)
5255

5356
#define AM_EVT_CTOR(id_) ((struct am_event){.id = (id_)})
5457

58+
#define AM_EVENT_POOL_INDEX_BITS 5
59+
5560
/** Event descriptor */
5661
struct am_event {
5762
/** event ID */
@@ -65,7 +70,7 @@ struct am_event {
6570
/** reference counter */
6671
unsigned ref_counter : 6;
6772
/** if set to zero, then event is statically allocated */
68-
unsigned pool_index : 5;
73+
unsigned pool_index : AM_EVENT_POOL_INDEX_BITS;
6974
/** tick domain for time events */
7075
unsigned tick_domain : AM_EVENT_TICK_DOMAIN_BITS;
7176
/** PUB/SUB time event */
@@ -74,4 +79,60 @@ struct am_event {
7479
unsigned reserved : 1;
7580
};
7681

82+
/**
83+
* Adds an event memory pool.
84+
* The event memory pools must be added in the order of increasing block sizes.
85+
* @param pool the memory pool pointer
86+
* @param size the memory pool size [bytes]
87+
* @param block_size the maximum size of allocated memory block [bytes]
88+
* @param alignment the required alignment of allocated memory blocks [bytes].
89+
*/
90+
void am_event_add_pool(void *pool, int size, int block_size, int alignment);
91+
92+
/**
93+
* The minimum number of free memory blocks available so far in the memory pool
94+
* with a given index.
95+
* Could be used to assess the usage of the underlying memory pool.
96+
* @param index memory pool index
97+
* @return the minimum number of blocks of size block_size available so far
98+
*/
99+
int am_event_get_pool_min_nfree(int index);
100+
101+
/**
102+
* The minimum number of free memory blocks available now in the memory pool
103+
* with a given index.
104+
* @param index memory pool index
105+
* @return the number of free blocks of size block_size available now
106+
*/
107+
int am_event_get_pool_nfree_now(int index);
108+
109+
/**
110+
* The number of blocks in the pool with the given index.
111+
* @param index the pool index
112+
* @return the number of blocks
113+
*/
114+
int am_event_get_pool_nblocks(int index);
115+
116+
/**
117+
* The number of registered pools.
118+
* @return the number of pools
119+
*/
120+
int am_event_get_pools_num(void);
121+
122+
/**
123+
* Allocates an event from memory pools provided at initialization.
124+
* The allocation cannot fail, if margin is 0.
125+
* @param id the event identifier
126+
* @param size the event size [bytes]
127+
* @param margin free memory blocks to be available after the allocation
128+
* @return the newly allocated event.
129+
*/
130+
struct am_event *am_event_allocate(int id, int size, int margin);
131+
132+
/**
133+
* Free the event allocated earlier with am_event_allocate().
134+
* @param event the event to free
135+
*/
136+
void am_event_free(const struct am_event *event);
137+
77138
#endif /* EVENT_H_INCLUDED */

libs/event/meson.build

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#
2+
# The MIT License (MIT)
3+
#
4+
# Copyright (c) Adel Mamin
5+
#
6+
# Permission is hereby granted, free of charge, to any person obtaining a copy
7+
# of this software and associated documentation files (the "Software"), to deal
8+
# in the Software without restriction, including without limitation the rights
9+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
# copies of the Software, and to permit persons to whom the Software is
11+
# furnished to do so, subject to the following conditions:
12+
#
13+
# The above copyright notice and this permission notice shall be included in all
14+
# copies or substantial portions of the Software.
15+
#
16+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
# SOFTWARE.
23+
#
24+
25+
event_src = [files('event.c')]
26+
src += [event_src]
27+
28+
libevent = library('event', [event_src], include_directories: [inc])
29+
libevent_dep = declare_dependency(
30+
link_with : libevent,
31+
include_directories : [inc]
32+
)

libs/meson.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#
22
# The MIT License (MIT)
33
#
4-
# Copyright (c) 2024 Adel Mamin
4+
# Copyright (c) Adel Mamin
55
#
66
# Permission is hereby granted, free of charge, to any person obtaining a copy
77
# of this software and associated documentation files (the "Software"), to deal
@@ -36,3 +36,4 @@ subdir('hsm')
3636
subdir('queue')
3737
subdir('slist')
3838
subdir('onesize')
39+
subdir('event')

0 commit comments

Comments
 (0)