#include #include #include #include #include #include #include #include #include #include #include #include #include #define PAGE_SIZE 4096 #include #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); #define ulog(f, a...) fprintf(stderr, f, ##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 -h\n", p); } static int get_id(int type, char *path) { int ret = -1; switch (type) { case KEVENT_TIMER: ret = 3000; break; case KEVENT_INODE: ret = open(path, O_RDONLY); break; } return ret; } static void *evtest_mmap(int fd, off_t *offset, unsigned int number) { void *start, *ptr; off_t o = *offset; start = NULL; ptr = mmap(start, PAGE_SIZE*number, PROT_READ, MAP_SHARED, fd, o*PAGE_SIZE); if (ptr == MAP_FAILED) { ulog_err("Failed to mmap: start: %p, number: %u, offset: %lu", start, number, o); return NULL; } printf("mmap: ptr: %p, start: %p, number: %u, offset: %lu.\n", ptr, start, number, o); *offset = o + number; return ptr; } int main(int argc, char *argv[]) { int ch, fd, err, type, event, oneshot, wait_num, number; unsigned int i, num, old_idx; char *path, *file; char buf[4096]; struct ukevent *uk; struct kevent_mring *ring; off_t offset; path = NULL; type = event = -1; oneshot = 0; wait_num = 10; offset = 0; number = 1; old_idx = 0; file = "/dev/kevent"; while ((ch = getopt(argc, argv, "f:p:t:e:o:n:h")) > 0) { switch (ch) { case 'f': file = optarg; break; case 'n': wait_num = atoi(optarg); break; case 'p': path = optarg; break; case 't': type = atoi(optarg); break; case 'e': event = atoi(optarg); break; case 'o': oneshot = atoi(optarg); break; default: usage(argv[0]); return -1; } } if (event == -1 || type == -1 || (type == KEVENT_INODE && !path)) { ulog("You need at least -t -e parameters and -p for inode notifications.\n"); 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; } ring = evtest_mmap(fd, &offset, number); if (!ring) return -1; memset(buf, 0, sizeof(buf)); num = 1; for (i=0; ievent = event; uk->type = type; if (oneshot) uk->req_flags |= KEVENT_REQ_ONESHOT; uk->user[0] = i; uk->id.raw[0] = get_id(uk->type, path); err = kevent_ctl(fd, KEVENT_CTL_ADD, 1, uk); if (err < 0) { ulog_err("Failed to perform control operation: type=%d, event=%d, oneshot=%d", type, event, oneshot); close(fd); return err; } if (err) { ulog("%d: ret_flags: 0x%x, ret_data: %u %d.\n", i, uk->ret_flags, uk->ret_data[0], (int)uk->ret_data[1]); } } while (1) { err = kevent_get_events(fd, 1, wait_num, 10000000000, buf, 0); if (err < 0) { ulog_err("Failed to perform control operation: type=%d, event=%d, oneshot=%d", type, event, oneshot); close(fd); return err; } num = ring->index; if (num != old_idx) { ulog("mmap: idx: %u, returned: %d.\n", num, err); while (old_idx != num) { if (old_idx < KEVENTS_ON_PAGE) { struct mukevent *m = &ring->event[old_idx]; ulog("%08x: %08x.%08x - %08x\n", i, m->id.raw[0], m->id.raw[1], m->ret_flags); } else { /* * Mmap next page. */ } if (++old_idx >= KEVENT_MAX_EVENTS) old_idx = 0; } old_idx = num; } num = (unsigned)err; if (num) { ulog("syscall dump: %u events.\n", num); uk = (struct ukevent *)buf; for (i=0; i