3
3
#include < cerrno>
4
4
#include < cmath>
5
5
#include < cstring>
6
- #include < cstdint>
7
6
#include < chrono>
8
7
#include < algorithm>
9
8
#include < cstdlib>
10
- #include < csignal>
11
9
#include < random>
12
10
#include < string>
13
11
#include < limits>
14
-
15
- #include < poll.h>
16
- #include < sys/ioctl.h>
17
12
#include < sys/mman.h>
18
- #include < sys/stat.h>
19
- #include < sys/types.h>
20
13
#include < sys/syscall.h>
21
14
#include < fcntl.h>
22
15
#include < unistd.h>
23
16
24
- #include < stdio.h>
25
-
17
+ #include " msgq/futex.h"
26
18
#include " msgq/msgq.h"
27
19
28
- void sigusr2_handler (int signal) {
29
- assert (signal == SIGUSR2);
30
- }
20
+ Futex g_futex (" /dev/shm/msgq_futex" );
31
21
32
22
uint64_t msgq_get_uid (void ){
33
23
std::random_device rd (" /dev/urandom" );
@@ -85,7 +75,6 @@ void msgq_wait_for_subscriber(msgq_queue_t *q){
85
75
86
76
int msgq_new_queue (msgq_queue_t * q, const char * path, size_t size){
87
77
assert (size < 0xFFFFFFFF ); // Buffer must be smaller than 2^32 bytes
88
- std::signal (SIGUSR2, sigusr2_handler);
89
78
90
79
std::string full_path = " /dev/shm/" ;
91
80
const char * prefix = std::getenv (" OPENPILOT_PREFIX" );
@@ -142,7 +131,6 @@ void msgq_close_queue(msgq_queue_t *q){
142
131
}
143
132
}
144
133
145
-
146
134
void msgq_init_publisher (msgq_queue_t * q) {
147
135
// std::cout << "Starting publisher" << std::endl;
148
136
uint64_t uid = msgq_get_uid ();
@@ -158,15 +146,6 @@ void msgq_init_publisher(msgq_queue_t * q) {
158
146
q->write_uid_local = uid;
159
147
}
160
148
161
- static void thread_signal (uint32_t tid) {
162
- #ifndef SYS_tkill
163
- // TODO: this won't work for multithreaded programs
164
- kill (tid, SIGUSR2);
165
- #else
166
- syscall (SYS_tkill, tid, SIGUSR2);
167
- #endif
168
- }
169
-
170
149
void msgq_init_subscriber (msgq_queue_t * q) {
171
150
assert (q != NULL );
172
151
assert (q->num_readers != NULL );
@@ -185,14 +164,11 @@ void msgq_init_subscriber(msgq_queue_t * q) {
185
164
186
165
for (size_t i = 0 ; i < NUM_READERS; i++){
187
166
*q->read_valids [i] = false ;
188
-
189
- uint64_t old_uid = *q->read_uids [i];
190
167
*q->read_uids [i] = 0 ;
191
-
192
- // Wake up reader in case they are in a poll
193
- thread_signal (old_uid & 0xFFFFFFFF );
194
168
}
195
169
170
+ // Notify readers
171
+ g_futex.broadcast ();
196
172
continue ;
197
173
}
198
174
@@ -293,10 +269,7 @@ int msgq_msg_send(msgq_msg_t * msg, msgq_queue_t *q){
293
269
PACK64 (*q->write_pointer , write_cycles, new_ptr);
294
270
295
271
// Notify readers
296
- for (uint64_t i = 0 ; i < num_readers; i++){
297
- uint64_t reader_uid = *q->read_uids [i];
298
- thread_signal (reader_uid & 0xFFFFFFFF );
299
- }
272
+ g_futex.broadcast ();
300
273
301
274
return msg->size ;
302
275
}
@@ -414,42 +387,31 @@ int msgq_msg_recv(msgq_msg_t * msg, msgq_queue_t * q){
414
387
goto start;
415
388
}
416
389
417
-
418
390
return msg->size ;
419
391
}
420
392
421
-
422
-
423
- int msgq_poll (msgq_pollitem_t * items, size_t nitems, int timeout){
393
+ int msgq_poll (msgq_pollitem_t * items, size_t nitems, int timeout) {
424
394
int num = 0 ;
395
+ int timeout_ms = (timeout == -1 ) ? 100 : timeout;
396
+ uint32_t current_futex_value = 0 ;
425
397
426
- // Check if messages ready
427
- for (size_t i = 0 ; i < nitems; i++) {
428
- items[i].revents = msgq_msg_ready (items[i].q );
429
- if (items[i].revents ) num++;
430
- }
431
-
432
- int ms = (timeout == -1 ) ? 100 : timeout;
433
- struct timespec ts;
434
- ts.tv_sec = ms / 1000 ;
435
- ts.tv_nsec = (ms % 1000 ) * 1000 * 1000 ;
436
-
437
-
398
+ auto start_time = std::chrono::high_resolution_clock::now ();
438
399
while (num == 0 ) {
439
- int ret;
440
-
441
- ret = nanosleep (&ts, &ts);
400
+ if (g_futex.wait (current_futex_value, timeout_ms)) {
401
+ current_futex_value = g_futex.value ();
442
402
443
- // Check if messages ready
444
- for (size_t i = 0 ; i < nitems; i++) {
445
- if (items[i].revents == 0 && msgq_msg_ready (items[i].q )){
446
- num += 1 ;
447
- items[i].revents = 1 ;
403
+ // Check if messages ready
404
+ for (size_t i = 0 ; i < nitems; i++) {
405
+ items[i].revents = msgq_msg_ready (items[i].q );
406
+ if (items[i].revents ) ++num;
448
407
}
449
408
}
450
409
451
- // exit if we had a timeout and the sleep finished
452
- if (timeout != -1 && ret == 0 ){
410
+ // Update the remaining timeout
411
+ auto current_time = std::chrono::high_resolution_clock::now ();
412
+ timeout_ms -= std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count ();
413
+ start_time = current_time;
414
+ if (timeout_ms <= 0 ) {
453
415
break ;
454
416
}
455
417
}
0 commit comments