diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/backlight.c | 5 | ||||
-rw-r--r-- | firmware/buffer.c | 4 | ||||
-rw-r--r-- | firmware/common/dircache.c | 4 | ||||
-rw-r--r-- | firmware/drivers/ata.c | 5 | ||||
-rw-r--r-- | firmware/drivers/ata_mmc.c | 4 | ||||
-rw-r--r-- | firmware/drivers/button.c | 2 | ||||
-rw-r--r-- | firmware/drivers/fmradio_i2c.c | 6 | ||||
-rw-r--r-- | firmware/drivers/i2c.c | 6 | ||||
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 2 | ||||
-rw-r--r-- | firmware/drivers/lcd-2bit-horz.c | 2 | ||||
-rw-r--r-- | firmware/drivers/lcd-h100-remote.c | 7 | ||||
-rw-r--r-- | firmware/drivers/lcd-h100.c | 4 | ||||
-rw-r--r-- | firmware/drivers/lcd-player.c | 2 | ||||
-rw-r--r-- | firmware/drivers/lcd-recorder.c | 4 | ||||
-rwxr-xr-x | firmware/drivers/lcd-remote-2bit-vi.c | 7 | ||||
-rw-r--r-- | firmware/export/config.h | 8 | ||||
-rw-r--r-- | firmware/export/kernel.h | 4 | ||||
-rw-r--r-- | firmware/export/thread.h | 88 | ||||
-rw-r--r-- | firmware/kernel.c | 65 | ||||
-rw-r--r-- | firmware/mpeg.c | 14 | ||||
-rw-r--r-- | firmware/pcm_record.c | 28 | ||||
-rw-r--r-- | firmware/powermgmt.c | 2 | ||||
-rw-r--r-- | firmware/thread.c | 485 | ||||
-rw-r--r-- | firmware/usb.c | 5 |
24 files changed, 555 insertions, 208 deletions
diff --git a/firmware/backlight.c b/firmware/backlight.c index bf88cbe9bc..4e76072822 100644 --- a/firmware/backlight.c +++ b/firmware/backlight.c | |||
@@ -618,12 +618,13 @@ static void backlight_tick(void) | |||
618 | 618 | ||
619 | void backlight_init(void) | 619 | void backlight_init(void) |
620 | { | 620 | { |
621 | queue_init(&backlight_queue); | 621 | queue_init(&backlight_queue, true); |
622 | #ifdef X5_BACKLIGHT_SHUTDOWN | 622 | #ifdef X5_BACKLIGHT_SHUTDOWN |
623 | backlight_thread_id = | 623 | backlight_thread_id = |
624 | #endif | 624 | #endif |
625 | create_thread(backlight_thread, backlight_stack, | 625 | create_thread(backlight_thread, backlight_stack, |
626 | sizeof(backlight_stack), backlight_thread_name); | 626 | sizeof(backlight_stack), backlight_thread_name |
627 | IF_PRIO(, PRIORITY_SYSTEM)); | ||
627 | tick_add_task(backlight_tick); | 628 | tick_add_task(backlight_tick); |
628 | #ifdef SIMULATOR | 629 | #ifdef SIMULATOR |
629 | /* do nothing */ | 630 | /* do nothing */ |
diff --git a/firmware/buffer.c b/firmware/buffer.c index 1eaff33de1..6af8eb9432 100644 --- a/firmware/buffer.c +++ b/firmware/buffer.c | |||
@@ -40,7 +40,9 @@ void *buffer_alloc(size_t size) | |||
40 | void *retval = audiobuf; | 40 | void *retval = audiobuf; |
41 | 41 | ||
42 | audiobuf += size; | 42 | audiobuf += size; |
43 | /* 32-bit aligned */; | 43 | /* 32-bit aligned */ |
44 | audiobuf = (void *)(((unsigned long)audiobuf + 3) & ~3); | 44 | audiobuf = (void *)(((unsigned long)audiobuf + 3) & ~3); |
45 | |||
45 | return retval; | 46 | return retval; |
46 | } | 47 | } |
48 | |||
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 17033e1827..0bdd0657bd 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c | |||
@@ -690,9 +690,9 @@ void dircache_init(void) | |||
690 | opendirs[i].secondary_entry.d_name = buffer_alloc(MAX_PATH); | 690 | opendirs[i].secondary_entry.d_name = buffer_alloc(MAX_PATH); |
691 | } | 691 | } |
692 | 692 | ||
693 | queue_init(&dircache_queue); | 693 | queue_init(&dircache_queue, true); |
694 | create_thread(dircache_thread, dircache_stack, | 694 | create_thread(dircache_thread, dircache_stack, |
695 | sizeof(dircache_stack), dircache_thread_name); | 695 | sizeof(dircache_stack), dircache_thread_name IF_PRIO(, PRIORITY_BACKGROUND)); |
696 | } | 696 | } |
697 | 697 | ||
698 | /** | 698 | /** |
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 8593eebea1..f57088504b 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -1932,11 +1932,12 @@ int ata_init(void) | |||
1932 | if (rc) | 1932 | if (rc) |
1933 | return -60 + rc; | 1933 | return -60 + rc; |
1934 | 1934 | ||
1935 | queue_init(&ata_queue); | 1935 | queue_init(&ata_queue, true); |
1936 | 1936 | ||
1937 | last_disk_activity = current_tick; | 1937 | last_disk_activity = current_tick; |
1938 | create_thread(ata_thread, ata_stack, | 1938 | create_thread(ata_thread, ata_stack, |
1939 | sizeof(ata_stack), ata_thread_name); | 1939 | sizeof(ata_stack), ata_thread_name |
1940 | IF_PRIO(, PRIORITY_SYSTEM)); | ||
1940 | initialized = true; | 1941 | initialized = true; |
1941 | 1942 | ||
1942 | } | 1943 | } |
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c index b2e79c419a..6303ca2851 100644 --- a/firmware/drivers/ata_mmc.c +++ b/firmware/drivers/ata_mmc.c | |||
@@ -1182,9 +1182,9 @@ int ata_init(void) | |||
1182 | if (!last_mmc_status) | 1182 | if (!last_mmc_status) |
1183 | mmc_status = MMC_UNTOUCHED; | 1183 | mmc_status = MMC_UNTOUCHED; |
1184 | #ifdef HAVE_HOTSWAP | 1184 | #ifdef HAVE_HOTSWAP |
1185 | queue_init(&mmc_queue); | 1185 | queue_init(&mmc_queue, true); |
1186 | create_thread(mmc_thread, mmc_stack, | 1186 | create_thread(mmc_thread, mmc_stack, |
1187 | sizeof(mmc_stack), mmc_thread_name); | 1187 | sizeof(mmc_stack), mmc_thread_name IF_PRIO(, PRIORITY_SYSTEM)); |
1188 | #endif | 1188 | #endif |
1189 | tick_add_task(mmc_tick); | 1189 | tick_add_task(mmc_tick); |
1190 | initialized = true; | 1190 | initialized = true; |
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index daad4f17de..6536a34037 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c | |||
@@ -674,7 +674,7 @@ void button_init(void) | |||
674 | GPIOA_INT_CLR = GPIOA_INT_STAT; | 674 | GPIOA_INT_CLR = GPIOA_INT_STAT; |
675 | GPIOA_INT_EN = 0xff; | 675 | GPIOA_INT_EN = 0xff; |
676 | #endif /* CONFIG_KEYPAD */ | 676 | #endif /* CONFIG_KEYPAD */ |
677 | queue_init(&button_queue); | 677 | queue_init(&button_queue, true); |
678 | button_read(); | 678 | button_read(); |
679 | lastbtn = button_read(); | 679 | lastbtn = button_read(); |
680 | tick_add_task(button_tick); | 680 | tick_add_task(button_tick); |
diff --git a/firmware/drivers/fmradio_i2c.c b/firmware/drivers/fmradio_i2c.c index 6f87e15b3e..62761b3aa7 100644 --- a/firmware/drivers/fmradio_i2c.c +++ b/firmware/drivers/fmradio_i2c.c | |||
@@ -317,8 +317,7 @@ static void fmradio_i2c_ack(int bit) | |||
317 | 317 | ||
318 | SCL_INPUT; /* Set the clock to input */ | 318 | SCL_INPUT; /* Set the clock to input */ |
319 | while(!SCL) /* and wait for the slave to release it */ | 319 | while(!SCL) /* and wait for the slave to release it */ |
320 | sleep_thread(); | 320 | sleep_thread(0); |
321 | wake_up_thread(); | ||
322 | 321 | ||
323 | DELAY; | 322 | DELAY; |
324 | SCL_OUTPUT; | 323 | SCL_OUTPUT; |
@@ -337,8 +336,7 @@ static int fmradio_i2c_getack(void) | |||
337 | SDA_INPUT; /* And set to input */ | 336 | SDA_INPUT; /* And set to input */ |
338 | SCL_INPUT; /* Set the clock to input */ | 337 | SCL_INPUT; /* Set the clock to input */ |
339 | while(!SCL) /* and wait for the slave to release it */ | 338 | while(!SCL) /* and wait for the slave to release it */ |
340 | sleep_thread(); | 339 | sleep_thread(0); |
341 | wake_up_thread(); | ||
342 | 340 | ||
343 | if (SDA) | 341 | if (SDA) |
344 | /* ack failed */ | 342 | /* ack failed */ |
diff --git a/firmware/drivers/i2c.c b/firmware/drivers/i2c.c index 71cb9cf8b0..2b439c23ad 100644 --- a/firmware/drivers/i2c.c +++ b/firmware/drivers/i2c.c | |||
@@ -145,8 +145,7 @@ void i2c_ack(int bit) | |||
145 | 145 | ||
146 | SCL_INPUT; /* Set the clock to input */ | 146 | SCL_INPUT; /* Set the clock to input */ |
147 | while(!SCL) /* and wait for the MAS to release it */ | 147 | while(!SCL) /* and wait for the MAS to release it */ |
148 | sleep_thread(); | 148 | sleep_thread(1); |
149 | wake_up_thread(); | ||
150 | 149 | ||
151 | DELAY; | 150 | DELAY; |
152 | SCL_OUTPUT; | 151 | SCL_OUTPUT; |
@@ -168,8 +167,7 @@ int i2c_getack(void) | |||
168 | SDA_INPUT; /* And set to input */ | 167 | SDA_INPUT; /* And set to input */ |
169 | SCL_INPUT; /* Set the clock to input */ | 168 | SCL_INPUT; /* Set the clock to input */ |
170 | while(!SCL) /* and wait for the MAS to release it */ | 169 | while(!SCL) /* and wait for the MAS to release it */ |
171 | sleep_thread(); | 170 | sleep_thread(1); |
172 | wake_up_thread(); | ||
173 | 171 | ||
174 | if (SDA) | 172 | if (SDA) |
175 | /* ack failed */ | 173 | /* ack failed */ |
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index e6ae28bc19..47c02ea7b7 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -79,7 +79,7 @@ void lcd_init(void) | |||
79 | /* Call device specific init */ | 79 | /* Call device specific init */ |
80 | lcd_init_device(); | 80 | lcd_init_device(); |
81 | create_thread(scroll_thread, scroll_stack, | 81 | create_thread(scroll_thread, scroll_stack, |
82 | sizeof(scroll_stack), scroll_name); | 82 | sizeof(scroll_stack), scroll_name, PRIORITY_SYSTEM); |
83 | } | 83 | } |
84 | 84 | ||
85 | /*** parameter handling ***/ | 85 | /*** parameter handling ***/ |
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c index 33f483d38d..dc49a37c8a 100644 --- a/firmware/drivers/lcd-2bit-horz.c +++ b/firmware/drivers/lcd-2bit-horz.c | |||
@@ -76,7 +76,7 @@ void lcd_init(void) | |||
76 | /* Call device specific init */ | 76 | /* Call device specific init */ |
77 | lcd_init_device(); | 77 | lcd_init_device(); |
78 | create_thread(scroll_thread, scroll_stack, | 78 | create_thread(scroll_thread, scroll_stack, |
79 | sizeof(scroll_stack), scroll_name); | 79 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
80 | } | 80 | } |
81 | 81 | ||
82 | /*** parameter handling ***/ | 82 | /*** parameter handling ***/ |
diff --git a/firmware/drivers/lcd-h100-remote.c b/firmware/drivers/lcd-h100-remote.c index ed5816cebf..5db6d548ff 100644 --- a/firmware/drivers/lcd-h100-remote.c +++ b/firmware/drivers/lcd-h100-remote.c | |||
@@ -573,7 +573,7 @@ static void remote_tick(void) | |||
573 | void lcd_remote_init(void) | 573 | void lcd_remote_init(void) |
574 | { | 574 | { |
575 | create_thread(scroll_thread, scroll_stack, | 575 | create_thread(scroll_thread, scroll_stack, |
576 | sizeof(scroll_stack), scroll_name); | 576 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
577 | } | 577 | } |
578 | #else /* !SIMULATOR */ | 578 | #else /* !SIMULATOR */ |
579 | 579 | ||
@@ -601,10 +601,11 @@ void lcd_remote_init(void) | |||
601 | #endif | 601 | #endif |
602 | lcd_remote_clear_display(); | 602 | lcd_remote_clear_display(); |
603 | 603 | ||
604 | queue_clear(&remote_scroll_queue); /* no queue_init() -- private queue */ | 604 | /* private queue */ |
605 | queue_init(&remote_scroll_queue, false); | ||
605 | tick_add_task(remote_tick); | 606 | tick_add_task(remote_tick); |
606 | create_thread(scroll_thread, scroll_stack, | 607 | create_thread(scroll_thread, scroll_stack, |
607 | sizeof(scroll_stack), scroll_name); | 608 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
608 | } | 609 | } |
609 | 610 | ||
610 | /*** update functions ***/ | 611 | /*** update functions ***/ |
diff --git a/firmware/drivers/lcd-h100.c b/firmware/drivers/lcd-h100.c index 8407876d34..ada6f29216 100644 --- a/firmware/drivers/lcd-h100.c +++ b/firmware/drivers/lcd-h100.c | |||
@@ -144,7 +144,7 @@ void lcd_set_flip(bool yesno) | |||
144 | void lcd_init(void) | 144 | void lcd_init(void) |
145 | { | 145 | { |
146 | create_thread(scroll_thread, scroll_stack, | 146 | create_thread(scroll_thread, scroll_stack, |
147 | sizeof(scroll_stack), scroll_name); | 147 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
148 | } | 148 | } |
149 | #else | 149 | #else |
150 | 150 | ||
@@ -193,7 +193,7 @@ void lcd_init(void) | |||
193 | lcd_write_command(LCD_CNTL_ON_OFF | 1); /* LCD ON */ | 193 | lcd_write_command(LCD_CNTL_ON_OFF | 1); /* LCD ON */ |
194 | 194 | ||
195 | create_thread(scroll_thread, scroll_stack, | 195 | create_thread(scroll_thread, scroll_stack, |
196 | sizeof(scroll_stack), scroll_name); | 196 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
197 | } | 197 | } |
198 | 198 | ||
199 | /*** update functions ***/ | 199 | /*** update functions ***/ |
diff --git a/firmware/drivers/lcd-player.c b/firmware/drivers/lcd-player.c index 16012470fa..050258d1f8 100644 --- a/firmware/drivers/lcd-player.c +++ b/firmware/drivers/lcd-player.c | |||
@@ -610,7 +610,7 @@ void lcd_init (void) | |||
610 | lcd_set_contrast(lcd_default_contrast()); | 610 | lcd_set_contrast(lcd_default_contrast()); |
611 | 611 | ||
612 | create_thread(scroll_thread, scroll_stack, | 612 | create_thread(scroll_thread, scroll_stack, |
613 | sizeof(scroll_stack), scroll_name); | 613 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
614 | } | 614 | } |
615 | 615 | ||
616 | void lcd_jump_scroll (int mode) /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */ | 616 | void lcd_jump_scroll (int mode) /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */ |
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c index 1987d9a3ed..e74cad7f03 100644 --- a/firmware/drivers/lcd-recorder.c +++ b/firmware/drivers/lcd-recorder.c | |||
@@ -232,7 +232,7 @@ void lcd_set_flip(bool yesno) | |||
232 | void lcd_init(void) | 232 | void lcd_init(void) |
233 | { | 233 | { |
234 | create_thread(scroll_thread, scroll_stack, | 234 | create_thread(scroll_thread, scroll_stack, |
235 | sizeof(scroll_stack), scroll_name); | 235 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
236 | } | 236 | } |
237 | #else | 237 | #else |
238 | 238 | ||
@@ -278,7 +278,7 @@ void lcd_init(void) | |||
278 | lcd_update(); | 278 | lcd_update(); |
279 | 279 | ||
280 | create_thread(scroll_thread, scroll_stack, | 280 | create_thread(scroll_thread, scroll_stack, |
281 | sizeof(scroll_stack), scroll_name); | 281 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
282 | } | 282 | } |
283 | 283 | ||
284 | /*** Update functions ***/ | 284 | /*** Update functions ***/ |
diff --git a/firmware/drivers/lcd-remote-2bit-vi.c b/firmware/drivers/lcd-remote-2bit-vi.c index 48f8b8a25f..bae2824050 100755 --- a/firmware/drivers/lcd-remote-2bit-vi.c +++ b/firmware/drivers/lcd-remote-2bit-vi.c | |||
@@ -1167,7 +1167,7 @@ static void scroll_thread(void) | |||
1167 | void lcd_remote_init(void) | 1167 | void lcd_remote_init(void) |
1168 | { | 1168 | { |
1169 | create_thread(scroll_thread, scroll_stack, | 1169 | create_thread(scroll_thread, scroll_stack, |
1170 | sizeof(scroll_stack), scroll_name); | 1170 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
1171 | } | 1171 | } |
1172 | #else | 1172 | #else |
1173 | void lcd_remote_init(void) | 1173 | void lcd_remote_init(void) |
@@ -1176,9 +1176,10 @@ void lcd_remote_init(void) | |||
1176 | lcd_remote_init_device(); | 1176 | lcd_remote_init_device(); |
1177 | 1177 | ||
1178 | lcd_remote_clear_display(); | 1178 | lcd_remote_clear_display(); |
1179 | queue_clear(&remote_scroll_queue); /* no queue_init() -- private queue */ | 1179 | /* private queue */ |
1180 | queue_init(&remote_scroll_queue, false); | ||
1180 | tick_add_task(remote_tick); | 1181 | tick_add_task(remote_tick); |
1181 | create_thread(scroll_thread, scroll_stack, | 1182 | create_thread(scroll_thread, scroll_stack, |
1182 | sizeof(scroll_stack), scroll_name); | 1183 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_SYSTEM)); |
1183 | } | 1184 | } |
1184 | #endif | 1185 | #endif |
diff --git a/firmware/export/config.h b/firmware/export/config.h index 18adaeeca2..1b756cc6bd 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h | |||
@@ -216,8 +216,12 @@ | |||
216 | /* Enable the directory cache and tagcache in RAM if we have | 216 | /* Enable the directory cache and tagcache in RAM if we have |
217 | * plenty of RAM. Both features can be enabled independently. */ | 217 | * plenty of RAM. Both features can be enabled independently. */ |
218 | #if (MEMORYSIZE > 8 || MEM > 8) && !defined(BOOTLOADER) | 218 | #if (MEMORYSIZE > 8 || MEM > 8) && !defined(BOOTLOADER) |
219 | #define HAVE_DIRCACHE 1 | 219 | #define HAVE_DIRCACHE |
220 | #define HAVE_TC_RAMCACHE 1 | 220 | #define HAVE_TC_RAMCACHE |
221 | #endif | ||
222 | |||
223 | #if (CONFIG_CODEC == SWCODEC) && !defined(SIMULATOR) && !defined(BOOTLOADER) | ||
224 | #define HAVE_PRIORITY_SCHEDULING | ||
221 | #endif | 225 | #endif |
222 | 226 | ||
223 | /* define for all cpus from coldfire family */ | 227 | /* define for all cpus from coldfire family */ |
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index 26b1cbe2e7..482516b9dc 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h | |||
@@ -56,12 +56,14 @@ struct event | |||
56 | struct event_queue | 56 | struct event_queue |
57 | { | 57 | { |
58 | struct event events[QUEUE_LENGTH]; | 58 | struct event events[QUEUE_LENGTH]; |
59 | struct thread_entry *thread; | ||
59 | unsigned int read; | 60 | unsigned int read; |
60 | unsigned int write; | 61 | unsigned int write; |
61 | }; | 62 | }; |
62 | 63 | ||
63 | struct mutex | 64 | struct mutex |
64 | { | 65 | { |
66 | struct thread_entry *thread; | ||
65 | bool locked; | 67 | bool locked; |
66 | }; | 68 | }; |
67 | 69 | ||
@@ -85,7 +87,7 @@ extern void sleep(int ticks); | |||
85 | int tick_add_task(void (*f)(void)); | 87 | int tick_add_task(void (*f)(void)); |
86 | int tick_remove_task(void (*f)(void)); | 88 | int tick_remove_task(void (*f)(void)); |
87 | 89 | ||
88 | extern void queue_init(struct event_queue *q); | 90 | extern void queue_init(struct event_queue *q, bool register_queue); |
89 | extern void queue_delete(struct event_queue *q); | 91 | extern void queue_delete(struct event_queue *q); |
90 | extern void queue_wait(struct event_queue *q, struct event *ev); | 92 | extern void queue_wait(struct event_queue *q, struct event *ev); |
91 | extern void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks); | 93 | extern void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks); |
diff --git a/firmware/export/thread.h b/firmware/export/thread.h index e102997dae..7e053bc507 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h | |||
@@ -21,8 +21,24 @@ | |||
21 | 21 | ||
22 | #include <stdbool.h> | 22 | #include <stdbool.h> |
23 | 23 | ||
24 | /* Priority scheduling (when enabled with HAVE_PRIORITY_SCHEDULING) works | ||
25 | * by giving high priority threads more CPU time than less priority threads | ||
26 | * when they need it. | ||
27 | * | ||
28 | * If software playback codec pcm buffer is going down to critical, codec | ||
29 | * can change it own priority to REALTIME to override user interface and | ||
30 | * prevent playback skipping. | ||
31 | */ | ||
32 | #define PRIORITY_REALTIME 1 | ||
33 | #define PRIORITY_USER_INTERFACE 4 /* The main thread */ | ||
34 | #define PRIORITY_RECORDING 4 /* Recording thread */ | ||
35 | #define PRIORITY_PLAYBACK 4 /* or REALTIME when needed */ | ||
36 | #define PRIORITY_BUFFERING 4 /* Codec buffering thread */ | ||
37 | #define PRIORITY_SYSTEM 6 /* All other firmware threads */ | ||
38 | #define PRIORITY_BACKGROUND 8 /* Normal application threads */ | ||
39 | |||
24 | #if CONFIG_CODEC == SWCODEC | 40 | #if CONFIG_CODEC == SWCODEC |
25 | #define MAXTHREADS 16 | 41 | #define MAXTHREADS 15 |
26 | #else | 42 | #else |
27 | #define MAXTHREADS 11 | 43 | #define MAXTHREADS 11 |
28 | #endif | 44 | #endif |
@@ -32,7 +48,7 @@ | |||
32 | #ifndef SIMULATOR | 48 | #ifndef SIMULATOR |
33 | /* Need to keep structures inside the header file because debug_menu | 49 | /* Need to keep structures inside the header file because debug_menu |
34 | * needs them. */ | 50 | * needs them. */ |
35 | #ifdef CPU_COLDFIRE | 51 | # ifdef CPU_COLDFIRE |
36 | struct regs | 52 | struct regs |
37 | { | 53 | { |
38 | unsigned int macsr; /* EMAC status register */ | 54 | unsigned int macsr; /* EMAC status register */ |
@@ -41,7 +57,7 @@ struct regs | |||
41 | void *sp; /* Stack pointer (a7) */ | 57 | void *sp; /* Stack pointer (a7) */ |
42 | void *start; /* Thread start address, or NULL when started */ | 58 | void *start; /* Thread start address, or NULL when started */ |
43 | }; | 59 | }; |
44 | #elif CONFIG_CPU == SH7034 | 60 | # elif CONFIG_CPU == SH7034 |
45 | struct regs | 61 | struct regs |
46 | { | 62 | { |
47 | unsigned int r[7]; /* Registers r8 thru r14 */ | 63 | unsigned int r[7]; /* Registers r8 thru r14 */ |
@@ -49,7 +65,7 @@ struct regs | |||
49 | void *pr; /* Procedure register */ | 65 | void *pr; /* Procedure register */ |
50 | void *start; /* Thread start address, or NULL when started */ | 66 | void *start; /* Thread start address, or NULL when started */ |
51 | }; | 67 | }; |
52 | #elif defined(CPU_ARM) | 68 | # elif defined(CPU_ARM) |
53 | struct regs | 69 | struct regs |
54 | { | 70 | { |
55 | unsigned int r[8]; /* Registers r4-r11 */ | 71 | unsigned int r[8]; /* Registers r4-r11 */ |
@@ -57,42 +73,72 @@ struct regs | |||
57 | unsigned int lr; /* r14 (lr) */ | 73 | unsigned int lr; /* r14 (lr) */ |
58 | void *start; /* Thread start address, or NULL when started */ | 74 | void *start; /* Thread start address, or NULL when started */ |
59 | }; | 75 | }; |
60 | #elif CONFIG_CPU == TCC730 | 76 | # elif CONFIG_CPU == TCC730 |
61 | struct regs | 77 | struct regs |
62 | { | 78 | { |
63 | void *sp; /* Stack pointer (a15) */ | 79 | void *sp; /* Stack pointer (a15) */ |
64 | void *start; /* Thread start address */ | 80 | void *start; /* Thread start address */ |
65 | int started; /* 0 when not started */ | 81 | int started; /* 0 when not started */ |
66 | }; | 82 | }; |
67 | #endif | 83 | # endif |
84 | |||
85 | #endif /* !SIMULATOR */ | ||
86 | |||
87 | #define STATE_RUNNING 0 | ||
88 | #define STATE_BLOCKED 1 | ||
89 | #define STATE_SLEEPING 2 | ||
90 | #define STATE_BLOCKED_W_TMO 3 | ||
91 | |||
92 | #define GET_STATE_ARG(state) (state & 0x3FFFFFFF) | ||
93 | #define GET_STATE(state) ((state >> 30) & 3) | ||
94 | #define SET_STATE(state,arg) ((state << 30) | (arg)) | ||
68 | 95 | ||
69 | struct thread_entry { | 96 | struct thread_entry { |
97 | #ifndef SIMULATOR | ||
70 | struct regs context; | 98 | struct regs context; |
99 | #endif | ||
71 | const char *name; | 100 | const char *name; |
72 | void *stack; | 101 | void *stack; |
73 | int stack_size; | 102 | unsigned long statearg; |
103 | unsigned short stack_size; | ||
104 | #ifdef HAVE_PRIORITY_SCHEDULING | ||
105 | unsigned short priority; | ||
106 | long last_run; | ||
107 | #endif | ||
108 | struct thread_entry *next, *prev; | ||
74 | }; | 109 | }; |
75 | 110 | ||
76 | struct core_entry { | 111 | struct core_entry { |
77 | int num_threads; | ||
78 | volatile int num_sleepers; | ||
79 | int current_thread; | ||
80 | struct thread_entry threads[MAXTHREADS]; | 112 | struct thread_entry threads[MAXTHREADS]; |
113 | struct thread_entry *running; | ||
114 | struct thread_entry *sleeping; | ||
81 | }; | 115 | }; |
116 | |||
117 | #ifdef HAVE_PRIORITY_SCHEDULING | ||
118 | #define IF_PRIO(empty, type) , type | ||
119 | #else | ||
120 | #define IF_PRIO(empty, type) | ||
82 | #endif | 121 | #endif |
83 | 122 | ||
84 | int create_thread(void (*function)(void), void* stack, int stack_size, | 123 | struct thread_entry* |
85 | const char *name); | 124 | create_thread(void (*function)(void), void* stack, int stack_size, |
86 | int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size, | 125 | const char *name IF_PRIO(, int priority)); |
87 | const char *name); | 126 | |
88 | void remove_thread(int threadnum); | 127 | struct thread_entry* |
89 | void remove_thread_on_core(unsigned int core, int threadnum); | 128 | create_thread_on_core(unsigned int core, void (*function)(void), |
90 | void switch_thread(void); | 129 | void* stack, int stack_size, |
91 | void sleep_thread(void); | 130 | const char *name |
92 | void wake_up_thread(void); | 131 | IF_PRIO(, int priority)); |
132 | |||
133 | void remove_thread(struct thread_entry *thread); | ||
134 | void switch_thread(bool save_context, struct thread_entry **blocked_list); | ||
135 | void sleep_thread(int ticks); | ||
136 | void block_thread(struct thread_entry **thread, int timeout); | ||
137 | void wakeup_thread(struct thread_entry **thread); | ||
138 | void thread_set_priority(struct thread_entry *thread, int priority); | ||
93 | void init_threads(void); | 139 | void init_threads(void); |
94 | int thread_stack_usage(int threadnum); | 140 | int thread_stack_usage(const struct thread_entry *thread); |
95 | int thread_stack_usage_on_core(unsigned int core, int threadnum); | 141 | int thread_get_status(const struct thread_entry *thread); |
96 | #ifdef RB_PROFILE | 142 | #ifdef RB_PROFILE |
97 | void profile_thread(void); | 143 | void profile_thread(void); |
98 | #endif | 144 | #endif |
diff --git a/firmware/kernel.c b/firmware/kernel.c index 889f950252..4a6d61515a 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c | |||
@@ -35,7 +35,6 @@ static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); | |||
35 | static struct event_queue *all_queues[32]; | 35 | static struct event_queue *all_queues[32]; |
36 | static int num_queues; | 36 | static int num_queues; |
37 | 37 | ||
38 | void sleep(int ticks) ICODE_ATTR; | ||
39 | void queue_wait(struct event_queue *q, struct event *ev) ICODE_ATTR; | 38 | void queue_wait(struct event_queue *q, struct event *ev) ICODE_ATTR; |
40 | 39 | ||
41 | /**************************************************************************** | 40 | /**************************************************************************** |
@@ -71,13 +70,7 @@ void sleep(int ticks) | |||
71 | } while(counter > 0); | 70 | } while(counter > 0); |
72 | 71 | ||
73 | #else | 72 | #else |
74 | /* Always sleep at least 1 tick */ | 73 | sleep_thread(ticks); |
75 | int timeout = current_tick + ticks + 1; | ||
76 | |||
77 | while (TIME_BEFORE( current_tick, timeout )) { | ||
78 | sleep_thread(); | ||
79 | } | ||
80 | wake_up_thread(); | ||
81 | #endif | 74 | #endif |
82 | } | 75 | } |
83 | 76 | ||
@@ -86,21 +79,24 @@ void yield(void) | |||
86 | #if (CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022) && defined(BOOTLOADER)) | 79 | #if (CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022) && defined(BOOTLOADER)) |
87 | /* Some targets don't like yielding in the bootloader */ | 80 | /* Some targets don't like yielding in the bootloader */ |
88 | #else | 81 | #else |
89 | switch_thread(); | 82 | switch_thread(true, NULL); |
90 | wake_up_thread(); | ||
91 | #endif | 83 | #endif |
92 | } | 84 | } |
93 | 85 | ||
94 | /**************************************************************************** | 86 | /**************************************************************************** |
95 | * Queue handling stuff | 87 | * Queue handling stuff |
96 | ****************************************************************************/ | 88 | ****************************************************************************/ |
97 | void queue_init(struct event_queue *q) | 89 | void queue_init(struct event_queue *q, bool register_queue) |
98 | { | 90 | { |
99 | q->read = 0; | 91 | q->read = 0; |
100 | q->write = 0; | 92 | q->write = 0; |
101 | 93 | q->thread = NULL; | |
102 | /* Add it to the all_queues array */ | 94 | |
103 | all_queues[num_queues++] = q; | 95 | if (register_queue) |
96 | { | ||
97 | /* Add it to the all_queues array */ | ||
98 | all_queues[num_queues++] = q; | ||
99 | } | ||
104 | } | 100 | } |
105 | 101 | ||
106 | void queue_delete(struct event_queue *q) | 102 | void queue_delete(struct event_queue *q) |
@@ -108,6 +104,8 @@ void queue_delete(struct event_queue *q) | |||
108 | int i; | 104 | int i; |
109 | bool found = false; | 105 | bool found = false; |
110 | 106 | ||
107 | wakeup_thread(&q->thread); | ||
108 | |||
111 | /* Find the queue to be deleted */ | 109 | /* Find the queue to be deleted */ |
112 | for(i = 0;i < num_queues;i++) | 110 | for(i = 0;i < num_queues;i++) |
113 | { | 111 | { |
@@ -132,26 +130,22 @@ void queue_delete(struct event_queue *q) | |||
132 | 130 | ||
133 | void queue_wait(struct event_queue *q, struct event *ev) | 131 | void queue_wait(struct event_queue *q, struct event *ev) |
134 | { | 132 | { |
135 | while(q->read == q->write) | 133 | if (q->read == q->write) |
136 | { | 134 | { |
137 | sleep_thread(); | 135 | block_thread(&q->thread, 0); |
138 | } | 136 | } |
139 | wake_up_thread(); | ||
140 | 137 | ||
141 | *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; | 138 | *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; |
142 | } | 139 | } |
143 | 140 | ||
144 | void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks) | 141 | void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks) |
145 | { | 142 | { |
146 | unsigned int timeout = current_tick + ticks; | 143 | if (q->read == q->write && ticks > 0) |
147 | |||
148 | while(q->read == q->write && TIME_BEFORE( current_tick, timeout )) | ||
149 | { | 144 | { |
150 | sleep_thread(); | 145 | block_thread(&q->thread, ticks); |
151 | } | 146 | } |
152 | wake_up_thread(); | ||
153 | 147 | ||
154 | if(q->read != q->write) | 148 | if (q->read != q->write) |
155 | { | 149 | { |
156 | *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; | 150 | *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; |
157 | } | 151 | } |
@@ -171,6 +165,9 @@ void queue_post(struct event_queue *q, long id, void *data) | |||
171 | 165 | ||
172 | q->events[wr].id = id; | 166 | q->events[wr].id = id; |
173 | q->events[wr].data = data; | 167 | q->events[wr].data = data; |
168 | |||
169 | wakeup_thread(&q->thread); | ||
170 | |||
174 | set_irq_level(oldlevel); | 171 | set_irq_level(oldlevel); |
175 | } | 172 | } |
176 | 173 | ||
@@ -250,7 +247,6 @@ void IMIA0(void) | |||
250 | } | 247 | } |
251 | 248 | ||
252 | current_tick++; | 249 | current_tick++; |
253 | wake_up_thread(); | ||
254 | 250 | ||
255 | TSR0 &= ~0x01; | 251 | TSR0 &= ~0x01; |
256 | } | 252 | } |
@@ -301,7 +297,6 @@ void TIMER0(void) | |||
301 | } | 297 | } |
302 | 298 | ||
303 | current_tick++; | 299 | current_tick++; |
304 | wake_up_thread(); | ||
305 | 300 | ||
306 | TER0 = 0xff; /* Clear all events */ | 301 | TER0 = 0xff; /* Clear all events */ |
307 | } | 302 | } |
@@ -330,7 +325,6 @@ void TIMER0(void) | |||
330 | } | 325 | } |
331 | 326 | ||
332 | current_tick++; | 327 | current_tick++; |
333 | wake_up_thread(); | ||
334 | 328 | ||
335 | /* re-enable timer by clearing the counter */ | 329 | /* re-enable timer by clearing the counter */ |
336 | TACON |= 0x80; | 330 | TACON |= 0x80; |
@@ -382,7 +376,6 @@ void TIMER1(void) | |||
382 | } | 376 | } |
383 | 377 | ||
384 | current_tick++; | 378 | current_tick++; |
385 | wake_up_thread(); | ||
386 | } | 379 | } |
387 | #endif | 380 | #endif |
388 | 381 | ||
@@ -415,7 +408,6 @@ void timer_handler(void) | |||
415 | } | 408 | } |
416 | 409 | ||
417 | current_tick++; | 410 | current_tick++; |
418 | wake_up_thread(); | ||
419 | 411 | ||
420 | TIMERR0C = 1; | 412 | TIMERR0C = 1; |
421 | } | 413 | } |
@@ -513,22 +505,27 @@ int tick_remove_task(void (*f)(void)) | |||
513 | void mutex_init(struct mutex *m) | 505 | void mutex_init(struct mutex *m) |
514 | { | 506 | { |
515 | m->locked = false; | 507 | m->locked = false; |
508 | m->thread = NULL; | ||
516 | } | 509 | } |
517 | 510 | ||
518 | void mutex_lock(struct mutex *m) | 511 | void mutex_lock(struct mutex *m) |
519 | { | 512 | { |
520 | /* Wait until the lock is open... */ | 513 | if (m->locked) |
521 | while(m->locked) | 514 | { |
522 | sleep_thread(); | 515 | /* Wait until the lock is open... */ |
523 | wake_up_thread(); | 516 | block_thread(&m->thread, 0); |
524 | 517 | } | |
518 | |||
525 | /* ...and lock it */ | 519 | /* ...and lock it */ |
526 | m->locked = true; | 520 | m->locked = true; |
527 | } | 521 | } |
528 | 522 | ||
529 | void mutex_unlock(struct mutex *m) | 523 | void mutex_unlock(struct mutex *m) |
530 | { | 524 | { |
531 | m->locked = false; | 525 | if (m->thread == NULL) |
526 | m->locked = false; | ||
527 | else | ||
528 | wakeup_thread(&m->thread); | ||
532 | } | 529 | } |
533 | 530 | ||
534 | #endif | 531 | #endif |
diff --git a/firmware/mpeg.c b/firmware/mpeg.c index df0cbbad12..61b0a22d87 100644 --- a/firmware/mpeg.c +++ b/firmware/mpeg.c | |||
@@ -761,7 +761,6 @@ void rec_tick(void) | |||
761 | { | 761 | { |
762 | prerecord_timeout = current_tick + HZ; | 762 | prerecord_timeout = current_tick + HZ; |
763 | queue_post(&mpeg_queue, MPEG_PRERECORDING_TICK, 0); | 763 | queue_post(&mpeg_queue, MPEG_PRERECORDING_TICK, 0); |
764 | wake_up_thread(); | ||
765 | } | 764 | } |
766 | } | 765 | } |
767 | else | 766 | else |
@@ -773,7 +772,6 @@ void rec_tick(void) | |||
773 | { | 772 | { |
774 | saving_status = BUFFER_FULL; | 773 | saving_status = BUFFER_FULL; |
775 | queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); | 774 | queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); |
776 | wake_up_thread(); | ||
777 | } | 775 | } |
778 | } | 776 | } |
779 | } | 777 | } |
@@ -894,8 +892,6 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
894 | *psize = 0; /* no more transfer */ | 892 | *psize = 0; /* no more transfer */ |
895 | } | 893 | } |
896 | } | 894 | } |
897 | |||
898 | wake_up_thread(); | ||
899 | } | 895 | } |
900 | 896 | ||
901 | static struct trackdata *add_track_to_tag_list(const char *filename) | 897 | static struct trackdata *add_track_to_tag_list(const char *filename) |
@@ -2119,8 +2115,7 @@ void audio_init_playback(void) | |||
2119 | queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, NULL); | 2115 | queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, NULL); |
2120 | 2116 | ||
2121 | while(!init_playback_done) | 2117 | while(!init_playback_done) |
2122 | sleep_thread(); | 2118 | sleep_thread(1); |
2123 | wake_up_thread(); | ||
2124 | } | 2119 | } |
2125 | 2120 | ||
2126 | 2121 | ||
@@ -2134,8 +2129,7 @@ void audio_init_recording(unsigned int buffer_offset) | |||
2134 | queue_post(&mpeg_queue, MPEG_INIT_RECORDING, NULL); | 2129 | queue_post(&mpeg_queue, MPEG_INIT_RECORDING, NULL); |
2135 | 2130 | ||
2136 | while(!init_recording_done) | 2131 | while(!init_recording_done) |
2137 | sleep_thread(); | 2132 | sleep_thread(1); |
2138 | wake_up_thread(); | ||
2139 | } | 2133 | } |
2140 | 2134 | ||
2141 | static void init_recording(void) | 2135 | static void init_recording(void) |
@@ -2886,10 +2880,10 @@ void audio_init(void) | |||
2886 | 2880 | ||
2887 | #ifndef SIMULATOR | 2881 | #ifndef SIMULATOR |
2888 | audiobuflen = audiobufend - audiobuf; | 2882 | audiobuflen = audiobufend - audiobuf; |
2889 | queue_init(&mpeg_queue); | 2883 | queue_init(&mpeg_queue, true); |
2890 | #endif /* !SIMULATOR */ | 2884 | #endif /* !SIMULATOR */ |
2891 | create_thread(mpeg_thread, mpeg_stack, | 2885 | create_thread(mpeg_thread, mpeg_stack, |
2892 | sizeof(mpeg_stack), mpeg_thread_name); | 2886 | sizeof(mpeg_stack), mpeg_thread_name IF_PRIO(, PRIORITY_SYSTEM)); |
2893 | 2887 | ||
2894 | memset(trackdata, sizeof(trackdata), 0); | 2888 | memset(trackdata, sizeof(trackdata), 0); |
2895 | 2889 | ||
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c index 68fc22b937..bce6fb5f25 100644 --- a/firmware/pcm_record.c +++ b/firmware/pcm_record.c | |||
@@ -172,9 +172,9 @@ static void close_wave(void); | |||
172 | /* Creates pcmrec_thread */ | 172 | /* Creates pcmrec_thread */ |
173 | void pcm_rec_init(void) | 173 | void pcm_rec_init(void) |
174 | { | 174 | { |
175 | queue_init(&pcmrec_queue); | 175 | queue_init(&pcmrec_queue, true); |
176 | create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), | 176 | create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), |
177 | pcmrec_thread_name); | 177 | pcmrec_thread_name IF_PRIO(, PRIORITY_RECORDING)); |
178 | } | 178 | } |
179 | 179 | ||
180 | 180 | ||
@@ -196,8 +196,7 @@ void audio_init_recording(unsigned int buffer_offset) | |||
196 | queue_post(&pcmrec_queue, PCMREC_INIT, 0); | 196 | queue_post(&pcmrec_queue, PCMREC_INIT, 0); |
197 | 197 | ||
198 | while(!init_done) | 198 | while(!init_done) |
199 | sleep_thread(); | 199 | sleep_thread(1); |
200 | wake_up_thread(); | ||
201 | } | 200 | } |
202 | 201 | ||
203 | void audio_close_recording(void) | 202 | void audio_close_recording(void) |
@@ -206,8 +205,7 @@ void audio_close_recording(void) | |||
206 | queue_post(&pcmrec_queue, PCMREC_CLOSE, 0); | 205 | queue_post(&pcmrec_queue, PCMREC_CLOSE, 0); |
207 | 206 | ||
208 | while(!close_done) | 207 | while(!close_done) |
209 | sleep_thread(); | 208 | sleep_thread(1); |
210 | wake_up_thread(); | ||
211 | 209 | ||
212 | audio_remove_encoder(); | 210 | audio_remove_encoder(); |
213 | } | 211 | } |
@@ -421,8 +419,7 @@ void audio_record(const char *filename) | |||
421 | queue_post(&pcmrec_queue, PCMREC_START, 0); | 419 | queue_post(&pcmrec_queue, PCMREC_START, 0); |
422 | 420 | ||
423 | while(!record_done) | 421 | while(!record_done) |
424 | sleep_thread(); | 422 | sleep_thread(1); |
425 | wake_up_thread(); | ||
426 | } | 423 | } |
427 | 424 | ||
428 | 425 | ||
@@ -438,8 +435,7 @@ void audio_new_file(const char *filename) | |||
438 | queue_post(&pcmrec_queue, PCMREC_NEW_FILE, 0); | 435 | queue_post(&pcmrec_queue, PCMREC_NEW_FILE, 0); |
439 | 436 | ||
440 | while(!new_file_done) | 437 | while(!new_file_done) |
441 | sleep_thread(); | 438 | sleep_thread(1); |
442 | wake_up_thread(); | ||
443 | 439 | ||
444 | logf("pcm_new_file done"); | 440 | logf("pcm_new_file done"); |
445 | } | 441 | } |
@@ -459,8 +455,7 @@ void audio_stop_recording(void) | |||
459 | queue_post(&pcmrec_queue, PCMREC_STOP, 0); | 455 | queue_post(&pcmrec_queue, PCMREC_STOP, 0); |
460 | 456 | ||
461 | while(!stop_done) | 457 | while(!stop_done) |
462 | sleep_thread(); | 458 | sleep_thread(1); |
463 | wake_up_thread(); | ||
464 | 459 | ||
465 | logf("pcm_stop done"); | 460 | logf("pcm_stop done"); |
466 | } | 461 | } |
@@ -482,8 +477,7 @@ void audio_pause_recording(void) | |||
482 | queue_post(&pcmrec_queue, PCMREC_PAUSE, 0); | 477 | queue_post(&pcmrec_queue, PCMREC_PAUSE, 0); |
483 | 478 | ||
484 | while(!pause_done) | 479 | while(!pause_done) |
485 | sleep_thread(); | 480 | sleep_thread(1); |
486 | wake_up_thread(); | ||
487 | } | 481 | } |
488 | 482 | ||
489 | void audio_resume_recording(void) | 483 | void audio_resume_recording(void) |
@@ -498,8 +492,7 @@ void audio_resume_recording(void) | |||
498 | queue_post(&pcmrec_queue, PCMREC_RESUME, 0); | 492 | queue_post(&pcmrec_queue, PCMREC_RESUME, 0); |
499 | 493 | ||
500 | while(!resume_done) | 494 | while(!resume_done) |
501 | sleep_thread(); | 495 | sleep_thread(1); |
502 | wake_up_thread(); | ||
503 | } | 496 | } |
504 | 497 | ||
505 | /* return peaks as int, so convert from short first | 498 | /* return peaks as int, so convert from short first |
@@ -817,9 +810,8 @@ static void pcmrec_stop(void) | |||
817 | /* wait for encoding finish */ | 810 | /* wait for encoding finish */ |
818 | is_paused = true; | 811 | is_paused = true; |
819 | while(!wav_queue_empty) | 812 | while(!wav_queue_empty) |
820 | sleep_thread(); | 813 | sleep_thread(1); |
821 | 814 | ||
822 | wake_up_thread(); | ||
823 | is_recording = false; | 815 | is_recording = false; |
824 | 816 | ||
825 | /* Flush buffers to file */ | 817 | /* Flush buffers to file */ |
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 8f832964b5..f1e1aac57f 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c | |||
@@ -998,7 +998,7 @@ void powermgmt_init(void) | |||
998 | memset(power_history, 0x00, sizeof(power_history)); | 998 | memset(power_history, 0x00, sizeof(power_history)); |
999 | 999 | ||
1000 | create_thread(power_thread, power_stack, sizeof(power_stack), | 1000 | create_thread(power_thread, power_stack, sizeof(power_stack), |
1001 | power_thread_name); | 1001 | power_thread_name IF_PRIO(, PRIORITY_SYSTEM)); |
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | #endif /* SIMULATOR */ | 1004 | #endif /* SIMULATOR */ |
diff --git a/firmware/thread.c b/firmware/thread.c index eb39c7ad32..e4dcbbcf9a 100644 --- a/firmware/thread.c +++ b/firmware/thread.c | |||
@@ -23,12 +23,18 @@ | |||
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "kernel.h" | 24 | #include "kernel.h" |
25 | #include "cpu.h" | 25 | #include "cpu.h" |
26 | 26 | #include "string.h" | |
27 | 27 | ||
28 | #define DEADBEEF ((unsigned int)0xdeadbeef) | 28 | #define DEADBEEF ((unsigned int)0xdeadbeef) |
29 | /* Cast to the the machine int type, whose size could be < 4. */ | 29 | /* Cast to the the machine int type, whose size could be < 4. */ |
30 | 30 | ||
31 | struct core_entry cores[NUM_CORES] IBSS_ATTR; | 31 | struct core_entry cores[NUM_CORES] IBSS_ATTR; |
32 | #ifdef HAVE_PRIORITY_SCHEDULING | ||
33 | static unsigned short highest_priority IBSS_ATTR; | ||
34 | #endif | ||
35 | |||
36 | /* Define to enable additional checks for blocking violations etc. */ | ||
37 | // #define THREAD_EXTRA_CHECKS | ||
32 | 38 | ||
33 | static const char main_thread_name[] = "main"; | 39 | static const char main_thread_name[] = "main"; |
34 | 40 | ||
@@ -48,7 +54,16 @@ int *cop_stackend = stackend; | |||
48 | #endif | 54 | #endif |
49 | #endif | 55 | #endif |
50 | 56 | ||
51 | void switch_thread(void) ICODE_ATTR; | 57 | /* Conserve IRAM |
58 | static void add_to_list(struct thread_entry **list, | ||
59 | struct thread_entry *thread) ICODE_ATTR; | ||
60 | static void remove_from_list(struct thread_entry **list, | ||
61 | struct thread_entry *thread) ICODE_ATTR; | ||
62 | */ | ||
63 | |||
64 | void switch_thread(bool save_context, struct thread_entry **blocked_list) | ||
65 | ICODE_ATTR; | ||
66 | |||
52 | static inline void store_context(void* addr) __attribute__ ((always_inline)); | 67 | static inline void store_context(void* addr) __attribute__ ((always_inline)); |
53 | static inline void load_context(const void* addr) __attribute__ ((always_inline)); | 68 | static inline void load_context(const void* addr) __attribute__ ((always_inline)); |
54 | 69 | ||
@@ -219,24 +234,109 @@ static inline void load_context(const void* addr) | |||
219 | 234 | ||
220 | #endif | 235 | #endif |
221 | 236 | ||
222 | /*--------------------------------------------------------------------------- | 237 | static void add_to_list(struct thread_entry **list, |
223 | * Switch thread in round robin fashion. | 238 | struct thread_entry *thread) |
224 | *--------------------------------------------------------------------------- | ||
225 | */ | ||
226 | void switch_thread(void) | ||
227 | { | 239 | { |
228 | #ifdef RB_PROFILE | 240 | if (*list == NULL) |
229 | profile_thread_stopped(cores[CURRENT_CORE].current_thread); | 241 | { |
230 | #endif | 242 | thread->next = thread; |
231 | int current; | 243 | thread->prev = thread; |
232 | unsigned int *stackptr; | 244 | *list = thread; |
245 | } | ||
246 | else | ||
247 | { | ||
248 | /* Insert last */ | ||
249 | thread->next = *list; | ||
250 | thread->prev = (*list)->prev; | ||
251 | thread->prev->next = thread; | ||
252 | (*list)->prev = thread; | ||
253 | |||
254 | /* Insert next | ||
255 | thread->next = (*list)->next; | ||
256 | thread->prev = *list; | ||
257 | thread->next->prev = thread; | ||
258 | (*list)->next = thread; | ||
259 | */ | ||
260 | } | ||
261 | } | ||
233 | 262 | ||
234 | #ifdef SIMULATOR | 263 | static void remove_from_list(struct thread_entry **list, |
235 | /* Do nothing */ | 264 | struct thread_entry *thread) |
236 | #else | 265 | { |
237 | while (cores[CURRENT_CORE].num_sleepers == cores[CURRENT_CORE].num_threads) | 266 | if (list != NULL) |
267 | { | ||
268 | if (thread == thread->next) | ||
269 | { | ||
270 | *list = NULL; | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | if (thread == *list) | ||
275 | *list = thread->next; | ||
276 | } | ||
277 | |||
278 | /* Fix links to jump over the removed entry. */ | ||
279 | thread->prev->next = thread->next; | ||
280 | thread->next->prev = thread->prev; | ||
281 | } | ||
282 | |||
283 | /* Compiler trick: Don't declare as static to prevent putting | ||
284 | * function in IRAM. */ | ||
285 | void check_sleepers(void) | ||
286 | { | ||
287 | struct thread_entry *current, *next; | ||
288 | |||
289 | /* Check sleeping threads. */ | ||
290 | current = cores[CURRENT_CORE].sleeping; | ||
291 | if (current == NULL) | ||
292 | return ; | ||
293 | |||
294 | for (;;) | ||
295 | { | ||
296 | next = current->next; | ||
297 | |||
298 | if ((unsigned)current_tick >= GET_STATE_ARG(current->statearg)) | ||
299 | { | ||
300 | /* Sleep timeout has been reached so bring the thread | ||
301 | * back to life again. */ | ||
302 | remove_from_list(&cores[CURRENT_CORE].sleeping, current); | ||
303 | add_to_list(&cores[CURRENT_CORE].running, current); | ||
304 | |||
305 | /* If there is no more processes in the list, break the loop. */ | ||
306 | if (cores[CURRENT_CORE].sleeping == NULL) | ||
307 | break; | ||
308 | |||
309 | current = next; | ||
310 | continue; | ||
311 | } | ||
312 | |||
313 | current = next; | ||
314 | |||
315 | /* Break the loop once we have walked through the list of all | ||
316 | * sleeping processes. */ | ||
317 | if (current == cores[CURRENT_CORE].sleeping) | ||
318 | break; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | static inline void sleep_core(void) | ||
323 | { | ||
324 | static long last_tick = 0; | ||
325 | |||
326 | for (;;) | ||
238 | { | 327 | { |
239 | /* Enter sleep mode, woken up on interrupt */ | 328 | if (last_tick != current_tick) |
329 | { | ||
330 | check_sleepers(); | ||
331 | last_tick = current_tick; | ||
332 | } | ||
333 | |||
334 | /* We must sleep until there is at least one process in the list | ||
335 | * of running processes. */ | ||
336 | if (cores[CURRENT_CORE].running != NULL) | ||
337 | break; | ||
338 | |||
339 | /* Enter sleep mode to reduce power usage, woken up on interrupt */ | ||
240 | #ifdef CPU_COLDFIRE | 340 | #ifdef CPU_COLDFIRE |
241 | asm volatile ("stop #0x2000"); | 341 | asm volatile ("stop #0x2000"); |
242 | #elif CONFIG_CPU == SH7034 | 342 | #elif CONFIG_CPU == SH7034 |
@@ -257,49 +357,232 @@ void switch_thread(void) | |||
257 | CLKCON |= 2; | 357 | CLKCON |= 2; |
258 | #endif | 358 | #endif |
259 | } | 359 | } |
260 | #endif | 360 | } |
261 | current = cores[CURRENT_CORE].current_thread; | 361 | |
262 | store_context(&cores[CURRENT_CORE].threads[current].context); | 362 | #ifdef RB_PROFILE |
263 | 363 | static int get_threadnum(struct thread_entry *thread) | |
264 | #if CONFIG_CPU != TCC730 | 364 | { |
265 | /* Check if the current thread stack is overflown */ | 365 | int i; |
266 | stackptr = cores[CURRENT_CORE].threads[current].stack; | 366 | |
267 | if(stackptr[0] != DEADBEEF) | 367 | for (i = 0; i < MAXTHREADS; i++) |
268 | panicf("Stkov %s", cores[CURRENT_CORE].threads[current].name); | 368 | { |
369 | if (&cores[CURRENT_CORE].threads[i] == thread) | ||
370 | return i; | ||
371 | } | ||
372 | |||
373 | return -1; | ||
374 | } | ||
269 | #endif | 375 | #endif |
270 | 376 | ||
271 | if (++current >= cores[CURRENT_CORE].num_threads) | 377 | /* Compiler trick: Don't declare as static to prevent putting |
272 | current = 0; | 378 | * function in IRAM. */ |
379 | void change_thread_state(struct thread_entry **blocked_list) | ||
380 | { | ||
381 | struct thread_entry *old; | ||
382 | |||
383 | /* Remove the thread from the list of running threads. */ | ||
384 | old = cores[CURRENT_CORE].running; | ||
385 | remove_from_list(&cores[CURRENT_CORE].running, old); | ||
386 | |||
387 | /* And put the thread into a new list of inactive threads. */ | ||
388 | if (GET_STATE(old->statearg) == STATE_BLOCKED) | ||
389 | add_to_list(blocked_list, old); | ||
390 | else | ||
391 | add_to_list(&cores[CURRENT_CORE].sleeping, old); | ||
392 | |||
393 | #ifdef HAVE_PRIORITY_SCHEDULING | ||
394 | /* Reset priorities */ | ||
395 | if (old->priority == highest_priority) | ||
396 | highest_priority = 100; | ||
397 | #endif | ||
398 | } | ||
273 | 399 | ||
274 | cores[CURRENT_CORE].current_thread = current; | 400 | /*--------------------------------------------------------------------------- |
275 | load_context(&cores[CURRENT_CORE].threads[current].context); | 401 | * Switch thread in round robin fashion. |
402 | *--------------------------------------------------------------------------- | ||
403 | */ | ||
404 | void switch_thread(bool save_context, struct thread_entry **blocked_list) | ||
405 | { | ||
276 | #ifdef RB_PROFILE | 406 | #ifdef RB_PROFILE |
277 | profile_thread_started(cores[CURRENT_CORE].current_thread); | 407 | profile_thread_stopped(get_threadnum(cores[CURRENT_CORE].running)); |
408 | #endif | ||
409 | unsigned int *stackptr; | ||
410 | |||
411 | #ifdef SIMULATOR | ||
412 | /* Do nothing */ | ||
413 | #else | ||
414 | |||
415 | /* Begin task switching by saving our current context so that we can | ||
416 | * restore the state of the current thread later to the point prior | ||
417 | * to this call. */ | ||
418 | if (save_context) | ||
419 | { | ||
420 | store_context(&cores[CURRENT_CORE].running->context); | ||
421 | |||
422 | # if CONFIG_CPU != TCC730 | ||
423 | /* Check if the current thread stack is overflown */ | ||
424 | stackptr = cores[CURRENT_CORE].running->stack; | ||
425 | if(stackptr[0] != DEADBEEF) | ||
426 | panicf("Stkov %s", cores[CURRENT_CORE].running->name); | ||
427 | # endif | ||
428 | |||
429 | /* Check if a thread state change has been requested. */ | ||
430 | if (cores[CURRENT_CORE].running->statearg) | ||
431 | { | ||
432 | /* Change running thread state and switch to next thread. */ | ||
433 | change_thread_state(blocked_list); | ||
434 | } | ||
435 | else | ||
436 | { | ||
437 | /* Switch to the next running thread. */ | ||
438 | cores[CURRENT_CORE].running = cores[CURRENT_CORE].running->next; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | /* Go through the list of sleeping task to check if we need to wake up | ||
443 | * any of them due to timeout. Also puts core into sleep state until | ||
444 | * there is at least one running process again. */ | ||
445 | sleep_core(); | ||
446 | |||
447 | #ifdef HAVE_PRIORITY_SCHEDULING | ||
448 | /* Select the new task based on priorities and the last time a process | ||
449 | * got CPU time. */ | ||
450 | for (;;) | ||
451 | { | ||
452 | int priority = cores[CURRENT_CORE].running->priority; | ||
453 | |||
454 | if (priority < highest_priority) | ||
455 | highest_priority = priority; | ||
456 | |||
457 | if (priority == highest_priority || (current_tick | ||
458 | - cores[CURRENT_CORE].running->last_run > priority * 8)) | ||
459 | { | ||
460 | break; | ||
461 | } | ||
462 | cores[CURRENT_CORE].running = cores[CURRENT_CORE].running->next; | ||
463 | } | ||
464 | |||
465 | /* Reset the value of thread's last running time to the current time. */ | ||
466 | cores[CURRENT_CORE].running->last_run = current_tick; | ||
467 | #endif | ||
468 | |||
469 | #endif | ||
470 | /* And finally give control to the next thread. */ | ||
471 | load_context(&cores[CURRENT_CORE].running->context); | ||
472 | |||
473 | #ifdef RB_PROFILE | ||
474 | profile_thread_started(get_threadnum(cores[CURRENT_CORE].running)); | ||
278 | #endif | 475 | #endif |
279 | } | 476 | } |
280 | 477 | ||
281 | void sleep_thread(void) | 478 | void sleep_thread(int ticks) |
282 | { | 479 | { |
283 | ++cores[CURRENT_CORE].num_sleepers; | 480 | /* Set the thread's new state and timeout and finally force a task switch |
284 | switch_thread(); | 481 | * so that scheduler removes thread from the list of running processes |
482 | * and puts it in list of sleeping tasks. */ | ||
483 | cores[CURRENT_CORE].running->statearg = | ||
484 | SET_STATE(STATE_SLEEPING, current_tick + ticks + 1); | ||
485 | switch_thread(true, NULL); | ||
486 | |||
487 | /* Clear all flags to indicate we are up and running again. */ | ||
488 | cores[CURRENT_CORE].running->statearg = 0; | ||
285 | } | 489 | } |
286 | 490 | ||
287 | void wake_up_thread(void) | 491 | void block_thread(struct thread_entry **list, int timeout) |
288 | { | 492 | { |
289 | cores[CURRENT_CORE].num_sleepers = 0; | 493 | struct thread_entry *current; |
494 | |||
495 | /* Get the entry for the current running thread. */ | ||
496 | current = cores[CURRENT_CORE].running; | ||
497 | |||
498 | /* At next task switch scheduler will immediately change the thread | ||
499 | * state (and we also force the task switch to happen). */ | ||
500 | if (timeout) | ||
501 | { | ||
502 | #ifdef THREAD_EXTRA_CHECKS | ||
503 | /* We can store only one thread to the "list" if thread is used | ||
504 | * in other list (such as core's list for sleeping tasks). */ | ||
505 | if (*list) | ||
506 | panicf("Blocking violation T->*B"); | ||
507 | #endif | ||
508 | |||
509 | current->statearg = | ||
510 | SET_STATE(STATE_BLOCKED_W_TMO, current_tick + timeout); | ||
511 | *list = current; | ||
512 | |||
513 | /* Now force a task switch and block until we have been woken up | ||
514 | * by another thread or timeout is reached. */ | ||
515 | switch_thread(true, NULL); | ||
516 | |||
517 | /* If timeout is reached, we must set list back to NULL here. */ | ||
518 | *list = NULL; | ||
519 | } | ||
520 | else | ||
521 | { | ||
522 | #ifdef THREAD_EXTRA_CHECKS | ||
523 | /* We are not allowed to mix blocking types in one queue. */ | ||
524 | if (*list && GET_STATE((*list)->statearg) == STATE_BLOCKED_W_TMO) | ||
525 | panicf("Blocking violation B->*T"); | ||
526 | #endif | ||
527 | |||
528 | current->statearg = SET_STATE(STATE_BLOCKED, 0); | ||
529 | |||
530 | /* Now force a task switch and block until we have been woken up | ||
531 | * by another thread or timeout is reached. */ | ||
532 | switch_thread(true, list); | ||
533 | } | ||
534 | |||
535 | /* Clear all flags to indicate we are up and running again. */ | ||
536 | current->statearg = 0; | ||
290 | } | 537 | } |
291 | 538 | ||
539 | void wakeup_thread(struct thread_entry **list) | ||
540 | { | ||
541 | struct thread_entry *thread; | ||
542 | |||
543 | /* Check if there is a blocked thread at all. */ | ||
544 | if (*list == NULL) | ||
545 | return ; | ||
546 | |||
547 | /* Wake up the last thread first. */ | ||
548 | thread = *list; | ||
549 | |||
550 | /* Determine thread's current state. */ | ||
551 | switch (GET_STATE(thread->statearg)) | ||
552 | { | ||
553 | case STATE_BLOCKED: | ||
554 | /* Remove thread from the list of blocked threads and add it | ||
555 | * to the scheduler's list of running processes. */ | ||
556 | remove_from_list(list, thread); | ||
557 | add_to_list(&cores[CURRENT_CORE].running, thread); | ||
558 | thread->statearg = 0; | ||
559 | break; | ||
560 | |||
561 | case STATE_BLOCKED_W_TMO: | ||
562 | /* Just remove the timeout to cause scheduler to immediately | ||
563 | * wake up the thread. */ | ||
564 | thread->statearg &= 0xC0000000; | ||
565 | *list = NULL; | ||
566 | break; | ||
567 | |||
568 | default: | ||
569 | /* Nothing to do. Thread has already been woken up | ||
570 | * or it's state is not blocked or blocked with timeout. */ | ||
571 | return ; | ||
572 | } | ||
573 | } | ||
292 | 574 | ||
293 | /*--------------------------------------------------------------------------- | 575 | /*--------------------------------------------------------------------------- |
294 | * Create thread on the current core. | 576 | * Create thread on the current core. |
295 | * Return ID if context area could be allocated, else -1. | 577 | * Return ID if context area could be allocated, else -1. |
296 | *--------------------------------------------------------------------------- | 578 | *--------------------------------------------------------------------------- |
297 | */ | 579 | */ |
298 | int create_thread(void (*function)(void), void* stack, int stack_size, | 580 | struct thread_entry* |
299 | const char *name) | 581 | create_thread(void (*function)(void), void* stack, int stack_size, |
582 | const char *name IF_PRIO(, int priority)) | ||
300 | { | 583 | { |
301 | return create_thread_on_core(CURRENT_CORE, function, stack, stack_size, | 584 | return create_thread_on_core(CURRENT_CORE, function, stack, stack_size, |
302 | name); | 585 | name IF_PRIO(, priority)); |
303 | } | 586 | } |
304 | 587 | ||
305 | /*--------------------------------------------------------------------------- | 588 | /*--------------------------------------------------------------------------- |
@@ -307,18 +590,28 @@ int create_thread(void (*function)(void), void* stack, int stack_size, | |||
307 | * Return ID if context area could be allocated, else -1. | 590 | * Return ID if context area could be allocated, else -1. |
308 | *--------------------------------------------------------------------------- | 591 | *--------------------------------------------------------------------------- |
309 | */ | 592 | */ |
310 | int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size, | 593 | struct thread_entry* |
311 | const char *name) | 594 | create_thread_on_core(unsigned int core, void (*function)(void), |
595 | void* stack, int stack_size, | ||
596 | const char *name IF_PRIO(, int priority)) | ||
312 | { | 597 | { |
313 | unsigned int i; | 598 | unsigned int i; |
314 | unsigned int stacklen; | 599 | unsigned int stacklen; |
315 | unsigned int *stackptr; | 600 | unsigned int *stackptr; |
601 | int n; | ||
316 | struct regs *regs; | 602 | struct regs *regs; |
317 | struct thread_entry *thread; | 603 | struct thread_entry *thread; |
318 | 604 | ||
319 | if (cores[core].num_threads >= MAXTHREADS) | 605 | for (n = 0; n < MAXTHREADS; n++) |
320 | return -1; | 606 | { |
321 | 607 | if (cores[core].threads[n].name == NULL) | |
608 | break; | ||
609 | } | ||
610 | |||
611 | if (n == MAXTHREADS) | ||
612 | return NULL; | ||
613 | |||
614 | |||
322 | /* Munge the stack to make it easy to spot stack overflows */ | 615 | /* Munge the stack to make it easy to spot stack overflows */ |
323 | stacklen = stack_size / sizeof(int); | 616 | stacklen = stack_size / sizeof(int); |
324 | stackptr = stack; | 617 | stackptr = stack; |
@@ -328,10 +621,17 @@ int create_thread_on_core(unsigned int core, void (*function)(void), void* stack | |||
328 | } | 621 | } |
329 | 622 | ||
330 | /* Store interesting information */ | 623 | /* Store interesting information */ |
331 | thread = &cores[core].threads[cores[core].num_threads]; | 624 | thread = &cores[core].threads[n]; |
332 | thread->name = name; | 625 | thread->name = name; |
333 | thread->stack = stack; | 626 | thread->stack = stack; |
334 | thread->stack_size = stack_size; | 627 | thread->stack_size = stack_size; |
628 | thread->statearg = 0; | ||
629 | #ifdef HAVE_PRIORITY_SCHEDULING | ||
630 | thread->priority = priority; | ||
631 | highest_priority = 100; | ||
632 | #endif | ||
633 | add_to_list(&cores[core].running, thread); | ||
634 | |||
335 | regs = &thread->context; | 635 | regs = &thread->context; |
336 | #if defined(CPU_COLDFIRE) || (CONFIG_CPU == SH7034) || defined(CPU_ARM) | 636 | #if defined(CPU_COLDFIRE) || (CONFIG_CPU == SH7034) || defined(CPU_ARM) |
337 | /* Align stack to an even 32 bit boundary */ | 637 | /* Align stack to an even 32 bit boundary */ |
@@ -343,8 +643,7 @@ int create_thread_on_core(unsigned int core, void (*function)(void), void* stack | |||
343 | #endif | 643 | #endif |
344 | regs->start = (void*)function; | 644 | regs->start = (void*)function; |
345 | 645 | ||
346 | wake_up_thread(); | 646 | return thread; |
347 | return cores[core].num_threads++; /* return the current ID, e.g for remove_thread() */ | ||
348 | } | 647 | } |
349 | 648 | ||
350 | /*--------------------------------------------------------------------------- | 649 | /*--------------------------------------------------------------------------- |
@@ -352,44 +651,58 @@ int create_thread_on_core(unsigned int core, void (*function)(void), void* stack | |||
352 | * Parameter is the ID as returned from create_thread(). | 651 | * Parameter is the ID as returned from create_thread(). |
353 | *--------------------------------------------------------------------------- | 652 | *--------------------------------------------------------------------------- |
354 | */ | 653 | */ |
355 | void remove_thread(int threadnum) | 654 | void remove_thread(struct thread_entry *thread) |
356 | { | 655 | { |
357 | remove_thread_on_core(CURRENT_CORE, threadnum); | 656 | if (thread == NULL) |
657 | thread = cores[CURRENT_CORE].running; | ||
658 | |||
659 | /* Free the entry by removing thread name. */ | ||
660 | thread->name = NULL; | ||
661 | #ifdef HAVE_PRIORITY_SCHEDULING | ||
662 | highest_priority = 100; | ||
663 | #endif | ||
664 | |||
665 | if (thread == cores[CURRENT_CORE].running) | ||
666 | { | ||
667 | remove_from_list(&cores[CURRENT_CORE].running, thread); | ||
668 | switch_thread(false, NULL); | ||
669 | return ; | ||
670 | } | ||
671 | |||
672 | if (thread == cores[CURRENT_CORE].sleeping) | ||
673 | remove_from_list(&cores[CURRENT_CORE].sleeping, thread); | ||
674 | |||
675 | remove_from_list(NULL, thread); | ||
358 | } | 676 | } |
359 | 677 | ||
360 | /*--------------------------------------------------------------------------- | 678 | #ifdef HAVE_PRIORITY_SCHEDULING |
361 | * Remove a thread on the specified core from the scheduler. | 679 | void thread_set_priority(struct thread_entry *thread, int priority) |
362 | * Parameters are the core and the ID as returned from create_thread(). | ||
363 | *--------------------------------------------------------------------------- | ||
364 | */ | ||
365 | void remove_thread_on_core(unsigned int core, int threadnum) | ||
366 | { | 680 | { |
367 | int i; | 681 | if (thread == NULL) |
368 | 682 | thread = cores[CURRENT_CORE].running; | |
369 | if (threadnum >= cores[core].num_threads) | 683 | |
370 | return; | 684 | thread->priority = priority; |
371 | 685 | highest_priority = 100; | |
372 | cores[core].num_threads--; | ||
373 | for (i=threadnum; i<cores[core].num_threads-1; i++) | ||
374 | { /* move all entries which are behind */ | ||
375 | cores[core].threads[i] = cores[core].threads[i+1]; | ||
376 | } | ||
377 | |||
378 | if (cores[core].current_thread == threadnum) /* deleting the current one? */ | ||
379 | cores[core].current_thread = cores[core].num_threads; /* set beyond last, avoid store harm */ | ||
380 | else if (cores[core].current_thread > threadnum) /* within the moved positions? */ | ||
381 | cores[core].current_thread--; /* adjust it, point to same context again */ | ||
382 | } | 686 | } |
687 | #endif | ||
383 | 688 | ||
384 | void init_threads(void) | 689 | void init_threads(void) |
385 | { | 690 | { |
386 | unsigned int core = CURRENT_CORE; | 691 | unsigned int core = CURRENT_CORE; |
387 | 692 | ||
388 | cores[core].num_threads = 1; /* We have 1 thread to begin with */ | 693 | memset(cores, 0, sizeof cores); |
389 | cores[core].current_thread = 0; /* The current thread is number 0 */ | 694 | cores[core].sleeping = NULL; |
695 | cores[core].running = NULL; | ||
390 | cores[core].threads[0].name = main_thread_name; | 696 | cores[core].threads[0].name = main_thread_name; |
391 | /* In multiple core setups, each core has a different stack. There is probably | 697 | cores[core].threads[0].statearg = 0; |
392 | a much better way to do this. */ | 698 | #ifdef HAVE_PRIORITY_SCHEDULING |
699 | cores[core].threads[0].priority = PRIORITY_USER_INTERFACE; | ||
700 | highest_priority = 100; | ||
701 | #endif | ||
702 | add_to_list(&cores[core].running, &cores[core].threads[0]); | ||
703 | |||
704 | /* In multiple core setups, each core has a different stack. There is probably | ||
705 | a much better way to do this. */ | ||
393 | if (core == CPU) | 706 | if (core == CPU) |
394 | { | 707 | { |
395 | cores[CPU].threads[0].stack = stackbegin; | 708 | cores[CPU].threads[0].stack = stackbegin; |
@@ -405,28 +718,24 @@ void init_threads(void) | |||
405 | #else | 718 | #else |
406 | cores[core].threads[0].context.start = 0; /* thread 0 already running */ | 719 | cores[core].threads[0].context.start = 0; /* thread 0 already running */ |
407 | #endif | 720 | #endif |
408 | cores[core].num_sleepers = 0; | ||
409 | } | ||
410 | |||
411 | int thread_stack_usage(int threadnum) | ||
412 | { | ||
413 | return thread_stack_usage_on_core(CURRENT_CORE, threadnum); | ||
414 | } | 721 | } |
415 | 722 | ||
416 | int thread_stack_usage_on_core(unsigned int core, int threadnum) | 723 | int thread_stack_usage(const struct thread_entry *thread) |
417 | { | 724 | { |
418 | unsigned int i; | 725 | unsigned int i; |
419 | unsigned int *stackptr = cores[core].threads[threadnum].stack; | 726 | unsigned int *stackptr = thread->stack; |
420 | |||
421 | if (threadnum >= cores[core].num_threads) | ||
422 | return -1; | ||
423 | 727 | ||
424 | for (i = 0;i < cores[core].threads[threadnum].stack_size/sizeof(int);i++) | 728 | for (i = 0;i < thread->stack_size/sizeof(int);i++) |
425 | { | 729 | { |
426 | if (stackptr[i] != DEADBEEF) | 730 | if (stackptr[i] != DEADBEEF) |
427 | break; | 731 | break; |
428 | } | 732 | } |
429 | 733 | ||
430 | return ((cores[core].threads[threadnum].stack_size - i * sizeof(int)) * 100) / | 734 | return ((thread->stack_size - i * sizeof(int)) * 100) / |
431 | cores[core].threads[threadnum].stack_size; | 735 | thread->stack_size; |
736 | } | ||
737 | |||
738 | int thread_get_status(const struct thread_entry *thread) | ||
739 | { | ||
740 | return GET_STATE(thread->statearg); | ||
432 | } | 741 | } |
diff --git a/firmware/usb.c b/firmware/usb.c index 6be5fda093..0be6c4011e 100644 --- a/firmware/usb.c +++ b/firmware/usb.c | |||
@@ -558,8 +558,9 @@ void usb_init(void) | |||
558 | last_usb_status = false; | 558 | last_usb_status = false; |
559 | 559 | ||
560 | #ifndef BOOTLOADER | 560 | #ifndef BOOTLOADER |
561 | queue_init(&usb_queue); | 561 | queue_init(&usb_queue, true); |
562 | create_thread(usb_thread, usb_stack, sizeof(usb_stack), usb_thread_name); | 562 | create_thread(usb_thread, usb_stack, sizeof(usb_stack), |
563 | usb_thread_name IF_PRIO(, PRIORITY_SYSTEM)); | ||
563 | 564 | ||
564 | tick_add_task(usb_tick); | 565 | tick_add_task(usb_tick); |
565 | #endif | 566 | #endif |