예제 #1
0
파일: connection.c 프로젝트: xaiki/IceCast
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;
}
예제 #2
0
파일: queue.c 프로젝트: breezechen/zevent
/**
 * 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;
}
예제 #3
0
파일: queue.c 프로젝트: breezechen/zevent
/**
 * 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;
}
예제 #4
0
파일: connection.c 프로젝트: xaiki/IceCast
/* 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);
}
예제 #5
0
파일: queue.c 프로젝트: breezechen/zevent
/**
 * 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;
}
예제 #6
0
파일: pthread.c 프로젝트: kstraube/hysim
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;
}
예제 #7
0
파일: queue.c 프로젝트: breezechen/zevent
/**
 * 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;
}
예제 #8
0
파일: sys_thread.c 프로젝트: tnodir/luasys
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
}
예제 #9
0
/**
 * @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;
}
예제 #10
0
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;
}
예제 #11
0
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;
}
예제 #12
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;
}
예제 #13
0
파일: runner.c 프로젝트: miksago/icecast
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;
}
예제 #14
0
파일: sys_thread.c 프로젝트: tnodir/luasys
/*
 * 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;
}
예제 #15
0
inline void tuple_fifo::ensure_writer_running() {
    thread_cond_signal(_writer_notify);
}
예제 #16
0
/*
 * 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 */
}
예제 #17
0
/*
 * 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;
}