#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PAGE_SIZE 4096 #include #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ type name (type1 arg1, type2 arg2, type3 arg3) \ {\ return syscall(__NR_##name, arg1, arg2, arg3);\ } #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ {\ return syscall(__NR_##name, arg1, arg2, arg3, arg4);\ } #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ type5,arg5) \ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ {\ return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5);\ } #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ type5,arg5,type6,arg6) \ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \ {\ return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6);\ } _syscall4(int, kevent_ctl, int, arg1, unsigned int, argv2, unsigned int, argv3, void *, argv4); _syscall6(int, kevent_get_events, int, arg1, unsigned int, argv2, unsigned int, argv3, __u64, argv4, void *, argv5, unsigned, arg6); _syscall4(int, kevent_wait, int, arg1, unsigned int, arg2, unsigned int, argv3, __u64, argv4); #define ulog(f, a...) fprintf(stderr, "%8u: "f, time(NULL), ##a) #define ulog_err(f, a...) ulog(f ": %s [%d].\n", ##a, strerror(errno), errno) static void usage(char *p) { ulog("Usage: %s -t type -e event -o oneshot -p path -n wait_num -f kevent_file -r ready_num -h\n", p); } static int evtest_mmap(int fd, struct kevent_mring **ring, int number) { int i; off_t o = 0; for (i=0; i 0) { switch (ch) { case 'f': file = optarg; break; case 'r': ready_num = atoi(optarg); break; case 'n': wait_num = atoi(optarg); break; case 't': tm_sec = atoi(optarg); break; case 'T': tm_nsec = atoi(optarg); break; case 'o': oneshot = atoi(optarg); break; default: usage(argv[0]); return -1; } } fd = open(file, O_RDWR); if (fd == -1) { ulog_err("Failed create kevent control block using file %s", file); return -1; } err = evtest_mmap(fd, ring, KEVENT_MAX_PAGES); if (err) return err; memset(buf, 0, sizeof(buf)); for (i=0; ievent = KEVENT_TIMER_FIRED; uk->type = KEVENT_TIMER; if (oneshot) uk->req_flags |= KEVENT_REQ_ONESHOT; uk->user[0] = i; uk->id.raw[0] = tm_sec; uk->id.raw[1] = tm_nsec+i; err = kevent_ctl(fd, KEVENT_CTL_ADD, 1, uk); if (err < 0) { ulog_err("Failed to perform control operation: oneshot: %d, sec: %u, nsec: %u", oneshot, tm_sec, tm_nsec); close(fd); return err; } if (err) { ulog("%d: %016llx: ret_flags: 0x%x, ret_data: %u %d.\n", i, uk->id.raw_u64, uk->ret_flags, uk->ret_data[0], (int)uk->ret_data[1]); } } old_idx = ready_num = 0; while (1) { new_idx = ring[0]->kidx; old_idx = ring[0]->uidx; if (new_idx != old_idx) { ready_num = (old_idx > new_idx)?(KEVENT_MAX_EVENTS - (old_idx - new_idx)):(new_idx - old_idx); ulog("mmap: new: %u, old: %u, ready: %u.\n", new_idx, old_idx, ready_num); for (i=0; ievent[idx % KEVENTS_ON_PAGE]; ulog("%08x: %08x.%08x - %08x\n", i, m->id.raw[0], m->id.raw[1], m->ret_flags); } } ulog("going to wait: old: %u, new: %u, ready_num: %u, uidx: %u, kidx: %u.\n", old_idx, new_idx, ready_num, ring[0]->uidx, ring[0]->kidx); err = kevent_wait(fd, old_idx, ready_num, 10000000000ULL); if (err < 0) { if (errno != EAGAIN) { ulog_err("Failed to perform control operation: oneshot: %d, sec: %u, nsec: %u", oneshot, tm_sec, tm_nsec); close(fd); return err; } old_idx = (old_idx + ready_num) % KEVENT_MAX_EVENTS; ready_num = 0; } ulog("wait: old: %u, ready: %u, ret: %d.\n", old_idx, ready_num, err); } close(fd); return 0; }