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); }
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; }
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); }
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); }
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); }
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); }
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; }
static uint32_t sys_sem_post(uint32_t arg[]) { sem_t sem_id = (sem_t) arg[0]; return ipc_sem_post(sem_id); }
void sys_sem_signal(sys_sem_t sem) { ipc_sem_post(sem); }
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); }
/* * 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); }