Exemple #1
0
/**
 * Step to the next object in a pool state
 *
 * @param walker Pointer to the pool state walker
 *
 * @return Index of the next object or SXE_POOL_NO_INDEX if the end of the state queue has been reached.
 *
 * @note Thread safety is implemented by verifying that the last node stepped to is still in the same state queue. If it is not,
 *       the state queue is rewalked to find a node with a time or count greater than or equal to the time that the last stepped
 *       to node had when it was stepped to.
 */
unsigned
sxe_pool_walker_step(SXE_POOL_WALKER * walker)
{
    SXE_POOL_NODE * node;
    SXE_POOL_IMPL * pool = walker->pool;
    unsigned        result;

    SXEE81("sxe_pool_walker_step(walker=%p)", walker);

    if ((result = sxe_pool_lock(pool)) == SXE_POOL_LOCK_NOT_TAKEN) {
        goto SXE_ERROR_OUT;
    }

    /* If not at the head of the state queue and the current object has been moved to another state.
     */
    if (((node = sxe_list_walker_find(&walker->list_walker)) != NULL)
            && (SXE_LIST_NODE_GET_ID(&node->list_node) != walker->state))
        /* TODO: Check for touching */
    {
        SXEL83("sxe_pool_walker_step: node %u moved from state %s to state %s by another thread", node - SXE_POOL_NODES(pool),
               (*pool->state_to_string)(walker->state), (*pool->state_to_string)(SXE_LIST_NODE_GET_ID(&node->list_node)));

        /* If there is a previous object and it has not been moved, get the new next one.
         */
        if (((node = sxe_list_walker_back(&walker->list_walker)) != NULL)
                && (SXE_LIST_NODE_GET_ID(&node->list_node) == walker->state))
            /* TODO: Check for touching */
        {
            node = sxe_list_walker_step(&walker->list_walker);
        }
        else {
            sxe_list_walker_construct(&walker->list_walker, &SXE_POOL_QUEUE(pool)[walker->state]);

            while ((node = sxe_list_walker_step(&walker->list_walker)) != NULL) {
                if (pool->options & SXE_POOL_OPTION_TIMED) {
                    if (node->last.time >= walker->last.time) {    /* Coverage Exclusion: TODO refactor SXE_POOL_TIME */
                        break;                                     /* Coverage Exclusion: TODO refactor SXE_POOL_TIME */
                    }
                }
                else {
                    if (node->last.count >= walker->last.count) {
                        break;
                    }
                }
            }
        }
    }
    else {
        node = sxe_list_walker_step(&walker->list_walker);
    }

    result = SXE_POOL_NO_INDEX;

    if (node != NULL) {
        result = node - SXE_POOL_NODES(pool);

        if (pool->options & SXE_POOL_OPTION_TIMED) {
            walker->last.time  = node->last.time;
        }
        else {
            walker->last.count = node->last.count;
        }
    }

    sxe_pool_unlock(pool);

SXE_ERROR_OUT:
    SXER81("return %s", sxe_pool_return_to_string(result));
    return result;
}
Exemple #2
0
int
main(int argc, char ** argv)
{
#ifdef WINDOWS_NT
    SXEL10("WARNING: Need to implement sxe_spawn() on Windows to run this test file!");
#else
    int           fd;
    double        start_time;
    unsigned      count;
    unsigned      id;
    unsigned    * pool;
    unsigned    * shared;
    size_t        size;
    SXE_MMAP      memmap;
    SXE_RETURN    result;
    SXE_SPAWN     spawn[TEST_CLIENT_INSTANCES];

    if (argc > 1) {
        count = atoi(argv[1]);
        sxe_mmap_open(&memmap, "memmap");
        shared  = (unsigned *)(unsigned long)SXE_MMAP_ADDR(&memmap);
        pool    = sxe_pool_from_base(shared);
        SXEL63("Instance %u mapped to shared pool // base=%p, pool=%p", count, shared, pool);
        do {
            usleep(10000 * count);
            id = sxe_pool_set_oldest_element_state_locked(pool, TEST_STATE_FREE, TEST_STATE_CLIENT_TAKE);
            SXEA10(id != SXE_POOL_LOCK_NEVER_TAKEN, "Got SXE_POOL_LOCK_NEVER_TAKEN");;
        } while (id == SXE_POOL_NO_INDEX);

        SXEL62("Instance %u got pool element %u", count, id);
        pool[id] = count;
        sxe_pool_set_indexed_element_state_locked(pool, id, TEST_STATE_CLIENT_TAKE, TEST_STATE_CLIENT_DONE);
        sxe_mmap_close(&memmap);
        SXEL61("Instance %u exiting", count);
        return 0;
    }

    plan_tests(5);
    ok((size = sxe_pool_size(TEST_CLIENT_INSTANCES/2, sizeof(*pool), TEST_STATE_NUMBER_OF_STATES)) >= TEST_CLIENT_INSTANCES * sizeof(*pool),
       "Expect pool size %u to be at least the size of the array %u", size, TEST_CLIENT_INSTANCES * sizeof(*pool));

    SXEA11((fd = open("memmap", O_CREAT | O_TRUNC | O_WRONLY, 0666)) >= 0, "Failed to create file 'memmap': %s",         strerror(errno));
    SXEA12(ftruncate(fd, size)                                       >= 0, "Failed to extend the file to %lu bytes: %s", size, strerror(errno));
    close(fd);
    sxe_mmap_open(&memmap, "memmap");
    shared = (unsigned *)(unsigned long)SXE_MMAP_ADDR(&memmap);

    pool = sxe_pool_construct(shared, "shared-pool", TEST_CLIENT_INSTANCES/2, sizeof(*pool), TEST_STATE_NUMBER_OF_STATES, SXE_POOL_LOCKS_ENABLED);

    sxe_register(TEST_CLIENT_INSTANCES + 1, 0);
    SXEA11((result = sxe_init()) == SXE_RETURN_OK,  "Failed to initialize the SXE package: %s",  sxe_return_to_string(result));

    for (count = 1; count <= TEST_CLIENT_INSTANCES; count++) {
        char buffer[12];

        snprintf(buffer, sizeof(buffer), "%u", count);
        result = sxe_spawn(NULL, &spawn[count - 1], argv[0], buffer, NULL, NULL, NULL, NULL);
        SXEA13(result == SXE_RETURN_OK, "Failed to spawn '%s %s': %s", argv[0], buffer, sxe_return_to_string(result));
    }

    start_time = sxe_get_time_in_seconds();
    for (count = 0; (count < TEST_CLIENT_INSTANCES); ) {
        SXEA10((TEST_WAIT + start_time ) > sxe_get_time_in_seconds(), "Unexpected timeout... is the hardware too slow?");
        usleep(10000);
        id = sxe_pool_set_oldest_element_state_locked(pool, TEST_STATE_CLIENT_DONE, TEST_STATE_FREE);

        /* Assert here in  the test. The actual service would take specific action here */
        SXEA12(id != SXE_POOL_LOCK_NEVER_TAKEN, "Parent: Failed to acqure lock .. yield limit reached. id %u vs %u", id, SXE_POOL_LOCK_NEVER_TAKEN);

        if (id != SXE_POOL_NO_INDEX) {
            SXEL62("Looks like instance %u got element %u", pool[id], id);
            count++;
        }
    }
    ok(count == TEST_CLIENT_INSTANCES, "All clients got an element in the pool");

    start_time = sxe_get_time_in_seconds();
    for (count = 0; (count < TEST_CLIENT_INSTANCES); count++) {
        SXEA10((TEST_WAIT + start_time ) > sxe_get_time_in_seconds(), "Unexpected timeout... is the hardware too slow?");
        waitpid(spawn[count].pid, NULL, 0);
    }

    ok(SXE_POOL_LOCK_NEVER_TAKEN != sxe_pool_lock(pool), "Forced lock to be always locked!");
    id = sxe_pool_set_oldest_element_state_locked(pool, TEST_STATE_FREE, TEST_STATE_FREE);
    ok(id == SXE_POOL_LOCK_NEVER_TAKEN,   "sxe_pool_set_oldest_element_state_locked() Failed to acquire lock");
    id = sxe_pool_set_indexed_element_state_locked(pool, 0, TEST_STATE_FREE, TEST_STATE_FREE);
    ok(id == SXE_POOL_LOCK_NEVER_TAKEN,   "sxe_pool_set_indexed_element_state_locked() Failed to acquire lock");
    sxe_pool_unlock(pool);
    sxe_pool_override_locked(pool); /* for coverage */

    sxe_mmap_close(&memmap);
    return exit_status();
#endif
}