void cache_wait(AbstractCache * cache) { #else void cache_wait_dbg(const char * file, int line, AbstractCache * cache) { #endif assert(is_dispatch_thread()); assert(current_client.client != NULL); if (current_client.client != NULL) { current_cache = cache; cache_miss_cnt++; #ifndef NDEBUG current_client.file = file; current_client.line = line; current_client.time_stamp = time(NULL); if (!cache_timer_posted) { post_event_with_delay(cache_timer, NULL, 5000000); cache_timer_posted = 1; } #endif } #ifndef NDEBUG else { trace(LOG_ALWAYS, "Illegal cache access at %s:%d", file, line); } #endif exception(ERR_CACHE_MISS); }
static ChannelServer * channel_server_create(PeerServer * ps, noPollCtx * np_ctx, noPollConn * np_listener, int is_ssl) { ServerNP * si = (ServerNP *)loc_alloc_zero(sizeof *si); /* TODO: need to investigate usage of sizeof(sockaddr_storage) for address buffer size */ si->serv.close = server_close; si->sock = nopoll_conn_socket(np_listener); si->serv.ps = ps; if (server_list.next == NULL) { list_init(&server_list); post_event_with_delay(refresh_all_peer_servers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000); } list_add_last(&si->serv.servlink, &channel_server_root); shutdown_set_normal(&channel_shutdown); list_add_last(&si->servlink, &server_list); refresh_peer_server(si->sock, ps); si->accreq.done = np_server_accept_done; si->accreq.u.user.data = si; si->accreq.u.user.func = np_wt_accept; si->accreq.client_data = si; si->accreq.type = AsyncReqUser; si->np_listener = np_listener; si->np_ctx = np_ctx; si->is_ssl = is_ssl; async_req_post(&si->accreq); return &si->serv; }
static int lua_post_event(lua_State *L) { struct post_event_extra *p; unsigned long delay; assert(L == luastate); if(lua_gettop(L) > 2 || !lua_isfunction(L, 1) || (lua_gettop(L) > 1 && !(lua_isnil(L, 2) || lua_isnumber(L, 2)))) { luaL_error(L, "wrong number or type of arguments"); } p = (struct post_event_extra *)lua_newuserdata(L, sizeof *p); memset(p, 0, sizeof *p); p->L = L; lua_pushvalue(L, -1); p->self_refp = luaref_new(L, p); lua_pushvalue(L, 1); p->handler_refp = luaref_new(L, p); trace(LOG_LUA, "lua_post_event %d", p->handler_refp); luaL_getmetatable(L, "tcf_post_event"); lua_setmetatable(L, -2); delay = lua_tointeger(L, 2); if(delay == 0) { post_event(lua_post_event_cb, p); } else { post_event_with_delay(lua_post_event_cb, p, delay); } return 1; }
static void np_write_stream(OutputStream * out, int byte) { ChannelNP * c = channel2np(out2channel(out)); assert(c->magic == CHANNEL_MAGIC); if (!c->chan.out.supports_zero_copy || c->chan.out.cur >= c->chan.out.end - 32 || byte < 0) { if (c->out_bin_block != NULL) np_bin_block_end(c); if (c->chan.out.cur == c->chan.out.end) np_flush_with_flags(c, MSG_MORE); if (byte < 0 || byte == ESC) { char esc = 0; *c->chan.out.cur++ = ESC; if (byte == ESC) esc = 0; else if (byte == MARKER_EOM) esc = 1; else if (byte == MARKER_EOS) esc = 2; else assert(0); if (c->chan.out.cur == c->chan.out.end) np_flush_with_flags(c, MSG_MORE); *c->chan.out.cur++ = esc; if (byte == MARKER_EOM) { c->out_eom_cnt++; if (c->out_flush_cnt < 2) { if (c->out_flush_cnt++ == 0) np_lock(&c->chan); post_event_with_delay(np_flush_event, c, 0); } } return; } } else if (c->out_bin_block == NULL) { np_bin_block_start(c); } *c->chan.out.cur++ = (char)byte; }
static void clear_stale_peers(void * x) { PeerServer ** sp = &peers; PeerServer * s; time_t timenow = time(NULL); int keep_timer = 0; assert(is_dispatch_thread()); while ((s = *sp) != NULL) { if (s->expiration_time <= timenow) { /* Delete stale entry */ *sp = s->next; notify_listeners(s, PS_EVENT_REMOVED); s->listed = 0; peer_server_free(s); } else { keep_timer = 1; sp = &s->next; } } if (keep_timer) { post_event_with_delay(clear_stale_peers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000); } else { stale_timer_active = 0; } }
static void refresh_all_peer_servers(void * x) { LINK * l = server_list.next; while (l != &server_list) { ServerNP * si = servlink2np(l); refresh_peer_server(si->sock, si->serv.ps); l = l->next; } post_event_with_delay(refresh_all_peer_servers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000); }
static void check_idle_timeout(void * args) { if (list_is_empty(&channel_root)) { idle_count++; if (idle_count > idle_timeout) { trace(LOG_ALWAYS, "No connections for %d seconds, shutting down", idle_timeout); discovery_stop(); cancel_event_loop(); return; } } post_event_with_delay(check_idle_timeout, NULL, 1000000); }
void cache_wait(AbstractCache * cache) { #else void cache_wait_dbg(const char * file, int line, AbstractCache * cache) { #endif assert(is_dispatch_thread()); assert(client_exited == 0); if (current_client.client != NULL && cache_miss_cnt == 0) { if (cache->wait_list_cnt >= cache->wait_list_max) { cache->wait_list_max += 8; cache->wait_list_buf = (WaitingCacheClient *)loc_realloc(cache->wait_list_buf, cache->wait_list_max * sizeof(WaitingCacheClient)); } if (current_client.args != NULL && !current_client.args_copy) { void * mem = loc_alloc(current_client.args_size); memcpy(mem, current_client.args, current_client.args_size); current_client.args = mem; current_client.args_copy = 1; } #ifndef NDEBUG current_client.file = file; current_client.line = line; current_client.time_stamp = time(NULL); if (!cache_timer_posted) { post_event_with_delay(cache_timer, NULL, 5000000); cache_timer_posted = 1; } #endif if (cache->wait_list_cnt == 0) list_add_last(&cache->link, &cache_list); if (current_client.channel != NULL) channel_lock_with_msg(current_client.channel, channel_lock_msg); cache->wait_list_buf[cache->wait_list_cnt++] = current_client; } #ifndef NDEBUG else if (current_client.client == NULL) { trace(LOG_ALWAYS, "Illegal cache access at %s:%d", file, line); } #endif cache_miss_cnt++; exception(ERR_CACHE_MISS); }
static void cache_timer(void * x) { LINK * l; time_t time_now = time(NULL); assert(cache_timer_posted); cache_timer_posted = 0; for (l = cache_list.next; l != &cache_list; l = l->next) { unsigned i; AbstractCache * cache = link_all2cache(l); assert(cache->wait_list_cnt > 0); for (i = 0; i < cache->wait_list_cnt; i++) { WaitingCacheClient * client = cache->wait_list_buf + i; if (time_now - client->time_stamp >= 30) { /* Client is waiting longer than 30 sec - it might be a bug */ trace(LOG_ALWAYS, "Stalled cache at %s:%d", client->file, client->line); } } } if (!list_is_empty(&cache_list)) { post_event_with_delay(cache_timer, NULL, 5000000); cache_timer_posted = 1; } }
static void pipe_write_stream(OutputStream * out, int byte) { ChannelPIPE * c = channel2pipe(out2channel(out)); assert(c->magic == CHANNEL_MAGIC); if (c->chan->state == ChannelStateDisconnected) return; if (c->chan->out.cur == c->chan->out.end) pipe_flush(c); if (byte < 0 || byte == ESC) { char esc = 0; *c->chan->out.cur++ = ESC; if (byte == ESC) esc = 0; else if (byte == MARKER_EOM) esc = 1; else if (byte == MARKER_EOS) esc = 2; else assert(0); if (c->chan->state == ChannelStateDisconnected) return; if (c->chan->out.cur == c->chan->out.end) pipe_flush(c); *c->chan->out.cur++ = esc; if (byte == MARKER_EOM && c->out_flush_cnt < 2) { if (c->out_flush_cnt++ == 0) pipe_lock(c->chan); post_event_with_delay(pipe_flush_event, c, 0); } return; } *c->chan->out.cur++ = (char)byte; }
PeerServer * peer_server_add(PeerServer * n, unsigned int stale_delta) { PeerServer ** sp = &peers; PeerServer * s; int type = PS_EVENT_ADDED; assert(!n->listed); assert(is_dispatch_thread()); while ((s = *sp) != NULL) { if (strcmp(s->id, n->id) == 0) { if (((s->flags & PS_FLAG_LOCAL) && !(n->flags & PS_FLAG_LOCAL)) || is_same(s, n)) { /* Never replace local entries with discovered ones */ s->expiration_time = time(NULL) + stale_delta; if (!(s->flags & PS_FLAG_LOCAL)) s->flags = n->flags; peer_server_free(n); notify_listeners(s, PS_EVENT_HEART_BEAT); return s; } *sp = s->next; s->listed = 0; peer_server_free(s); type = PS_EVENT_CHANGED; break; } sp = &s->next; } n->listed = 1; n->creation_time = time(NULL); n->expiration_time = n->creation_time + stale_delta; n->next = peers; peers = n; notify_listeners(n, type); if (!stale_timer_active) { stale_timer_active = 1; post_event_with_delay(clear_stale_peers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000); } return n; }
static void port_connection_close(PortConnection * conn) { PortServer * server = conn->server; PortConnection * prev; port_connection_unbind(conn); if (conn->connected) { if (server->disconnect_callback) server->disconnect_callback(server, server->callback_data); disconnect_port(conn); conn->connected = 0; return; } if (conn->lock_cnt > 0) return; if (server->list == conn) server->list = conn->next; else { prev = server->list; while (prev->next != conn) prev = prev->next; assert (prev->next == conn); prev->next = conn->next; } loc_free(conn); /* If the last port connection has been closed and server shutdown is * in progress, complete it. */ if (server->list == NULL) { if (server->sock == -1) { port_server_shutdown(server); } else if (server->auto_connect) { /* Retry target connection */ post_event_with_delay(port_connection_open_event, server, server->auto_connect_period * 1000000); } } }
static void run_safe_events(void * arg) { LINK * qp; pid_t mem; if ((uintptr_t)arg != safe_event_generation) return; assert(safe_event_list != NULL); assert(are_channels_suspended(suspend_group)); safe_event_pid_count = 0; mem = safe_event_list->mem; for (qp = context_root.next; qp != &context_root; qp = qp->next) { Context * ctx = ctxl2ctxp(qp); if (ctx->exited || ctx->exiting || ctx->stopped || !context_has_state(ctx)) { ctx->pending_safe_event = 0; continue; } if (mem > 0 && ctx->mem != mem) { ctx->pending_safe_event = 0; continue; } if (!ctx->pending_step || ctx->pending_safe_event >= STOP_ALL_MAX_CNT / 2) { if (context_stop(ctx) < 0) { int error = errno; #ifdef _WRS_KERNEL if (error == S_vxdbgLib_INVALID_CTX) { /* Most often this means that context has exited, * but exit event is not delivered yet. * Not an error. */ error = 0; } #endif if (error) { trace(LOG_ALWAYS, "error: can't temporary stop pid %d; error %d: %s", ctx->pid, error, errno_to_str(error)); } } assert(!ctx->stopped); } if (ctx->pending_safe_event >= STOP_ALL_MAX_CNT) { trace(LOG_ALWAYS, "error: can't temporary stop pid %d; error: timeout", ctx->pid); ctx->exiting = 1; ctx->pending_safe_event = 0; } else { ctx->pending_safe_event++; safe_event_pid_count++; } } while (safe_event_list) { Trap trap; SafeEvent * i = safe_event_list; assert((uintptr_t)arg == safe_event_generation); if (safe_event_pid_count > 0) { post_event_with_delay(run_safe_events, (void *)++safe_event_generation, STOP_ALL_TIMEOUT); return; } if (mem > 0 && i->mem != mem) { post_event(run_safe_events, (void *)++safe_event_generation); return; } assert(is_all_stopped(i->mem)); safe_event_list = i->next; if (set_trap(&trap)) { i->done(i->arg); clear_trap(&trap); } else { trace(LOG_ALWAYS, "Unhandled exception in \"safe\" event dispatch: %d %s", trap.error, errno_to_str(trap.error)); } loc_free(i); if ((uintptr_t)arg != safe_event_generation) return; } channels_resume(suspend_group); cmdline_resume(); /* Lazily continue execution of temporary stopped contexts */ post_event(continue_temporary_stopped, (void *)safe_event_generation); }