static void *fsel_producer(void *data) { const struct timespec interval = { 0, 250000000 }; unsigned idx = 0, nr = 1; (void) data; while (1) { int i, t; pthread_mutex_lock(&fsel_mutex); /* * This is the main producer loop which is executed * ever 500ms. On each iteration, it fills one byte * to 1, 2 or 4 files and sends poll notification if * requested. */ for (i = 0, t = idx; i < nr; i++, t = (t + FSEL_FILES / nr) % FSEL_FILES) { if (fsel_cnt[t] == FSEL_CNT_MAX) continue; fsel_cnt[t]++; if (fsel_fuse && (fsel_poll_notify_mask & (1 << t))) { struct fuse_pollhandle *ph; printf("NOTIFY %X\n", t); ph = fsel_poll_handle[t]; fuse_notify_poll(ph); fuse_pollhandle_destroy(ph); fsel_poll_notify_mask &= ~(1 << t); fsel_poll_handle[t] = NULL; } } idx = (idx + 1) % FSEL_FILES; if (idx == 0) nr = (nr * 2) % 7; /* cycle through 1, 2 and 4 */ pthread_mutex_unlock(&fsel_mutex); nanosleep(&interval, NULL); } return NULL; }
static int fsel_poll(const char *path, struct fuse_file_info *fi, struct fuse_pollhandle *ph, unsigned *reventsp) { static unsigned polled_zero; int idx = fi->fh; (void) path; /* * Poll notification requires pointer to struct fuse which * can't be obtained when using fuse_main(). As notification * happens only after poll is called, fill it here from * fuse_context. */ if (!fsel_fuse) { struct fuse_context *cxt = fuse_get_context(); if (cxt) fsel_fuse = cxt->fuse; } pthread_mutex_lock(&fsel_mutex); if (ph != NULL) { struct fuse_pollhandle *oldph = fsel_poll_handle[idx]; if (oldph) fuse_pollhandle_destroy(oldph); fsel_poll_notify_mask |= (1 << idx); fsel_poll_handle[idx] = ph; } if (fsel_cnt[idx]) { *reventsp |= POLLIN; printf("POLL %X cnt=%u polled_zero=%u\n", idx, fsel_cnt[idx], polled_zero); polled_zero = 0; } else polled_zero++; pthread_mutex_unlock(&fsel_mutex); return 0; }
static int pollhandle_destroy(struct fuse_pollhandle *ph) { fuse_pollhandle_destroy(ph); return 0; }