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