/** * \brief Function for putting a char in the UART buffer * * \param data the data to add to the UART buffer and send * */ static inline void uart_putchar(uint8_t data) { // Disable interrupts to get exclusive access to ring_buffer_out. cli(); if (ring_buffer_is_empty(&ring_buffer_out)) { // First data in buffer, enable data ready interrupt UCSR0B |= (1 << UDRIE0); } // Put data in buffer ring_buffer_put(&ring_buffer_out, data); // Re-enable interrupts sei(); }
static void test_init_buffer_state() { RingBuffer rb; _ringbuffer_init(&rb); assert_false(ring_buffer_is_full(&rb), "buffer should not be full"); assert_true(ring_buffer_is_empty(&rb), "buffer should be empty"); assert_true(ring_buffer_count(&rb) == 0, "buffer should be empty"); assert_true(ring_buffer_capacity(&rb) == capacity, "invalid buffer capacity"); ring_buffer_free(&rb); }
gpointer ring_buffer_pop(RingBuffer *self) { gpointer r = NULL; g_assert(self->buffer != NULL); if (ring_buffer_is_empty(self)) return NULL; r = self->buffer + self->head * self->element_size; --self->count; self->head = (self->head + 1) % self->capacity; return r; }
static void late_ack_tracker_manage_msg_ack(AckTracker *s, LogMessage *msg, AckType ack_type) { LateAckTracker *self = (LateAckTracker *)s; LateAckRecord *ack_rec = (LateAckRecord *)msg->ack_record; LateAckRecord *last_in_range = NULL; guint32 ack_range_length = 0; ack_rec->acked = TRUE; if (ack_type == AT_SUSPENDED) log_source_flow_control_suspend(self->super.source); late_ack_tracker_lock(s); { ack_range_length = _get_continuous_range_length(self); if (ack_range_length > 0) { last_in_range = ring_buffer_element_at(&self->ack_record_storage, ack_range_length - 1); if (ack_type != AT_ABORTED) { Bookmark *bookmark = &(last_in_range->bookmark); bookmark->save(bookmark); } _drop_range(self, ack_range_length); if (ack_type == AT_SUSPENDED) log_source_flow_control_adjust_when_suspended(self->super.source, ack_range_length); else log_source_flow_control_adjust(self->super.source, ack_range_length); if (ring_buffer_is_empty(&self->ack_record_storage)) late_ack_tracker_on_all_acked_call(s); } } late_ack_tracker_unlock(s); log_msg_unref(msg); log_pipe_unref((LogPipe *)self->super.source); }
/** * \brief Function to check if we have a char waiting in the UART receive buffer * * \retval true if data is waiting * \retval false if no data is waiting */ static inline bool uart_char_waiting(void) { return !ring_buffer_is_empty(&ring_buffer_in); }
/** read from beginning of queue (and remove that element) */ int pop(struct buffer *buffer) /*@ requires [?f]buffer(buffer, ?id_text, ?id_progress_read, ?id_progress_write) &*& token(id_progress_read, ?t1) &*& op(id_text, id_progress_read, t1, ?c, ?t2); @*/ /*@ ensures [f]buffer(buffer, id_text, id_progress_read, id_progress_write) &*& token(id_progress_read, t2) &*& result == c; @*/ { //@ open buffer(buffer, _, _, _); //@ assert [f]buffer->mutex |-> ?mutex; mutex_acquire(buffer->mutex); //@ open buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); //@ open token(id_progress_read, ?n_read); //@ assert [_]ghost_cell<list<int> >(id_text, ?alltext); while (ring_buffer_is_empty(buffer->ring_buffer)) /*@ invariant buffer->ring_buffer |-> ?ring_buffer &*& [f]buffer->mutex |-> mutex &*& ring_buffer(ring_buffer, ?size, ?contents) &*& [f]buffer->cond_can_pop |-> ?cond_can_pop &*& [f]mutex_cond(cond_can_pop, mutex) &*& mutex_held(mutex, (buffer_protected)(buffer, id_text, id_progress_read, id_progress_write), currentThread, f) &*& [_]ghost_cell<list<int> >(id_text, alltext) &*& [1/2]ghost_cell<int>(id_progress_write, ?n_write) &*& [1/2]ghost_cell<int>(id_progress_read, n_read) &*& [1/2]ghost_cell<int>(id_progress_read, n_read) &*& take(n_write - n_read, drop(n_read, alltext)) == contents ; @*/ { //@ close buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); mutex_cond_wait(buffer->cond_can_pop, buffer->mutex); //@ open buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); } bool was_full = ring_buffer_is_full(buffer->ring_buffer); int x = ring_buffer_pop(buffer->ring_buffer); if (was_full){ mutex_cond_signal(buffer->cond_can_push); } //@ ghost_cell_mutate(id_progress_read, t2); //@ close token(id_progress_read, t2); //@ open op(_, _, _, c, _); //@ assert c == nth(t1, alltext); //@ assert x == head(contents); //@ assert x == head(take(n_write - n_read, drop(n_read, alltext))); //@ assume (x == nth(n_read, alltext)); //@ assert c == x; //@ assert take(n_write - n_read, drop(n_read, alltext)) == contents; //@ assume (take(n_write - (n_read + 1), drop((n_read+1), alltext)) == tail(contents)); //@ close buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); mutex_release(buffer->mutex); //@ close [f]buffer(buffer, id_text, id_progress_read, id_progress_write); return x; }
/** add to end of queue */ void push(struct buffer *buffer, int x) /*@ requires [?f]buffer(buffer, ?id_text, ?id_progress_read, ?id_progress_write) &*& token(id_progress_write, ?t1) &*& op(id_text, id_progress_write, t1, x, ?t2); @*/ /*@ ensures [f]buffer(buffer, id_text, id_progress_read, id_progress_write) &*& token(id_progress_write, t2); @*/ { //@ open buffer(buffer, _, _, _); //@ assert [f]buffer->mutex |-> ?mutex; mutex_acquire(buffer->mutex); //@ open buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); //@ open token(id_progress_write, ?n_write); //@ assert [_]ghost_cell<list<int> >(id_text, ?alltext); while (ring_buffer_is_full(buffer->ring_buffer)) /*@ invariant buffer->ring_buffer |-> ?ring_buffer &*& [f]buffer->mutex |-> mutex &*& ring_buffer(ring_buffer, ?size, ?contents) &*& [f]buffer->cond_can_push |-> ?cond_can_push &*& [f]mutex_cond(cond_can_push, mutex) &*& mutex_held(mutex, (buffer_protected)(buffer, id_text, id_progress_read, id_progress_write), currentThread, f) &*& [_]ghost_cell<list<int> >(id_text, alltext) &*& [1/2]ghost_cell<int>(id_progress_read, ?n_read) &*& [1/2]ghost_cell<int>(id_progress_write, n_write) &*& [1/2]ghost_cell<int>(id_progress_write, n_write) &*& take(n_write - n_read, drop(n_read, alltext)) == contents ; @*/ { //@ close buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); mutex_cond_wait(buffer->cond_can_push, buffer->mutex); //@ open buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); } bool was_empty = ring_buffer_is_empty(buffer->ring_buffer); ring_buffer_push(buffer->ring_buffer, x); if (was_empty){ mutex_cond_signal(buffer->cond_can_pop); } //@ ghost_cell_mutate(id_progress_write, n_write + 1); //@ open op(_, _, _, _, _); //@ assert t2 == n_write + 1; //@ close token(id_progress_write, n_write + 1); //@ assert take(n_write - n_read, drop(n_read, alltext)) == contents; //@ assume (take(n_write+1 - n_read, drop(n_read, alltext)) == append(contents, cons(nth(n_write, alltext), nil))); //@ close buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); mutex_release(buffer->mutex); //@ close [f]buffer(buffer, id_text, id_progress_read, id_progress_write); }
/** * Reads one integer from the given queue. * * This is blocking. If the queue is empty, this function waits until the queue is not empty anymore. */ int getchar/*@<u> @*/(struct queue *queue, struct proph_tree *tree) //@ requires [?f_queue]queue(?queue_id, queue) &*& getchar_io<u>(queue_id, ?t1, ?c, ?t2, tree) &*& token(t1); //@ ensures [f_queue]queue(queue_id, queue) &*& token(t2) &*& result == c; { //@ open [f_queue]queue(_,_); //@ assert [f_queue]queue->mutex |-> ?mutex; // bind mutex so we know it won't change. mutex_acquire(queue->mutex); //@ open queue_invariant(queue_id, queue)(); //@ open token(t1); while (ring_buffer_is_empty(queue->ring_buffer)) /*@ invariant // from queue: [f_queue]queue->mutex |-> mutex &*& [f_queue]queue->cond_can_pop |-> ?cond_can_pop &*& [f_queue]mutex_cond(cond_can_pop, mutex) // from the mutex: &*& queue->ring_buffer |-> ?buffer &*& ring_buffer(buffer, _, ?buffer_contents) &*& [1/2]ghost_cell<list<int> >(queue_id, buffer_contents) &*& mutex_held(mutex, (queue_invariant)(queue_id, queue), currentThread, f_queue); @*/ { //@ close queue_invariant(queue_id, queue)(); mutex_cond_wait(queue->cond_can_pop, queue->mutex); //@ open queue_invariant(queue_id, queue)(); } bool was_full = ring_buffer_is_full(queue->ring_buffer); //@ open getchar_io(queue_id, t1, c, t2, _); int ret = ring_buffer_pop(queue->ring_buffer); //@ open proph_tree(_, _, _, _, _); prophecy_assign(tree->id, ret); free(tree); if (was_full){ mutex_cond_signal(queue->cond_can_push); } /*@ { predicate pre() = [1/2]ghost_cell<list<int> >(queue_id, buffer_contents) &*& c == head(buffer_contents) &*& token_without_invar(t1) &*& is_getchar_invar_updatable(?invar_updater, queue_id, t1, c, t2); predicate post() = [1/2]ghost_cell(queue_id, tail(buffer_contents)) &*& token_without_invar(t2); close pre(); produce_lemma_function_pointer_chunk(empty_lemma) : ghost_mutex_critical_section_t(place_io_invar(t1), pre, post)() { open pre(); assert is_getchar_invar_updatable(?invar_updater, queue_id, t1, c, t2); close exists(place_io_invar(t1)); open token_without_invar(t1); invar_updater(); close token_without_invar(t2); close post(); leak is_getchar_invar_updatable(_, _, _, _, _); call(); } { ghost_mutex_use(place_mutex(t1), pre, post); } open post(); } @*/ //@ close queue_invariant(queue_id, queue)(); mutex_release(queue->mutex); //@ close [f_queue]queue(queue_id, queue); return ret; }
gboolean late_ack_tracker_is_empty(AckTracker *s) { LateAckTracker *self = (LateAckTracker *)s; return ring_buffer_is_empty(&self->ack_record_storage); }