interrupt void ISR() { if (TMR1IE && TMR1IF) { TMR1IF = OFF; TMR1ON = OFF; if (++count == MAX_COUNT) { TMR1 = 0xFFFF - EXTRA_COUNT; TMR1ON = ON; idle_loop(); } else if (++count > MAX_COUNT) { stop(); reset(); blink(); } else if (++count < MAX_COUNT) { TMR1 = 0; TMR1ON = ON; idle_loop(); } } if (INTF && INTE) { INTF = 0; // if timer is running, we are not blinking if (TMR1ON) { #if DEBUG == 1 LED = ~LED; #endif idle_loop(); } else { // reset timer and start it because it was blinking start(); #if DEBUG == 1 LED = 1; int tmp = 0; while (++tmp < 500); #endif idle_loop(); } } }
// ************************************************************************************************* // @fn main // @brief Main routine // @param none // @return none // ************************************************************************************************* int main(void) { #ifdef EMU emu_init(); #endif // Init MCU init_application(); // Assign initial value to global variables init_global_variables(); #ifdef CONFIG_TEST // Branch to welcome screen test_mode(); #else display_all_off(); #endif // Main control loop: wait in low power mode until some event needs to be processed while(1) { // When idle go to LPM3 idle_loop(); // Process wake-up events if (button.all_flags || sys.all_flags) wakeup_event(); // Process actions requested by logic modules if (request.all_flags) process_requests(); // Before going to LPM3, update display if (display.all_flags) display_update(); } }
static size_t incremental_gc(mrb_state *mrb, size_t limit) { idle_loop(); switch (mrb->gc_state) { case GC_STATE_ROOT: root_scan_phase(mrb); mrb->gc_state = GC_STATE_MARK; flip_white_part(mrb); return 0; case GC_STATE_MARK: if (mrb->gray_list) { return incremental_marking_phase(mrb, limit); } else { final_marking_phase(mrb); prepare_incremental_sweep(mrb); return 0; } case GC_STATE_SWEEP: { size_t tried_sweep = 0; tried_sweep = incremental_sweep_phase(mrb, limit); if (tried_sweep == 0) mrb->gc_state = GC_STATE_ROOT; return tried_sweep; } default: /* unknown state */ mrb_assert(0); return 0; } }
void config() { // disable POR and BOR flags (inverted) nPOR = 1; nBOR = 1; nBOD = 1; // disable analog ins ANSEL = 0; // assign prescaler to WDT (instead of timer0) PSA = 1; // turn off gate enable TMR1GE = OFF; // //enable Synchronous mode //T1SYNC = 1; // prescale clock by 8 T1CKPS1 = 1; T1CKPS0 = 1; // use internal clock/4 for incrementing TMR1CS = 0; // clear timer 1 TMR1 = 0; // set 2 to input and 1 to out TRISIO2 = 1; TRISIO1 = 0; #if DEBUG == 3 LED = 1; idle_loop(); #endif // enable weak pullups nGPPU = ~ON; WPU = ~0x8; // enable interrupts //global GIE = ON; // peripheral PEIE = ON; // Timer 1 clear TMR1IF = OFF; // timer1 enable TMR1IE = ON; // clear interrupt before enabling INTF = OFF; // enable interrupt on change for INT2 INTE = ON; // set to falling edge of interrupt INTEDG = 0; return; }
/** thread_init(): Initialize a thread on Windows. This is written by Teemu Pudas. Created 071108; last modified 071108 **/ DWORD WINAPI thread_init(LPVOID arg) { board.id = *(int *)arg; initialize_board(NULL); initialize_hash(); board.split_ply = board.split_ply_stack; board.split_ply_stack[0] = -1; board.split_point = board.split_point_stack; board.split_point_stack[0] = NULL; idle_loop(board.id); return 0; }
int main(int argc, char** argv) { #if DEBUG == 4 TRISIO2 = 1; TRISIO1 = 0; nGPPU = 0; LED = 1; while (1) { } #elif DEBUG == 0 //asm("nop"); //while(1); config(); start(); // keeps the program going idle_loop(); #endif return (EXIT_SUCCESS); }
int cpu_idle(void) { idle_loop(); return 0; }
static int check_itimer(int which) { int err; struct timeval start, end; struct itimerval val = { .it_value.tv_sec = DELAY, }; printf("Check itimer "); if (which == ITIMER_VIRTUAL) printf("virtual... "); else if (which == ITIMER_PROF) printf("prof... "); else if (which == ITIMER_REAL) printf("real... "); fflush(stdout); done = 0; if (which == ITIMER_VIRTUAL) signal(SIGVTALRM, sig_handler); else if (which == ITIMER_PROF) signal(SIGPROF, sig_handler); else if (which == ITIMER_REAL) signal(SIGALRM, sig_handler); err = gettimeofday(&start, NULL); if (err < 0) { perror("Can't call gettimeofday()\n"); return -1; } err = setitimer(which, &val, NULL); if (err < 0) { perror("Can't set timer\n"); return -1; } if (which == ITIMER_VIRTUAL) user_loop(); else if (which == ITIMER_PROF) kernel_loop(); else if (which == ITIMER_REAL) idle_loop(); gettimeofday(&end, NULL); if (err < 0) { perror("Can't call gettimeofday()\n"); return -1; } if (!check_diff(start, end)) printf("[OK]\n"); else printf("[FAIL]\n"); return 0; } static int check_timer_create(int which) { int err; timer_t id; struct timeval start, end; struct itimerspec val = { .it_value.tv_sec = DELAY, }; printf("Check timer_create() "); if (which == CLOCK_THREAD_CPUTIME_ID) { printf("per thread... "); } else if (which == CLOCK_PROCESS_CPUTIME_ID) { printf("per process... "); } fflush(stdout); done = 0; err = timer_create(which, NULL, &id); if (err < 0) { perror("Can't create timer\n"); return -1; } signal(SIGALRM, sig_handler); err = gettimeofday(&start, NULL); if (err < 0) { perror("Can't call gettimeofday()\n"); return -1; } err = timer_settime(id, 0, &val, NULL); if (err < 0) { perror("Can't set timer\n"); return -1; } user_loop(); gettimeofday(&end, NULL); if (err < 0) { perror("Can't call gettimeofday()\n"); return -1; } if (!check_diff(start, end)) printf("[OK]\n"); else printf("[FAIL]\n"); return 0; } int main(int argc, char **argv) { printf("Testing posix timers. False negative may happen on CPU execution \n"); printf("based timers if other threads run on the CPU...\n"); if (check_itimer(ITIMER_VIRTUAL) < 0) return ksft_exit_fail(); if (check_itimer(ITIMER_PROF) < 0) return ksft_exit_fail(); if (check_itimer(ITIMER_REAL) < 0) return ksft_exit_fail(); if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0) return ksft_exit_fail(); /* * It's unfortunately hard to reliably test a timer expiration * on parallel multithread cputime. We could arm it to expire * on DELAY * nr_threads, with nr_threads busy looping, then wait * the normal DELAY since the time is elapsing nr_threads faster. * But for that we need to ensure we have real physical free CPUs * to ensure true parallelism. So test only one thread until we * find a better solution. */ if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0) return ksft_exit_fail(); return ksft_exit_pass(); }
// ************************************************************************************************* // @fn set_value // @brief Generic value setting routine // @param s32 * value Pointer to value to set // u8digits Number of digits // u8 blanks Number of whitespaces before first valid digit // s32 limitLow Lower limit of value // s32 limitHigh Upper limit of value // u16 mode // u8 segments Segments where value should be drawn // fptr_setValue_display_function1 Value-specific display routine // @return none // ************************************************************************************************* void set_value(s32 * value, u8 digits, u8 blanks, s32 limitLow, s32 limitHigh, u16 mode, u8 segments, void (*fptr_setValue_display_function1)(u8 segments, u32 value, u8 digits, u8 blanks)) { u8 update; s16 stepValue = 1; u8 doRound = 0; u32 val; // Clear button flags button.all_flags = 0; // Clear blink memory clear_blink_mem(); // For safety only - buzzer on/off and button_repeat share same IRQ stop_buzzer(); // Init step size and repeat counter sButton.repeats = 0; // Initial display update update = 1; // Turn on 200ms button repeat function button_repeat_on(200); // Start blinking with with 2Hz set_blink_rate(BIT6 + BIT5); // Value set loop while(1) { // Idle timeout: exit function if (sys.flag.idle_timeout) break; // STAR (short) button: exit function if (button.flag.star) break; // NUM button: exit function and goto to next value (if available) if (button.flag.num) { if ((mode & SETVALUE_NEXT_VALUE) == SETVALUE_NEXT_VALUE) break; } // UP button: increase value if(button.flag.up) { // Increase value * value = * value + stepValue; // Check value limits if (* value > limitHigh) { // Check if value can roll over, else stick to limit if ((mode & SETVALUE_ROLLOVER_VALUE) == SETVALUE_ROLLOVER_VALUE) * value = limitLow; else * value = limitHigh; // Reset step size to default stepValue = 1; } // Trigger display update update = 1; // Clear button flag button.flag.up = 0; } // DOWN button: decrease value if(button.flag.down) { // Decrease value * value = * value - stepValue; // Check value limits if (* value < limitLow) { // Check if value can roll over, else stick to limit if ((mode & SETVALUE_ROLLOVER_VALUE) == SETVALUE_ROLLOVER_VALUE) * value = limitHigh; else * value = limitLow; // Reset step size to default stepValue = 1; } // Trigger display update update = 1; // Clear button flag button.flag.down = 0; } // When fast mode is enabled, increase step size if Sx button is continuously if ((mode & SETVALUE_FAST_MODE) == SETVALUE_FAST_MODE) { switch (sButton.repeats) { case 0: stepValue = 1; doRound = 0; break; case 10: case -10: stepValue = 10; doRound = 1; break; case 20: case -20: stepValue = 100; doRound = 1; break; case 30: case -30: stepValue = 1000; doRound = 1; break; } // Round value to avoid odd numbers on display if (stepValue != 1 && doRound == 1) { * value -= * value % stepValue; doRound = 0; } } // Update display when there is new data if (update) { // Display up or down arrow according to sign of value if ((mode & SETVALUE_DISPLAY_ARROWS) == SETVALUE_DISPLAY_ARROWS) { if (* value >= 0) { display_symbol(LCD_SYMB_ARROW_UP, SEG_ON); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); val = *value; } else { display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON); val = *value * (-1); } } else { val = *value; } // Display function can either display value directly, modify value before displaying // or display a string referenced by the value fptr_setValue_display_function1(segments, val, digits, blanks); // Clear update flag update = 0; } // Call idle loop to serve background tasks idle_loop(); } // Clear up and down arrows display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); // Set blinking rate to 1Hz and stop set_blink_rate(BIT7 + BIT6 + BIT5); clear_blink_mem(); // Turn off button repeat function button_repeat_off(); }
void cpu_hatch(struct cpu_info *ci) { struct pmap_tlb_info * const ti = ci->ci_tlb_info; /* * Invalidate all the TLB enties (even wired ones) and then reserve * space for the wired TLB entries. */ mips3_cp0_wired_write(0); tlb_invalidate_all(); mips3_cp0_wired_write(ti->ti_wired); /* * Setup HWRENA and USERLOCAL COP0 registers (MIPSxxR2). */ cpu_hwrena_setup(); /* * If we are using register zero relative addressing to access cpu_info * in the exception vectors, enter that mapping into TLB now. */ if (ci->ci_tlb_slot >= 0) { const uint32_t tlb_lo = MIPS3_PG_G|MIPS3_PG_V | mips3_paddr_to_tlbpfn((vaddr_t)ci); const struct tlbmask tlbmask = { .tlb_hi = -PAGE_SIZE | KERNEL_PID, #if (PGSHIFT & 1) .tlb_lo0 = tlb_lo, .tlb_lo1 = tlb_lo + MIPS3_PG_NEXT, #else .tlb_lo0 = 0, .tlb_lo1 = tlb_lo, #endif .tlb_mask = -1, }; tlb_invalidate_addr(tlbmask.tlb_hi, KERNEL_PID); tlb_write_entry(ci->ci_tlb_slot, &tlbmask); } /* * Flush the icache just be sure. */ mips_icache_sync_all(); /* * Let this CPU do its own initialization (for things that have to be * done on the local CPU). */ (*mips_locoresw.lsw_cpu_init)(ci); // Show this CPU as present. atomic_or_ulong(&ci->ci_flags, CPUF_PRESENT); /* * Announce we are hatched */ kcpuset_atomic_set(cpus_hatched, cpu_index(ci)); /* * Now wait to be set free! */ while (! kcpuset_isset(cpus_running, cpu_index(ci))) { /* spin, spin, spin */ } /* * initialize the MIPS count/compare clock */ mips3_cp0_count_write(ci->ci_data.cpu_cc_skew); KASSERT(ci->ci_cycles_per_hz != 0); ci->ci_next_cp0_clk_intr = ci->ci_data.cpu_cc_skew + ci->ci_cycles_per_hz; mips3_cp0_compare_write(ci->ci_next_cp0_clk_intr); ci->ci_data.cpu_cc_skew = 0; /* * Let this CPU do its own post-running initialization * (for things that have to be done on the local CPU). */ (*mips_locoresw.lsw_cpu_run)(ci); /* * Now turn on interrupts (and verify they are on). */ spl0(); KASSERTMSG(ci->ci_cpl == IPL_NONE, "cpl %d", ci->ci_cpl); KASSERT(mips_cp0_status_read() & MIPS_SR_INT_IE); kcpuset_atomic_set(pmap_kernel()->pm_onproc, cpu_index(ci)); kcpuset_atomic_set(pmap_kernel()->pm_active, cpu_index(ci)); /* * And do a tail call to idle_loop */ idle_loop(NULL); } void cpu_boot_secondary_processors(void) { CPU_INFO_ITERATOR cii; struct cpu_info *ci; for (CPU_INFO_FOREACH(cii, ci)) { if (CPU_IS_PRIMARY(ci)) continue; KASSERT(ci->ci_data.cpu_idlelwp); /* * Skip this CPU if it didn't sucessfully hatch. */ if (!kcpuset_isset(cpus_hatched, cpu_index(ci))) continue; ci->ci_data.cpu_cc_skew = mips3_cp0_count_read(); atomic_or_ulong(&ci->ci_flags, CPUF_RUNNING); kcpuset_set(cpus_running, cpu_index(ci)); // Spin until the cpu calls idle_loop for (u_int i = 0; i < 100; i++) { if (kcpuset_isset(cpus_running, cpu_index(ci))) break; delay(1000); } } }
void cpu_hatch(struct cpu_info *ci) { struct pmap_tlb_info * const ti = ci->ci_tlb_info; /* * Invalidate all the TLB enties (even wired ones) and then reserve * space for the wired TLB entries. */ mips3_cp0_wired_write(0); tlb_invalidate_all(); mips3_cp0_wired_write(ti->ti_wired); /* * Setup HWRENA and USERLOCAL COP0 registers (MIPSxxR2). */ cpu_hwrena_setup(); /* * If we are using register zero relative addressing to access cpu_info * in the exception vectors, enter that mapping into TLB now. */ if (ci->ci_tlb_slot >= 0) { const uint32_t tlb_lo = MIPS3_PG_G|MIPS3_PG_V | mips3_paddr_to_tlbpfn((vaddr_t)ci); tlb_enter(ci->ci_tlb_slot, -PAGE_SIZE, tlb_lo); } /* * Flush the icache just be sure. */ mips_icache_sync_all(); /* * Let this CPU do its own initialization (for things that have to be * done on the local CPU). */ (*mips_locoresw.lsw_cpu_init)(ci); /* * Announce we are hatched */ CPUSET_ADD(cpus_hatched, cpu_index(ci)); /* * Now wait to be set free! */ while (! CPUSET_HAS_P(cpus_running, cpu_index(ci))) { /* spin, spin, spin */ } /* * initialize the MIPS count/compare clock */ mips3_cp0_count_write(ci->ci_data.cpu_cc_skew); KASSERT(ci->ci_cycles_per_hz != 0); ci->ci_next_cp0_clk_intr = ci->ci_data.cpu_cc_skew + ci->ci_cycles_per_hz; mips3_cp0_compare_write(ci->ci_next_cp0_clk_intr); ci->ci_data.cpu_cc_skew = 0; /* * Let this CPU do its own post-running initialization * (for things that have to be done on the local CPU). */ (*mips_locoresw.lsw_cpu_run)(ci); /* * Now turn on interrupts. */ spl0(); /* * And do a tail call to idle_loop */ idle_loop(NULL); }
/** initialize_smp(): Initializes the smp functionality for the given number of processes. Created 081305; last modified 103008 **/ void initialize_smp(int procs) { int x; int y; int z; /* Set up the default signals. This is because the child processes inherit all of the parent's signal handlers, and we don't want that. */ signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); // signal(SIGCHLD, SIG_IGN); if (smp_data != NULL) smp_cleanup(); else if (atexit(smp_cleanup) == -1 || atexit(smp_cleanup_final) == -1) { smp_cleanup(); smp_cleanup_final(); fatal_error("fatal error: atexit failed"); } zct->process_count = procs; /* Allocate the shared memory to the various data structures needed. */ split_point_size = sizeof(SPLIT_POINT) * MAX_SPLIT_POINTS; smp_block_size = sizeof(SMP_BLOCK) * procs; smp_data_size = sizeof(SMP_DATA); split_point = (SPLIT_POINT *)shared_alloc(split_point_size); smp_block = (SMP_BLOCK *)shared_alloc(smp_block_size); smp_data = (SMP_DATA *)shared_alloc(smp_data_size); #define DBG(t,s,i) do{int p;\ print("%s: %x\n", #t, sizeof(t));\ for (p=0;p<i;p++){\ print("%p",&s[p]);\ if(p>0)\ print(" %i",((BITBOARD)&s[p])-((BITBOARD)&s[p-1]));\ print("\n");\ }}while(0) /* DBG(SMP_BLOCK, smp_block, procs); DBG(SMP_DATA, smp_data, 1); */ /* Initialize the data. */ /* SMP data */ smp_data->return_flag = FALSE; /* smp blocks */ for (x = 0; x < procs; x++) { smp_block[x].id = x; smp_block[x].idle = FALSE; smp_block[x].last_idle_time = 0; smp_block[x].message_count = 0; smp_block[x].input = 0; smp_block[x].output = 0; for (y = 0; y < MAX_PLY; y++) initialize_split_score(&smp_block[x].tree.sb_score[y]); // initialize_split_score(&smp_block[x].tree.split_score); /* The split ID is id*MAX_CPUS+board.id, so instead of calculating that every time we split, we just start at board.id and increment by MAX_CPUS. */ smp_block[x].split_id = x; #ifdef ZCT_WINDOWS _pipe(smp_block[x].wait_pipe, 8, O_BINARY); #else pipe(smp_block[x].wait_pipe); #endif } /* split points */ for (x = 0; x < MAX_SPLIT_POINTS; x++) { split_point[x].n = x; split_point[x].active = FALSE; split_point[x].child_count = 0; for (y = 0; y < MAX_CPUS; y++) { split_point[x].update[y] = FALSE; split_point[x].is_child[y] = FALSE; } } /* main processor's smp info */ board.id = 0; board.split_ply = board.split_ply_stack; board.split_ply_stack[0] = -1; board.split_point = board.split_point_stack; board.split_point_stack[0] = NULL; /* Initialize the spin locks. */ LOCK_INIT(smp_data->io_lock); LOCK_INIT(smp_data->lock); for (x = 0; x < procs; x++) { LOCK_INIT(smp_block[x].lock); LOCK_INIT(smp_block[x].input_lock); } for (x = 0; x < MAX_SPLIT_POINTS; x++) { LOCK_INIT(split_point[x].lock); LOCK_INIT(split_point[x].move_lock); } /* Now start the child processes. */ for (x = 1; x < zct->process_count; x++) { /* Child process. */ if ((y = fork()) == 0) { board.id = x; idle_loop(x); } /* Parent process. */ else { smp_block[x].pid = y; smp_tell(x, SMP_INIT, 0); } } /* Set up the signals to use for the master processor. */ if (board.id == 0) { signal(SIGINT, smp_cleanup_sig); signal(SIGTERM, smp_cleanup_sig); // signal(SIGCHLD, smp_cleanup_sig); } /* Now that the processors are spawned, make them idle until we start searching. */ stop_child_processors(); }
// ************************************************************************************************* // @fn set_value // @brief Generic value setting routine // @param int32_t * value Pointer to value to set // uint8_tdigits Number of digits // uint8_t blanks Number of whitespaces before first valid digit // int32_t limitLow Lower limit of value // int32_t limitHigh Upper limit of value // uint16_t mode // uint8_t segments Segments where value should be drawn // fptr_setValue_display_function1 Value-specific display routine // @return none // ************************************************************************************************* void set_value(int32_t * value, uint8_t digits, uint8_t blanks, int32_t limitLow, int32_t limitHigh, uint16_t mode, uint8_t segments, void (*fptr_setValue_display_function1)(uint8_t segments, uint32_t value, uint8_t digits, uint8_t blanks, uint8_t disp_mode)) { uint8_t update; int16_t stepValue; if((mode & SETVALUE_STEP_FIFE ) == SETVALUE_STEP_FIFE) { stepValue=5; } else { stepValue=1; } uint8_t doRound = 0; #ifdef CONFIG_STOP_WATCH uint8_t stopwatch_state; #endif uint32_t val; int32_t orig_val=*value; // Clear button flags button.all_flags = 0; // Clear blink memory clear_blink_mem(); // For safety only - buzzer on/off and button_repeat share same IRQ stop_buzzer(); #ifdef CONFIG_STOP_WATCH // Disable stopwatch display update while function is active stopwatch_state = sStopwatch.state; sStopwatch.state = STOPWATCH_HIDE; #endif // Init step size and repeat counter sButton.repeats = 0; // Initial display update update = 1; // Turn on 200ms button repeat function button_repeat_on(200); // Start blinking with with 2Hz set_blink_rate(BIT6 + BIT5); // Value set loop while(1) { // Idle timeout: exit function if (sys.flag.idle_timeout) break; // Button STAR (short) button: exit function if (button.flag.star) break; // NUM button: exit function and goto to next value (if available) if (button.flag.num) { if ((mode & SETVALUE_NEXT_VALUE) == SETVALUE_NEXT_VALUE) break; } // UP button: increase value if(button.flag.up) { // Increase value * value = * value + stepValue; // Check value limits if (* value > limitHigh) { // Check if value can roll over, else stick to limit if ((mode & SETVALUE_ROLLOVER_VALUE) == SETVALUE_ROLLOVER_VALUE) * value = limitLow; else * value = limitHigh; // Reset step size to default if((mode & SETVALUE_STEP_FIFE ) == SETVALUE_STEP_FIFE) { stepValue=5; } else { stepValue=1; } } // Trigger display update update = 1; // Clear button flag button.flag.up = 0; } // DOWN button: decrease value if(button.flag.down) { // Decrease value * value = * value - stepValue; // Check value limits if (* value < limitLow) { // Check if value can roll over, else stick to limit if ((mode & SETVALUE_ROLLOVER_VALUE) == SETVALUE_ROLLOVER_VALUE) * value = limitHigh; else * value = limitLow; // Reset step size to default if((mode & SETVALUE_STEP_FIFE ) == SETVALUE_STEP_FIFE) { stepValue=5; } else { stepValue=1; } } // Trigger display update update = 1; // Clear button flag button.flag.down = 0; } // When fast mode is enabled, increase step size if Sx button is continuously if ((mode & SETVALUE_FAST_MODE) == SETVALUE_FAST_MODE) { switch (sButton.repeats) { case 0: if((mode & SETVALUE_STEP_FIFE ) == SETVALUE_STEP_FIFE){ stepValue=5; doRound = 1; } else { stepValue=1; doRound = 0; } break; case 10: case -10: stepValue = 10; doRound = 1; break; case 20: case -20: stepValue = 100; doRound = 1; break; case 30: case -30: stepValue = 1000; doRound = 1; break; } // Round value to avoid odd numbers on display if (stepValue != 1 && doRound == 1) { * value -= * value % stepValue; doRound = 0; } } // Update display when there is new data if (update) { // Display up or down arrow according to sign of value if ((mode & SETVALUE_DISPLAY_ARROWS) == SETVALUE_DISPLAY_ARROWS) { if (* value >= 0) { display_symbol(LCD_SYMB_ARROW_UP, SEG_ON); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); val = *value; } else { display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON); val = *value * (-1); } } else { val = *value; } if((mode & SETVALUE_DISPLAY_SYMBOL) == SETVALUE_DISPLAY_SYMBOL) { display_symbol(segments,SEG_ON_BLINK_ON); // return when value is changed if( orig_val != *value ) break; } else if( (mode & SETVALUE_SWITCH_ARROWS) == SETVALUE_SWITCH_ARROWS ) { //show up arrow if value is odd if( val & 0x1 ) { display_symbol(LCD_SYMB_ARROW_UP,SEG_ON_BLINK_ON); display_symbol(LCD_SYMB_ARROW_DOWN,SEG_OFF_BLINK_OFF); } //show down arrow if value is even else { display_symbol(LCD_SYMB_ARROW_DOWN,SEG_ON_BLINK_ON); display_symbol(LCD_SYMB_ARROW_UP,SEG_OFF_BLINK_OFF); } } else { // Display function can either display value directly, modify value before displaying // or display a string referenced by the value fptr_setValue_display_function1(segments, val, digits, blanks, SEG_ON_BLINK_ON); } // Clear update flag update = 0; } // Call idle loop to serve background tasks idle_loop(); } //switch symbol if((mode & SETVALUE_DISPLAY_SYMBOL) == SETVALUE_DISPLAY_SYMBOL) { display_symbol(segments,SEG_OFF); } // Set blinking rate to 1Hz and stop set_blink_rate(BIT7 + BIT6 + BIT5); clear_blink_mem(); // Turn off button repeat function button_repeat_off(); #ifdef CONFIG_STOP_WATCH // Enable stopwatch display updates again sStopwatch.state = stopwatch_state; #endif }
void ThreadsManager::split(Position& pos, SearchStack* ss, Value* alpha, const Value beta, Value* bestValue, Depth depth, Move threatMove, int moveCount, MovePicker* mp, bool pvNode) { assert(pos.is_ok()); assert(*bestValue >= -VALUE_INFINITE); assert(*bestValue <= *alpha); assert(*alpha < beta); assert(beta <= VALUE_INFINITE); assert(depth > DEPTH_ZERO); assert(pos.thread() >= 0 && pos.thread() < activeThreads); assert(activeThreads > 1); int i, master = pos.thread(); Thread& masterThread = threads[master]; lock_grab(&mpLock); // If no other thread is available to help us, or if we have too many // active split points, don't split. if ( !available_slave_exists(master) || masterThread.activeSplitPoints >= MAX_ACTIVE_SPLIT_POINTS) { lock_release(&mpLock); return; } // Pick the next available split point object from the split point stack SplitPoint& splitPoint = masterThread.splitPoints[masterThread.activeSplitPoints++]; // Initialize the split point object splitPoint.parent = masterThread.splitPoint; splitPoint.master = master; splitPoint.is_betaCutoff = false; splitPoint.depth = depth; splitPoint.threatMove = threatMove; splitPoint.alpha = *alpha; splitPoint.beta = beta; splitPoint.pvNode = pvNode; splitPoint.bestValue = *bestValue; splitPoint.mp = mp; splitPoint.moveCount = moveCount; splitPoint.pos = &pos; splitPoint.nodes = 0; splitPoint.ss = ss; for (i = 0; i < activeThreads; i++) splitPoint.is_slave[i] = false; masterThread.splitPoint = &splitPoint; // If we are here it means we are not available assert(masterThread.state != Thread::AVAILABLE); int workersCnt = 1; // At least the master is included // Allocate available threads setting state to THREAD_BOOKED for (i = 0; !Fake && i < activeThreads && workersCnt < maxThreadsPerSplitPoint; i++) if (i != master && threads[i].is_available_to(master)) { threads[i].state = Thread::BOOKED; threads[i].splitPoint = &splitPoint; splitPoint.is_slave[i] = true; workersCnt++; } assert(Fake || workersCnt > 1); // We can release the lock because slave threads are already booked and master is not available lock_release(&mpLock); // Tell the threads that they have work to do. This will make them leave // their idle loop. for (i = 0; i < activeThreads; i++) if (i == master || splitPoint.is_slave[i]) { assert(i == master || threads[i].state == Thread::BOOKED); threads[i].state = Thread::WORKISWAITING; // This makes the slave to exit from idle_loop() if (useSleepingThreads && i != master) threads[i].wake_up(); } // Everything is set up. The master thread enters the idle loop, from // which it will instantly launch a search, because its state is // THREAD_WORKISWAITING. We send the split point as a second parameter to the // idle loop, which means that the main thread will return from the idle // loop when all threads have finished their work at this split point. idle_loop(master, &splitPoint); // We have returned from the idle loop, which means that all threads are // finished. Update alpha and bestValue, and return. lock_grab(&mpLock); *alpha = splitPoint.alpha; *bestValue = splitPoint.bestValue; masterThread.activeSplitPoints--; masterThread.splitPoint = splitPoint.parent; pos.set_nodes_searched(pos.nodes_searched() + splitPoint.nodes); lock_release(&mpLock); }