diff options
author | Daniel Ankers <dan@weirdo.org.uk> | 2006-08-21 17:35:35 +0000 |
---|---|---|
committer | Daniel Ankers <dan@weirdo.org.uk> | 2006-08-21 17:35:35 +0000 |
commit | 0aec12f3fd801c5acc03a75818e06741957d51b9 (patch) | |
tree | d78b6d52c5962a00a5fefde97e977653a15c0428 /firmware | |
parent | e09dc8d51323bf0940b19ff8e12de7891fda2c52 (diff) | |
download | rockbox-0aec12f3fd801c5acc03a75818e06741957d51b9.tar.gz rockbox-0aec12f3fd801c5acc03a75818e06741957d51b9.zip |
Threading changes in preparation for multiple core support
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10681 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/export/config.h | 17 | ||||
-rw-r--r-- | firmware/export/system.h | 14 | ||||
-rw-r--r-- | firmware/export/thread.h | 4 | ||||
-rw-r--r-- | firmware/system.c | 102 | ||||
-rw-r--r-- | firmware/thread.c | 170 |
5 files changed, 201 insertions, 106 deletions
diff --git a/firmware/export/config.h b/firmware/export/config.h index 8f1a5e65cc..cd674b63f8 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h | |||
@@ -151,6 +151,10 @@ | |||
151 | #define USBOTG_ISP1362 1362 | 151 | #define USBOTG_ISP1362 1362 |
152 | #define USBOTG_M5636 5636 | 152 | #define USBOTG_M5636 5636 |
153 | 153 | ||
154 | /* Multiple cores */ | ||
155 | #define CPU 0 | ||
156 | #define COP 1 | ||
157 | |||
154 | /* now go and pick yours */ | 158 | /* now go and pick yours */ |
155 | #if defined(ARCHOS_PLAYER) | 159 | #if defined(ARCHOS_PLAYER) |
156 | #include "config-player.h" | 160 | #include "config-player.h" |
@@ -219,6 +223,19 @@ | |||
219 | /* define for all cpus from PP family */ | 223 | /* define for all cpus from PP family */ |
220 | #if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5024) | 224 | #if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5024) |
221 | #define CPU_PP | 225 | #define CPU_PP |
226 | |||
227 | /* PP family has dual cores */ | ||
228 | #if 0 | ||
229 | /* Keep it as single core until dual core support is ready */ | ||
230 | #define NUM_CORES 2 | ||
231 | #define CURRENT_CORE current_core() | ||
232 | #endif | ||
233 | |||
234 | #define NUM_CORES 1 | ||
235 | #define CURRENT_CORE 0 | ||
236 | #else | ||
237 | #define NUM_CORES 1 | ||
238 | #define CURRENT_CORE 0 | ||
222 | #endif | 239 | #endif |
223 | 240 | ||
224 | /* define for all cpus from ARM family */ | 241 | /* define for all cpus from ARM family */ |
diff --git a/firmware/export/system.h b/firmware/export/system.h index 1b326e1b8b..d13b27c529 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h | |||
@@ -43,6 +43,8 @@ static inline void udelay(unsigned usecs) | |||
43 | unsigned start = USEC_TIMER; | 43 | unsigned start = USEC_TIMER; |
44 | while ((USEC_TIMER - start) < usecs); | 44 | while ((USEC_TIMER - start) < usecs); |
45 | } | 45 | } |
46 | |||
47 | unsigned int current_core(void); | ||
46 | #endif | 48 | #endif |
47 | 49 | ||
48 | struct flash_header { | 50 | struct flash_header { |
@@ -88,7 +90,7 @@ void cpu_idle_mode(bool on_off); | |||
88 | #define betoh32(x) swap32(x) | 90 | #define betoh32(x) swap32(x) |
89 | #define htobe16(x) swap16(x) | 91 | #define htobe16(x) swap16(x) |
90 | #define htobe32(x) swap32(x) | 92 | #define htobe32(x) swap32(x) |
91 | #else | 93 | #else |
92 | #define letoh16(x) swap16(x) | 94 | #define letoh16(x) swap16(x) |
93 | #define letoh32(x) swap32(x) | 95 | #define letoh32(x) swap32(x) |
94 | #define htole16(x) swap16(x) | 96 | #define htole16(x) swap16(x) |
@@ -178,7 +180,7 @@ static inline void coldfire_set_macsr(unsigned long flags) | |||
178 | static inline unsigned long coldfire_get_macsr(void) | 180 | static inline unsigned long coldfire_get_macsr(void) |
179 | { | 181 | { |
180 | unsigned long m; | 182 | unsigned long m; |
181 | 183 | ||
182 | asm volatile ("move.l %%macsr, %0" : "=r" (m)); | 184 | asm volatile ("move.l %%macsr, %0" : "=r" (m)); |
183 | return m; | 185 | return m; |
184 | } | 186 | } |
@@ -301,7 +303,7 @@ static inline void invalidate_icache(void) | |||
301 | "move.l #0x80000000,%d0\n" | 303 | "move.l #0x80000000,%d0\n" |
302 | "movec.l %d0,%cacr"); | 304 | "movec.l %d0,%cacr"); |
303 | } | 305 | } |
304 | 306 | ||
305 | #define CPUFREQ_DEFAULT_MULT 1 | 307 | #define CPUFREQ_DEFAULT_MULT 1 |
306 | #define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ) | 308 | #define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ) |
307 | #define CPUFREQ_NORMAL_MULT 4 | 309 | #define CPUFREQ_NORMAL_MULT 4 |
@@ -315,7 +317,7 @@ static inline void invalidate_icache(void) | |||
315 | 317 | ||
316 | #define CPUFREQ_DEFAULT_MULT 8 | 318 | #define CPUFREQ_DEFAULT_MULT 8 |
317 | #define CPUFREQ_DEFAULT 24000000 | 319 | #define CPUFREQ_DEFAULT 24000000 |
318 | #define CPUFREQ_NORMAL_MULT 10 | 320 | #define CPUFREQ_NORMAL_MULT 10 |
319 | #define CPUFREQ_NORMAL 30000000 | 321 | #define CPUFREQ_NORMAL 30000000 |
320 | #define CPUFREQ_MAX_MULT 25 | 322 | #define CPUFREQ_MAX_MULT 25 |
321 | #define CPUFREQ_MAX 75000000 | 323 | #define CPUFREQ_MAX 75000000 |
@@ -336,7 +338,7 @@ static inline unsigned long swap32(unsigned long value) | |||
336 | result[15.. 8] = value[23..16]; | 338 | result[15.. 8] = value[23..16]; |
337 | result[ 7.. 0] = value[31..24]; | 339 | result[ 7.. 0] = value[31..24]; |
338 | */ | 340 | */ |
339 | { | 341 | { |
340 | unsigned int tmp; | 342 | unsigned int tmp; |
341 | 343 | ||
342 | asm volatile ( | 344 | asm volatile ( |
@@ -418,7 +420,7 @@ static inline int set_irq_level(int level) | |||
418 | __asm__ volatile ("clrsr ie"); | 420 | __asm__ volatile ("clrsr ie"); |
419 | else | 421 | else |
420 | __asm__ volatile ("setsr ie"); | 422 | __asm__ volatile ("setsr ie"); |
421 | 423 | ||
422 | return result; | 424 | return result; |
423 | } | 425 | } |
424 | 426 | ||
diff --git a/firmware/export/thread.h b/firmware/export/thread.h index 762e315a4c..a5034aedab 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h | |||
@@ -31,12 +31,16 @@ | |||
31 | 31 | ||
32 | int create_thread(void (*function)(void), void* stack, int stack_size, | 32 | int create_thread(void (*function)(void), void* stack, int stack_size, |
33 | const char *name); | 33 | const char *name); |
34 | int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size, | ||
35 | const char *name); | ||
34 | void remove_thread(int threadnum); | 36 | void remove_thread(int threadnum); |
37 | void remove_thread_on_core(unsigned int core, int threadnum); | ||
35 | void switch_thread(void); | 38 | void switch_thread(void); |
36 | void sleep_thread(void); | 39 | void sleep_thread(void); |
37 | void wake_up_thread(void); | 40 | void wake_up_thread(void); |
38 | void init_threads(void); | 41 | void init_threads(void); |
39 | int thread_stack_usage(int threadnum); | 42 | int thread_stack_usage(int threadnum); |
43 | int thread_stack_usage_on_core(unsigned int core, int threadnum); | ||
40 | #ifdef RB_PROFILE | 44 | #ifdef RB_PROFILE |
41 | void profile_thread(void); | 45 | void profile_thread(void); |
42 | #endif | 46 | #endif |
diff --git a/firmware/system.c b/firmware/system.c index c97b5233ec..6aee823205 100644 --- a/firmware/system.c +++ b/firmware/system.c | |||
@@ -91,21 +91,21 @@ bool detect_flashed_rockbox(void) | |||
91 | { | 91 | { |
92 | struct flash_header hdr; | 92 | struct flash_header hdr; |
93 | uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT; | 93 | uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT; |
94 | 94 | ||
95 | # ifndef BOOTLOADER | 95 | # ifndef BOOTLOADER |
96 | int oldmode; | 96 | int oldmode; |
97 | oldmode = system_memory_guard(MEMGUARD_NONE); | 97 | oldmode = system_memory_guard(MEMGUARD_NONE); |
98 | # endif | 98 | # endif |
99 | 99 | ||
100 | memcpy(&hdr, src, sizeof(struct flash_header)); | 100 | memcpy(&hdr, src, sizeof(struct flash_header)); |
101 | 101 | ||
102 | # ifndef BOOTLOADER | 102 | # ifndef BOOTLOADER |
103 | system_memory_guard(oldmode); | 103 | system_memory_guard(oldmode); |
104 | # endif | 104 | # endif |
105 | 105 | ||
106 | if (hdr.magic != FLASH_MAGIC) | 106 | if (hdr.magic != FLASH_MAGIC) |
107 | return false; | 107 | return false; |
108 | 108 | ||
109 | return true; | 109 | return true; |
110 | } | 110 | } |
111 | #else | 111 | #else |
@@ -139,13 +139,13 @@ void ddma_transfer(int dir, int mem, void* intAddr, long extAddr, int num) { | |||
139 | /* HW wants those two in word units. */ | 139 | /* HW wants those two in word units. */ |
140 | num /= 2; | 140 | num /= 2; |
141 | externalAddress /= 2; | 141 | externalAddress /= 2; |
142 | 142 | ||
143 | DDMACFG = (dir << 1) | (mem << 2); | 143 | DDMACFG = (dir << 1) | (mem << 2); |
144 | DDMAIADR = internalAddress; | 144 | DDMAIADR = internalAddress; |
145 | DDMAEADR = externalAddress; | 145 | DDMAEADR = externalAddress; |
146 | DDMANUM = num; | 146 | DDMANUM = num; |
147 | DDMACOM |= 0x4; /* start */ | 147 | DDMACOM |= 0x4; /* start */ |
148 | 148 | ||
149 | ddma_wait_idle(); /* wait for completion */ | 149 | ddma_wait_idle(); /* wait for completion */ |
150 | set_irq_level(irq); | 150 | set_irq_level(irq); |
151 | } | 151 | } |
@@ -164,13 +164,13 @@ static void ddma_transfer_noicode(int dir, int mem, long intAddr, long extAddr, | |||
164 | /* HW wants those two in word units. */ | 164 | /* HW wants those two in word units. */ |
165 | num /= 2; | 165 | num /= 2; |
166 | externalAddress /= 2; | 166 | externalAddress /= 2; |
167 | 167 | ||
168 | DDMACFG = (dir << 1) | (mem << 2); | 168 | DDMACFG = (dir << 1) | (mem << 2); |
169 | DDMAIADR = internalAddress; | 169 | DDMAIADR = internalAddress; |
170 | DDMAEADR = externalAddress; | 170 | DDMAEADR = externalAddress; |
171 | DDMANUM = num; | 171 | DDMANUM = num; |
172 | DDMACOM |= 0x4; /* start */ | 172 | DDMACOM |= 0x4; /* start */ |
173 | 173 | ||
174 | ddma_wait_idle_noicode(); /* wait for completion */ | 174 | ddma_wait_idle_noicode(); /* wait for completion */ |
175 | set_irq_level(irq); | 175 | set_irq_level(irq); |
176 | } | 176 | } |
@@ -220,7 +220,7 @@ void smsc_delay() { | |||
220 | Delay doesn't depend on CPU speed in Archos' firmware. | 220 | Delay doesn't depend on CPU speed in Archos' firmware. |
221 | */ | 221 | */ |
222 | for (i = 0; i < 100; i++) { | 222 | for (i = 0; i < 100; i++) { |
223 | 223 | ||
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
@@ -228,9 +228,9 @@ static void extra_init(void) { | |||
228 | /* Power on stuff */ | 228 | /* Power on stuff */ |
229 | P1 |= 0x07; | 229 | P1 |= 0x07; |
230 | P1CON |= 0x1f; | 230 | P1CON |= 0x1f; |
231 | 231 | ||
232 | /* P5 conf | 232 | /* P5 conf |
233 | * lines 0, 1 & 4 are digital, other analog. : | 233 | * lines 0, 1 & 4 are digital, other analog. : |
234 | */ | 234 | */ |
235 | P5CON = 0xec; | 235 | P5CON = 0xec; |
236 | 236 | ||
@@ -294,21 +294,21 @@ void system_init(void) | |||
294 | /******** | 294 | /******** |
295 | * CPU | 295 | * CPU |
296 | */ | 296 | */ |
297 | 297 | ||
298 | 298 | ||
299 | /* PLL0 (cpu osc. frequency) */ | 299 | /* PLL0 (cpu osc. frequency) */ |
300 | /* set_cpu_frequency(CPU_FREQ); */ | 300 | /* set_cpu_frequency(CPU_FREQ); */ |
301 | 301 | ||
302 | 302 | ||
303 | /******************* | 303 | /******************* |
304 | * configure S(D)RAM | 304 | * configure S(D)RAM |
305 | */ | 305 | */ |
306 | 306 | ||
307 | /************************ | 307 | /************************ |
308 | * Copy .icode section to icram | 308 | * Copy .icode section to icram |
309 | */ | 309 | */ |
310 | ddma_transfer_noicode(0, 0, 0x40, (long)&icodecopy, (int)&icodesize); | 310 | ddma_transfer_noicode(0, 0, 0x40, (long)&icodecopy, (int)&icodesize); |
311 | 311 | ||
312 | 312 | ||
313 | /*************************** | 313 | /*************************** |
314 | * Interrupts | 314 | * Interrupts |
@@ -472,12 +472,12 @@ void UIE (void) /* Unexpected Interrupt or Exception */ | |||
472 | unsigned int format_vector, pc; | 472 | unsigned int format_vector, pc; |
473 | int vector; | 473 | int vector; |
474 | char str[32]; | 474 | char str[32]; |
475 | 475 | ||
476 | asm volatile ("move.l (52,%%sp),%0": "=r"(format_vector)); | 476 | asm volatile ("move.l (52,%%sp),%0": "=r"(format_vector)); |
477 | asm volatile ("move.l (56,%%sp),%0": "=r"(pc)); | 477 | asm volatile ("move.l (56,%%sp),%0": "=r"(pc)); |
478 | 478 | ||
479 | vector = (format_vector >> 18) & 0xff; | 479 | vector = (format_vector >> 18) & 0xff; |
480 | 480 | ||
481 | /* clear screen */ | 481 | /* clear screen */ |
482 | lcd_clear_display (); | 482 | lcd_clear_display (); |
483 | #ifdef HAVE_LCD_BITMAP | 483 | #ifdef HAVE_LCD_BITMAP |
@@ -488,7 +488,7 @@ void UIE (void) /* Unexpected Interrupt or Exception */ | |||
488 | snprintf(str,sizeof(str),"at %08x",pc); | 488 | snprintf(str,sizeof(str),"at %08x",pc); |
489 | lcd_puts(0,1,str); | 489 | lcd_puts(0,1,str); |
490 | lcd_update(); | 490 | lcd_update(); |
491 | 491 | ||
492 | /* set cpu frequency to 11mhz (to prevent overheating) */ | 492 | /* set cpu frequency to 11mhz (to prevent overheating) */ |
493 | DCR = (DCR & ~0x01ff) | 1; | 493 | DCR = (DCR & ~0x01ff) | 1; |
494 | PLLCR = 0x10800000; | 494 | PLLCR = 0x10800000; |
@@ -510,7 +510,7 @@ void UIE (void) /* Unexpected Interrupt or Exception */ | |||
510 | } | 510 | } |
511 | 511 | ||
512 | /* reset vectors are handled in crt0.S */ | 512 | /* reset vectors are handled in crt0.S */ |
513 | void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = | 513 | void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = |
514 | { | 514 | { |
515 | UIE,UIE,UIE,UIE,UIE,UIE, | 515 | UIE,UIE,UIE,UIE,UIE,UIE, |
516 | UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE, | 516 | UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE, |
@@ -520,7 +520,7 @@ void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = | |||
520 | 520 | ||
521 | TRAP0,TRAP1,TRAP2,TRAP3,TRAP4,TRAP5,TRAP6,TRAP7, | 521 | TRAP0,TRAP1,TRAP2,TRAP3,TRAP4,TRAP5,TRAP6,TRAP7, |
522 | TRAP8,TRAP9,TRAP10,TRAP11,TRAP12,TRAP13,TRAP14,TRAP15, | 522 | TRAP8,TRAP9,TRAP10,TRAP11,TRAP12,TRAP13,TRAP14,TRAP15, |
523 | 523 | ||
524 | SWT,UIE,UIE,I2C,UART1,UART2,DMA0,DMA1, | 524 | SWT,UIE,UIE,I2C,UART1,UART2,DMA0,DMA1, |
525 | DMA2,DMA3,QSPI,UIE,UIE,UIE,UIE,UIE, | 525 | DMA2,DMA3,QSPI,UIE,UIE,UIE,UIE,UIE, |
526 | PDIR1FULL,PDIR2FULL,EBUTXEMPTY,IIS2TXEMPTY, | 526 | PDIR1FULL,PDIR2FULL,EBUTXEMPTY,IIS2TXEMPTY, |
@@ -741,7 +741,7 @@ static const char* const irqname[] = { | |||
741 | 741 | ||
742 | asm ( | 742 | asm ( |
743 | 743 | ||
744 | /* Vector table. | 744 | /* Vector table. |
745 | * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols | 745 | * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols |
746 | * defined in an asm block -- silly. | 746 | * defined in an asm block -- silly. |
747 | * Reset vectors (0..3) are handled in crt0.S */ | 747 | * Reset vectors (0..3) are handled in crt0.S */ |
@@ -854,7 +854,7 @@ asm ( | |||
854 | RESERVE_INTERRUPT ( 108) | 854 | RESERVE_INTERRUPT ( 108) |
855 | DEFAULT_INTERRUPT (ADITI, 109) | 855 | DEFAULT_INTERRUPT (ADITI, 109) |
856 | 856 | ||
857 | /* UIE# block. | 857 | /* UIE# block. |
858 | * Must go into the same section as the UIE() handler */ | 858 | * Must go into the same section as the UIE() handler */ |
859 | 859 | ||
860 | "\t.text\n" | 860 | "\t.text\n" |
@@ -979,7 +979,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ | |||
979 | char str[32]; | 979 | char str[32]; |
980 | 980 | ||
981 | asm volatile ("sts\tpr,%0" : "=r"(n)); | 981 | asm volatile ("sts\tpr,%0" : "=r"(n)); |
982 | 982 | ||
983 | /* clear screen */ | 983 | /* clear screen */ |
984 | lcd_clear_display (); | 984 | lcd_clear_display (); |
985 | #ifdef HAVE_LCD_BITMAP | 985 | #ifdef HAVE_LCD_BITMAP |
@@ -1002,7 +1002,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ | |||
1002 | volatile int i; | 1002 | volatile int i; |
1003 | led (state); | 1003 | led (state); |
1004 | state = !state; | 1004 | state = !state; |
1005 | 1005 | ||
1006 | for (i = 0; i < 240000; ++i); | 1006 | for (i = 0; i < 240000; ++i); |
1007 | #endif | 1007 | #endif |
1008 | 1008 | ||
@@ -1018,7 +1018,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ | |||
1018 | #elif CONFIG_KEYPAD == ONDIO_PAD | 1018 | #elif CONFIG_KEYPAD == ONDIO_PAD |
1019 | if (!(PCDR & 0x0008)) | 1019 | if (!(PCDR & 0x0008)) |
1020 | #endif | 1020 | #endif |
1021 | { | 1021 | { |
1022 | /* enable the watchguard timer, but don't service it */ | 1022 | /* enable the watchguard timer, but don't service it */ |
1023 | RSTCSR_W = 0x5a40; /* Reset enabled, power-on reset */ | 1023 | RSTCSR_W = 0x5a40; /* Reset enabled, power-on reset */ |
1024 | TCSR_W = 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */ | 1024 | TCSR_W = 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */ |
@@ -1086,7 +1086,7 @@ int system_memory_guard(int newmode) | |||
1086 | 1086 | ||
1087 | int oldmode = MEMGUARD_NONE; | 1087 | int oldmode = MEMGUARD_NONE; |
1088 | int i; | 1088 | int i; |
1089 | 1089 | ||
1090 | /* figure out the old mode from what is in the UBC regs. If the register | 1090 | /* figure out the old mode from what is in the UBC regs. If the register |
1091 | values don't match any mode, assume MEMGUARD_NONE */ | 1091 | values don't match any mode, assume MEMGUARD_NONE */ |
1092 | for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++) | 1092 | for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++) |
@@ -1098,7 +1098,7 @@ int system_memory_guard(int newmode) | |||
1098 | break; | 1098 | break; |
1099 | } | 1099 | } |
1100 | } | 1100 | } |
1101 | 1101 | ||
1102 | if (newmode == MEMGUARD_KEEP) | 1102 | if (newmode == MEMGUARD_KEEP) |
1103 | newmode = oldmode; | 1103 | newmode = oldmode; |
1104 | 1104 | ||
@@ -1109,7 +1109,7 @@ int system_memory_guard(int newmode) | |||
1109 | BAR = modes[newmode].addr; | 1109 | BAR = modes[newmode].addr; |
1110 | BAMR = modes[newmode].mask; | 1110 | BAMR = modes[newmode].mask; |
1111 | BBR = modes[newmode].bbr; | 1111 | BBR = modes[newmode].bbr; |
1112 | 1112 | ||
1113 | return oldmode; | 1113 | return oldmode; |
1114 | } | 1114 | } |
1115 | #elif defined(CPU_ARM) | 1115 | #elif defined(CPU_ARM) |
@@ -1124,7 +1124,7 @@ static const char* const uiename[] = { | |||
1124 | void UIE(unsigned int pc, unsigned int num) | 1124 | void UIE(unsigned int pc, unsigned int num) |
1125 | { | 1125 | { |
1126 | char str[32]; | 1126 | char str[32]; |
1127 | 1127 | ||
1128 | lcd_clear_display(); | 1128 | lcd_clear_display(); |
1129 | #ifdef HAVE_LCD_BITMAP | 1129 | #ifdef HAVE_LCD_BITMAP |
1130 | lcd_setfont(FONT_SYSFIXED); | 1130 | lcd_setfont(FONT_SYSFIXED); |
@@ -1133,7 +1133,7 @@ void UIE(unsigned int pc, unsigned int num) | |||
1133 | snprintf(str, sizeof(str), "at %08x", pc); | 1133 | snprintf(str, sizeof(str), "at %08x", pc); |
1134 | lcd_puts(0, 1, str); | 1134 | lcd_puts(0, 1, str); |
1135 | lcd_update(); | 1135 | lcd_update(); |
1136 | 1136 | ||
1137 | while (1) | 1137 | while (1) |
1138 | { | 1138 | { |
1139 | /* TODO: perhaps add button handling in here when we get a polling | 1139 | /* TODO: perhaps add button handling in here when we get a polling |
@@ -1160,7 +1160,7 @@ void irq(void) | |||
1160 | else if (CPU_INT_STAT & TIMER2_MASK) | 1160 | else if (CPU_INT_STAT & TIMER2_MASK) |
1161 | TIMER2(); | 1161 | TIMER2(); |
1162 | else if (CPU_HI_INT_STAT & GPIO_MASK) | 1162 | else if (CPU_HI_INT_STAT & GPIO_MASK) |
1163 | ipod_mini_button_int(); | 1163 | ipod_mini_button_int(); |
1164 | } | 1164 | } |
1165 | #elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) | 1165 | #elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) |
1166 | /* TODO: this should really be in the target tree, but moving it there caused | 1166 | /* TODO: this should really be in the target tree, but moving it there caused |
@@ -1170,14 +1170,14 @@ void irq(void) | |||
1170 | if (CPU_INT_STAT & TIMER1_MASK) | 1170 | if (CPU_INT_STAT & TIMER1_MASK) |
1171 | TIMER1(); | 1171 | TIMER1(); |
1172 | else if (CPU_INT_STAT & TIMER2_MASK) | 1172 | else if (CPU_INT_STAT & TIMER2_MASK) |
1173 | TIMER2(); | 1173 | TIMER2(); |
1174 | } | 1174 | } |
1175 | #else | 1175 | #else |
1176 | extern void ipod_4g_button_int(void); | 1176 | extern void ipod_4g_button_int(void); |
1177 | 1177 | ||
1178 | void irq(void) | 1178 | void irq(void) |
1179 | { | 1179 | { |
1180 | if (CPU_INT_STAT & TIMER1_MASK) | 1180 | if (CPU_INT_STAT & TIMER1_MASK) |
1181 | TIMER1(); | 1181 | TIMER1(); |
1182 | else if (CPU_INT_STAT & TIMER2_MASK) | 1182 | else if (CPU_INT_STAT & TIMER2_MASK) |
1183 | TIMER2(); | 1183 | TIMER2(); |
@@ -1187,11 +1187,21 @@ void irq(void) | |||
1187 | #endif | 1187 | #endif |
1188 | #endif /* BOOTLOADER */ | 1188 | #endif /* BOOTLOADER */ |
1189 | 1189 | ||
1190 | unsigned int current_core(void) | ||
1191 | { | ||
1192 | if(((*(volatile unsigned long *)(0x60000000)) & 0xff) == 0x55) | ||
1193 | { | ||
1194 | return CPU; | ||
1195 | } | ||
1196 | return COP; | ||
1197 | } | ||
1198 | |||
1199 | |||
1190 | /* TODO: The following two function have been lifted straight from IPL, and | 1200 | /* TODO: The following two function have been lifted straight from IPL, and |
1191 | hence have a lot of numeric addresses used straight. I'd like to use | 1201 | hence have a lot of numeric addresses used straight. I'd like to use |
1192 | #defines for these, but don't know what most of them are for or even what | 1202 | #defines for these, but don't know what most of them are for or even what |
1193 | they should be named. Because of this I also have no way of knowing how | 1203 | they should be named. Because of this I also have no way of knowing how |
1194 | to extend the funtions to do alternate cache configurations and/or | 1204 | to extend the funtions to do alternate cache configurations and/or |
1195 | some other CPU frequency scaling. */ | 1205 | some other CPU frequency scaling. */ |
1196 | 1206 | ||
1197 | #ifndef BOOTLOADER | 1207 | #ifndef BOOTLOADER |
@@ -1251,7 +1261,7 @@ void set_cpu_frequency(long frequency) | |||
1251 | #if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) | 1261 | #if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) |
1252 | /* We don't know why the timer interrupt gets disabled on the PP5020 | 1262 | /* We don't know why the timer interrupt gets disabled on the PP5020 |
1253 | based ipods, but without the following line, the 4Gs will freeze | 1263 | based ipods, but without the following line, the 4Gs will freeze |
1254 | when CPU frequency changing is enabled. | 1264 | when CPU frequency changing is enabled. |
1255 | 1265 | ||
1256 | Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used | 1266 | Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used |
1257 | elsewhere to enable interrupts) doesn't work, we need "|=". | 1267 | elsewhere to enable interrupts) doesn't work, we need "|=". |
@@ -1321,19 +1331,29 @@ extern void TIMER2(void); | |||
1321 | 1331 | ||
1322 | void irq(void) | 1332 | void irq(void) |
1323 | { | 1333 | { |
1324 | if (CPU_INT_STAT & TIMER1_MASK) | 1334 | if (CPU_INT_STAT & TIMER1_MASK) |
1325 | TIMER1(); | 1335 | TIMER1(); |
1326 | else if (CPU_INT_STAT & TIMER2_MASK) | 1336 | else if (CPU_INT_STAT & TIMER2_MASK) |
1327 | TIMER2(); | 1337 | TIMER2(); |
1328 | } | 1338 | } |
1329 | 1339 | ||
1330 | #endif | 1340 | #endif |
1331 | 1341 | ||
1342 | unsigned int current_core(void) | ||
1343 | { | ||
1344 | if(((*(volatile unsigned long *)(0xc4000000)) & 0xff) == 0x55) | ||
1345 | { | ||
1346 | return CPU; | ||
1347 | } | ||
1348 | return COP; | ||
1349 | } | ||
1350 | |||
1351 | |||
1332 | /* TODO: The following two function have been lifted straight from IPL, and | 1352 | /* TODO: The following two function have been lifted straight from IPL, and |
1333 | hence have a lot of numeric addresses used straight. I'd like to use | 1353 | hence have a lot of numeric addresses used straight. I'd like to use |
1334 | #defines for these, but don't know what most of them are for or even what | 1354 | #defines for these, but don't know what most of them are for or even what |
1335 | they should be named. Because of this I also have no way of knowing how | 1355 | they should be named. Because of this I also have no way of knowing how |
1336 | to extend the funtions to do alternate cache configurations and/or | 1356 | to extend the funtions to do alternate cache configurations and/or |
1337 | some other CPU frequency scaling. */ | 1357 | some other CPU frequency scaling. */ |
1338 | 1358 | ||
1339 | #ifndef BOOTLOADER | 1359 | #ifndef BOOTLOADER |
@@ -1370,7 +1390,7 @@ void set_cpu_frequency(long frequency) | |||
1370 | else | 1390 | else |
1371 | postmult = CPUFREQ_DEFAULT_MULT; | 1391 | postmult = CPUFREQ_DEFAULT_MULT; |
1372 | cpu_frequency = frequency; | 1392 | cpu_frequency = frequency; |
1373 | 1393 | ||
1374 | outl(0x02, 0xcf005008); | 1394 | outl(0x02, 0xcf005008); |
1375 | outl(0x55, 0xcf00500c); | 1395 | outl(0x55, 0xcf00500c); |
1376 | outl(0x6000, 0xcf005010); | 1396 | outl(0x6000, 0xcf005010); |
@@ -1501,7 +1521,7 @@ void system_init(void) | |||
1501 | IRQ_WRITE_WAIT(0, 0, v == 0); | 1521 | IRQ_WRITE_WAIT(0, 0, v == 0); |
1502 | IRQ_WRITE_WAIT(4, 0, v == 0); | 1522 | IRQ_WRITE_WAIT(4, 0, v == 0); |
1503 | */ | 1523 | */ |
1504 | 1524 | ||
1505 | for (i = 0; i < 0x1c; i++) | 1525 | for (i = 0; i < 0x1c; i++) |
1506 | { | 1526 | { |
1507 | IRQ_WRITE_WAIT(0x404 + i * 4, 0x1e000001, (v & 0x3010f) == 1); | 1527 | IRQ_WRITE_WAIT(0x404 + i * 4, 0x1e000001, (v & 0x3010f) == 1); |
diff --git a/firmware/thread.c b/firmware/thread.c index 0013d49519..c194b2694d 100644 --- a/firmware/thread.c +++ b/firmware/thread.c | |||
@@ -41,7 +41,7 @@ struct regs | |||
41 | void *pr; /* Procedure register */ | 41 | void *pr; /* Procedure register */ |
42 | void *start; /* Thread start address, or NULL when started */ | 42 | void *start; /* Thread start address, or NULL when started */ |
43 | }; | 43 | }; |
44 | #elif defined(CPU_ARM) | 44 | #elif defined(CPU_ARM) |
45 | struct regs | 45 | struct regs |
46 | { | 46 | { |
47 | unsigned int r[8]; /* Registers r4-r11 */ | 47 | unsigned int r[8]; /* Registers r4-r11 */ |
@@ -62,18 +62,31 @@ struct regs | |||
62 | /* Cast to the the machine int type, whose size could be < 4. */ | 62 | /* Cast to the the machine int type, whose size could be < 4. */ |
63 | 63 | ||
64 | 64 | ||
65 | int num_threads; | 65 | int num_threads[NUM_CORES]; |
66 | static volatile int num_sleepers; | 66 | static volatile int num_sleepers[NUM_CORES]; |
67 | static int current_thread; | 67 | static int current_thread[NUM_CORES]; |
68 | static struct regs thread_contexts[MAXTHREADS] IBSS_ATTR; | 68 | static struct regs thread_contexts[NUM_CORES][MAXTHREADS] IBSS_ATTR; |
69 | const char *thread_name[MAXTHREADS]; | 69 | const char *thread_name[NUM_CORES][MAXTHREADS]; |
70 | void *thread_stack[MAXTHREADS]; | 70 | void *thread_stack[NUM_CORES][MAXTHREADS]; |
71 | int thread_stack_size[MAXTHREADS]; | 71 | int thread_stack_size[NUM_CORES][MAXTHREADS]; |
72 | static const char main_thread_name[] = "main"; | 72 | static const char main_thread_name[] = "main"; |
73 | 73 | ||
74 | extern int stackbegin[]; | 74 | extern int stackbegin[]; |
75 | extern int stackend[]; | 75 | extern int stackend[]; |
76 | 76 | ||
77 | #ifdef CPU_PP | ||
78 | #ifndef BOOTLOADER | ||
79 | extern int cop_stackbegin[]; | ||
80 | extern int cop_stackend[]; | ||
81 | #else | ||
82 | /* The coprocessor stack is not set up in the bootloader code, but the | ||
83 | threading is. No threads are run on the coprocessor, so set up some dummy | ||
84 | stack */ | ||
85 | int *cop_stackbegin = stackbegin; | ||
86 | int *cop_stackend = stackend; | ||
87 | #endif | ||
88 | #endif | ||
89 | |||
77 | void switch_thread(void) ICODE_ATTR; | 90 | void switch_thread(void) ICODE_ATTR; |
78 | static inline void store_context(void* addr) __attribute__ ((always_inline)); | 91 | static inline void store_context(void* addr) __attribute__ ((always_inline)); |
79 | static inline void load_context(const void* addr) __attribute__ ((always_inline)); | 92 | static inline void load_context(const void* addr) __attribute__ ((always_inline)); |
@@ -86,7 +99,7 @@ void profile_thread(void) { | |||
86 | #endif | 99 | #endif |
87 | 100 | ||
88 | #if defined(CPU_ARM) | 101 | #if defined(CPU_ARM) |
89 | /*--------------------------------------------------------------------------- | 102 | /*--------------------------------------------------------------------------- |
90 | * Store non-volatile context. | 103 | * Store non-volatile context. |
91 | *--------------------------------------------------------------------------- | 104 | *--------------------------------------------------------------------------- |
92 | */ | 105 | */ |
@@ -116,7 +129,7 @@ static inline void load_context(const void* addr) | |||
116 | } | 129 | } |
117 | 130 | ||
118 | #elif defined(CPU_COLDFIRE) | 131 | #elif defined(CPU_COLDFIRE) |
119 | /*--------------------------------------------------------------------------- | 132 | /*--------------------------------------------------------------------------- |
120 | * Store non-volatile context. | 133 | * Store non-volatile context. |
121 | *--------------------------------------------------------------------------- | 134 | *--------------------------------------------------------------------------- |
122 | */ | 135 | */ |
@@ -199,7 +212,7 @@ static inline void load_context(const void* addr) | |||
199 | } | 212 | } |
200 | 213 | ||
201 | #elif CONFIG_CPU == TCC730 | 214 | #elif CONFIG_CPU == TCC730 |
202 | /*--------------------------------------------------------------------------- | 215 | /*--------------------------------------------------------------------------- |
203 | * Store non-volatile context. | 216 | * Store non-volatile context. |
204 | *--------------------------------------------------------------------------- | 217 | *--------------------------------------------------------------------------- |
205 | */ | 218 | */ |
@@ -215,7 +228,7 @@ static inline void load_context(const void* addr) | |||
215 | "push a14\n\t" \ | 228 | "push a14\n\t" \ |
216 | "ldw @[%0+0], a15\n\t" : : "a" (addr) ); | 229 | "ldw @[%0+0], a15\n\t" : : "a" (addr) ); |
217 | 230 | ||
218 | /*--------------------------------------------------------------------------- | 231 | /*--------------------------------------------------------------------------- |
219 | * Load non-volatile context. | 232 | * Load non-volatile context. |
220 | *--------------------------------------------------------------------------- | 233 | *--------------------------------------------------------------------------- |
221 | */ | 234 | */ |
@@ -260,7 +273,7 @@ void switch_thread(void) | |||
260 | #ifdef SIMULATOR | 273 | #ifdef SIMULATOR |
261 | /* Do nothing */ | 274 | /* Do nothing */ |
262 | #else | 275 | #else |
263 | while (num_sleepers == num_threads) | 276 | while (num_sleepers[CURRENT_CORE] == num_threads[CURRENT_CORE]) |
264 | { | 277 | { |
265 | /* Enter sleep mode, woken up on interrupt */ | 278 | /* Enter sleep mode, woken up on interrupt */ |
266 | #ifdef CPU_COLDFIRE | 279 | #ifdef CPU_COLDFIRE |
@@ -284,21 +297,21 @@ void switch_thread(void) | |||
284 | #endif | 297 | #endif |
285 | } | 298 | } |
286 | #endif | 299 | #endif |
287 | current = current_thread; | 300 | current = current_thread[CURRENT_CORE]; |
288 | store_context(&thread_contexts[current]); | 301 | store_context(&thread_contexts[CURRENT_CORE][current]); |
289 | 302 | ||
290 | #if CONFIG_CPU != TCC730 | 303 | #if CONFIG_CPU != TCC730 |
291 | /* Check if the current thread stack is overflown */ | 304 | /* Check if the current thread stack is overflown */ |
292 | stackptr = thread_stack[current]; | 305 | stackptr = thread_stack[CURRENT_CORE][current]; |
293 | if(stackptr[0] != DEADBEEF) | 306 | if(stackptr[0] != DEADBEEF) |
294 | panicf("Stkov %s", thread_name[current]); | 307 | panicf("Stkov %s", thread_name[CURRENT_CORE][current]); |
295 | #endif | 308 | #endif |
296 | 309 | ||
297 | if (++current >= num_threads) | 310 | if (++current >= num_threads[CURRENT_CORE]) |
298 | current = 0; | 311 | current = 0; |
299 | 312 | ||
300 | current_thread = current; | 313 | current_thread[CURRENT_CORE] = current; |
301 | load_context(&thread_contexts[current]); | 314 | load_context(&thread_contexts[CURRENT_CORE][current]); |
302 | #ifdef RB_PROFILE | 315 | #ifdef RB_PROFILE |
303 | profile_thread_started(current_thread); | 316 | profile_thread_started(current_thread); |
304 | #endif | 317 | #endif |
@@ -306,29 +319,42 @@ void switch_thread(void) | |||
306 | 319 | ||
307 | void sleep_thread(void) | 320 | void sleep_thread(void) |
308 | { | 321 | { |
309 | ++num_sleepers; | 322 | ++num_sleepers[CURRENT_CORE]; |
310 | switch_thread(); | 323 | switch_thread(); |
311 | } | 324 | } |
312 | 325 | ||
313 | void wake_up_thread(void) | 326 | void wake_up_thread(void) |
314 | { | 327 | { |
315 | num_sleepers = 0; | 328 | num_sleepers[CURRENT_CORE] = 0; |
316 | } | 329 | } |
317 | 330 | ||
318 | /*--------------------------------------------------------------------------- | 331 | |
319 | * Create thread. | 332 | /*--------------------------------------------------------------------------- |
333 | * Create thread on the current core. | ||
320 | * Return ID if context area could be allocated, else -1. | 334 | * Return ID if context area could be allocated, else -1. |
321 | *--------------------------------------------------------------------------- | 335 | *--------------------------------------------------------------------------- |
322 | */ | 336 | */ |
323 | int create_thread(void (*function)(void), void* stack, int stack_size, | 337 | int create_thread(void (*function)(void), void* stack, int stack_size, |
324 | const char *name) | 338 | const char *name) |
325 | { | 339 | { |
340 | return create_thread_on_core(CURRENT_CORE, function, stack, stack_size, | ||
341 | name); | ||
342 | } | ||
343 | |||
344 | /*--------------------------------------------------------------------------- | ||
345 | * Create thread on a specific core. | ||
346 | * Return ID if context area could be allocated, else -1. | ||
347 | *--------------------------------------------------------------------------- | ||
348 | */ | ||
349 | int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size, | ||
350 | const char *name) | ||
351 | { | ||
326 | unsigned int i; | 352 | unsigned int i; |
327 | unsigned int stacklen; | 353 | unsigned int stacklen; |
328 | unsigned int *stackptr; | 354 | unsigned int *stackptr; |
329 | struct regs *regs; | 355 | struct regs *regs; |
330 | 356 | ||
331 | if (num_threads >= MAXTHREADS) | 357 | if (num_threads[core] >= MAXTHREADS) |
332 | return -1; | 358 | return -1; |
333 | 359 | ||
334 | /* Munge the stack to make it easy to spot stack overflows */ | 360 | /* Munge the stack to make it easy to spot stack overflows */ |
@@ -340,10 +366,10 @@ int create_thread(void (*function)(void), void* stack, int stack_size, | |||
340 | } | 366 | } |
341 | 367 | ||
342 | /* Store interesting information */ | 368 | /* Store interesting information */ |
343 | thread_name[num_threads] = name; | 369 | thread_name[core][num_threads[core]] = name; |
344 | thread_stack[num_threads] = stack; | 370 | thread_stack[core][num_threads[core]] = stack; |
345 | thread_stack_size[num_threads] = stack_size; | 371 | thread_stack_size[core][num_threads[core]] = stack_size; |
346 | regs = &thread_contexts[num_threads]; | 372 | regs = &thread_contexts[core][num_threads[core]]; |
347 | #if defined(CPU_COLDFIRE) || (CONFIG_CPU == SH7034) || defined(CPU_ARM) | 373 | #if defined(CPU_COLDFIRE) || (CONFIG_CPU == SH7034) || defined(CPU_ARM) |
348 | /* Align stack to an even 32 bit boundary */ | 374 | /* Align stack to an even 32 bit boundary */ |
349 | regs->sp = (void*)(((unsigned int)stack + stack_size) & ~3); | 375 | regs->sp = (void*)(((unsigned int)stack + stack_size) & ~3); |
@@ -355,65 +381,91 @@ int create_thread(void (*function)(void), void* stack, int stack_size, | |||
355 | regs->start = (void*)function; | 381 | regs->start = (void*)function; |
356 | 382 | ||
357 | wake_up_thread(); | 383 | wake_up_thread(); |
358 | return num_threads++; /* return the current ID, e.g for remove_thread() */ | 384 | return num_threads[core]++; /* return the current ID, e.g for remove_thread() */ |
359 | } | 385 | } |
360 | 386 | ||
361 | /*--------------------------------------------------------------------------- | 387 | /*--------------------------------------------------------------------------- |
362 | * Remove a thread from the scheduler. | 388 | * Remove a thread on the current core from the scheduler. |
363 | * Parameter is the ID as returned from create_thread(). | 389 | * Parameter is the ID as returned from create_thread(). |
364 | *--------------------------------------------------------------------------- | 390 | *--------------------------------------------------------------------------- |
365 | */ | 391 | */ |
366 | void remove_thread(int threadnum) | 392 | void remove_thread(int threadnum) |
367 | { | 393 | { |
394 | remove_thread_on_core(CURRENT_CORE, threadnum); | ||
395 | } | ||
396 | |||
397 | /*--------------------------------------------------------------------------- | ||
398 | * Remove a thread on the specified core from the scheduler. | ||
399 | * Parameters are the core and the ID as returned from create_thread(). | ||
400 | *--------------------------------------------------------------------------- | ||
401 | */ | ||
402 | void remove_thread_on_core(unsigned int core, int threadnum) | ||
403 | { | ||
368 | int i; | 404 | int i; |
369 | 405 | ||
370 | if(threadnum >= num_threads) | 406 | if(threadnum >= num_threads[core]) |
371 | return; | 407 | return; |
372 | 408 | ||
373 | num_threads--; | 409 | num_threads[core]--; |
374 | for (i=threadnum; i<num_threads-1; i++) | 410 | for (i=threadnum; i<num_threads[core]-1; i++) |
375 | { /* move all entries which are behind */ | 411 | { /* move all entries which are behind */ |
376 | thread_name[i] = thread_name[i+1]; | 412 | thread_name[core][i] = thread_name[core][i+1]; |
377 | thread_stack[i] = thread_stack[i+1]; | 413 | thread_stack[core][i] = thread_stack[core][i+1]; |
378 | thread_stack_size[i] = thread_stack_size[i+1]; | 414 | thread_stack_size[core][i] = thread_stack_size[core][i+1]; |
379 | thread_contexts[i] = thread_contexts[i+1]; | 415 | thread_contexts[core][i] = thread_contexts[core][i+1]; |
380 | } | 416 | } |
381 | 417 | ||
382 | if (current_thread == threadnum) /* deleting the current one? */ | 418 | if (current_thread[core] == threadnum) /* deleting the current one? */ |
383 | current_thread = num_threads; /* set beyond last, avoid store harm */ | 419 | current_thread[core] = num_threads[core]; /* set beyond last, avoid store harm */ |
384 | else if (current_thread > threadnum) /* within the moved positions? */ | 420 | else if (current_thread[core] > threadnum) /* within the moved positions? */ |
385 | current_thread--; /* adjust it, point to same context again */ | 421 | current_thread[core]--; /* adjust it, point to same context again */ |
386 | } | 422 | } |
387 | 423 | ||
388 | void init_threads(void) | 424 | void init_threads(void) |
389 | { | 425 | { |
390 | num_threads = 1; /* We have 1 thread to begin with */ | 426 | unsigned int core = CURRENT_CORE; |
391 | current_thread = 0; /* The current thread is number 0 */ | 427 | |
392 | thread_name[0] = main_thread_name; | 428 | num_threads[core] = 1; /* We have 1 thread to begin with */ |
393 | thread_stack[0] = stackbegin; | 429 | current_thread[core] = 0; /* The current thread is number 0 */ |
394 | thread_stack_size[0] = (int)stackend - (int)stackbegin; | 430 | thread_name[core][0] = main_thread_name; |
431 | /* In multiple core setups, each core has a different stack. There is probably | ||
432 | a much better way to do this. */ | ||
433 | if(core == CPU) | ||
434 | { | ||
435 | thread_stack[CPU][0] = stackbegin; | ||
436 | thread_stack_size[CPU][0] = (int)stackend - (int)stackbegin; | ||
437 | } else { | ||
438 | #if NUM_CORES > 1 /* This code path will not be run on single core targets */ | ||
439 | thread_stack[COP][0] = cop_stackbegin; | ||
440 | thread_stack_size[COP][0] = (int)cop_stackend - (int)cop_stackbegin; | ||
441 | #endif | ||
442 | } | ||
395 | #if CONFIG_CPU == TCC730 | 443 | #if CONFIG_CPU == TCC730 |
396 | thread_contexts[0].started = 1; | 444 | thread_contexts[core][0].started = 1; |
397 | #else | 445 | #else |
398 | thread_contexts[0].start = 0; /* thread 0 already running */ | 446 | thread_contexts[core][0].start = 0; /* thread 0 already running */ |
399 | #endif | 447 | #endif |
400 | num_sleepers = 0; | 448 | num_sleepers[core] = 0; |
449 | } | ||
450 | |||
451 | int thread_stack_usage(int threadnum){ | ||
452 | return thread_stack_usage_on_core(CURRENT_CORE, threadnum); | ||
401 | } | 453 | } |
402 | 454 | ||
403 | int thread_stack_usage(int threadnum) | 455 | int thread_stack_usage_on_core(unsigned int core, int threadnum) |
404 | { | 456 | { |
405 | unsigned int i; | 457 | unsigned int i; |
406 | unsigned int *stackptr = thread_stack[threadnum]; | 458 | unsigned int *stackptr = thread_stack[core][threadnum]; |
407 | 459 | ||
408 | if(threadnum >= num_threads) | 460 | if(threadnum >= num_threads[core]) |
409 | return -1; | 461 | return -1; |
410 | 462 | ||
411 | for(i = 0;i < thread_stack_size[threadnum]/sizeof(int);i++) | 463 | for(i = 0;i < thread_stack_size[core][threadnum]/sizeof(int);i++) |
412 | { | 464 | { |
413 | if(stackptr[i] != DEADBEEF) | 465 | if(stackptr[i] != DEADBEEF) |
414 | break; | 466 | break; |
415 | } | 467 | } |
416 | 468 | ||
417 | return ((thread_stack_size[threadnum] - i * sizeof(int)) * 100) / | 469 | return ((thread_stack_size[core][threadnum] - i * sizeof(int)) * 100) / |
418 | thread_stack_size[threadnum]; | 470 | thread_stack_size[core][threadnum]; |
419 | } | 471 | } |