/** * Allocate and contruct a hash * * @param name = Name of the hash, used in diagnostics * @param element_count = Maximum number of elements in the hash * @param element_size = Size of each element in the hash in bytes * @param key_offset = Offset of start of key from start of element in bytes * @param key_size = Size of the key in bytes * @param options = SXE_HASH_OPTION_UNLOCKED | SXE_HASH_OPTION_LOCKED (single threaded or use locking) * + SXE_HASH_OPTION_PREHASHED | SXE_HASH_OPTION_LOOKUP3_HASH (key is prehashed or use lookup3) * * @return A pointer to an array of hash elements */ void * sxe_hash_new_plus(const char * name, unsigned element_count, unsigned element_size, unsigned key_offset, unsigned key_size, unsigned options) { SXE_HASH * hash; unsigned size; SXEE6("sxe_hash_new_plus(name=%s,element_count=%u,element_size=%u,key_offset=%u,key_size=%u,options=%u)", name, element_count, element_size, key_offset, key_size, options); size = sizeof(SXE_HASH) + sxe_pool_size(element_count, element_size, element_count + SXE_HASH_BUCKETS_RESERVED); SXEA1((hash = malloc(size)) != NULL, "Unable to allocate %u bytes of memory for hash %s", size, name); SXEL6("Base address of hash %s = %p", name, hash); /* Note: hash + 1 == pool base */ hash->pool = sxe_pool_construct(hash + 1, name, element_count, element_size, element_count + SXE_HASH_BUCKETS_RESERVED, options & SXE_HASH_OPTION_LOCKED ? SXE_POOL_OPTION_LOCKED : 0); hash->count = element_count; hash->size = element_size; hash->key_offset = key_offset; hash->key_size = key_size; hash->options = options; hash->hash_key = options & SXE_HASH_OPTION_LOOKUP3_HASH ? lookup3_hash : sxe_prehashed_key_hash; SXER6("return array=%p", hash->pool); return hash->pool; }
SXEL6("Instance %2u got pool element %u", count, id); pool[id] = count; sxe_pool_set_indexed_element_state(pool, id, TEST_STATE_CLIENT_TAKE, TEST_STATE_CLIENT_DONE); sxe_mmap_close(&memmap); SXEL6("Instance %2u exiting", count); return 0; } plan_tests(6); sxe_test_get_temp_file_name("test-sxe-mmap-pool", unique_memmap_path_and_file_master_buffer, sizeof(unique_memmap_path_and_file_master_buffer), &unique_memmap_path_and_file_master_buffer_used); unique_memmap_path_and_file = &unique_memmap_path_and_file_master_buffer[0]; SXEL1("Instance %2d unique memmap path and file: %s", count, unique_memmap_path_and_file); 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", (unsigned)size, (unsigned)(TEST_CLIENT_INSTANCES * sizeof(*pool))); SXEA1((fd = open(unique_memmap_path_and_file, O_CREAT | O_TRUNC | O_WRONLY, 0666)) >= 0, "Failed to create file '%s': %s", unique_memmap_path_and_file, strerror(errno)); SXEA1(ftruncate(fd, size) >= 0, "Failed to extend the file to %p bytes: %s", SXE_CAST(void *, size), strerror(errno)); close(fd); sxe_mmap_open(&memmap, unique_memmap_path_and_file); shared = SXE_CAST(unsigned *, SXE_MMAP_ADDR(&memmap)); pool = sxe_pool_construct(shared, "shared-pool", TEST_CLIENT_INSTANCES/2, sizeof(*pool), TEST_STATE_NUMBER_OF_STATES, SXE_POOL_OPTION_LOCKED); for (count = 0; count < TEST_CLIENT_INSTANCES; count++) { char buffer[12]; snprintf(buffer, sizeof(buffer), "%u", count + 1);
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 }