/** Pop control-plane message * * This function is called ONLY from the receiving thread. * * @param[in] aq the recipients atomic queue for control-plane messages * @param[out] p_id the ident of this message. * @param[in,out] data where the data is stored * @param[in] data_size the size of the buffer where we store the data. * @return * - <0 the size of the data we need to read the next message * - 0 this kevent is not for us. * - >0 the amount of data we've read */ ssize_t fr_control_message_pop(fr_atomic_queue_t *aq, uint32_t *p_id, void *data, size_t data_size) { uint8_t *p; fr_control_message_t *m; MPRINT("CONTROL pop aq %p\n", aq); if (!fr_atomic_queue_pop(aq, (void **) &m)) return 0; rad_assert(m->status == FR_CONTROL_MESSAGE_USED); /* * There isn't enough room to store the data, die. */ if (data_size < m->data_size) { fr_strerror_printf("Allocation size should be at least %zd", m->data_size); return -(m->data_size); } p = (uint8_t *) m; data_size = m->data_size; memcpy(data, p + sizeof(*m), data_size); m->status = FR_CONTROL_MESSAGE_DONE; *p_id = m->id; return data_size; }
int main(int argc, char *argv[]) { int c, i, rcode = 0; int size; intptr_t val; void *data; fr_atomic_queue_t *aq; TALLOC_CTX *autofree = talloc_autofree_context(); size = 4; while ((c = getopt(argc, argv, "hs:tx")) != EOF) switch (c) { case 's': size = atoi(optarg); break; case 'x': debug_lvl++; break; case 'h': default: usage(); } #if 0 argc -= (optind - 1); argv += (optind - 1); #endif aq = fr_atomic_queue_create(autofree, size); #ifndef NDEBUG if (debug_lvl) { printf("Start\n"); fr_atomic_queue_debug(aq, stdout); if (debug_lvl > 1) printf("Filling with %d\n", size); } #endif for (i = 0; i < size; i++) { val = i + OFFSET; data = (void *) val; if (!fr_atomic_queue_push(aq, data)) { fprintf(stderr, "Failed pushing at %d\n", i); exit(EXIT_FAILURE); } #ifndef NDEBUG if (debug_lvl > 1) { printf("iteration %d\n", i); fr_atomic_queue_debug(aq, stdout); } #endif } val = size + OFFSET; data = (void *) val; /* * Queue is full. No more pushes are allowed. */ if (fr_atomic_queue_push(aq, data)) { fprintf(stderr, "Pushed an entry past the end of the queue."); exit(EXIT_FAILURE); } #ifndef NDEBUG if (debug_lvl) { printf("Full\n"); fr_atomic_queue_debug(aq, stdout); if (debug_lvl > 1) printf("Emptying\n"); } #endif /* * And now pop them all. */ for (i = 0; i < size; i++) { if (!fr_atomic_queue_pop(aq, &data)) { fprintf(stderr, "Failed popping at %d\n", i); exit(EXIT_FAILURE); } val = (intptr_t) data; if (val != (i + OFFSET)) { fprintf(stderr, "Pop expected %d, got %d\n", i + OFFSET, (int) val); exit(EXIT_FAILURE); } #ifndef NDEBUG if (debug_lvl > 1) { printf("iteration %d\n", i); fr_atomic_queue_debug(aq, stdout); } #endif } /* * Queue is empty. No more pops are allowed. */ if (fr_atomic_queue_pop(aq, &data)) { fprintf(stderr, "Popped an entry past the end of the queue."); exit(EXIT_FAILURE); } #ifndef NDEBUG if (debug_lvl) { printf("Empty\n"); fr_atomic_queue_debug(aq, stdout); } #endif return rcode; }