Blame src/openpa/test/test_queue.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2010 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * Uncomment this definition to disable the OPA library and instead use naive
Packit Service c5cf8c
 * (non-atomic) operations.  This should cause failures.
Packit Service c5cf8c
 */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * Note: The NAIVE implementation is likely to cause an infinite loop because of
Packit Service c5cf8c
 * the busy wait in OPA_Queue_dequeue that might never exit if an element was
Packit Service c5cf8c
 * enqueued improperly.
Packit Service c5cf8c
 */
Packit Service c5cf8c
/*
Packit Service c5cf8c
#define OPA_TEST_NAIVE
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
#include "opa_test.h"
Packit Service c5cf8c
#include "opa_queue.h"
Packit Service c5cf8c
Packit Service c5cf8c
/* Definitions for test_queue_sanity */
Packit Service c5cf8c
typedef struct {
Packit Service c5cf8c
    OPA_Queue_element_hdr_t hdr;        /* Queue element header */
Packit Service c5cf8c
    int val;                    /* Value of element */
Packit Service c5cf8c
} sanity_t;
Packit Service c5cf8c
Packit Service c5cf8c
/* Definitions for test_queue_threaded */
Packit Service c5cf8c
#define THREADED_NITER 500000
Packit Service c5cf8c
typedef struct {
Packit Service c5cf8c
    OPA_Queue_element_hdr_t hdr;        /* Queue element header */
Packit Service c5cf8c
    int threadno;               /* Unique thread number */
Packit Service c5cf8c
    int sequenceno;             /* Unique sequence number within thread */
Packit Service c5cf8c
} threaded_element_t;
Packit Service c5cf8c
typedef enum {
Packit Service c5cf8c
    THREADED_MODE_DEFAULT,      /* Test does not try to influence scheduling */
Packit Service c5cf8c
    THREADED_MODE_EMPTY,        /* Test tries to keep queue empty */
Packit Service c5cf8c
    THREADED_MODE_FULL,         /* Test tries to keep queue full */
Packit Service c5cf8c
    THREADED_MODE_NMODES        /* Number of modes (must be last) */
Packit Service c5cf8c
} threaded_mode_t;
Packit Service c5cf8c
typedef struct {
Packit Service c5cf8c
    OPA_Queue_info_t *qhead;    /* Head for shared queue */
Packit Service c5cf8c
    int threadno;               /* Unique thread number */
Packit Service c5cf8c
    threaded_mode_t mode;       /* Test mode (empty or full) */
Packit Service c5cf8c
} threaded_t;
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
/*-------------------------------------------------------------------------
Packit Service c5cf8c
 * Function: test_queue_sanity
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Purpose: Tests basic functionality of the OPA Queue in a single
Packit Service c5cf8c
 *          threaded environment.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Return: Success: 0
Packit Service c5cf8c
 *         Failure: 1
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Programmer: Neil Fortner
Packit Service c5cf8c
 *             Wednesday, April 1, 2009
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Modifications:
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *-------------------------------------------------------------------------
Packit Service c5cf8c
 */
