Exemplo n.º 1
0
static cs_error_t
msg_send (
	struct ipc_instance *ipc_instance,
	const struct iovec *iov,
	unsigned int iov_len)
{
	int i;
	int res;
	int req_buffer_idx = 0;

	for (i = 0; i < iov_len; i++) {
		if ((req_buffer_idx + iov[i].iov_len) > 
			ipc_instance->request_size) {
			return (CS_ERR_INVALID_PARAM);
		}
		memcpy (&ipc_instance->request_buffer[req_buffer_idx],
			iov[i].iov_base,
			iov[i].iov_len);
		req_buffer_idx += iov[i].iov_len;
	}

	/*
	 * Signal semaphore #3 and #0 indicting a new message from client
	 * to server request queue
	 */
	res = ipc_sem_post (ipc_instance->control_buffer, SEMAPHORE_REQUEST);
	if (res != CS_OK) {
		return (CS_ERR_LIBRARY);
	}
	res = ipc_sem_post (ipc_instance->control_buffer, SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT);
	if (res != CS_OK) {
		return (CS_ERR_LIBRARY);
	}
	return (CS_OK);
}
Exemplo n.º 2
0
int ipc_read(void* buff, size_t len) {

    int res;
    struct Queue* queue = me->queue;
    struct Entry* entry;

    ipc_sem_wait(queue->readWait);
    sem_wait(me->lock);
    assert_sems(me);

    entry = &(queue->slots[queue->index[0]]);
    if (len > entry->len) {
        res = entry->len;
    } else {
        res = len;
    }
    memcpy(buff, entry->content, res);

    entry->len = 0;
    for (size_t i = 1; i < ENTRIES_PER_QUEUE; i++) {
        queue->index[i - 1] = queue->index[i];
        queue->index[i] = -1;
    }

    sem_post(me->lock);
    ipc_sem_post(queue->writeSem);

    return res;
}
Exemplo n.º 3
0
static void msg_send (void *conn, const struct iovec *iov, unsigned int iov_len,
		      int locked)
{
	struct conn_info *conn_info = (struct conn_info *)conn;
	int res;
	int i;
	char buf;

	for (i = 0; i < iov_len; i++) {
		memcpy_dwrap (conn_info, iov[i].iov_base, iov[i].iov_len);
	}

	buf = list_empty (&conn_info->outq_head);
	res = send (conn_info->fd, &buf, 1, MSG_NOSIGNAL);
	if (res != 1) {
		conn_info->pending_semops += 1;
		if (conn_info->poll_state == POLL_STATE_IN) {
			conn_info->poll_state = POLL_STATE_INOUT;
			api->poll_dispatch_modify (conn_info->fd,
				POLLIN|POLLOUT|POLLNVAL);
		}
	}

	ipc_sem_post (conn_info->control_buffer, SEMAPHORE_DISPATCH);
}
Exemplo n.º 4
0
int coroipcs_response_send (void *conn, const void *msg, size_t mlen)
{
	struct conn_info *conn_info = (struct conn_info *)conn;

	memcpy (conn_info->response_buffer, msg, mlen);

	ipc_sem_post (conn_info->control_buffer, SEMAPHORE_RESPONSE);

	api->stats_increment_value (conn_info->stats_handle, "responses");
	return (0);
}
Exemplo n.º 5
0
static void ipc_disconnect (struct conn_info *conn_info)
{
	if (conn_info->state == CONN_STATE_THREAD_INACTIVE) {
		conn_info->state = CONN_STATE_DISCONNECT_INACTIVE;
		return;
	}
	if (conn_info->state != CONN_STATE_THREAD_ACTIVE) {
		return;
	}
	pthread_mutex_lock (&conn_info->mutex);
	conn_info->state = CONN_STATE_THREAD_REQUEST_EXIT;
	pthread_mutex_unlock (&conn_info->mutex);

	ipc_sem_post (conn_info->control_buffer, SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT);
}
Exemplo n.º 6
0
int coroipcs_response_iov_send (void *conn, const struct iovec *iov, unsigned int iov_len)
{
	struct conn_info *conn_info = (struct conn_info *)conn;
	int write_idx = 0;
	int i;

	for (i = 0; i < iov_len; i++) {
		memcpy (&conn_info->response_buffer[write_idx],
			iov[i].iov_base, iov[i].iov_len);
		write_idx += iov[i].iov_len;
	}

	ipc_sem_post (conn_info->control_buffer, SEMAPHORE_RESPONSE);

	api->stats_increment_value (conn_info->stats_handle, "responses");
	return (0);
}
Exemplo n.º 7
0
int ipc_write(ipc_t conn, const void* buff, size_t len) {
    size_t slot, i;
    struct Queue* queue = conn->queue;
    struct Entry* entry;

    ipc_sem_wait(queue->writeSem);
    sem_wait(conn->lock);
    assert_sems(conn);

    // If we got this far, we know we have a place to write on!
    for (slot = 0; slot < ENTRIES_PER_QUEUE; slot++) {
        if (queue->slots[slot].len == 0) {
            break;
        }
    }

    for (i = 0; i < ENTRIES_PER_QUEUE; i++) {
        if (queue->index[i] == -1) {
            break;
        }
    }
    // I could sanity check those values, and I also could start working out.
    if (slot == ENTRIES_PER_QUEUE) {
        print_error("[%s] Trying to write to invalid slot\n", conn->name);
    }
    if (i == ENTRIES_PER_QUEUE) {
        print_error("[%s] Trying to write to invalid index entry\n", conn->name);
    }

    queue->index[i] = slot;
    entry = &queue->slots[slot];
    if (len > IPC_MAX_PACKET_LEN) {
        len = IPC_MAX_PACKET_LEN;
        print_error("[%s] Trying to write something bigger than max packet len\n", conn->name);
    }
    entry->len = len;
    memcpy(entry->content, buff, len);

    sem_post(conn->lock);
    ipc_sem_post(queue->readWait);

    return len;
}
Exemplo n.º 8
0
static uint32_t sys_sem_post(uint32_t arg[])
{
	sem_t sem_id = (sem_t) arg[0];
	return ipc_sem_post(sem_id);
}
Exemplo n.º 9
0
void sys_sem_signal(sys_sem_t sem)
{
	ipc_sem_post(sem);
}
Exemplo n.º 10
0
cs_error_t
coroipcc_dispatch_get (
	hdb_handle_t handle,
	void **data,
	int timeout)
{
	struct pollfd ufds;
	int poll_events;
	char buf;
	struct ipc_instance *ipc_instance;
	char *data_addr;
	cs_error_t error = CS_OK;
	int res;

	error = hdb_error_to_cs (hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance));
	if (error != CS_OK) {
		return (error);
	}

	if (shared_mem_dispatch_bytes_left (ipc_instance) > (ipc_instance->dispatch_size/2)) {
		/*
		 * Notify coroipcs to flush any pending dispatch messages
		 */
		res = ipc_sem_post (ipc_instance->control_buffer, SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT);
		if (res != CS_OK) {
			error = CS_ERR_LIBRARY;
			goto error_put;
		}
	}

	*data = NULL;

	ufds.fd = ipc_instance->fd;
	ufds.events = POLLIN;
	ufds.revents = 0;

	poll_events = poll (&ufds, 1, timeout);
	if (poll_events == -1 && errno == EINTR) {
		error = CS_ERR_TRY_AGAIN;
		goto error_put;
	} else
	if (poll_events == -1) {
		error = CS_ERR_LIBRARY;
		goto error_put;
	} else
	if (poll_events == 0) {
		error = CS_ERR_TRY_AGAIN;
		goto error_put;
	}
	if (poll_events == 1 && (ufds.revents & (POLLERR|POLLHUP))) {
		error = CS_ERR_LIBRARY;
		goto error_put;
	}

	error = socket_recv (ipc_instance->fd, &buf, 1);
