void sxe_sync_ev_init(unsigned concurrency, void (*send_event)(void * sync, void * user_data)) { unsigned short port; SXEE82("sxe_sync_ev_init(concurrency=%u,send_event=%p)", concurrency, send_event); sxe_sync_ev_pool = sxe_pool_new("http_sync_ev", concurrency, sizeof(SXE_SYNC_EV), 2); sxe_sync_ev_sock = sxe_sync_ev_socket(); sxe_sync_generic_event = send_event; sxe_sync_ev_addr.sin_family = AF_INET; sxe_sync_ev_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); for (port = 1025; ; port++) { sxe_sync_ev_addr.sin_port = htons(port); if (bind(sxe_sync_ev_sock, (struct sockaddr *)&sxe_sync_ev_addr, sizeof(sxe_sync_ev_addr)) >= 0) { break; } SXEA12(port < USHRT_MAX, "Not able to bind any port between 1024 and %hu: %s", port, /* Coverage Exclusion - Assert */ sxe_socket_get_last_error_as_str()); } /* Coverage Exclusion - Not Reached */ SXEL81("Listening on port %hu", port); ev_io_init(&sxe_sync_ev_io, sxe_sync_ev_read, _open_osfhandle(sxe_sync_ev_sock, 0), EV_READ); ev_io_start(ev_default_loop(0), &sxe_sync_ev_io); SXER80("return"); }
void sxe_ring_buffer_join(void * base, SXE_RING_BUFFER_CONTEXT * context, bool replay_half) { SXEE80("sxe_ring_buffer_join()"); context->itteration = SXE_RING_BUFFER_ITERATION; context->data_block = SXE_RING_BUFFER_CURRENT; context->data_block_len = 0; if (replay_half) { if (SXE_RING_BUFFER_CURRENT - SXE_RING_BUFFER_ARRAY_BASE >= (int)(SXE_RING_BUFFER_SIZE / 2)) { // If the current pointer is over half way through SXEL90("Current pointer is more then half way through ring"); context->data_block = SXE_RING_BUFFER_CURRENT - (unsigned)(SXE_RING_BUFFER_SIZE / 2); } else if (SXE_RING_BUFFER_ITERATION == 0) { // First iteration, and havn't writen a half ring yet, go to the start of the array context->data_block = SXE_RING_BUFFER_ARRAY_BASE; } else { // else we have to go back an itteration SXEL90("Current pointer is less then half way through ring"); SXEL90("Going back an itteration"); context->itteration--; context->data_block = SXE_RING_BUFFER_CURRENT + (int)((SXE_RING_BUFFER_WRITEN_END - SXE_RING_BUFFER_ARRAY_BASE + 1) / 2); } } SXEL92("context data_block: %p, itteration: %u", context->data_block, context->itteration); SXER80("return"); }
void * sxe_sync_ev_delete(void * sync_point) { SXEE81("sxe_sync_ev_delete(sync_point=%p)", sync_point); sxe_pool_set_indexed_element_state(sxe_sync_ev_pool, (SXE_SYNC_EV *)sync_point - sxe_sync_ev_pool, 1, 0); SXER80("return NULL"); return NULL; }
static void test_pool_3_timeout(void * array, unsigned array_index, void * caller_info) { SXEE82("test_pool_3_timeout(array=%p,array_index=%u)", array, array_index); SXE_UNUSED_PARAMETER(caller_info); sxe_pool_set_indexed_element_state(array, array_index, 0, 1); sxe_pool_set_indexed_element_state(array, array_index, 1, 0); SXER80("return"); }
void sxe_ring_buffer_force_ring_wrap(void * base) { SXEE80("sxe_ring_buffer_force_ring_wrap()"); SXE_RING_BUFFER_WRITEN_END = SXE_RING_BUFFER_CURRENT - 1; SXE_RING_BUFFER_CURRENT = SXE_RING_BUFFER_ARRAY_BASE; SXE_RING_BUFFER_ITERATION++; SXER80("return"); }
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_sync_ev_post(void * sync_point) { SXE_SYNC_EV * sync_ev = (SXE_SYNC_EV *)sync_point; SXEE81("sxe_sync_ev_post(sync_point=%p)", sync_point); SXEA11(sendto(sync_ev->sock, (MOCK_SOCKET_VOID *)&sync_point, sizeof(sync_point), 0, (struct sockaddr *)&sxe_sync_ev_addr, sizeof(sxe_sync_ev_addr)) == sizeof(sync_point), "Can't send to sync_point listener port: %s", sxe_socket_get_last_error_as_str()); 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"); }
static void test_pool_1_timeout(void * array, unsigned array_index, void * caller_info) { SXEE83("test_pool_1_timeout(array=%p,array_index=%u,caller_info=%p)", array, array_index, caller_info); SXE_UNUSED_PARAMETER(caller_info); test_pool_1_timeout_call_count ++; if (1 == test_pool_1_timeout_call_count) { sxe_pool_set_indexed_element_state(array, array_index, TEST_STATE_ABUSED, TEST_STATE_FREE); } if (2 == test_pool_1_timeout_call_count) { sxe_pool_set_indexed_element_state(array, array_index, TEST_STATE_USED, TEST_STATE_FREE); } SXER80("return"); }
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_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"); }
static void sxe_sync_ev_read(EV_P_ ev_io * io, int revents) { SXE_SYNC_EV * handle; SXEE82("sxe_sync_ev_read(io=%p,revents=%d)", io, revents); #if EV_MULTIPLICITY SXE_UNUSED_ARGUMENT(loop); #endif SXE_UNUSED_ARGUMENT(io); SXE_UNUSED_ARGUMENT(revents); while(recvfrom(sxe_sync_ev_sock, &handle, sizeof(handle), 0, NULL, NULL) == sizeof(handle)) { (*sxe_sync_generic_event)(handle, handle->user_data); } SXEA11(sxe_socket_get_last_error() == SXE_SOCKET_ERROR(EWOULDBLOCK), "Unexpected error receiving from sync socket: %s", sxe_socket_get_last_error_as_str()); SXER80("return"); }
/** * Construct a pool state walker (AKA iterator) * * @param walker Pointer to the walker * @param array Pointer to the pool array * @param state State to walk * * @exception If the pool is both locked and timed, it cannot be walked safely */ void sxe_pool_walker_construct(SXE_POOL_WALKER * walker, void * array, unsigned state) { SXE_POOL_IMPL * pool = SXE_POOL_ARRAY_TO_IMPL(array); SXEE83("sxe_pool_walker_construct(walker=%p,pool=%s,state=%s)", walker, pool->name, (*pool->state_to_string)(state)); SXEA11(!((pool->options & SXE_POOL_OPTION_LOCKED) && (pool->options & SXE_POOL_OPTION_TIMED)), "sxe_pool_walker_construct: Can't walk thread safe timed pool %s safely", pool->name); sxe_list_walker_construct(&walker->list_walker, &SXE_POOL_QUEUE(pool)[state]); walker->pool = pool; walker->state = state; if (pool->options & SXE_POOL_OPTION_TIMED) { walker->last.time = 0.0; } else { walker->last.count = 0; } SXER80("return"); }
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"); }
static void select_modify (EV_P_ int fd, int oev, int nev) { SXEE83("select_modify(fd=%p, oev=%d, nev=%d)", fd, oev, nev); if (oev == nev) { SXER80("return // oev == nev"); return; } { #if EV_SELECT_USE_FD_SET #if EV_SELECT_IS_WINSOCKET SOCKET handle = anfds [fd].handle; #else int handle = fd; #endif SXEL80("#if EV_SELECT_USE_FD_SET"); SXEL81("handle = %d", handle); assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE)); /* FD_SET is broken on windows (it adds the fd to a set twice or more, * which eventually leads to overflows). Need to call it only on changes. */ #if EV_SELECT_IS_WINSOCKET if ((oev ^ nev) & EV_READ) { SXEL80("EV_SELECT_IS_WINSOCKET => (oev ^ nev) & EV_READ == TRUE"); #endif if (nev & EV_READ) { SXEL82("FD_SET(handle=%d, vec_ri=%p)", handle, vec_ri); FD_SET (handle, (fd_set *)vec_ri); } else { SXEL82("FD_CLR(handle=%d, vec_ri=%p)", handle, vec_ri); FD_CLR (handle, (fd_set *)vec_ri); } #if EV_SELECT_IS_WINSOCKET } #endif #if EV_SELECT_IS_WINSOCKET if ((oev ^ nev) & EV_WRITE) { SXEL80("EV_SELECT_IS_WINSOCKET => (oev ^ nev) & EV_WRITE == TRUE"); #endif if (nev & EV_WRITE) { SXEL82("FD_SET(handle=%d, vec_wi=%p)", handle, vec_wi); FD_SET (handle, (fd_set *)vec_wi); } else { SXEL82("FD_CLR(handle=%d, vec_wi=%p)", handle, vec_wi); FD_CLR (handle, (fd_set *)vec_wi); } #if EV_SELECT_IS_WINSOCKET } #endif SXEL80("#endif // EV_SELECT_USE_FD_SET"); #else SXEL80("#if *NOT* EV_SELECT_USE_FD_SET"); int word = fd / NFDBITS; fd_mask mask = 1UL << (fd % NFDBITS); if (expect_false (vec_max <= word)) { int new_max = word + 1; vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES); vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */ vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES); vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */ #ifdef _WIN32 vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */ #endif for (; vec_max < new_max; ++vec_max) ((fd_mask *)vec_ri) [vec_max] = ((fd_mask *)vec_wi) [vec_max] = 0; } ((fd_mask *)vec_ri) [word] |= mask; if (!(nev & EV_READ)) ((fd_mask *)vec_ri) [word] &= ~mask; ((fd_mask *)vec_wi) [word] |= mask; if (!(nev & EV_WRITE)) ((fd_mask *)vec_wi) [word] &= ~mask; SXEL80("#endif // *NOT* EV_SELECT_USE_FD_SET"); #endif } SXER80("return"); }
static void select_poll (EV_P_ ev_tstamp timeout) { struct timeval tv; int res; int fd_setsize; EV_RELEASE_CB; tv.tv_sec = (long)timeout; tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6); #if EV_SELECT_USE_FD_SET fd_setsize = sizeof (fd_set); #else fd_setsize = vec_max * NFDBYTES; #endif SXEE81("select_poll(timeout=%f)", timeout); memcpy (vec_ro, vec_ri, fd_setsize); memcpy (vec_wo, vec_wi, fd_setsize); #ifdef _WIN32 SXEL80("Using select() on Windows"); /* pass in the write set as except set. * the idea behind this is to work around a windows bug that causes * errors to be reported as an exception and not by setting * the writable bit. this is so uncontrollably lame. */ memcpy (vec_eo, vec_wi, fd_setsize); res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv); #elif EV_SELECT_USE_FD_SET SXEL80("Using select() with fd_set..."); fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE; res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); #else SXEL80("Using select() without fd_set..."); res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); #endif EV_ACQUIRE_CB; if (expect_false (res < 0)) { SXEL81("expect_false (res < 0) // res=%d", res); #if EV_SELECT_IS_WINSOCKET errno = WSAGetLastError (); SXEL81("errno=%d", errno); #endif #ifdef WSABASEERR /* on windows, select returns incompatible error codes, fix this */ if (errno >= WSABASEERR && errno < WSABASEERR + 1000) if (errno == WSAENOTSOCK) errno = EBADF; else errno -= WSABASEERR; SXEL81("errno=%d // after fixing error code", errno); #endif #ifdef _WIN32 /* select on windows errornously returns EINVAL when no fd sets have been * provided (this is documented). what microsoft doesn't tell you that this bug * exists even when the fd sets _are_ provided, so we have to check for this bug * here and emulate by sleeping manually. * we also get EINVAL when the timeout is invalid, but we ignore this case here * and assume that EINVAL always means: you have to wait manually. */ if (errno == EINVAL) { SXEL81("ev_sleep(timeout=%f)", timeout); ev_sleep (timeout); SXER80("return // errno == EINVAL"); return; } #endif if (errno == EBADF) fd_ebadf (EV_A); else if (errno == ENOMEM && !syserr_cb) fd_enomem (EV_A); else if (errno != EINTR) ev_syserr ("(libev) select"); SXER80("return // expect_false (res < 0)"); return; } #if EV_SELECT_USE_FD_SET { int fd; SXEL80("#if EV_SELECT_USE_FD_SET"); for (fd = 0; fd < anfdmax; ++fd) if (anfds [fd].events) { int events = 0; #if EV_SELECT_IS_WINSOCKET SOCKET handle = anfds [fd].handle; #else int handle = fd; #endif if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ; if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE; #ifdef _WIN32 if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE; #endif if (expect_true (events)) fd_event (EV_A_ fd, events); } SXEL80("#endif // EV_SELECT_USE_FD_SET"); } #else { int word, bit; SXEL80("#if *not* EV_SELECT_USE_FD_SET"); for (word = vec_max; word--; ) { fd_mask word_r = ((fd_mask *)vec_ro) [word]; fd_mask word_w = ((fd_mask *)vec_wo) [word]; #ifdef _WIN32 word_w |= ((fd_mask *)vec_eo) [word]; #endif if (word_r || word_w) for (bit = NFDBITS; bit--; ) { fd_mask mask = 1UL << bit; int events = 0; events |= word_r & mask ? EV_READ : 0; events |= word_w & mask ? EV_WRITE : 0; if (expect_true (events)) fd_event (EV_A_ word * NFDBITS + bit, events); } } SXEL80("#endif // *not* EV_SELECT_USE_FD_SET"); } #endif SXER80("return"); }