Packit Service c5cf8c
static int test_queue_sanity(void)
Packit Service c5cf8c
{
Packit Service c5cf8c
    OPA_Queue_info_t qhead;
Packit Service c5cf8c
    sanity_t elements[4];
Packit Service c5cf8c
    sanity_t *element;
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
Packit Service c5cf8c
    TESTING("queue sanity", 0);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Initialize queue */
Packit Service c5cf8c
    OPA_Queue_init(&qhead);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Make sure the queue is empty */
Packit Service c5cf8c
    if (!OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    if (NULL != OPA_Queue_peek_head(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Initialize elements */
Packit Service c5cf8c
    for (i = 0; i < 4; i++) {
Packit Service c5cf8c
        OPA_Queue_header_init(&elements[i].hdr);
Packit Service c5cf8c
        elements[i].val = i;
Packit Service c5cf8c
    }   /* end for */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Enqueue element 0 */
Packit Service c5cf8c
    OPA_Queue_enqueue(&qhead, &elements[0], sanity_t, hdr);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Peek and make sure we get element 0 */
Packit Service c5cf8c
    if (OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    if (NULL == (element = OPA_Queue_peek_head(&qhead)))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    if (element->val != 0)
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Dequeue and make sure we get element 0 */
Packit Service c5cf8c
    if (OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    OPA_Queue_dequeue(&qhead, element, sanity_t, hdr);
Packit Service c5cf8c
    if (element->val != 0)
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Make sure the queue is now empty */
Packit Service c5cf8c
    if (!OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Enqueue elements 1 and 2 */
Packit Service c5cf8c
    OPA_Queue_enqueue(&qhead, &elements[1], sanity_t, hdr);
Packit Service c5cf8c
    OPA_Queue_enqueue(&qhead, &elements[2], sanity_t, hdr);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Peek and make sure we get element 1 */
Packit Service c5cf8c
    if (OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    if (NULL == (element = OPA_Queue_peek_head(&qhead)))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    if (element->val != 1)
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Dequeue and make sure we get element 1 */
Packit Service c5cf8c
    if (OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    OPA_Queue_dequeue(&qhead, element, sanity_t, hdr);
Packit Service c5cf8c
    if (element->val != 1)
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Enqueue element 3 */
Packit Service c5cf8c
    OPA_Queue_enqueue(&qhead, &elements[3], sanity_t, hdr);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Dequeue and make sure we get element 2 */
Packit Service c5cf8c
    if (OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    OPA_Queue_dequeue(&qhead, element, sanity_t, hdr);
Packit Service c5cf8c
    if (element->val != 2)
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Peek and make sure we get element 3 */
Packit Service c5cf8c
    if (OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    if (NULL == (element = OPA_Queue_peek_head(&qhead)))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    if (element->val != 3)
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Dequeue and make sure we get element 3 */
Packit Service c5cf8c
    if (OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
    OPA_Queue_dequeue(&qhead, element, sanity_t, hdr);
Packit Service c5cf8c
    if (element->val != 3)
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Make sure the queue is now empty */
Packit Service c5cf8c
    if (!OPA_Queue_is_empty(&qhead))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    PASSED();
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
Packit Service c5cf8c
  error:
Packit Service c5cf8c
    return 1;
Packit Service c5cf8c
}       /* end test_queue_sanity() */
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
#if defined(OPA_HAVE_PTHREAD_H)
Packit Service c5cf8c
/*-------------------------------------------------------------------------
Packit Service c5cf8c
 * Function: test_queue_threaded_enqueue
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Purpose: Helper (enqueue) routine for test_queue_threaded.  Enqueues
Packit Service c5cf8c
 *          elements to the shared queue with increasing sequence number
Packit Service c5cf8c
 *          and constant thread number.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Return: Success: NULL
Packit Service c5cf8c
 *         Failure: non-NULL
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Programmer: Neil Fortner
Packit Service c5cf8c
 *             Tuesday, June 8, 2010
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Modifications:
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *-------------------------------------------------------------------------
Packit Service c5cf8c
 */
Packit Service c5cf8c
static void *test_queue_threaded_enqueue(void *_udata)
Packit Service c5cf8c
{
Packit Service c5cf8c
    threaded_t *udata = (threaded_t *) _udata;
Packit Service c5cf8c
    threaded_element_t *element = NULL; /* Element to enqueue */
Packit Service c5cf8c
    int niter = THREADED_NITER / iter_reduction[curr_test];
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Main loop */
Packit Service c5cf8c
    for (i = 0; i < niter; i++) {
Packit Service c5cf8c
        /* If we're trying to keep the queue empty, yield here so the dequeuer
Packit Service c5cf8c
         * has a chance to empty the queue */
Packit Service c5cf8c
        if (udata->mode == THREADED_MODE_EMPTY)
Packit Service c5cf8c
            OPA_TEST_YIELD();
Packit Service c5cf8c
Packit Service c5cf8c
        /* Create an element to enqueue */
Packit Service c5cf8c
        if (NULL == (element = (threaded_element_t *) malloc(sizeof(threaded_element_t))))
Packit Service c5cf8c
            pthread_exit((void *) 1);
Packit Service c5cf8c
        OPA_Queue_header_init(&element->hdr);
Packit Service c5cf8c
        element->threadno = udata->threadno;
Packit Service c5cf8c
        element->sequenceno = i;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Enqueue the element */
Packit Service c5cf8c
        OPA_Queue_enqueue(udata->qhead, element, threaded_element_t, hdr);
Packit Service c5cf8c
    }   /* end for */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Exit */
Packit Service c5cf8c
    pthread_exit(NULL);
Packit Service c5cf8c
}       /* end test_queue_threaded_enqueue() */
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
/*-------------------------------------------------------------------------
Packit Service c5cf8c
 * Function: test_queue_threaded_dequeue
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Purpose: Helper (dequeue) routine for test_queue_threaded.  Dequeues
Packit Service c5cf8c
 *          elements from the shared queue and verifies that each thread
Packit Service c5cf8c
 *          added each sequence number exactly once and in the right
Packit Service c5cf8c
 *          order, and that order was preserved by the queue.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Return: Success: 0
Packit Service c5cf8c
 *         Failure: 1
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Programmer: Neil Fortner
Packit Service c5cf8c
 *             Tuesday, June 8, 2010
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Modifications:
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *-------------------------------------------------------------------------
Packit Service c5cf8c
 */
Packit Service c5cf8c
static int test_queue_threaded_dequeue(void *_udata)
Packit Service c5cf8c
{
Packit Service c5cf8c
    threaded_t *udata = (threaded_t *) _udata;
Packit Service c5cf8c
    threaded_element_t *element = NULL; /* Dequeued element */
Packit Service c5cf8c
    threaded_element_t *peek_element = NULL;    /* Peeked element */
Packit Service c5cf8c
    int *expect_sn = NULL;      /* Expected sequence numbers */
Packit Service c5cf8c
    const int nenqueuers = num_threads[curr_test] - 1;
Packit Service c5cf8c
    int ndequeues = 0;          /* Number of times we have dequeued */
Packit Service c5cf8c
    int peek_counter = 0;       /* Iterations since last peek */
Packit Service c5cf8c
    const int niter = (THREADED_NITER / iter_reduction[curr_test])
Packit Service c5cf8c
        * nenqueuers;
Packit Service c5cf8c
    int nerrors = 0;            /* Number of errors */
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Allocate expect_sn array */
Packit Service c5cf8c
    if (NULL == (expect_sn = (int *) calloc(nenqueuers, sizeof(int))))
Packit Service c5cf8c
        return (1);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Main loop.  Terminates when either the expected number of elements have
Packit Service c5cf8c
     * been dequeued or the loop has continued too many times. */
Packit Service c5cf8c
    for (i = 0; ndequeues < niter && i < (1000 * niter); i++) {
Packit Service c5cf8c
        /* If we're trying to keep the queue full, yield here so the enqueuers
Packit Service c5cf8c
         * have a chance to fill the queue */
Packit Service c5cf8c
        if (udata->mode == THREADED_MODE_FULL)
Packit Service c5cf8c
            OPA_TEST_YIELD();
Packit Service c5cf8c
Packit Service c5cf8c
        /* Check if the queue is nonempty */
Packit Service c5cf8c
        if (!OPA_Queue_is_empty(udata->qhead)) {
Packit Service c5cf8c
            /* Increment peek counter, and peek if the counter is 100 */
Packit Service c5cf8c
            peek_counter++;
Packit Service c5cf8c
            if (peek_counter == 100) {
Packit Service c5cf8c
                if (NULL == (peek_element = OPA_Queue_peek_head(udata->qhead)))
Packit Service c5cf8c
                    nerrors++;
Packit Service c5cf8c
                peek_counter = 0;
Packit Service c5cf8c
                if (OPA_Queue_is_empty(udata->qhead))
Packit Service c5cf8c
                    return (1);
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* end if */
Packit Service c5cf8c
            /* Dequeue the head element */
Packit Service c5cf8c
            OPA_Queue_dequeue(udata->qhead, element, threaded_element_t, hdr);
Packit Service c5cf8c
Packit Service c5cf8c
            /* Increment the counter */
Packit Service c5cf8c
            ndequeues++;
Packit Service c5cf8c
Packit Service c5cf8c
            /* Make sure the dequeued element is the same as the peeked element,
Packit Service c5cf8c
             * if applicable */
Packit Service c5cf8c
            if (peek_element) {
Packit Service c5cf8c
                if (peek_element->threadno != element->threadno
Packit Service c5cf8c
                    || peek_element->sequenceno != element->sequenceno) {
Packit Service c5cf8c
                    printf("    Dequeued element does not match peeked element\n");
Packit Service c5cf8c
                    nerrors++;
Packit Service c5cf8c
                }       /* end if */
Packit Service c5cf8c
                peek_element = NULL;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* end if */
Packit Service c5cf8c
            /* Check if the thread number is valid */
Packit Service c5cf8c
            if (element->threadno < 0 || element->threadno >= nenqueuers) {
Packit Service c5cf8c
                printf("    Unexpected thread number: %d\n", element->threadno);
Packit Service c5cf8c
                nerrors++;
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                /* Check if the sequence number is equal to that expected, and
Packit Service c5cf8c
                 * update the expected sequence number */
Packit Service c5cf8c
                if (element->sequenceno != expect_sn[element->threadno]) {
Packit Service c5cf8c
                    printf("    Unexpected sequence number: %d Expected: %d\n",
Packit Service c5cf8c
                           element->sequenceno, expect_sn[element->threadno]);
Packit Service c5cf8c
                    nerrors++;
Packit Service c5cf8c
                }       /* end if */
Packit Service c5cf8c
                expect_sn[element->threadno] = element->sequenceno + 1;
Packit Service c5cf8c
            }   /* end else */
Packit Service c5cf8c
Packit Service c5cf8c
            /* Free the element */
Packit Service c5cf8c
            free(element);
Packit Service c5cf8c
        } else
Packit Service c5cf8c
            OPA_TEST_YIELD();
Packit Service c5cf8c
    }   /* end for */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Check if the expected number of elements were dequeued */
Packit Service c5cf8c
    if (ndequeues != niter) {
Packit Service c5cf8c
        printf("    Incorrect number of elements dequeued: %d Expected: %d\n", ndequeues, niter);
Packit Service c5cf8c
        nerrors++;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* end if */
Packit Service c5cf8c
    /* Verify that the queue is now empty */
Packit Service c5cf8c
    if (!OPA_Queue_is_empty(udata->qhead)) {
Packit Service c5cf8c
        printf("    Queue is not empty at end of test!\n");
Packit Service c5cf8c
        nerrors++;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* end if */
Packit Service c5cf8c
    /* Sanity checking that expect_sn is consistent if no errors */
Packit Service c5cf8c
    if (!nerrors)
Packit Service c5cf8c
        for (i = 0; i < nenqueuers; i++)
Packit Service c5cf8c
            assert(expect_sn[i] == THREADED_NITER / iter_reduction[curr_test]);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Free expect_sn */
Packit Service c5cf8c
    free(expect_sn);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Any non-NULL exit value indicates an error, we use (void *) 1 here */
Packit Service c5cf8c
    return (nerrors ? 1 : 0);
Packit Service c5cf8c
}       /* end test_queue_threaded_dequeue() */
Packit Service c5cf8c
#endif /* OPA_HAVE_PTHREAD_H */
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
/*-------------------------------------------------------------------------
Packit Service c5cf8c
 * Function: test_queue_threaded
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Purpose: Tests that the queue behaves correctly in a multithreaded
Packit Service c5cf8c
 *          environment.  Creates many enqueuers and one dequeuer, and
Packit Service c5cf8c
 *          makes sure that elements are dequeued in the expected order.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Return: Success: 0
Packit Service c5cf8c
 *         Failure: 1
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Programmer: Neil Fortner
Packit Service c5cf8c
 *             Wednesday, April 1, 2009
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Modifications:
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *-------------------------------------------------------------------------
Packit Service c5cf8c
 */
Packit Service c5cf8c
static int test_queue_threaded(threaded_mode_t mode)
Packit Service c5cf8c
{
Packit Service c5cf8c
#if defined(OPA_HAVE_PTHREAD_H)
Packit Service c5cf8c
    pthread_t *threads = NULL;  /* Threads */
Packit Service c5cf8c
    pthread_attr_t ptattr;      /* Thread attributes */
Packit Service c5cf8c
    static threaded_t *thread_data = NULL;      /* User data structs for threads */
Packit Service c5cf8c
    OPA_Queue_info_t qhead;     /* The queue */
Packit Service c5cf8c
    void *ret;                  /* Thread return value */
Packit Service c5cf8c
    unsigned nthreads = num_threads[curr_test];
Packit Service c5cf8c
    int nerrors = 0;            /* number of errors */
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
Packit Service c5cf8c
    switch (mode) {
Packit Service c5cf8c
        case THREADED_MODE_DEFAULT:
Packit Service c5cf8c
            TESTING("multithreaded queue", nthreads);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case THREADED_MODE_EMPTY:
Packit Service c5cf8c
            TESTING("multithreaded queue (empty queue)", nthreads);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case THREADED_MODE_FULL:
Packit Service c5cf8c
            TESTING("multithreaded queue (full queue)", nthreads);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        default:
Packit Service c5cf8c
            FAIL_OP_ERROR(printf("    Unknown mode\n"));
Packit Service c5cf8c
    }   /* end switch */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Allocate array of threads */
Packit Service c5cf8c
    if (NULL == (threads = (pthread_t *) malloc(nthreads * sizeof(pthread_t))))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Set threads to be joinable */
Packit Service c5cf8c
    pthread_attr_init(&ptattr);
Packit Service c5cf8c
    pthread_attr_setdetachstate(&ptattr, PTHREAD_CREATE_JOINABLE);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Allocate array of thread data */
Packit Service c5cf8c
    if (NULL == (thread_data = (threaded_t *) calloc(nthreads, sizeof(threaded_t))))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Initialize queue */
Packit Service c5cf8c
    OPA_Queue_init(&qhead);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Initialize thread data structs */
Packit Service c5cf8c
    for (i = 0; i < nthreads; i++) {
Packit Service c5cf8c
        thread_data[i].qhead = &qhead;
Packit Service c5cf8c
        thread_data[i].threadno = i;
Packit Service c5cf8c
        thread_data[i].mode = mode;
Packit Service c5cf8c
    }   /* end for */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Create the threads. */
Packit Service c5cf8c
    for (i = 0; i < (nthreads - 1); i++)
Packit Service c5cf8c
        if (pthread_create(&threads[i], &ptattr, test_queue_threaded_enqueue, &thread_data[i]))
Packit Service c5cf8c
            TEST_ERROR;
Packit Service c5cf8c
    nerrors = test_queue_threaded_dequeue(&thread_data[i]);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Free the attribute */
Packit Service c5cf8c
    if (pthread_attr_destroy(&ptattr))
Packit Service c5cf8c
        TEST_ERROR;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Join the threads */
Packit Service c5cf8c
    for (i = 0; i < (nthreads - 1); i++) {
Packit Service c5cf8c
        if (pthread_join(threads[i], &ret))
Packit Service c5cf8c
            TEST_ERROR;
Packit Service c5cf8c
        if (ret)
Packit Service c5cf8c
            nerrors++;
Packit Service c5cf8c
    }   /* end for */
Packit Service c5cf8c
Packit Service c5cf8c
    /* Check for errors */
Packit Service c5cf8c
    if (nerrors)
Packit Service c5cf8c
        FAIL_OP_ERROR(printf("    Unexpected return from %d thread%s\n", nerrors,
Packit Service c5cf8c
                             nerrors == 1 ? "" : "s"));
Packit Service c5cf8c
Packit Service c5cf8c
    /* Free memory */
Packit Service c5cf8c
    free(threads);
Packit Service c5cf8c
    free(thread_data);
Packit Service c5cf8c
Packit Service c5cf8c
    PASSED();
Packit Service c5cf8c
Packit Service c5cf8c
#else /* OPA_HAVE_PTHREAD_H */
Packit Service c5cf8c
    TESTING("multithreaded queue", 0);
Packit Service c5cf8c
    SKIPPED();
Packit Service c5cf8c
    puts("    pthread.h not available");
Packit Service c5cf8c
#endif /* OPA_HAVE_PTHREAD_H */
Packit Service c5cf8c
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
Packit Service c5cf8c
#if defined(OPA_HAVE_PTHREAD_H)
Packit Service c5cf8c
  error:
Packit Service c5cf8c
    if (threads)
Packit Service c5cf8c
        free(threads);
Packit Service c5cf8c
    if (thread_data)
Packit Service c5cf8c
        free(thread_data);
Packit Service c5cf8c
    return 1;
Packit Service c5cf8c
#endif /* OPA_HAVE_PTHREAD_H */
Packit Service c5cf8c
}       /* end test_barriers_linear_array() */
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
/*-------------------------------------------------------------------------
Packit Service c5cf8c
 * Function:    main
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Purpose:     Tests the opa queue
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Return:      Success:        exit(0)
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *              Failure:        exit(1)
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Programmer:  Neil Fortner
Packit Service c5cf8c
 *              Tuesday, June 8, 2010
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Modifications:
Packit Service c5cf8c
 *
Packit Service c5cf8c
 *-------------------------------------------------------------------------
Packit Service c5cf8c
 */
Packit Service c5cf8c
int main(int argc, char **argv)
Packit Service c5cf8c
{
Packit Service c5cf8c
    threaded_mode_t mode;       /* Mode for threaded test */
Packit Service c5cf8c
    unsigned nerrors = 0;
Packit Service c5cf8c
#if defined(OPA_USE_LOCK_BASED_PRIMITIVES)
Packit Service c5cf8c
    OPA_emulation_ipl_t shm_lock;
Packit Service c5cf8c
    OPA_Interprocess_lock_init(&shm_lock, 1 /*isLeader */);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    /* Initialize shared memory.  Because we are just running threads in one
Packit Service c5cf8c
     * process, the memory will always be symmetric.  Just set the base address
Packit Service c5cf8c
     * to 0. */
Packit Service c5cf8c
    if (OPA_Shm_asymm_init((char *) 0) != 0) {
Packit Service c5cf8c
        printf("Unable to initialize shared memory\n");
Packit Service c5cf8c
        goto error;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* end if */
Packit Service c5cf8c
    /* Simple tests */
Packit Service c5cf8c
    nerrors += test_queue_sanity();
Packit Service c5cf8c
Packit Service c5cf8c
    /* Loop over test configurations */
Packit Service c5cf8c
    for (curr_test = 0; curr_test < num_thread_tests; curr_test++) {
Packit Service c5cf8c
        /* Don't test with only 1 thread */
Packit Service c5cf8c
        if (num_threads[curr_test] == 1)
Packit Service c5cf8c
            continue;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Threaded tests */
Packit Service c5cf8c
        for (mode = THREADED_MODE_DEFAULT; mode < THREADED_MODE_NMODES; mode++)
Packit Service c5cf8c
            nerrors += test_queue_threaded(mode);
Packit Service c5cf8c
    }   /* end for */
Packit Service c5cf8c
Packit Service c5cf8c
    if (nerrors)
Packit Service c5cf8c
        goto error;
Packit Service c5cf8c
    printf("All queue tests passed.\n");
Packit Service c5cf8c
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
Packit Service c5cf8c
  error:
Packit Service c5cf8c
    if (!nerrors)
Packit Service c5cf8c
        nerrors = 1;
Packit Service c5cf8c
    printf("***** %d QUEUE TEST%s FAILED! *****\n", nerrors, 1 == nerrors ? "" : "S");
Packit Service c5cf8c
    return 1;
Packit Service c5cf8c
}       /* end main() */