SXE_RETURN sxe_ring_buffer_consumed(void * base, SXE_RING_BUFFER_CONTEXT * context, unsigned len) { SXE_RETURN result = SXE_RETURN_OK; SXEE81("sxe_ring_buffer_consumed(len:%u)", len); if ((result = sxe_ring_buffer_check_over_run(base, context)) == SXE_RETURN_ERROR_INTERNAL) { goto SXE_ERROR_OUT; } SXEL92("data_block was: %p, moving to %p", context->data_block, context->data_block + len); context->data_block += len; context->data_block_len -= len; SXEA10(context->data_block <= SXE_RING_BUFFER_WRITEN_END + 1, "the data block did not go off the end of the array"); if ((context->data_block == SXE_RING_BUFFER_WRITEN_END + 1) && (context->data_block != SXE_RING_BUFFER_CURRENT)) { SXEA10(context->data_block_len == 0, "If this consume brought us to the end of the array, the remaining length must be zero"); SXEL90("Wrapping data_block to the start of the ring"); context->data_block = SXE_RING_BUFFER_ARRAY_BASE; context->itteration++; } SXE_EARLY_OR_ERROR_OUT: SXEL93("context data_block: %p, data_block_len: %u itteration: %u", context->data_block, context->data_block_len, context->itteration); SXER81("return %s", sxe_return_to_string(result)); return result; }
static SXE_THREAD_RETURN SXE_STDCALL test_thread_main(void * lock) { SXEE81("test_thread_main(lock=%p)", lock); SXEA10(lock == &ping, "Ping lock not passed to the thread"); SXEA10(sxe_spinlock_take(&pong) == SXE_SPINLOCK_STATUS_TAKEN, "Pong lock not taken by thread"); SXEA10(sxe_spinlock_take(&ping) == SXE_SPINLOCK_STATUS_TAKEN, "Ping lock not taken by thread"); SXEL10("thread: about to pong the main thread"); sxe_spinlock_give(&pong); for (;;) { sleep(1); } SXER80("return NULL"); return (SXE_THREAD_RETURN)0; }
void sxe_ring_buffer_next_writable_block(void * base, SXE_RING_BUFFER_CONTEXT * context) { SXEE80("sxe_ring_buffer_next_writable_block()"); context->writable_block = SXE_RING_BUFFER_CURRENT; context->writable_block_len = SXE_RING_BUFFER_END - SXE_RING_BUFFER_CURRENT + 1; SXEA10(context->writable_block_len != 0, "The writable block length is not zero"); SXEL92("Writable block: %p, Writable block length: %u", context->writable_block, context->writable_block_len); SXER80("return"); }
void sxe_ring_buffer_next_writable_block_size(void * base, SXE_RING_BUFFER_CONTEXT * context, unsigned size) { SXEE81("sxe_ring_buffer_next_writable_block_size(size=%u)", size); SXEA10(size <= SXE_RING_BUFFER_SIZE, "The requested size is equall or smaller then the ring"); sxe_ring_buffer_next_writable_block(base, context); if (context->writable_block_len < size) { sxe_ring_buffer_force_ring_wrap(base); sxe_ring_buffer_next_writable_block(base, context); } SXER80("return"); }
void * sxe_sync_ev_new(void * user_data) { unsigned id; SXEE81("sxe_sync_ev_new(user_data=%p)", user_data); SXEA10((id = sxe_pool_set_oldest_element_state(sxe_sync_ev_pool, 0, 1)) != SXE_POOL_NO_INDEX, "Could not allocate a sync object"); sxe_sync_ev_pool[id].sock = sxe_sync_ev_socket(); sxe_sync_ev_pool[id].user_data = user_data; SXER81("return sync=%p", &sxe_sync_ev_pool[id]); return &sxe_sync_ev_pool[id]; }
void sxe_ring_buffer_wrote_block(void * base, SXE_RING_BUFFER_CONTEXT * context, unsigned len) { SXEE81("sxe_ring_buffer_wrote_block(len=%u)", len); SXEA10(context->writable_block == SXE_RING_BUFFER_CURRENT, "The current pointer is still where it was when you asked for it"); SXEA10(len <= (unsigned)(SXE_RING_BUFFER_END - SXE_RING_BUFFER_CURRENT + 1), "Did not overwrite end of buffer ring"); SXE_RING_BUFFER_CURRENT = SXE_RING_BUFFER_CURRENT + len; if (SXE_RING_BUFFER_CURRENT == (SXE_RING_BUFFER_END + 1)) { SXEL90("Wrote to the last byte in the array, wrapping pointer"); SXE_RING_BUFFER_ITERATION++; SXE_RING_BUFFER_CURRENT = SXE_RING_BUFFER_ARRAY_BASE; SXE_RING_BUFFER_WRITEN_END = SXE_RING_BUFFER_END; } else { if (SXE_RING_BUFFER_WRITEN_END < SXE_RING_BUFFER_CURRENT) { SXE_RING_BUFFER_WRITEN_END = SXE_RING_BUFFER_CURRENT - 1; } } SXEL93("Current: %p, Writen End %p, Itteration: %u", SXE_RING_BUFFER_CURRENT, SXE_RING_BUFFER_WRITEN_END, SXE_RING_BUFFER_ITERATION); SXER80("return"); }
void * sxe_ring_buffer_new(unsigned size) { void * base; SXEE81("sxe_ring_buffer_new(size=%u)", size); SXEA10((base = malloc(size + SXE_RING_BUFFER_SIZE_OF_INTERNALS)) != NULL, "Error allocating sxe-ring-buffer"); SXE_RING_BUFFER_SIZE = size; SXE_RING_BUFFER_ITERATION = 0; SXE_RING_BUFFER_CURRENT = SXE_RING_BUFFER_ARRAY_BASE; SXE_RING_BUFFER_WRITEN_END = SXE_RING_BUFFER_CURRENT; SXEL92("Array base=%p, End of Array=%p", SXE_RING_BUFFER_ARRAY_BASE, SXE_RING_BUFFER_END); SXER81("return base=%p", base); return base; }
void sxe_ring_buffer_add(void * base, const char * buf, unsigned len) { unsigned available_space; SXEE82("sxe_ring_buffer_add(buf=%p,len=%u)", buf, len); SXEL92("Current: %p, Itteration: %u", SXE_RING_BUFFER_CURRENT, SXE_RING_BUFFER_ITERATION); SXEA10(len <= SXE_RING_BUFFER_SIZE, "The item we're will fit in the whole array"); available_space = (SXE_RING_BUFFER_END - SXE_RING_BUFFER_CURRENT + 1); SXEL91("There is %u space between the current pointer and the end of the array", available_space); if (available_space >= len) { // Can we fit it on the end of the array? SXEL92("Adding %u bytes at %p", len, SXE_RING_BUFFER_CURRENT); memcpy(SXE_RING_BUFFER_CURRENT, buf, len); SXE_RING_BUFFER_CURRENT = SXE_RING_BUFFER_CURRENT + len; if (SXE_RING_BUFFER_CURRENT == (SXE_RING_BUFFER_END + 1)) { SXEL90("Wrote to the last byte in the array, wrapping pointer"); SXE_RING_BUFFER_ITERATION++; SXE_RING_BUFFER_CURRENT = SXE_RING_BUFFER_ARRAY_BASE; SXE_RING_BUFFER_WRITEN_END = SXE_RING_BUFFER_END; } else { if (SXE_RING_BUFFER_WRITEN_END < SXE_RING_BUFFER_CURRENT) { SXE_RING_BUFFER_WRITEN_END = SXE_RING_BUFFER_CURRENT - 1; } } } else { // else we have to wrap around the ring memcpy(SXE_RING_BUFFER_CURRENT, buf, available_space); SXE_RING_BUFFER_WRITEN_END = SXE_RING_BUFFER_END; SXE_RING_BUFFER_ITERATION++; SXE_RING_BUFFER_CURRENT = SXE_RING_BUFFER_ARRAY_BASE; memcpy(SXE_RING_BUFFER_CURRENT, buf + available_space, (len - available_space)); SXE_RING_BUFFER_CURRENT = SXE_RING_BUFFER_CURRENT + (len - available_space); } SXEL93("Current: %p, Writen End %p, Itteration: %u", SXE_RING_BUFFER_CURRENT, SXE_RING_BUFFER_WRITEN_END, SXE_RING_BUFFER_ITERATION); SXER80("return"); }
/* Note that the decoded_name will be NUL terminated, and therefore the * maximum_name_length_maximum should probably be 254 and not 253 (though, with * pointers, the decoded name could well be *longer* than 253 characters! */ static SXE_RETURN sxe_dns_decode_name( const unsigned char * dns_packet , unsigned dns_packet_length , unsigned name_offset , char * decoded_name , unsigned decoded_name_length_maximum, unsigned * decoded_name_length ) { SXE_RETURN result = SXE_RETURN_ERROR_INTERNAL; unsigned decoded_name_offset = 0; SXEE86("sxe_dns_decode_name(dns_packet=%p, dns_packet_length=%u, name_offset=%u, decoded_name=%p, decoded_name_length_maximum=%u, decoded_name_length=%p)", dns_packet, dns_packet_length, name_offset, decoded_name, decoded_name_length_maximum, decoded_name_length); SXEA10(decoded_name_length != 0, "A value for decoded_name_length must be provided"); SXEA10(decoded_name == NULL || decoded_name_length_maximum != 0, "NAME can not be decoded into an empty buffer"); while (name_offset < dns_packet_length) { unsigned char len = dns_packet[name_offset]; if (len == '\0') { SXEL60("NAME is terminated normally"); if (decoded_name_offset > 0) { --decoded_name_offset; } if (decoded_name != NULL) { decoded_name[decoded_name_offset] = '\0'; } *decoded_name_length = decoded_name_offset; result = SXE_RETURN_OK; goto SXE_EARLY_OUT; } else if ((len & SXE_DNS_LABEL_LENGTH_POINTER) == 0) { SXEL73("Normal label of length %u '%.*s'", len, len, &dns_packet[name_offset + 1]); /* Don't allow the NAME to exceed the known packet length */ if ((decoded_name != NULL) && (decoded_name_offset + len + 1 >= decoded_name_length_maximum)) { SXEL51("sxe_dns_decode_name(): NAME is invalid; Decoded NAME is longer than the provided buffer length %u", decoded_name_length_maximum); goto SXE_ERROR_OUT; } /* Copy the label */ if (decoded_name != NULL) { memcpy((unsigned char*)(decoded_name + decoded_name_offset), dns_packet + name_offset + 1, len); decoded_name[decoded_name_offset + len] = '.'; } decoded_name_offset += len + 1; } else if ((len & SXE_DNS_LABEL_LENGTH_POINTER) == SXE_DNS_LABEL_LENGTH_POINTER) { SXEL60("NAME includes a pointer"); name_offset = (len & ~SXE_DNS_LABEL_LENGTH_POINTER) + dns_packet[name_offset + 1]; SXEL61("New NAME offset is %u", name_offset); /* Prevent looping forever - a pointer should never point to a pointer */ if ((dns_packet[name_offset] & SXE_DNS_LABEL_LENGTH_POINTER) != 0) { SXEL51("sxe_dns_decode_name(): NAME contains a pointer which points to another pointer at packet offset %u", name_offset); goto SXE_ERROR_OUT; } continue; } else { SXEL51("sxe_dns_decode_name(): NAME is invalid; NAME contains an invalid length/pointer value at packet offset %u", name_offset); goto SXE_ERROR_OUT; } name_offset += len + 1; } SXEL60("NAME is invalid because it extends outside the packet"); SXE_ERROR_OUT: SXE_EARLY_OUT: SXER81("return // result=%s", sxe_return_to_string(result)); return result; }
int main(int argc, char ** argv) { const char * line; unsigned i; if (argc > 1) { test_program_arg = argv[1]; sxe_log_hook_line_out(test_log_line_out_to_stdout); SXEA10(sxe_log_hook_line_out(test_log_line_out_to_stdout) == test_log_line_out_to_stdout, "sxe_log_hook_line_out failed to hook test_log_line_out_to_stdout"); if (strcmp(argv[1], "1") == 0) { if (getenv("SXE_LOG_LEVEL") != NULL) { SXED80("should not see this (level too high)", strlen("should not see this (level too high)")); /* Cover early out in dump */ } SXEL40("BOO"); } else if (strcmp(argv[1], "2") == 0) { #ifndef LOCAL_SXE_DEBUG sxe_log_set_indent_maximum(~0U); #endif sxe_log_set_level(SXE_LOG_LEVEL_WARNING); SXEE50("level_five()"); test_level_six(SXE_LOG_LEVEL_LIBRARY_DUMP); SXER50("return // five"); SXEE50("level_five()"); test_level_six(SXE_LOG_LEVEL_WARNING); SXER50("return // five"); SXEL20("that's all, folks"); } exit(0); } test_program_name = argv[0]; plan_tests(3 * TEST_LINES_EXPECTED + 3); /* Tests for different log level settings */ tap_test_case_name("Level settings"); ok((line = test_log_first("1")) != NULL, "Test log at default level wrote a line"); diag("line = %s", line); SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL=2") >= 0, "%s: Failed to putenv: %s", test_program_name, strerror(errno)); ok(test_log_first("1") == NULL, "Test log with SXE_LOG_LEVEL=2 failed to write a line"); /* TODO: Replace putenvs with calls to the TBD function that allows setting fine grained levels programmatically. */ SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL_LIBSXE=5") >= 0, "%s: Failed to putenv: %s", test_program_name, strerror(errno)); ok((line = test_log_first("1")) != NULL, "Test log with SXE_LOG_LEVEL_LIBSXE=5 wrote a line"); diag("line = %s", line); SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG=2") >= 0, "%s: Failed to setenv: %s", test_program_name, strerror(errno)); ok(test_log_first("1") == NULL, "Test log with SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG=2 failed to write a line"); SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG_TEST_TEST_SXE_LOG_LEVELS=7") >= 0, "%s: Failed to putenv: %s", test_program_name, strerror(errno)); ok((line = test_log_first("1")) != NULL, "Test log with SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG_TEST_TEST_SXE_LOG_LEVELS=7 wrote a line"); diag("line = %s", line); /* Remove the more specific environment variables */ SXEA12(unsetenv("SXE_LOG_LEVEL_LIBSXE") == 0, "%s: unsetenv failed: %s", test_program_name, strerror(errno)); SXEA12(unsetenv("SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG") == 0, "%s: unsetenv failed: %s", test_program_name, strerror(errno)); SXEA12(unsetenv("SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG_TEST_TEST_SXE_LOG_LEVELS") == 0, "%s: unsetenv failed: %s", test_program_name, strerror(errno)); /* Tests for indentation interacting with log level */ tap_test_case_name("Indentation"); line = test_log_first("2"); for (i = 0; i < TEST_LINES_EXPECTED; i++) { ok(line != NULL, "Got line %u", 2 * i + 1); ok(strstr(line, test_expected[i]) != NULL, "Found '%s' in '%.*s'", test_expected[i], (int)strlen(line) - 1, line); if (i > 2) { ok(test_log_next() != NULL, "Got line %u", 2 * i + 2); } line = test_log_next(); } ok(line == NULL, "Got EOF"); return exit_status(); }
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 }