From 0aec12f3fd801c5acc03a75818e06741957d51b9 Mon Sep 17 00:00:00 2001 From: Daniel Ankers Date: Mon, 21 Aug 2006 17:35:35 +0000 Subject: Threading changes in preparation for multiple core support git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10681 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/config.h | 17 +++++ firmware/export/system.h | 14 ++-- firmware/export/thread.h | 4 ++ firmware/system.c | 102 ++++++++++++++++------------ firmware/thread.c | 170 +++++++++++++++++++++++++++++++---------------- 5 files changed, 201 insertions(+), 106 deletions(-) (limited to 'firmware') 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 @@ #define USBOTG_ISP1362 1362 #define USBOTG_M5636 5636 +/* Multiple cores */ +#define CPU 0 +#define COP 1 + /* now go and pick yours */ #if defined(ARCHOS_PLAYER) #include "config-player.h" @@ -219,6 +223,19 @@ /* define for all cpus from PP family */ #if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5024) #define CPU_PP + +/* PP family has dual cores */ +#if 0 +/* Keep it as single core until dual core support is ready */ +#define NUM_CORES 2 +#define CURRENT_CORE current_core() +#endif + +#define NUM_CORES 1 +#define CURRENT_CORE 0 +#else +#define NUM_CORES 1 +#define CURRENT_CORE 0 #endif /* 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) unsigned start = USEC_TIMER; while ((USEC_TIMER - start) < usecs); } + +unsigned int current_core(void); #endif struct flash_header { @@ -88,7 +90,7 @@ void cpu_idle_mode(bool on_off); #define betoh32(x) swap32(x) #define htobe16(x) swap16(x) #define htobe32(x) swap32(x) -#else +#else #define letoh16(x) swap16(x) #define letoh32(x) swap32(x) #define htole16(x) swap16(x) @@ -178,7 +180,7 @@ static inline void coldfire_set_macsr(unsigned long flags) static inline unsigned long coldfire_get_macsr(void) { unsigned long m; - + asm volatile ("move.l %%macsr, %0" : "=r" (m)); return m; } @@ -301,7 +303,7 @@ static inline void invalidate_icache(void) "move.l #0x80000000,%d0\n" "movec.l %d0,%cacr"); } - + #define CPUFREQ_DEFAULT_MULT 1 #define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ) #define CPUFREQ_NORMAL_MULT 4 @@ -315,7 +317,7 @@ static inline void invalidate_icache(void) #define CPUFREQ_DEFAULT_MULT 8 #define CPUFREQ_DEFAULT 24000000 -#define CPUFREQ_NORMAL_MULT 10 +#define CPUFREQ_NORMAL_MULT 10 #define CPUFREQ_NORMAL 30000000 #define CPUFREQ_MAX_MULT 25 #define CPUFREQ_MAX 75000000 @@ -336,7 +338,7 @@ static inline unsigned long swap32(unsigned long value) result[15.. 8] = value[23..16]; result[ 7.. 0] = value[31..24]; */ -{ +{ unsigned int tmp; asm volatile ( @@ -418,7 +420,7 @@ static inline int set_irq_level(int level) __asm__ volatile ("clrsr ie"); else __asm__ volatile ("setsr ie"); - + return result; } 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 @@ int create_thread(void (*function)(void), void* stack, int stack_size, const char *name); +int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size, + const char *name); void remove_thread(int threadnum); +void remove_thread_on_core(unsigned int core, int threadnum); void switch_thread(void); void sleep_thread(void); void wake_up_thread(void); void init_threads(void); int thread_stack_usage(int threadnum); +int thread_stack_usage_on_core(unsigned int core, int threadnum); #ifdef RB_PROFILE void profile_thread(void); #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) { struct flash_header hdr; uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT; - + # ifndef BOOTLOADER int oldmode; oldmode = system_memory_guard(MEMGUARD_NONE); # endif - + memcpy(&hdr, src, sizeof(struct flash_header)); - + # ifndef BOOTLOADER system_memory_guard(oldmode); # endif - + if (hdr.magic != FLASH_MAGIC) return false; - + return true; } #else @@ -139,13 +139,13 @@ void ddma_transfer(int dir, int mem, void* intAddr, long extAddr, int num) { /* HW wants those two in word units. */ num /= 2; externalAddress /= 2; - + DDMACFG = (dir << 1) | (mem << 2); DDMAIADR = internalAddress; DDMAEADR = externalAddress; DDMANUM = num; DDMACOM |= 0x4; /* start */ - + ddma_wait_idle(); /* wait for completion */ set_irq_level(irq); } @@ -164,13 +164,13 @@ static void ddma_transfer_noicode(int dir, int mem, long intAddr, long extAddr, /* HW wants those two in word units. */ num /= 2; externalAddress /= 2; - + DDMACFG = (dir << 1) | (mem << 2); DDMAIADR = internalAddress; DDMAEADR = externalAddress; DDMANUM = num; DDMACOM |= 0x4; /* start */ - + ddma_wait_idle_noicode(); /* wait for completion */ set_irq_level(irq); } @@ -220,7 +220,7 @@ void smsc_delay() { Delay doesn't depend on CPU speed in Archos' firmware. */ for (i = 0; i < 100; i++) { - + } } @@ -228,9 +228,9 @@ static void extra_init(void) { /* Power on stuff */ P1 |= 0x07; P1CON |= 0x1f; - + /* P5 conf - * lines 0, 1 & 4 are digital, other analog. : + * lines 0, 1 & 4 are digital, other analog. : */ P5CON = 0xec; @@ -294,21 +294,21 @@ void system_init(void) /******** * CPU */ - - + + /* PLL0 (cpu osc. frequency) */ /* set_cpu_frequency(CPU_FREQ); */ /******************* - * configure S(D)RAM + * configure S(D)RAM */ /************************ * Copy .icode section to icram */ ddma_transfer_noicode(0, 0, 0x40, (long)&icodecopy, (int)&icodesize); - + /*************************** * Interrupts @@ -472,12 +472,12 @@ void UIE (void) /* Unexpected Interrupt or Exception */ unsigned int format_vector, pc; int vector; char str[32]; - + asm volatile ("move.l (52,%%sp),%0": "=r"(format_vector)); asm volatile ("move.l (56,%%sp),%0": "=r"(pc)); vector = (format_vector >> 18) & 0xff; - + /* clear screen */ lcd_clear_display (); #ifdef HAVE_LCD_BITMAP @@ -488,7 +488,7 @@ void UIE (void) /* Unexpected Interrupt or Exception */ snprintf(str,sizeof(str),"at %08x",pc); lcd_puts(0,1,str); lcd_update(); - + /* set cpu frequency to 11mhz (to prevent overheating) */ DCR = (DCR & ~0x01ff) | 1; PLLCR = 0x10800000; @@ -510,7 +510,7 @@ void UIE (void) /* Unexpected Interrupt or Exception */ } /* reset vectors are handled in crt0.S */ -void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = +void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = { UIE,UIE,UIE,UIE,UIE,UIE, UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE, @@ -520,7 +520,7 @@ void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) = TRAP0,TRAP1,TRAP2,TRAP3,TRAP4,TRAP5,TRAP6,TRAP7, TRAP8,TRAP9,TRAP10,TRAP11,TRAP12,TRAP13,TRAP14,TRAP15, - + SWT,UIE,UIE,I2C,UART1,UART2,DMA0,DMA1, DMA2,DMA3,QSPI,UIE,UIE,UIE,UIE,UIE, PDIR1FULL,PDIR2FULL,EBUTXEMPTY,IIS2TXEMPTY, @@ -741,7 +741,7 @@ static const char* const irqname[] = { asm ( -/* Vector table. +/* Vector table. * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols * defined in an asm block -- silly. * Reset vectors (0..3) are handled in crt0.S */ @@ -854,7 +854,7 @@ asm ( RESERVE_INTERRUPT ( 108) DEFAULT_INTERRUPT (ADITI, 109) -/* UIE# block. +/* UIE# block. * Must go into the same section as the UIE() handler */ "\t.text\n" @@ -979,7 +979,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ char str[32]; asm volatile ("sts\tpr,%0" : "=r"(n)); - + /* clear screen */ lcd_clear_display (); #ifdef HAVE_LCD_BITMAP @@ -1002,7 +1002,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ volatile int i; led (state); state = !state; - + for (i = 0; i < 240000; ++i); #endif @@ -1018,7 +1018,7 @@ void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */ #elif CONFIG_KEYPAD == ONDIO_PAD if (!(PCDR & 0x0008)) #endif - { + { /* enable the watchguard timer, but don't service it */ RSTCSR_W = 0x5a40; /* Reset enabled, power-on reset */ TCSR_W = 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */ @@ -1086,7 +1086,7 @@ int system_memory_guard(int newmode) int oldmode = MEMGUARD_NONE; int i; - + /* figure out the old mode from what is in the UBC regs. If the register values don't match any mode, assume MEMGUARD_NONE */ for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++) @@ -1098,7 +1098,7 @@ int system_memory_guard(int newmode) break; } } - + if (newmode == MEMGUARD_KEEP) newmode = oldmode; @@ -1109,7 +1109,7 @@ int system_memory_guard(int newmode) BAR = modes[newmode].addr; BAMR = modes[newmode].mask; BBR = modes[newmode].bbr; - + return oldmode; } #elif defined(CPU_ARM) @@ -1124,7 +1124,7 @@ static const char* const uiename[] = { void UIE(unsigned int pc, unsigned int num) { char str[32]; - + lcd_clear_display(); #ifdef HAVE_LCD_BITMAP lcd_setfont(FONT_SYSFIXED); @@ -1133,7 +1133,7 @@ void UIE(unsigned int pc, unsigned int num) snprintf(str, sizeof(str), "at %08x", pc); lcd_puts(0, 1, str); lcd_update(); - + while (1) { /* TODO: perhaps add button handling in here when we get a polling @@ -1160,7 +1160,7 @@ void irq(void) else if (CPU_INT_STAT & TIMER2_MASK) TIMER2(); else if (CPU_HI_INT_STAT & GPIO_MASK) - ipod_mini_button_int(); + ipod_mini_button_int(); } #elif (defined IRIVER_H10) || (defined IRIVER_H10_5GB) /* TODO: this should really be in the target tree, but moving it there caused @@ -1170,14 +1170,14 @@ void irq(void) if (CPU_INT_STAT & TIMER1_MASK) TIMER1(); else if (CPU_INT_STAT & TIMER2_MASK) - TIMER2(); + TIMER2(); } #else extern void ipod_4g_button_int(void); void irq(void) { - if (CPU_INT_STAT & TIMER1_MASK) + if (CPU_INT_STAT & TIMER1_MASK) TIMER1(); else if (CPU_INT_STAT & TIMER2_MASK) TIMER2(); @@ -1187,11 +1187,21 @@ void irq(void) #endif #endif /* BOOTLOADER */ +unsigned int current_core(void) +{ + if(((*(volatile unsigned long *)(0x60000000)) & 0xff) == 0x55) + { + return CPU; + } + return COP; +} + + /* TODO: The following two function have been lifted straight from IPL, and hence have a lot of numeric addresses used straight. I'd like to use #defines for these, but don't know what most of them are for or even what they should be named. Because of this I also have no way of knowing how - to extend the funtions to do alternate cache configurations and/or + to extend the funtions to do alternate cache configurations and/or some other CPU frequency scaling. */ #ifndef BOOTLOADER @@ -1251,7 +1261,7 @@ void set_cpu_frequency(long frequency) #if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) /* We don't know why the timer interrupt gets disabled on the PP5020 based ipods, but without the following line, the 4Gs will freeze - when CPU frequency changing is enabled. + when CPU frequency changing is enabled. Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used elsewhere to enable interrupts) doesn't work, we need "|=". @@ -1321,19 +1331,29 @@ extern void TIMER2(void); void irq(void) { - if (CPU_INT_STAT & TIMER1_MASK) + if (CPU_INT_STAT & TIMER1_MASK) TIMER1(); - else if (CPU_INT_STAT & TIMER2_MASK) + else if (CPU_INT_STAT & TIMER2_MASK) TIMER2(); } #endif +unsigned int current_core(void) +{ + if(((*(volatile unsigned long *)(0xc4000000)) & 0xff) == 0x55) + { + return CPU; + } + return COP; +} + + /* TODO: The following two function have been lifted straight from IPL, and hence have a lot of numeric addresses used straight. I'd like to use #defines for these, but don't know what most of them are for or even what they should be named. Because of this I also have no way of knowing how - to extend the funtions to do alternate cache configurations and/or + to extend the funtions to do alternate cache configurations and/or some other CPU frequency scaling. */ #ifndef BOOTLOADER @@ -1370,7 +1390,7 @@ void set_cpu_frequency(long frequency) else postmult = CPUFREQ_DEFAULT_MULT; cpu_frequency = frequency; - + outl(0x02, 0xcf005008); outl(0x55, 0xcf00500c); outl(0x6000, 0xcf005010); @@ -1501,7 +1521,7 @@ void system_init(void) IRQ_WRITE_WAIT(0, 0, v == 0); IRQ_WRITE_WAIT(4, 0, v == 0); */ - + for (i = 0; i < 0x1c; i++) { 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 void *pr; /* Procedure register */ void *start; /* Thread start address, or NULL when started */ }; -#elif defined(CPU_ARM) +#elif defined(CPU_ARM) struct regs { unsigned int r[8]; /* Registers r4-r11 */ @@ -62,18 +62,31 @@ struct regs /* Cast to the the machine int type, whose size could be < 4. */ -int num_threads; -static volatile int num_sleepers; -static int current_thread; -static struct regs thread_contexts[MAXTHREADS] IBSS_ATTR; -const char *thread_name[MAXTHREADS]; -void *thread_stack[MAXTHREADS]; -int thread_stack_size[MAXTHREADS]; +int num_threads[NUM_CORES]; +static volatile int num_sleepers[NUM_CORES]; +static int current_thread[NUM_CORES]; +static struct regs thread_contexts[NUM_CORES][MAXTHREADS] IBSS_ATTR; +const char *thread_name[NUM_CORES][MAXTHREADS]; +void *thread_stack[NUM_CORES][MAXTHREADS]; +int thread_stack_size[NUM_CORES][MAXTHREADS]; static const char main_thread_name[] = "main"; extern int stackbegin[]; extern int stackend[]; +#ifdef CPU_PP +#ifndef BOOTLOADER +extern int cop_stackbegin[]; +extern int cop_stackend[]; +#else +/* The coprocessor stack is not set up in the bootloader code, but the + threading is. No threads are run on the coprocessor, so set up some dummy + stack */ +int *cop_stackbegin = stackbegin; +int *cop_stackend = stackend; +#endif +#endif + void switch_thread(void) ICODE_ATTR; static inline void store_context(void* addr) __attribute__ ((always_inline)); static inline void load_context(const void* addr) __attribute__ ((always_inline)); @@ -86,7 +99,7 @@ void profile_thread(void) { #endif #if defined(CPU_ARM) -/*--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- * Store non-volatile context. *--------------------------------------------------------------------------- */ @@ -116,7 +129,7 @@ static inline void load_context(const void* addr) } #elif defined(CPU_COLDFIRE) -/*--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- * Store non-volatile context. *--------------------------------------------------------------------------- */ @@ -199,7 +212,7 @@ static inline void load_context(const void* addr) } #elif CONFIG_CPU == TCC730 -/*--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- * Store non-volatile context. *--------------------------------------------------------------------------- */ @@ -215,7 +228,7 @@ static inline void load_context(const void* addr) "push a14\n\t" \ "ldw @[%0+0], a15\n\t" : : "a" (addr) ); -/*--------------------------------------------------------------------------- +/*--------------------------------------------------------------------------- * Load non-volatile context. *--------------------------------------------------------------------------- */ @@ -260,7 +273,7 @@ void switch_thread(void) #ifdef SIMULATOR /* Do nothing */ #else - while (num_sleepers == num_threads) + while (num_sleepers[CURRENT_CORE] == num_threads[CURRENT_CORE]) { /* Enter sleep mode, woken up on interrupt */ #ifdef CPU_COLDFIRE @@ -284,21 +297,21 @@ void switch_thread(void) #endif } #endif - current = current_thread; - store_context(&thread_contexts[current]); - + current = current_thread[CURRENT_CORE]; + store_context(&thread_contexts[CURRENT_CORE][current]); + #if CONFIG_CPU != TCC730 /* Check if the current thread stack is overflown */ - stackptr = thread_stack[current]; + stackptr = thread_stack[CURRENT_CORE][current]; if(stackptr[0] != DEADBEEF) - panicf("Stkov %s", thread_name[current]); + panicf("Stkov %s", thread_name[CURRENT_CORE][current]); #endif - if (++current >= num_threads) + if (++current >= num_threads[CURRENT_CORE]) current = 0; - current_thread = current; - load_context(&thread_contexts[current]); + current_thread[CURRENT_CORE] = current; + load_context(&thread_contexts[CURRENT_CORE][current]); #ifdef RB_PROFILE profile_thread_started(current_thread); #endif @@ -306,29 +319,42 @@ void switch_thread(void) void sleep_thread(void) { - ++num_sleepers; + ++num_sleepers[CURRENT_CORE]; switch_thread(); } void wake_up_thread(void) { - num_sleepers = 0; + num_sleepers[CURRENT_CORE] = 0; } -/*--------------------------------------------------------------------------- - * Create thread. + +/*--------------------------------------------------------------------------- + * Create thread on the current core. * Return ID if context area could be allocated, else -1. *--------------------------------------------------------------------------- */ int create_thread(void (*function)(void), void* stack, int stack_size, const char *name) +{ + return create_thread_on_core(CURRENT_CORE, function, stack, stack_size, + name); +} + +/*--------------------------------------------------------------------------- + * Create thread on a specific core. + * Return ID if context area could be allocated, else -1. + *--------------------------------------------------------------------------- + */ +int create_thread_on_core(unsigned int core, void (*function)(void), void* stack, int stack_size, + const char *name) { unsigned int i; unsigned int stacklen; unsigned int *stackptr; struct regs *regs; - if (num_threads >= MAXTHREADS) + if (num_threads[core] >= MAXTHREADS) return -1; /* 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, } /* Store interesting information */ - thread_name[num_threads] = name; - thread_stack[num_threads] = stack; - thread_stack_size[num_threads] = stack_size; - regs = &thread_contexts[num_threads]; + thread_name[core][num_threads[core]] = name; + thread_stack[core][num_threads[core]] = stack; + thread_stack_size[core][num_threads[core]] = stack_size; + regs = &thread_contexts[core][num_threads[core]]; #if defined(CPU_COLDFIRE) || (CONFIG_CPU == SH7034) || defined(CPU_ARM) /* Align stack to an even 32 bit boundary */ regs->sp = (void*)(((unsigned int)stack + stack_size) & ~3); @@ -355,65 +381,91 @@ int create_thread(void (*function)(void), void* stack, int stack_size, regs->start = (void*)function; wake_up_thread(); - return num_threads++; /* return the current ID, e.g for remove_thread() */ + return num_threads[core]++; /* return the current ID, e.g for remove_thread() */ } -/*--------------------------------------------------------------------------- - * Remove a thread from the scheduler. +/*--------------------------------------------------------------------------- + * Remove a thread on the current core from the scheduler. * Parameter is the ID as returned from create_thread(). *--------------------------------------------------------------------------- */ void remove_thread(int threadnum) +{ + remove_thread_on_core(CURRENT_CORE, threadnum); +} + +/*--------------------------------------------------------------------------- + * Remove a thread on the specified core from the scheduler. + * Parameters are the core and the ID as returned from create_thread(). + *--------------------------------------------------------------------------- + */ +void remove_thread_on_core(unsigned int core, int threadnum) { int i; - if(threadnum >= num_threads) + if(threadnum >= num_threads[core]) return; - num_threads--; - for (i=threadnum; i threadnum) /* within the moved positions? */ - current_thread--; /* adjust it, point to same context again */ + if (current_thread[core] == threadnum) /* deleting the current one? */ + current_thread[core] = num_threads[core]; /* set beyond last, avoid store harm */ + else if (current_thread[core] > threadnum) /* within the moved positions? */ + current_thread[core]--; /* adjust it, point to same context again */ } void init_threads(void) { - num_threads = 1; /* We have 1 thread to begin with */ - current_thread = 0; /* The current thread is number 0 */ - thread_name[0] = main_thread_name; - thread_stack[0] = stackbegin; - thread_stack_size[0] = (int)stackend - (int)stackbegin; + unsigned int core = CURRENT_CORE; + + num_threads[core] = 1; /* We have 1 thread to begin with */ + current_thread[core] = 0; /* The current thread is number 0 */ + thread_name[core][0] = main_thread_name; +/* In multiple core setups, each core has a different stack. There is probably + a much better way to do this. */ + if(core == CPU) + { + thread_stack[CPU][0] = stackbegin; + thread_stack_size[CPU][0] = (int)stackend - (int)stackbegin; + } else { +#if NUM_CORES > 1 /* This code path will not be run on single core targets */ + thread_stack[COP][0] = cop_stackbegin; + thread_stack_size[COP][0] = (int)cop_stackend - (int)cop_stackbegin; +#endif + } #if CONFIG_CPU == TCC730 - thread_contexts[0].started = 1; + thread_contexts[core][0].started = 1; #else - thread_contexts[0].start = 0; /* thread 0 already running */ + thread_contexts[core][0].start = 0; /* thread 0 already running */ #endif - num_sleepers = 0; + num_sleepers[core] = 0; +} + +int thread_stack_usage(int threadnum){ + return thread_stack_usage_on_core(CURRENT_CORE, threadnum); } -int thread_stack_usage(int threadnum) +int thread_stack_usage_on_core(unsigned int core, int threadnum) { unsigned int i; - unsigned int *stackptr = thread_stack[threadnum]; + unsigned int *stackptr = thread_stack[core][threadnum]; - if(threadnum >= num_threads) + if(threadnum >= num_threads[core]) return -1; - for(i = 0;i < thread_stack_size[threadnum]/sizeof(int);i++) + for(i = 0;i < thread_stack_size[core][threadnum]/sizeof(int);i++) { if(stackptr[i] != DEADBEEF) break; } - return ((thread_stack_size[threadnum] - i * sizeof(int)) * 100) / - thread_stack_size[threadnum]; -} + return ((thread_stack_size[core][threadnum] - i * sizeof(int)) * 100) / + thread_stack_size[core][threadnum]; +} -- cgit v1.2.3