void connection_shutdown(void) { if (!_initialized) return; _connection_running = 0; thread_cond_signal(_connection_cond); DEBUG0 ("waiting for connection thread"); thread_join(_connection_thread_id); #ifdef HAVE_OPENSSL SSL_CTX_free (ssl_ctx); #endif if (banned_ip.contents) avl_tree_free (banned_ip.contents, free_filtered_ip); if (allowed_ip.contents) avl_tree_free (allowed_ip.contents, free_filtered_ip); thread_cond_destroy (_connection_cond); free (_connection_cond); thread_cond_destroy(&global.shutdown_cond); thread_rwlock_destroy(&_source_shutdown_rwlock); thread_spin_destroy (&_connection_lock); thread_mutex_destroy(&move_clients_mutex); _initialized = 0; }
/** * Push new data onto the queue. If the queue is full, return QUEUE_EAGAIN. If * the push operation completes successfully, it signals other threads * waiting in queue_pop() that they may continue consuming sockets. */ int queue_trypush(queue_t *queue, void *data) { int rv; if (queue->terminated) { return QUEUE_EOF; /* no more elements ever again */ } rv = thread_mutex_lock(queue->one_big_mutex); if (rv != 0) { return rv; } if (queue_full(queue)) { rv = thread_mutex_unlock(queue->one_big_mutex); return QUEUE_EAGAIN; } queue->data[queue->in] = data; queue->in = (queue->in + 1) % queue->bounds; queue->nelts++; if (queue->empty_waiters) { rv = thread_cond_signal(queue->not_empty); if (rv != 0) { thread_mutex_unlock(queue->one_big_mutex); return rv; } } rv = thread_mutex_unlock(queue->one_big_mutex); return rv; }
/** * Retrieves the next item from the queue. If there are no * items available, return QUEUE_EAGAIN. Once retrieved, * the item is placed into the address specified by 'data'. */ int queue_trypop(queue_t *queue, void **data) { int rv; if (queue->terminated) { return QUEUE_EOF; /* no more elements ever again */ } rv = thread_mutex_lock(queue->one_big_mutex); if (rv != 0) { return rv; } if (queue_empty(queue)) { rv = thread_mutex_unlock(queue->one_big_mutex); return QUEUE_EAGAIN; } *data = queue->data[queue->out]; queue->nelts--; queue->out = (queue->out + 1) % queue->bounds; if (queue->full_waiters) { rv = thread_cond_signal(queue->not_full); if (rv != 0) { thread_mutex_unlock(queue->one_big_mutex); return rv; } } rv = thread_mutex_unlock(queue->one_big_mutex); return rv; }
/* add a connection to connection queue. At this point the connection * has just been accepted, we push it to the queue and return so that * we can keep getting connections in. */ static void _add_connection (connection_queue_t *node) { WARN ("added connection"); *_con_queue_tail = node; _con_queue_tail = (volatile connection_queue_t **)&node->next; thread_cond_signal(_connection_cond); }
/** * Retrieves the next item from the queue. If there are no * items available, it will block until one becomes available. * Once retrieved, the item is placed into the address specified by * 'data'. */ int queue_pop(queue_t *queue, void **data) { int rv; if (queue->terminated) { return QUEUE_EOF; /* no more elements ever again */ } rv = thread_mutex_lock(queue->one_big_mutex); if (rv != 0) { return rv; } /* Keep waiting until we wake up and find that the queue is not empty. */ if (queue_empty(queue)) { if (!queue->terminated) { queue->empty_waiters++; rv = thread_cond_wait(queue->not_empty, queue->one_big_mutex); queue->empty_waiters--; if (rv != 0) { thread_mutex_unlock(queue->one_big_mutex); return rv; } } /* If we wake up and it's still empty, then we were interrupted */ if (queue_empty(queue)) { rv = thread_mutex_unlock(queue->one_big_mutex); if (rv != 0) { return rv; } if (queue->terminated) { return QUEUE_EOF; /* no more elements ever again */ } else { return QUEUE_EINTR; } } } *data = queue->data[queue->out]; queue->nelts--; queue->out = (queue->out + 1) % queue->bounds; if (queue->full_waiters) { rv = thread_cond_signal(queue->not_full); if (rv != 0) { thread_mutex_unlock(queue->one_big_mutex); return rv; } } rv = thread_mutex_unlock(queue->one_big_mutex); return rv; }
int pthread_cond_signal(pthread_cond_t *cond) { if (cond == NULL) return_errno(EINVAL, EINVAL); if (*cond == PTHREAD_COND_INITIALIZER) if (pthread_cond_init(cond, NULL) != OK) return errno; if (!thread_cond_signal((cond_t *)(*cond))) return errno; return OK; }
/** * Push new data onto the queue. Blocks if the queue is full. Once * the push operation has completed, it signals other threads waiting * in queue_pop() that they may continue consuming sockets. */ int queue_push(queue_t *queue, void *data) { int rv; if (queue->terminated) { return QUEUE_EOF; /* no more elements ever again */ } rv = thread_mutex_lock(queue->one_big_mutex); if (rv != 0) { return rv; } if (queue_full(queue)) { if (!queue->terminated) { queue->full_waiters++; rv = thread_cond_wait(queue->not_full, queue->one_big_mutex); queue->full_waiters--; if (rv != 0) { thread_mutex_unlock(queue->one_big_mutex); return rv; } } /* If we wake up and it's still empty, then we were interrupted */ if (queue_full(queue)) { rv = thread_mutex_unlock(queue->one_big_mutex); if (rv != 0) { return rv; } if (queue->terminated) { return QUEUE_EOF; /* no more elements ever again */ } else { return QUEUE_EINTR; } } } queue->data[queue->in] = data; queue->in = (queue->in + 1) % queue->bounds; queue->nelts++; if (queue->empty_waiters) { rv = thread_cond_signal(queue->not_empty); if (rv != 0) { thread_mutex_unlock(queue->one_big_mutex); return rv; } } rv = thread_mutex_unlock(queue->one_big_mutex); return rv; }
void sys_thread_resume (struct sys_thread *td) { lua_assert(td); td->suspended = 0; #ifndef _WIN32 pthread_cond_broadcast(&td->cond); #else (void) thread_cond_signal(&td->cond); #endif }
/** * @brief Both producer and consumer may call this method. This method * is used to notify the "other side" that we are terminating * abnormally. The other side should receive a * TerminatedBufferException on the next tuple_fifo operation. * * If successful, the other end will be notified through an * exception at some point in the future and will be responsible * for deleting the FIFO. The caller must not access the FIFO * again if terminate() returns true. * * @return True if we successfully terminate. False if the other side * has already terminated. */ bool tuple_fifo::terminate() { // * * * BEGIN CRITICAL SECTION * * * critical_section_t cs(_lock); // did the other end beat me to it? Note: if _done_writing is true // the reader is responsible for deleting the buffer; either the // the reader doesn't know yet or the writer is making an illegal // access. False is the right return value for both cases. if(is_terminated() || is_done_writing()) return false; // make sure nobody is sleeping (either the reader or writer could // be calling this) _state.transition(tuple_fifo_state_t::TERMINATED); thread_cond_signal(_reader_notify); thread_cond_signal(_writer_notify); // * * * END CRITICAL SECTION * * * return true; }
static int channel_get (lua_State *L) { struct channel *chan = checkudata(L, 1, CHANNEL_TYPENAME); const msec_t timeout = lua_isnoneornil(L, 2) ? TIMEOUT_INFINITE : (msec_t) lua_tointeger(L, 2); int nput; int idx; int i; lua_settop(L, 1); lua_getfenv(L, 1); /* storage */ lua_insert(L, 1); sys_vm_leave(); thread_critsect_enter(&chan->mutex); thread_cond_signal(&chan->get); /* wait signal */ while (chan->n == 0) { thread_cond_wait(&chan->put, &chan->mutex, timeout); } /* get from storage */ idx = chan->idx + 1; lua_rawgeti(L, 1, idx); nput = lua_tointeger(L, -1); lua_pushnil(L); lua_rawseti(L, 1, idx); chan->idx = idx + nput; for (i = chan->idx; i > idx; --i) { lua_rawgeti(L, 1, i); lua_pushnil(L); lua_rawseti(L, 1, i); } if (chan->idx == chan->top) chan->idx = chan->top = 0; chan->n--; thread_critsect_leave(&chan->mutex); sys_vm_enter(); return nput; }
static int channel_put (lua_State *L) { struct sys_thread *td = sys_get_thread(); struct channel *chan = checkudata(L, 1, CHANNEL_TYPENAME); int nput = lua_gettop(L) - 1; if (!td) luaL_argerror(L, 0, "Threading not initialized"); if (!nput) luaL_argerror(L, 2, "data expected"); lua_getfenv(L, 1); /* get the storage table */ lua_insert(L, 1); sys_vm_leave(); thread_critsect_enter(&chan->mutex); thread_cond_signal(&chan->put); /* move the data to storage */ { int top = chan->top; lua_pushinteger(L, nput); do { lua_rawseti(L, 1, ++top); } while (nput--); chan->top = top; chan->n++; } while (chan->n > chan->max) { thread_cond_wait(&chan->get, &chan->mutex, TIMEOUT_INFINITE); } thread_critsect_leave(&chan->mutex); sys_vm_enter(); return 0; }
int main(void) { int rv; thread_mutex_t *thread_mutex = NULL; thread_cond_t *thread_cond = NULL; thread_mutex_create(&thread_mutex,THREAD_MUTEX_DEFAULT); thread_cond_create(&thread_cond); rv = thread_cond_signal(thread_cond); rv = thread_mutex_lock(thread_mutex); rv = thread_cond_timedwait(thread_cond, thread_mutex, 10000); printf("rv:%d\n",rv); rv = thread_mutex_unlock(thread_mutex); rv = thread_cond_broadcast(thread_cond); rv = thread_mutex_lock(thread_mutex); rv = thread_cond_timedwait(thread_cond, thread_mutex, 10000); rv = thread_mutex_unlock(thread_mutex); thread_cond_destroy(thread_cond); thread_mutex_destroy(thread_mutex); return 0; }
int send_to_runner (struct runner *run, input_buffer *buffer) { if (run) { buffer->next = NULL; #ifdef USE_PIPES if (write (run->fd[1], &buffer, sizeof (buffer)) < (ssize_t)sizeof (buffer)) { LOG_WARN0 ("unable to write to runner"); return -1; } #else *run->pending_tail = buffer; run->pending_tail = &buffer->next; thread_cond_signal (&run->data_available); #endif return 0; } input_free_buffer (buffer); return 0; }
/* * Arguments: [status (number)] */ static THREAD_FUNC_RES thread_exit (struct sys_thread *td) { struct sys_thread *reftd = td->reftd; const int is_vm = thread_isvm(td); lua_Integer res; td->sched_ctx = NULL; if (td->flags != SYS_THREAD_KILLED) { td->flags = SYS_THREAD_KILLED; td->exit_status = lua_tointeger(td->L, -1); } res = td->exit_status; if (is_vm) { thread_waitvm(td->vmtd, TIMEOUT_INFINITE); lua_close(td->L); } else { struct sys_thread *vmtd = thread_getvm(td); #ifndef _WIN32 pthread_cond_broadcast(&td->cond); #endif /* stop collector to prevent self-deadlock on GC */ lua_gc(vmtd->L, LUA_GCSTOP, 0); sys_thread_del(td); lua_gc(vmtd->L, LUA_GCRESTART, 0); sys_vm2_leave(vmtd); } /* decrease VM-thread's reference count */ if (reftd) { struct sys_vmthread *vmref = reftd->vmtd; sys_vm2_enter(reftd); if (is_vm) { reftd->flags = SYS_THREAD_KILLED; reftd->exit_status = res; #ifndef _WIN32 pthread_cond_broadcast(&reftd->cond); #endif sys_thread_del(reftd); } if (!--vmref->nref) { #ifndef _WIN32 pthread_cond_broadcast(&vmref->td.cond); #else (void) thread_cond_signal(&vmref->td.cond); #endif } sys_vm2_leave(reftd); } #ifndef _WIN32 pthread_exit((THREAD_FUNC_RES) res); #else _endthreadex((THREAD_FUNC_RES) res); #endif return 0; }
inline void tuple_fifo::ensure_writer_running() { thread_cond_signal(_writer_notify); }
/* * Arguments: pipe_udata, [timeout (milliseconds)] * Returns: [pipe_udata | timedout (false), message_items (any) ...] */ static int pipe_get (lua_State *L) { struct sys_thread *td = sys_thread_get(); struct pipe *pp = lua_unboxpointer(L, 1, PIPE_TYPENAME); const msec_t timeout = lua_isnoneornil(L, 2) ? TIMEOUT_INFINITE : (msec_t) lua_tointeger(L, 2); thread_critsect_t *csp = pipe_critsect_ptr(pp); struct message msg; if (!td) luaL_argerror(L, 0, "Threading not initialized"); /* read message from buffer */ thread_critsect_enter(csp); for (; ; ) { if (pp->nmsg) { struct pipe_buf *pb = pp->rbuf; struct pipe_buf buf = *pb; struct message *mp = pipe_buf_ptr(pb, buf.begin); if (!mp->size) { /* buffer is wrapped */ mp = pipe_buf_ptr(pb, 0); buf.begin = 0; } memcpy(&msg, mp, mp->size); buf.begin += mp->size; if (buf.begin == buf.end) { buf.begin = buf.end = 0; if (pp->nmsg > 1) pp->rbuf = buf.next_buf; } else if (buf.begin == buf.len) { buf.begin = 0; } *pb = buf; if (--pp->nmsg && pp->signal_on_put) { (void) thread_cond_signal(&pp->put_cond); } } else { /* wait `put' signal */ int res; pp->signal_on_put++; res = pipe_cond_wait(&pp->put_cond, csp, td, timeout); pp->signal_on_put--; if (!res) continue; thread_critsect_leave(csp); sys_thread_check(td); if (res == 1) { lua_pushboolean(L, 0); return 1; /* timed out */ } return sys_seterror(L, 0); } break; } if (pp->signal_on_get) { (void) thread_cond_signal(&pp->get_cond); } thread_critsect_leave(csp); lua_settop(L, 1); return 1 + pipe_msg_parse(L, &msg); /* deconstruct the message */ }
/* * Arguments: pipe_udata, message_items (any) ... * Returns: [pipe_udata | timedout (false)] */ static int pipe_put (lua_State *L) { struct sys_thread *td = sys_thread_get(); struct pipe_ref *pr = checkudata(L, 1, PIPE_TYPENAME); struct pipe *pp = pr->pipe; thread_critsect_t *csp = pipe_critsect_ptr(pp); struct message msg; if (!td) luaL_argerror(L, 0, "Threading not initialized"); pipe_msg_build(L, &msg, 2); /* construct the message */ /* write message to buffer */ thread_critsect_enter(csp); for (; ; ) { struct pipe_buf *pb = pp->wbuf; struct pipe_buf buf = *pb; const int wrapped = (buf.end < buf.begin); const unsigned int len = (wrapped ? buf.begin : buf.len) - buf.end; if (msg.size > len) { if (!wrapped && buf.begin > msg.size) { /* wrap the buffer */ struct message *mp = pipe_buf_ptr(pb, buf.end); mp->size = 0; /* sentinel tag */ buf.end = 0; } else if (pb != buf.next_buf && !buf.next_buf->begin && !buf.next_buf->end) { /* use next free buffer */ pb = pp->wbuf = buf.next_buf; buf = *pb; } else { const unsigned int buf_size = pp->buf_size; struct pipe_buf *wpb = (2 * buf_size <= pp->buf_max_size) ? malloc(buf_size) : NULL; if (wpb) { /* allocate new buffer */ buf.begin = buf.end = 0; buf.len = buf_size - PIPE_BUF_EXTRASIZE; /* buf->next_buf is already correct */ pb->next_buf = wpb; pp->buf_size = buf_size * 2; pp->wbuf = wpb; pb = wpb; } else { /* wait `get' signal */ int res; pp->signal_on_get++; res = pipe_cond_wait(&pp->get_cond, csp, td, pr->put_timeout); if (--pp->signal_on_get) { (void) thread_cond_signal(&pp->get_cond); } if (!res) continue; thread_critsect_leave(csp); sys_thread_check(td); if (res == 1) { lua_pushboolean(L, 0); return 1; /* timed out */ } return sys_seterror(L, 0); } } } memcpy(pipe_buf_ptr(pb, buf.end), &msg, msg.size); buf.end += msg.size; *pb = buf; pp->nmsg++; break; } if (pp->signal_on_put) { (void) thread_cond_signal(&pp->put_cond); } thread_critsect_leave(csp); lua_settop(L, 1); return 1; }