#if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
	/* On many OS poll() never returns POLLHUP or POLLERR.
	 * EOF is detected when recvmsg() return 0.
	 */
	if ( error == CS_ERR_LIBRARY )
		goto error_put;
#endif
	assert (error == CS_OK);

	if (shared_mem_dispatch_bytes_left (ipc_instance) > (ipc_instance->dispatch_size/2)) {
		/*
		 * Notify coroipcs to flush any pending dispatch messages
		 */
		
		res = ipc_sem_post (ipc_instance->control_buffer, SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT);
		if (res != CS_OK) {
			error = CS_ERR_LIBRARY;
			goto error_put;
		}


	}

	data_addr = ipc_instance->dispatch_buffer;

	data_addr = &data_addr[ipc_instance->control_buffer->read];

	*data = (void *)data_addr;

	return (CS_OK);
error_put:
	hdb_handle_put (&ipc_hdb, handle);
	return (error);
}
Exemplo n.º 11
0
/*
 * returns 0 if should be called again, -1 if finished
 */
static inline int conn_info_destroy (struct conn_info *conn_info)
{
	unsigned int res;
	void *retval;

	list_del (&conn_info->list);
	list_init (&conn_info->list);
	list_add (&conn_info->list, &conn_info_exit_list_head);

	if (conn_info->state == CONN_STATE_THREAD_REQUEST_EXIT) {
		res = pthread_join (conn_info->thread, &retval);
		conn_info->state = CONN_STATE_THREAD_DESTROYED;
		return (0);
	}

	if (conn_info->state == CONN_STATE_THREAD_INACTIVE ||
		conn_info->state == CONN_STATE_DISCONNECT_INACTIVE) {
		list_del (&conn_info->list);
		close (conn_info->fd);
		api->free (conn_info);
		return (-1);
	}

	if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
		ipc_sem_post (conn_info->control_buffer, SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT);
		return (0);
	}

	/*
	 * Retry library exit function if busy
	 */
	if (conn_info->state == CONN_STATE_THREAD_DESTROYED) {
		api->serialize_lock ();
		res = api->exit_fn_get (conn_info->service) (conn_info);
		api->serialize_unlock ();
		api->stats_destroy_connection (conn_info->stats_handle);
		if (res == -1) {
			return (0);
		} else {
			conn_info->state = CONN_STATE_LIB_EXIT_CALLED;
		}
	}

	pthread_mutex_lock (&conn_info->mutex);
	if (conn_info->refcount > 0) {
		pthread_mutex_unlock (&conn_info->mutex);
		return (0);
	}
	list_del (&conn_info->list);
	pthread_mutex_unlock (&conn_info->mutex);

	/*
	 * Let library know, that connection is now closed
	 */
	conn_info->control_buffer->ipc_closed = 1;
	ipc_sem_post (conn_info->control_buffer, SEMAPHORE_RESPONSE);
	ipc_sem_post (conn_info->control_buffer, SEMAPHORE_DISPATCH);

#if _POSIX_THREAD_PROCESS_SHARED > 0
	sem_destroy (&conn_info->control_buffer->sem_request_or_flush_or_exit);
	sem_destroy (&conn_info->control_buffer->sem_request);
	sem_destroy (&conn_info->control_buffer->sem_response);
	sem_destroy (&conn_info->control_buffer->sem_dispatch);
#else
	semctl (conn_info->control_buffer->semid, 0, IPC_RMID);
#endif
	/*
	 * Destroy shared memory segment and semaphore
	 */
	res = munmap ((void *)conn_info->control_buffer, conn_info->control_size);
	res = munmap ((void *)conn_info->request_buffer, conn_info->request_size);
	res = munmap ((void *)conn_info->response_buffer, conn_info->response_size);

	/*
	 * Free allocated data needed to retry exiting library IPC connection
	 */
	if (conn_info->private_data) {
		api->free (conn_info->private_data);
	}
	close (conn_info->fd);
	res = circular_memory_unmap (conn_info->dispatch_buffer, conn_info->dispatch_size);
	zcb_all_free (conn_info);
	api->free (conn_info);
	return (-1);
}