10b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
20b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *
30b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * Redistribution and use in source and binary forms, with or without
40b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * modification, are permitted provided that the following conditions are
50b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * met:
60b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *     * Redistributions of source code must retain the above copyright
70b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *       notice, this list of conditions and the following disclaimer.
80b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *     * Redistributions in binary form must reproduce the above
90b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *       copyright notice, this list of conditions and the following
100b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *       disclaimer in the documentation and/or other materials provided
110b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *       with the distribution.
120b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *     * Neither the name of The Linux Foundation nor the names of its
130b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *       contributors may be used to endorse or promote products derived
140b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *       from this software without specific prior written permission.
150b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *
160b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
170b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
190b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
200b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
210b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
220b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
230b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
240b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
250b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
260b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
270b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam *
280b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam */
290b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
300b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam#include "cam_list.h"
310b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
320b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tamtypedef struct {
330b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    struct cam_list list;
340b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    void *data;
350b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam} cam_node_t;
360b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
370b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tamtypedef struct {
380b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    cam_node_t head; /* dummy head */
390b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    uint32_t size;
400b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pthread_mutex_t lock;
410b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam} cam_queue_t;
420b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
430b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tamstatic inline int32_t cam_queue_init(cam_queue_t *queue)
440b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam{
450b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pthread_mutex_init(&queue->lock, NULL);
460b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    cam_list_init(&queue->head.list);
470b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    queue->size = 0;
480b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    return 0;
490b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam}
500b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
510b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tamstatic inline int32_t cam_queue_enq(cam_queue_t *queue, void *data)
520b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam{
530b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    cam_node_t *node =
540b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        (cam_node_t *)malloc(sizeof(cam_node_t));
550b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    if (NULL == node) {
560b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        return -1;
570b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    }
580b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
590b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    memset(node, 0, sizeof(cam_node_t));
600b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    node->data = data;
610b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
620b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pthread_mutex_lock(&queue->lock);
630b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    cam_list_add_tail_node(&node->list, &queue->head.list);
640b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    queue->size++;
650b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pthread_mutex_unlock(&queue->lock);
660b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
670b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    return 0;
680b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam}
690b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
700b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tamstatic inline void *cam_queue_deq(cam_queue_t *queue)
710b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam{
720b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    cam_node_t *node = NULL;
730b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    void *data = NULL;
740b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    struct cam_list *head = NULL;
750b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    struct cam_list *pos = NULL;
760b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
770b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pthread_mutex_lock(&queue->lock);
780b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    head = &queue->head.list;
790b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pos = head->next;
800b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    if (pos != head) {
810b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        node = member_of(pos, cam_node_t, list);
820b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        cam_list_del_node(&node->list);
830b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        queue->size--;
840b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    }
850b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pthread_mutex_unlock(&queue->lock);
860b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
870b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    if (NULL != node) {
880b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        data = node->data;
890b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        free(node);
900b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    }
910b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
920b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    return data;
930b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam}
940b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
950b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tamstatic inline int32_t cam_queue_flush(cam_queue_t *queue)
960b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam{
970b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    cam_node_t *node = NULL;
980b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    struct cam_list *head = NULL;
990b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    struct cam_list *pos = NULL;
1000b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
1010b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pthread_mutex_lock(&queue->lock);
1020b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    head = &queue->head.list;
1030b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pos = head->next;
1040b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
1050b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    while(pos != head) {
1060b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        node = member_of(pos, cam_node_t, list);
1070b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        pos = pos->next;
1080b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        cam_list_del_node(&node->list);
1090b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        queue->size--;
1100b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
1110b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        /* TODO later to consider ptr inside data */
1120b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        /* for now we only assume there is no ptr inside data
1130b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam         * so we free data directly */
1140b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        if (NULL != node->data) {
1150b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam            free(node->data);
1160b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        }
1170b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam        free(node);
1180b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
1190b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    }
1200b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    queue->size = 0;
1210b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pthread_mutex_unlock(&queue->lock);
1220b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    return 0;
1230b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam}
1240b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam
1250b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tamstatic inline int32_t cam_queue_deinit(cam_queue_t *queue)
1260b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam{
1270b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    cam_queue_flush(queue);
1280b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    pthread_mutex_destroy(&queue->lock);
1290b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam    return 0;
1300b22217da5945fcfef82ce2c0e0ccb2de2fb63ecEd Tam}
131