11#include "events.h"
22
33#include <stdlib.h>
4- #include <stddef .h>
4+ #include <string .h>
55
66
7- // internal callback callback
8- struct ecallback {
9- void (* cb )(void * );
10- void * data ;
11- };
12-
13- static void ecallback_dispatch (void * p ) {
14- struct ecallback * e = (struct ecallback * )p ;
15- e -> cb (e -> data );
16- }
17-
18- // equeue functions
19- static inline struct event * equeue_event (struct equeue * q , unsigned i ) {
20- return (struct event * )((char * )q -> buffer + i * q -> size );
21- }
22-
23- static inline unsigned equeue_size (unsigned size ) {
24- if (size < sizeof (struct ecallback )) {
25- size = sizeof (struct ecallback );
26- }
27-
28- unsigned alignment = offsetof(struct { char c ; struct event e ; }, e );
29- size += sizeof (struct event );
30- return (size + alignment - 1 ) & ~(alignment - 1 );
31- }
32-
33- int equeue_create (struct equeue * q , unsigned count , unsigned size ) {
34- void * buffer = malloc (count * equeue_size (size ));
7+ int equeue_create (struct equeue * q , unsigned size ) {
8+ void * buffer = malloc (size );
359 if (!buffer ) {
3610 return -1 ;
3711 }
3812
39- return equeue_create_inplace (q , count , size , buffer );
13+ int err = equeue_create_inplace (q , size , buffer );
14+ q -> buffer = buffer ;
15+ return err ;
4016}
4117
42- int equeue_create_inplace (struct equeue * q ,
43- unsigned count , unsigned size , void * buffer ) {
44- q -> size = equeue_size (size );
45- q -> buffer = buffer ;
46- q -> free = (struct event * )buffer ;
18+ int equeue_create_inplace (struct equeue * q , unsigned size , void * buffer ) {
19+ q -> slab .size = size ;
20+ q -> slab .data = buffer ;
21+ q -> chunks = 0 ;
22+ q -> buffer = 0 ;
23+
4724 q -> queue = 0 ;
4825 q -> next_id = 42 ;
4926 q -> break_ = (struct event ){
5027 .id = 0 ,
5128 .period = -1 ,
5229 };
5330
54- if (q -> free ) {
55- for (unsigned i = 0 ; i < count - 1 ; i ++ ) {
56- equeue_event (q , i )-> next = equeue_event (q , i + 1 );
57- }
58- equeue_event (q , count - 1 )-> next = 0 ;
59- }
60-
6131 int err ;
6232 err = events_sema_create (& q -> eventsema );
6333 if (err < 0 ) {
@@ -84,56 +54,108 @@ void equeue_destroy(struct equeue *q) {
8454 free (q -> buffer );
8555}
8656
87- // equeue mem functions
88- static int equeue_next_id (struct equeue * q ) {
57+ // equeue allocation functions
58+ static void * equeue_alloc (struct equeue * q , unsigned size ) {
59+ size = size + sizeof (unsigned );
60+ size = (size + sizeof (unsigned )-1 ) & ~(sizeof (unsigned )-1 );
61+ if (size < sizeof (struct equeue_chunk )) {
62+ size = sizeof (struct equeue_chunk );
63+ }
64+
65+ events_mutex_lock (& q -> freelock );
66+
67+ for (struct equeue_chunk * * p = & q -> chunks ; * p ; p = & (* p )-> nchunk ) {
68+ if ((* p )-> size >= size ) {
69+ struct equeue_chunk * c = * p ;
70+ if (c -> next ) {
71+ * p = c -> next ;
72+ (* p )-> nchunk = c -> nchunk ;
73+ } else {
74+ * p = c -> nchunk ;
75+ }
76+ events_mutex_unlock (& q -> freelock );
77+ return (unsigned * )c + 1 ;
78+ }
79+ }
80+
81+ if (q -> slab .size >= size ) {
82+ struct equeue_chunk * c = (struct equeue_chunk * )q -> slab .data ;
83+ q -> slab .data += size ;
84+ q -> slab .size -= size ;
85+ c -> size = size ;
86+ events_mutex_unlock (& q -> freelock );
87+ return (unsigned * )c + 1 ;
88+ }
89+
90+ events_mutex_unlock (& q -> freelock );
91+ return 0 ;
92+ }
93+
94+ static void equeue_dealloc (struct equeue * q , void * e ) {
95+ struct equeue_chunk * c = (struct equeue_chunk * )((unsigned * )e - 1 );
96+
97+ events_mutex_lock (& q -> freelock );
98+
99+ struct equeue_chunk * * p = & q -> chunks ;
100+ while (* p && (* p )-> size < c -> size ) {
101+ p = & (* p )-> nchunk ;
102+ }
103+
104+ if (* p && (* p )-> size == c -> size ) {
105+ c -> next = * p ;
106+ c -> nchunk = (* p )-> nchunk ;
107+ } else {
108+ c -> next = 0 ;
109+ c -> nchunk = * p ;
110+ }
111+ * p = c ;
112+
113+ events_mutex_unlock (& q -> freelock );
114+ }
115+
116+ // event allocation functions
117+ static inline int event_next_id (struct equeue * q ) {
89118 int id = q -> next_id ++ ;
90119 if (q -> next_id < 0 ) {
91120 q -> next_id = 42 ;
92121 }
93122 return id ;
94123}
95124
96- static struct event * equeue_alloc (struct equeue * q ) {
97- struct event * e = 0 ;
98-
99- events_mutex_lock (& q -> freelock );
100- if (!q -> free ) {
101- events_mutex_unlock (& q -> freelock );
125+ void * event_alloc (struct equeue * q , unsigned size ) {
126+ struct event * e = equeue_alloc (q , sizeof (struct event ) + size );
127+ if (!e ) {
102128 return 0 ;
103129 }
104130
105- e = q -> free ;
106- q -> free = e -> next ;
107- events_mutex_unlock (& q -> freelock );
108-
109- e -> id = equeue_next_id (q );
131+ e -> id = event_next_id (q );
110132 e -> target = 0 ;
111133 e -> period = -1 ;
112134 e -> dtor = 0 ;
113- return e ;
135+
136+ return e + 1 ;
114137}
115138
116- static void equeue_dealloc (struct equeue * q , struct event * e ) {
139+ void event_dealloc (struct equeue * q , void * p ) {
140+ struct event * e = (struct event * )p - 1 ;
141+
117142 if (e -> dtor ) {
118143 e -> dtor (e + 1 );
119144 }
120145
121- events_mutex_lock (& q -> freelock );
122- e -> next = q -> free ;
123- q -> free = e ;
124- events_mutex_unlock (& q -> freelock );
146+ equeue_dealloc (q , e );
125147}
126148
127149// equeue scheduling functions
128- static inline int tickdiff (unsigned a , unsigned b ) {
150+ static inline int equeue_tickdiff (unsigned a , unsigned b ) {
129151 return (int )(a - b );
130152}
131153
132154static int equeue_enqueue (struct equeue * q , struct event * e , int ms ) {
133155 e -> target = events_tick () + (unsigned )ms ;
134156
135157 struct event * * p = & q -> queue ;
136- while (* p && tickdiff ((* p )-> target , e -> target ) <= 0 ) {
158+ while (* p && equeue_tickdiff ((* p )-> target , e -> target ) <= 0 ) {
137159 p = & (* p )-> next ;
138160 }
139161
@@ -169,7 +191,7 @@ static void equeue_cancel(struct equeue *q, int id) {
169191 events_mutex_unlock (& q -> queuelock );
170192
171193 if (e ) {
172- equeue_dealloc (q , e );
194+ event_dealloc (q , e + 1 );
173195 }
174196}
175197
@@ -194,7 +216,7 @@ void equeue_dispatch(struct equeue *q, int ms) {
194216 break ;
195217 }
196218
197- deadline = tickdiff (q -> queue -> target , events_tick ());
219+ deadline = equeue_tickdiff (q -> queue -> target , events_tick ());
198220 if (deadline > 0 ) {
199221 events_mutex_unlock (& q -> queuelock );
200222 break ;
@@ -218,7 +240,7 @@ void equeue_dispatch(struct equeue *q, int ms) {
218240 e -> cb (e + 1 );
219241
220242 if (e -> period < 0 ) {
221- equeue_dealloc (q , e );
243+ event_dealloc (q , e + 1 );
222244 }
223245 }
224246
@@ -227,25 +249,6 @@ void equeue_dispatch(struct equeue *q, int ms) {
227249}
228250
229251// event functions
230- void * event_alloc (struct equeue * q , unsigned size ) {
231- if (size > q -> size - sizeof (struct event )) {
232- return 0 ;
233- }
234-
235- struct event * e = equeue_alloc (q );
236- if (!e ) {
237- return 0 ;
238- }
239-
240- return e + 1 ;
241- }
242-
243- void event_dealloc (struct equeue * q , void * p ) {
244- struct event * e = (struct event * )p - 1 ;
245- equeue_dealloc (q , e );
246- }
247-
248- // configuring events
249252void event_delay (void * p , int ms ) {
250253 struct event * e = (struct event * )p - 1 ;
251254 e -> target = ms ;
@@ -273,7 +276,17 @@ void event_cancel(struct equeue *q, int id) {
273276 return equeue_cancel (q , id );
274277}
275278
276- // event helper functions
279+ // simple callbacks
280+ struct ecallback {
281+ void (* cb )(void * );
282+ void * data ;
283+ };
284+
285+ static void ecallback_dispatch (void * p ) {
286+ struct ecallback * e = (struct ecallback * )p ;
287+ e -> cb (e -> data );
288+ }
289+
277290int event_call (struct equeue * q , void (* cb )(void * ), void * data ) {
278291 struct ecallback * e = event_alloc (q , sizeof (struct ecallback ));
279292 if (!e ) {
0 commit comments