void test_perf(void) { lwt_t chld1, chld2; int i; unsigned long long start, end; /* Performance tests */ rdtscll(start); for (i = 0 ; i < ITER ; i++) { lwt_chan_t c = lwt_chan(0); chld1 = lwt_create(fn_null, NULL, 0, c); lwt_join(chld1); } rdtscll(end); printf("[PERF] %lld <- fork/join\n", (end-start)/ITER); IS_RESET(); lwt_chan_t c1 = lwt_chan(0); chld1 = lwt_create(fn_bounce, (void*)1, 0, c1); lwt_chan_t c2 = lwt_chan(0); chld2 = lwt_create(fn_bounce, NULL, 0, c2); lwt_join(chld1); lwt_join(chld2); IS_RESET(); }
int test_speed_create_join() { int i=0; unsigned long long start, end; lwt_t tid1, tid2, tid3; tid1 = lwt_create(fn, NULL, 0, 0); lwt_join(tid1); IS_RESET(); rdtscll(start); for(i=0 ; i < ITER; i++) { tid1 = lwt_create(fn, NULL, 0, 0); lwt_join(tid1); } rdtscll(end); IS_RESET(); printf("performance of fork/join: --> %lld\n", (end-start)/ITER); for(i=0 ; i < ITER; i++) { tid1 = lwt_create(fn, NULL, 0, 0); tid2 = lwt_create(fn, NULL, 0, 0); tid3 = lwt_create(fn, NULL, 0, 0); lwt_join(tid3); lwt_join(tid1); lwt_join(tid2); } IS_RESET(); return 0; }
void test_function_basic() { lwt_t id; IS_RESET(); id = lwt_create(fn_nested_create, 0, 0, 0); lwt_yield(LWT_NULL); printf("join in parent\n"); lwt_join(id); lwt_yield(LWT_NULL); IS_RESET(); }
int main(int argc, char** argv) { IS_RESET(); test_function_basic(); IS_RESET(); test_speed_create_join(); IS_RESET(); test_speed_yield(); IS_RESET(); test_perf_channels(0); IS_RESET(); printf("back to main\n"); return EXIT_SUCCESS; }
void test_crt_join_sched(void) { lwt_t chld1, chld2; printf("[TEST] thread creation/join/scheduling\n"); /* functional tests: scheduling */ lwt_yield(LWT_NULL); lwt_chan_t c1 = lwt_chan(0); chld1 = lwt_create(fn_sequence, (void*)1, 0, c1); lwt_chan_t c2 = lwt_chan(0); chld2 = lwt_create(fn_sequence, (void*)2, 0, c2); lwt_join(chld2); lwt_join(chld1); IS_RESET(); /* functional tests: join */ lwt_chan_t c3 = lwt_chan(0); chld1 = lwt_create(fn_null, NULL, 0, c3); lwt_join(chld1); IS_RESET(); lwt_chan_t c4 = lwt_chan(0); chld1 = lwt_create(fn_null, NULL, 0, c4); lwt_yield(LWT_NULL); lwt_join(chld1); IS_RESET(); lwt_chan_t c5 = lwt_chan(0); chld1 = lwt_create(fn_nested_joins, NULL, 0, c5); lwt_join(chld1); IS_RESET(); /* functional tests: join only from parents */ lwt_chan_t c6 = lwt_chan(0); chld1 = lwt_create(fn_identity, (void*)0x37337, 0, c6); lwt_chan_t c7 = lwt_chan(0); chld2 = lwt_create(fn_join, chld1, 0, c7); lwt_yield(LWT_NULL); lwt_yield(LWT_NULL); lwt_join(chld2); lwt_join(chld1); IS_RESET(); /* functional tests: passing data between threads */ lwt_chan_t c8 = lwt_chan(0); chld1 = lwt_create(fn_identity, (void*)0x37337, 0, c8); assert((void*)0x37337 == lwt_join(chld1)); IS_RESET(); /* functional tests: directed yield */ lwt_chan_t c9 = lwt_chan(0); chld1 = lwt_create(fn_null, NULL, 0, c9); lwt_yield(chld1); assert(lwt_info(LWT_INFO_NTHD_ZOMBIES) == 1); lwt_join(chld1); IS_RESET(); }
void test_speed_yield() { lwt_t tid1, tid2; tid1 = lwt_create(fn_bounce, (void*)1, 0, 0); tid2 = lwt_create(fn_bounce, NULL, 0, 0); lwt_yield(LWT_NULL); lwt_join(tid1); lwt_join(tid2); lwt_yield(LWT_NULL); IS_RESET(); }
void test_perf(void) { lwt_t chld1, chld2; int i; unsigned long long start, end; /* Performance tests */ rdtscll(start); for (i = 0 ; i < ITER ; i++) { chld1 = lwt_create(fn_null, NULL); lwt_join(chld1); } rdtscll(end); printf("Overhead for fork/join is %lld\n", (end-start)/ITER); IS_RESET(); chld1 = lwt_create(fn_bounce, (void*)1); chld2 = lwt_create(fn_bounce, NULL); lwt_join(chld1); lwt_join(chld2); IS_RESET(); }
void test_crt_join_sched(void) { lwt_t chld1, chld2; /* functional tests: scheduling */ lwt_yield(LWT_NULL); chld1 = lwt_create(fn_sequence, (void*)1); chld2 = lwt_create(fn_sequence, (void*)2); lwt_join(chld2); lwt_join(chld1); IS_RESET(); /* functional tests: join */ chld1 = lwt_create(fn_null, NULL); lwt_join(chld1); IS_RESET(); chld1 = lwt_create(fn_null, NULL); lwt_yield(LWT_NULL); lwt_join(chld1); IS_RESET(); chld1 = lwt_create(fn_nested_joins, NULL); lwt_join(chld1); IS_RESET(); /* functional tests: join only from parents */ chld1 = lwt_create(fn_identity, (void*)0x37337); chld2 = lwt_create(fn_join, chld1); lwt_yield(LWT_NULL); lwt_yield(LWT_NULL); lwt_join(chld2); lwt_join(chld1); IS_RESET(); /* functional tests: passing data between threads */ chld1 = lwt_create(fn_identity, (void*)0x37337); assert((void*)0x37337 == lwt_join(chld1)); IS_RESET(); /* functional tests: directed yield */ chld1 = lwt_create(fn_null, NULL); lwt_yield(chld1); assert(lwt_info(LWT_INFO_NTHD_ZOMBIES) == 1); lwt_join(chld1); IS_RESET(); }
/** * ir_nec_decode() - Decode one NEC pulse or space * @input_dev: the struct input_dev descriptor of the device * @duration: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct nec_dec *data = &ir_dev->raw->nec; u32 scancode; u8 address, not_address, command, not_command; if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC)) return 0; if (IS_RESET(ev)) { data->state = STATE_INACTIVE; return 0; } IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n", data->state, TO_US(ev.duration), TO_STR(ev.pulse)); switch (data->state) { case STATE_INACTIVE: if (!ev.pulse) break; if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) { data->is_nec_x = false; data->necx_repeat = false; } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) data->is_nec_x = true; else break; data->count = 0; data->state = STATE_HEADER_SPACE; return 0; case STATE_HEADER_SPACE: if (ev.pulse) break; if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) { data->state = STATE_BIT_PULSE; return 0; } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { ir_repeat(input_dev); IR_dprintk(1, "Repeat last key\n"); data->state = STATE_TRAILER_PULSE; return 0; } break; case STATE_BIT_PULSE: if (!ev.pulse) break; if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2)) break; data->state = STATE_BIT_SPACE; return 0; case STATE_BIT_SPACE: if (ev.pulse) break; if (data->necx_repeat && data->count == NECX_REPEAT_BITS && geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) { IR_dprintk(1, "Repeat last key\n"); ir_repeat(input_dev); data->state = STATE_INACTIVE; return 0; } else if (data->count > NECX_REPEAT_BITS) data->necx_repeat = false; data->bits <<= 1; if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) data->bits |= 1; else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2)) break; data->count++; if (data->count == NEC_NBITS) data->state = STATE_TRAILER_PULSE; else data->state = STATE_BIT_PULSE; return 0; case STATE_TRAILER_PULSE: if (!ev.pulse) break; if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2)) break; data->state = STATE_TRAILER_SPACE; return 0; case STATE_TRAILER_SPACE: if (ev.pulse) break; if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) break; address = bitrev8((data->bits >> 24) & 0xff); not_address = bitrev8((data->bits >> 16) & 0xff); command = bitrev8((data->bits >> 8) & 0xff); not_command = bitrev8((data->bits >> 0) & 0xff); if ((command ^ not_command) != 0xff) { IR_dprintk(1, "NEC checksum error: received 0x%08x\n", data->bits); break; } if ((address ^ not_address) != 0xff) { /* Extended NEC */ scancode = address << 16 | not_address << 8 | command; IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); } else { /* Normal NEC */ scancode = address << 8 | command; IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); } if (data->is_nec_x) data->necx_repeat = true; ir_keydown(input_dev, scancode, 0); data->state = STATE_INACTIVE; return 0; } IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n", data->state, TO_US(ev.duration), TO_STR(ev.pulse)); data->state = STATE_INACTIVE; return -EINVAL; }
/** * ir_rc6_decode() - Decode one RC6 pulse or space * @input_dev: the struct input_dev descriptor of the device * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct rc6_dec *data = &ir_dev->raw->rc6; u32 scancode; u8 toggle; if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6)) return 0; if (IS_RESET(ev)) { data->state = STATE_INACTIVE; return 0; } if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) goto out; again: IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n", data->state, TO_US(ev.duration), TO_STR(ev.pulse)); if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) return 0; switch (data->state) { case STATE_INACTIVE: if (!ev.pulse) break; /* Note: larger margin on first pulse since each RC6_UNIT is quite short and some hardware takes some time to adjust to the signal */ if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT)) break; data->state = STATE_PREFIX_SPACE; data->count = 0; return 0; case STATE_PREFIX_SPACE: if (ev.pulse) break; if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2)) break; data->state = STATE_HEADER_BIT_START; return 0; case STATE_HEADER_BIT_START: if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) break; data->header <<= 1; if (ev.pulse) data->header |= 1; data->count++; data->state = STATE_HEADER_BIT_END; return 0; case STATE_HEADER_BIT_END: if (!is_transition(&ev, &ir_dev->raw->prev_ev)) break; if (data->count == RC6_HEADER_NBITS) data->state = STATE_TOGGLE_START; else data->state = STATE_HEADER_BIT_START; decrease_duration(&ev, RC6_BIT_END); goto again; case STATE_TOGGLE_START: if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2)) break; data->toggle = ev.pulse; data->state = STATE_TOGGLE_END; return 0; case STATE_TOGGLE_END: if (!is_transition(&ev, &ir_dev->raw->prev_ev) || !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) break; if (!(data->header & RC6_STARTBIT_MASK)) { IR_dprintk(1, "RC6 invalid start bit\n"); break; } data->state = STATE_BODY_BIT_START; decrease_duration(&ev, RC6_TOGGLE_END); data->count = 0; switch (rc6_mode(data)) { case RC6_MODE_0: data->wanted_bits = RC6_0_NBITS; break; case RC6_MODE_6A: /* This might look weird, but we basically check the value of the first body bit to determine the number of bits in mode 6A */ if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) || geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) data->wanted_bits = RC6_6A_LARGE_NBITS; else data->wanted_bits = RC6_6A_SMALL_NBITS; break; default: IR_dprintk(1, "RC6 unknown mode\n"); goto out; } goto again; case STATE_BODY_BIT_START: if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) break; data->body <<= 1; if (ev.pulse) data->body |= 1; data->count++; data->state = STATE_BODY_BIT_END; return 0; case STATE_BODY_BIT_END: if (!is_transition(&ev, &ir_dev->raw->prev_ev)) break; if (data->count == data->wanted_bits) data->state = STATE_FINISHED; else data->state = STATE_BODY_BIT_START; decrease_duration(&ev, RC6_BIT_END); goto again; case STATE_FINISHED: if (ev.pulse) break; switch (rc6_mode(data)) { case RC6_MODE_0: scancode = data->body & 0xffff; toggle = data->toggle; IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n", scancode, toggle); break; case RC6_MODE_6A: if (data->wanted_bits == RC6_6A_LARGE_NBITS) { toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0; scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK; } else { toggle = 0; scancode = data->body & 0xffffff; } IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n", scancode, toggle); break; default: IR_dprintk(1, "RC6 unknown mode\n"); goto out; } ir_keydown(input_dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } out: IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n", data->state, TO_US(ev.duration), TO_STR(ev.pulse)); data->state = STATE_INACTIVE; return -EINVAL; }
/** * ir_sony_decode() - Decode one Sony pulse or space * @input_dev: the struct input_dev descriptor of the device * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct sony_dec *data = &ir_dev->raw->sony; u32 scancode; u8 device, subdevice, function; if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY)) return 0; if (IS_RESET(ev)) { data->state = STATE_INACTIVE; return 0; } if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) goto out; IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n", data->state, TO_US(ev.duration), TO_STR(ev.pulse)); switch (data->state) { case STATE_INACTIVE: if (!ev.pulse) break; if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2)) break; data->count = 0; data->state = STATE_HEADER_SPACE; return 0; case STATE_HEADER_SPACE: if (ev.pulse) break; if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2)) break; data->state = STATE_BIT_PULSE; return 0; case STATE_BIT_PULSE: if (!ev.pulse) break; data->bits <<= 1; if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2)) data->bits |= 1; else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2)) break; data->count++; data->state = STATE_BIT_SPACE; return 0; case STATE_BIT_SPACE: if (ev.pulse) break; if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2)) break; decrease_duration(&ev, SONY_BIT_SPACE); if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) { data->state = STATE_BIT_PULSE; return 0; } data->state = STATE_FINISHED; /* Fall through */ case STATE_FINISHED: if (ev.pulse) break; if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2)) break; switch (data->count) { case 12: device = bitrev8((data->bits << 3) & 0xF8); subdevice = 0; function = bitrev8((data->bits >> 4) & 0xFE); break; case 15: device = bitrev8((data->bits >> 0) & 0xFF); subdevice = 0; function = bitrev8((data->bits >> 7) & 0xFD); break; case 20: device = bitrev8((data->bits >> 5) & 0xF8); subdevice = bitrev8((data->bits >> 0) & 0xFF); function = bitrev8((data->bits >> 12) & 0xFE); break; default: IR_dprintk(1, "Sony invalid bitcount %u\n", data->count); goto out; } scancode = device << 16 | subdevice << 8 | function; IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode); ir_keydown(input_dev, scancode, 0); data->state = STATE_INACTIVE; return 0; } out: IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n", data->state, TO_US(ev.duration), TO_STR(ev.pulse)); data->state = STATE_INACTIVE; return -EINVAL; }