Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add queue_send synchronous message sending. Right now only for SWCODEC. Actual usage to be added to playback and recording shortly in upcoming commits.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11776 a1c6a512-1295-4272-9138-f99709370657

+440 -31
+4
firmware/export/config.h
··· 216 216 #endif 217 217 #endif 218 218 219 + #if CONFIG_CODEC == SWCODEC && !defined(BOOTLOADER) 220 + #define HAVE_EXTENDED_MESSAGING_AND_NAME 221 + #endif 222 + 219 223 #if (CONFIG_CODEC == SWCODEC) && !defined(SIMULATOR) && !defined(BOOTLOADER) 220 224 #define HAVE_PRIORITY_SCHEDULING 221 225 #define HAVE_SCHEDULER_BOOSTCTRL
+25 -2
firmware/export/kernel.h
··· 33 33 #define QUEUE_LENGTH 16 /* MUST be a power of 2 */ 34 34 #define QUEUE_LENGTH_MASK (QUEUE_LENGTH - 1) 35 35 36 - /* System defined message ID's, occupying the top 5 bits of the event ID */ 36 + /* System defined message ID's, occupying the top 8 bits of the event ID */ 37 37 #define SYS_EVENT (long)0x80000000 /* SYS events are negative */ 38 38 #define SYS_USB_CONNECTED ((SYS_EVENT | ((long)1 << 27))) 39 39 #define SYS_USB_CONNECTED_ACK ((SYS_EVENT | ((long)2 << 27))) ··· 55 55 void *data; 56 56 }; 57 57 58 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 59 + struct queue_sender 60 + { 61 + struct thread_entry *thread; 62 + void *retval; 63 + }; 64 + 65 + struct queue_sender_list 66 + { 67 + /* If non-NULL, there is a thread waiting for the corresponding event */ 68 + struct queue_sender *senders[QUEUE_LENGTH]; 69 + /* Send info for last message dequeued or NULL if replied or not sent */ 70 + struct queue_sender *curr_sender; 71 + }; 72 + #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 73 + 58 74 struct event_queue 59 75 { 60 76 struct event events[QUEUE_LENGTH]; 61 77 struct thread_entry *thread; 62 78 unsigned int read; 63 79 unsigned int write; 80 + struct queue_sender_list *send; 64 81 }; 65 82 66 83 struct mutex ··· 90 107 int tick_remove_task(void (*f)(void)); 91 108 92 109 extern void queue_init(struct event_queue *q, bool register_queue); 110 + extern void queue_enable_queue_send(struct event_queue *q, struct queue_sender_list *send); 93 111 extern void queue_delete(struct event_queue *q); 94 112 extern void queue_wait(struct event_queue *q, struct event *ev); 95 113 extern void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks); 96 114 extern void queue_post(struct event_queue *q, long id, void *data); 115 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 116 + extern void * queue_send(struct event_queue *q, long id, void *data); 117 + extern void queue_reply(struct event_queue *q, void *retval); 118 + extern bool queue_in_queue_send(struct event_queue *q); 119 + #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 97 120 extern bool queue_empty(const struct event_queue* q); 98 - void queue_clear(struct event_queue* q); 121 + extern void queue_clear(struct event_queue* q); 99 122 extern void queue_remove_from_head(struct event_queue *q, long id); 100 123 extern int queue_broadcast(long id, void *data); 101 124
+7
firmware/export/thread.h
··· 143 143 void sleep_thread(int ticks); 144 144 void block_thread(struct thread_entry **thread); 145 145 void block_thread_w_tmo(struct thread_entry **thread, int timeout); 146 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 147 + void set_irq_level_and_block_thread(struct thread_entry **thread, int level); 148 + #if 0 149 + void set_irq_level_and_block_thread_w_tmo(struct thread_entry **list, 150 + int timeout, int level) 151 + #endif 152 + #endif 146 153 void wakeup_thread(struct thread_entry **thread); 147 154 #ifdef HAVE_PRIORITY_SCHEDULING 148 155 int thread_set_priority(struct thread_entry *thread, int priority);
+191 -18
firmware/kernel.c
··· 86 86 /**************************************************************************** 87 87 * Queue handling stuff 88 88 ****************************************************************************/ 89 + 90 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 91 + /* Moves waiting thread's descriptor to the current sender when a 92 + message is dequeued */ 93 + static void queue_fetch_sender(struct queue_sender_list *send, 94 + unsigned int i) 95 + { 96 + int old_level = set_irq_level(HIGHEST_IRQ_LEVEL); 97 + struct queue_sender **spp = &send->senders[i]; 98 + 99 + if(*spp) 100 + { 101 + send->curr_sender = *spp; 102 + *spp = NULL; 103 + } 104 + 105 + set_irq_level(old_level); 106 + } 107 + 108 + /* Puts the specified return value in the waiting thread's return value 109 + and wakes the thread - a sender should be confirmed to exist first */ 110 + static void queue_release_sender(struct queue_sender **sender, void *retval) 111 + { 112 + (*sender)->retval = retval; 113 + wakeup_thread(&(*sender)->thread); 114 + *sender = NULL; 115 + } 116 + 117 + /* Releases any waiting threads that are queued with queue_send - 118 + reply with NULL */ 119 + static void queue_release_all_senders(struct event_queue *q) 120 + { 121 + if(q->send) 122 + { 123 + unsigned int i; 124 + for(i = q->read; i != q->write; i++) 125 + { 126 + struct queue_sender **spp = 127 + &q->send->senders[i & QUEUE_LENGTH_MASK]; 128 + if(*spp) 129 + { 130 + queue_release_sender(spp, NULL); 131 + } 132 + } 133 + } 134 + } 135 + 136 + /* Enables queue_send on the specified queue - caller allocates the extra 137 + data structure */ 138 + void queue_enable_queue_send(struct event_queue *q, 139 + struct queue_sender_list *send) 140 + { 141 + q->send = send; 142 + memset(send, 0, sizeof(*send)); 143 + } 144 + #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 145 + 146 + 89 147 void queue_init(struct event_queue *q, bool register_queue) 90 148 { 91 - q->read = 0; 92 - q->write = 0; 149 + q->read = 0; 150 + q->write = 0; 93 151 q->thread = NULL; 94 - 95 - if (register_queue) 152 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 153 + q->send = NULL; /* No message sending by default */ 154 + #endif 155 + 156 + if(register_queue) 96 157 { 97 158 /* Add it to the all_queues array */ 98 159 all_queues[num_queues++] = q; ··· 118 179 119 180 if(found) 120 181 { 182 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 183 + /* Release waiting threads and reply to any dequeued message 184 + waiting for one. */ 185 + queue_release_all_senders(q); 186 + queue_reply(q, NULL); 187 + #endif 121 188 /* Move the following queues up in the list */ 122 189 for(;i < num_queues-1;i++) 123 190 { ··· 130 197 131 198 void queue_wait(struct event_queue *q, struct event *ev) 132 199 { 133 - if (q->read == q->write) 200 + unsigned int rd; 201 + 202 + if(q->read == q->write) 134 203 { 135 204 block_thread(&q->thread); 136 205 } 137 206 138 - *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; 207 + rd = q->read++ & QUEUE_LENGTH_MASK; 208 + *ev = q->events[rd]; 209 + 210 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 211 + if(q->send && q->send->senders[rd]) 212 + { 213 + /* Get data for a waiting thread if one */ 214 + queue_fetch_sender(q->send, rd); 215 + } 216 + #endif 139 217 } 140 218 141 219 void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks) 142 220 { 143 - if (q->read == q->write && ticks > 0) 221 + if(q->read == q->write && ticks > 0) 144 222 { 145 223 block_thread_w_tmo(&q->thread, ticks); 146 224 } 147 225 148 - if (q->read != q->write) 226 + if(q->read != q->write) 149 227 { 150 - *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; 228 + unsigned int rd = q->read++ & QUEUE_LENGTH_MASK; 229 + *ev = q->events[rd]; 230 + 231 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 232 + if(q->send && q->send->senders[rd]) 233 + { 234 + /* Get data for a waiting thread if one */ 235 + queue_fetch_sender(q->send, rd); 236 + } 237 + #endif 151 238 } 152 239 else 153 240 { ··· 157 244 158 245 void queue_post(struct event_queue *q, long id, void *data) 159 246 { 160 - int wr; 161 - int oldlevel; 247 + int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 248 + unsigned int wr = q->write++ & QUEUE_LENGTH_MASK; 162 249 163 - oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 164 - wr = (q->write++) & QUEUE_LENGTH_MASK; 250 + q->events[wr].id = id; 251 + q->events[wr].data = data; 165 252 166 - q->events[wr].id = id; 253 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 254 + if(q->send) 255 + { 256 + struct queue_sender **spp = &q->send->senders[wr]; 257 + 258 + if(*spp) 259 + { 260 + /* overflow protect - unblock any thread waiting at this index */ 261 + queue_release_sender(spp, NULL); 262 + } 263 + } 264 + #endif 265 + 266 + wakeup_thread(&q->thread); 267 + set_irq_level(oldlevel); 268 + } 269 + 270 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 271 + void * queue_send(struct event_queue *q, long id, void *data) 272 + { 273 + int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 274 + unsigned int wr = q->write++ & QUEUE_LENGTH_MASK; 275 + 276 + q->events[wr].id = id; 167 277 q->events[wr].data = data; 168 - 278 + 279 + if(q->send) 280 + { 281 + struct queue_sender **spp = &q->send->senders[wr]; 282 + struct queue_sender sender; 283 + 284 + if(*spp) 285 + { 286 + /* overflow protect - unblock any thread waiting at this index */ 287 + queue_release_sender(spp, NULL); 288 + } 289 + 290 + *spp = &sender; 291 + sender.thread = NULL; 292 + 293 + wakeup_thread(&q->thread); 294 + set_irq_level_and_block_thread(&sender.thread, oldlevel); 295 + return sender.retval; 296 + } 297 + 298 + /* Function as queue_post if sending is not enabled */ 169 299 wakeup_thread(&q->thread); 170 - 171 300 set_irq_level(oldlevel); 301 + return NULL; 172 302 } 173 303 304 + #if 0 /* not used now but probably will be later */ 305 + /* Query if the last message dequeued was added by queue_send or not */ 306 + bool queue_in_queue_send(struct event_queue *q) 307 + { 308 + return q->send && q->send->curr_sender; 309 + } 310 + #endif 311 + 312 + /* Replies with retval to any dequeued message sent with queue_send */ 313 + void queue_reply(struct event_queue *q, void *retval) 314 + { 315 + if(q->send && q->send->curr_sender) 316 + { 317 + queue_release_sender(&q->send->curr_sender, retval); 318 + } 319 + } 320 + #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 321 + 174 322 bool queue_empty(const struct event_queue* q) 175 323 { 176 324 return ( q->read == q->write ); ··· 179 327 void queue_clear(struct event_queue* q) 180 328 { 181 329 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 330 + 331 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 332 + /* Release all thread waiting in the queue for a reply - 333 + dequeued sent message will be handled by owning thread */ 334 + queue_release_all_senders(q); 335 + #endif 336 + 182 337 q->read = 0; 183 338 q->write = 0; 184 339 set_irq_level(oldlevel); ··· 188 343 { 189 344 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 190 345 191 - while (q->read != q->write && 192 - q->events[(q->read) & QUEUE_LENGTH_MASK].id == id) 346 + while(q->read != q->write) 193 347 { 348 + unsigned int rd = q->read & QUEUE_LENGTH_MASK; 349 + 350 + if(q->events[rd].id != id) 351 + { 352 + break; 353 + } 354 + 355 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 356 + if(q->send) 357 + { 358 + struct queue_sender **spp = &q->send->senders[rd]; 359 + 360 + if(*spp) 361 + { 362 + /* Release any thread waiting on this message */ 363 + queue_release_sender(spp, NULL); 364 + } 365 + } 366 + #endif 194 367 q->read++; 195 368 } 196 369
+35
firmware/thread.c
··· 39 39 static int boosted_threads IBSS_ATTR; 40 40 #endif 41 41 42 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 43 + #define STAY_IRQ_LEVEL -1 44 + static int switch_to_irq_level = STAY_IRQ_LEVEL; 45 + #endif 46 + 42 47 /* Define to enable additional checks for blocking violations etc. */ 43 48 #define THREAD_EXTRA_CHECKS 44 49 ··· 388 393 389 394 /* Rearrange thread lists as needed */ 390 395 change_thread_state(blocked_list); 396 + 397 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 398 + /* This has to be done after the scheduler is finished with the 399 + blocked_list pointer so that an IRQ can't kill us by attempting 400 + a wake but before attempting any core sleep. */ 401 + if (switch_to_irq_level != STAY_IRQ_LEVEL) 402 + { 403 + int level = switch_to_irq_level; 404 + switch_to_irq_level = STAY_IRQ_LEVEL; 405 + set_irq_level(level); 406 + } 407 + #endif 391 408 } 392 409 393 410 /* Go through the list of sleeping task to check if we need to wake up ··· 471 488 /* Set the state to blocked and ask the scheduler to switch tasks, 472 489 * this takes us off of the run queue until we are explicitly woken */ 473 490 SET_STATE(current->statearg, STATE_BLOCKED, 0); 491 + 474 492 switch_thread(true, list); 475 493 476 494 #ifdef HAVE_SCHEDULER_BOOSTCTRL ··· 521 539 /* It is now safe for another thread to block on this "list" */ 522 540 *list = NULL; 523 541 } 542 + 543 + #if defined(HAVE_EXTENDED_MESSAGING_AND_NAME) && !defined(SIMULATOR) 544 + void set_irq_level_and_block_thread(struct thread_entry **list, int level) 545 + { 546 + switch_to_irq_level = level; 547 + block_thread(list); 548 + } 549 + 550 + #if 0 551 + void set_irq_level_and_block_thread_w_tmo(struct thread_entry **list, 552 + int timeout, int level) 553 + { 554 + switch_to_irq_level = level; 555 + block_thread_w_tmo(list, timeout); 556 + } 557 + #endif 558 + #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 524 559 525 560 void wakeup_thread(struct thread_entry **list) 526 561 {
+178 -11
uisimulator/sdl/kernel.c
··· 18 18 ****************************************************************************/ 19 19 20 20 #include <stdlib.h> 21 + #include "memory.h" 21 22 #include "uisdl.h" 22 23 #include "kernel.h" 23 24 #include "thread-sdl.h" ··· 32 33 return (_lv = level); 33 34 } 34 35 36 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 37 + /* Moves waiting thread's descriptor to the current sender when a 38 + message is dequeued */ 39 + static void queue_fetch_sender(struct queue_sender_list *send, 40 + unsigned int i) 41 + { 42 + int old_level = set_irq_level(15<<4); 43 + struct queue_sender **spp = &send->senders[i]; 44 + 45 + if(*spp) 46 + { 47 + send->curr_sender = *spp; 48 + *spp = NULL; 49 + } 50 + 51 + set_irq_level(old_level); 52 + } 53 + 54 + /* Puts the specified return value in the waiting thread's return value 55 + and wakes the thread - a sender should be confirmed to exist first */ 56 + static void queue_release_sender(struct queue_sender **sender, void *retval) 57 + { 58 + (*sender)->retval = retval; 59 + *sender = NULL; 60 + } 61 + 62 + /* Releases any waiting threads that are queued with queue_send - 63 + reply with NULL */ 64 + static void queue_release_all_senders(struct event_queue *q) 65 + { 66 + if(q->send) 67 + { 68 + unsigned int i; 69 + for(i = q->read; i != q->write; i++) 70 + { 71 + struct queue_sender **spp = 72 + &q->send->senders[i & QUEUE_LENGTH_MASK]; 73 + if(*spp) 74 + { 75 + queue_release_sender(spp, NULL); 76 + } 77 + } 78 + } 79 + } 80 + 81 + /* Enables queue_send on the specified queue - caller allocates the extra 82 + data structure */ 83 + void queue_enable_queue_send(struct event_queue *q, 84 + struct queue_sender_list *send) 85 + { 86 + q->send = send; 87 + memset(send, 0, sizeof(*send)); 88 + } 89 + #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 90 + 35 91 void queue_init(struct event_queue *q, bool register_queue) 36 92 { 37 93 (void)register_queue; 38 94 39 - q->read = 0; 40 - q->write = 0; 95 + q->read = 0; 96 + q->write = 0; 41 97 q->thread = NULL; 98 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 99 + q->send = NULL; /* No message sending by default */ 100 + #endif 42 101 } 43 102 44 103 void queue_delete(struct event_queue *q) ··· 48 107 49 108 void queue_wait(struct event_queue *q, struct event *ev) 50 109 { 110 + unsigned int rd; 111 + 51 112 while(q->read == q->write) 52 113 { 53 114 switch_thread(true, NULL); 54 115 } 55 116 56 - *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; 117 + rd = q->read++ & QUEUE_LENGTH_MASK; 118 + *ev = q->events[rd]; 119 + 120 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 121 + if(q->send && q->send->senders[rd]) 122 + { 123 + /* Get data for a waiting thread if one */ 124 + queue_fetch_sender(q->send, rd); 125 + } 126 + #endif 57 127 } 58 128 59 129 void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks) ··· 67 137 68 138 if(q->read != q->write) 69 139 { 70 - *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; 140 + unsigned int rd = q->read++ & QUEUE_LENGTH_MASK; 141 + *ev = q->events[rd]; 142 + 143 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 144 + if(q->send && q->send->senders[rd]) 145 + { 146 + /* Get data for a waiting thread if one */ 147 + queue_fetch_sender(q->send, rd); 148 + } 149 + #endif 71 150 } 72 151 else 73 152 { ··· 77 156 78 157 void queue_post(struct event_queue *q, long id, void *data) 79 158 { 80 - int wr; 81 - int oldlevel; 159 + int oldlevel = set_irq_level(15<<4); 160 + unsigned int wr = q->write++ & QUEUE_LENGTH_MASK; 161 + 162 + q->events[wr].id = id; 163 + q->events[wr].data = data; 164 + 165 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 166 + if(q->send) 167 + { 168 + struct queue_sender **spp = &q->send->senders[wr]; 82 169 83 - oldlevel = set_irq_level(15<<4); 84 - wr = (q->write++) & QUEUE_LENGTH_MASK; 170 + if(*spp) 171 + { 172 + /* overflow protect - unblock any thread waiting at this index */ 173 + queue_release_sender(spp, NULL); 174 + } 175 + } 176 + #endif 85 177 86 - q->events[wr].id = id; 178 + set_irq_level(oldlevel); 179 + } 180 + 181 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 182 + void * queue_send(struct event_queue *q, long id, void *data) 183 + { 184 + int oldlevel = set_irq_level(15<<4); 185 + unsigned int wr = q->write++ & QUEUE_LENGTH_MASK; 186 + 187 + q->events[wr].id = id; 87 188 q->events[wr].data = data; 189 + 190 + if(q->send) 191 + { 192 + struct queue_sender **spp = &q->send->senders[wr]; 193 + struct queue_sender sender; 194 + 195 + if(*spp) 196 + { 197 + /* overflow protect - unblock any thread waiting at this index */ 198 + queue_release_sender(spp, NULL); 199 + } 200 + 201 + *spp = &sender; 202 + 203 + set_irq_level(oldlevel); 204 + while (*spp != NULL) 205 + { 206 + switch_thread(true, NULL); 207 + } 208 + 209 + return sender.retval; 210 + } 211 + 212 + /* Function as queue_post if sending is not enabled */ 88 213 set_irq_level(oldlevel); 214 + return NULL; 89 215 } 90 216 217 + #if 0 /* not used now but probably will be later */ 218 + /* Query if the last message dequeued was added by queue_send or not */ 219 + bool queue_in_queue_send(struct event_queue *q) 220 + { 221 + return q->send && q->send->curr_sender; 222 + } 223 + #endif 224 + 225 + /* Replies with retval to any dequeued message sent with queue_send */ 226 + void queue_reply(struct event_queue *q, void *retval) 227 + { 228 + if(q->send && q->send->curr_sender) 229 + { 230 + queue_release_sender(&q->send->curr_sender, retval); 231 + } 232 + } 233 + #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 234 + 91 235 bool queue_empty(const struct event_queue* q) 92 236 { 93 237 return ( q->read == q->write ); ··· 96 240 void queue_clear(struct event_queue* q) 97 241 { 98 242 /* fixme: This is potentially unsafe in case we do interrupt-like processing */ 243 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 244 + /* Release all thread waiting in the queue for a reply - 245 + dequeued sent message will be handled by owning thread */ 246 + queue_release_all_senders(q); 247 + #endif 99 248 q->read = 0; 100 249 q->write = 0; 101 250 } ··· 104 253 { 105 254 int oldlevel = set_irq_level(15<<4); 106 255 107 - while (q->read != q->write && 108 - q->events[(q->read) & QUEUE_LENGTH_MASK].id == id) 256 + while(q->read != q->write) 109 257 { 258 + unsigned int rd = q->read & QUEUE_LENGTH_MASK; 259 + 260 + if(q->events[rd].id != id) 261 + { 262 + break; 263 + } 264 + 265 + #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 266 + if(q->send) 267 + { 268 + struct queue_sender **spp = &q->send->senders[rd]; 269 + 270 + if(*spp) 271 + { 272 + /* Release any thread waiting on this message */ 273 + queue_release_sender(spp, NULL); 274 + } 275 + } 276 + #endif 110 277 q->read++; 111 278 } 112 279