/* Simple queue management */ struct v4l2_q_node { struct v4l2_q_node *forw, *back; }; struct v4l2_queue { struct v4l2_q_node *forw, *back; rwlock_t qlock; }; /* * Simple queue management */ static rwlock_t rw_lock_unlocked = RW_LOCK_UNLOCKED; void v4l2_q_init(struct v4l2_queue *q) { if (q == NULL) return; q->qlock = rw_lock_unlocked; q->forw = (struct v4l2_q_node *)q; q->back = (struct v4l2_q_node *)q; } void v4l2_q_add_head(struct v4l2_queue *q, struct v4l2_q_node *node) { unsigned long flags; if (q == NULL || node == NULL) return; if (q->forw == NULL || q->back == NULL) v4l2_q_init(q); write_lock_irqsave(&(q->qlock), flags); node->forw = q->forw; node->back = (struct v4l2_q_node *)q; q->forw->back = node; q->forw = node; write_unlock_irqrestore(&(q->qlock), flags); } void v4l2_q_add_tail(struct v4l2_queue *q, struct v4l2_q_node *node) { unsigned long flags; if (q == NULL || node == NULL) return; if (q->forw == NULL || q->back == NULL) v4l2_q_init(q); write_lock_irqsave(&(q->qlock), flags); node->forw = (struct v4l2_q_node *)q; node->back = q->back; q->back->forw = node; q->back = node; write_unlock_irqrestore(&(q->qlock), flags); } void * v4l2_q_del_head(struct v4l2_queue *q) { unsigned long flags; struct v4l2_q_node *node; if (q == NULL) return NULL; write_lock_irqsave(&(q->qlock), flags); if (q->forw == NULL || q->back == NULL || q->forw == (struct v4l2_q_node *)q || q->back == (struct v4l2_q_node *)q) { write_unlock_irqrestore(&(q->qlock), flags); return NULL; } node = q->forw; node->forw->back = (struct v4l2_q_node *)q; q->forw = node->forw; node->forw = NULL; node->back = NULL; write_unlock_irqrestore(&(q->qlock), flags); return node; } void * v4l2_q_del_tail(struct v4l2_queue *q) { unsigned long flags; struct v4l2_q_node *node; if (q == NULL) return NULL; write_lock_irqsave(&(q->qlock), flags); if (q->forw == NULL || q->back == NULL || q->forw == (struct v4l2_q_node *)q || q->back == (struct v4l2_q_node *)q) { write_unlock_irqrestore(&(q->qlock), flags); return NULL; } node = q->back; node->back->forw = (struct v4l2_q_node *)q; q->back = node->back; node->forw = NULL; node->back = NULL; write_unlock_irqrestore(&(q->qlock), flags); return node; } void * v4l2_q_peek_head(struct v4l2_queue *q) { unsigned long flags; struct v4l2_q_node *node; read_lock_irqsave(&(q->qlock), flags); if (q == NULL || q->forw == NULL || q->forw == (struct v4l2_q_node *)q) { read_unlock_irqrestore(&(q->qlock), flags); return NULL; } node = q->forw; read_unlock_irqrestore(&(q->qlock), flags); return node; } void * v4l2_q_peek_tail(struct v4l2_queue *q) { unsigned long flags; struct v4l2_q_node *node; read_lock_irqsave(&(q->qlock), flags); if (q == NULL || q->back == NULL || q->back == (struct v4l2_q_node *)q) { read_unlock_irqrestore(&(q->qlock), flags); return NULL; } node = q->back; read_unlock_irqrestore(&(q->qlock), flags); return node; } void * v4l2_q_yank_node(struct v4l2_queue *q, struct v4l2_q_node *node) { unsigned long flags; struct v4l2_q_node *t; if (v4l2_q_peek_head(q) == NULL || node == NULL) return NULL; write_lock_irqsave(&(q->qlock), flags); for (t = q->forw; t != (struct v4l2_q_node *)q; t = t->forw) if (t == node) { node->back->forw = node->forw; node->forw->back = node->back; node->forw = NULL; node->back = NULL; write_unlock_irqrestore(&(q->qlock), flags); return node; } write_unlock_irqrestore(&(q->qlock), flags); return NULL; } int v4l2_q_last(struct v4l2_queue *q) { /* This function by Olivier Carmona */ unsigned long flags; read_lock_irqsave(&(q->qlock), flags); if (q == NULL) { read_unlock_irqrestore(&(q->qlock), flags); return -1; } if (q->forw == NULL || q->back == NULL || q->forw == (struct v4l2_q_node *)q || q->back == (struct v4l2_q_node *)q) { read_unlock_irqrestore(&(q->qlock), flags); return -1; } if (q->forw == q->back) { read_unlock_irqrestore(&(q->qlock), flags); return 1; } read_unlock_irqrestore(&(q->qlock), flags); return 0; } extern void v4l2_q_init(struct v4l2_queue *q); extern void v4l2_q_add_head(struct v4l2_queue *q, struct v4l2_q_node *node); extern void v4l2_q_add_tail(struct v4l2_queue *q, struct v4l2_q_node *node); extern void *v4l2_q_del_head(struct v4l2_queue *q); extern void *v4l2_q_del_tail(struct v4l2_queue *q); extern void *v4l2_q_peek_head(struct v4l2_queue *q); extern void *v4l2_q_peek_tail(struct v4l2_queue *q); extern void *v4l2_q_yank_node(struct v4l2_queue *q, struct v4l2_q_node *node); extern int v4l2_q_last(struct v4l2_queue *q);