static cs_error_t reply_receive ( struct ipc_instance *ipc_instance, void *res_msg, size_t res_len) { coroipc_response_header_t *response_header; cs_error_t res; retry_ipc_sem_wait: res = ipc_sem_wait (ipc_instance->control_buffer, SEMAPHORE_RESPONSE, ipc_instance->fd); if (res != CS_OK) { if (res == CS_ERR_TRY_AGAIN) { priv_change_send (ipc_instance); goto retry_ipc_sem_wait; } else { return (res); } } response_header = (coroipc_response_header_t *)ipc_instance->response_buffer; if (response_header->error == CS_ERR_TRY_AGAIN) { return (CS_ERR_TRY_AGAIN); } memcpy (res_msg, ipc_instance->response_buffer, res_len); 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; }
u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) { int ret = ipc_sem_wait(sem, timeout); #ifdef LWIP_ARCH_DEBUG cprintf("[%d] sem: %d ret: %d timeout: %d\n", current->pid, sem, ret, timeout); #endif if (ret == 0) return 0; else return SYS_ARCH_TIMEOUT; }
cs_error_t coroipcc_dispatch_put (hdb_handle_t handle) { coroipc_response_header_t *header; struct ipc_instance *ipc_instance; cs_error_t res; char *addr; unsigned int read_idx; res = hdb_error_to_cs (hdb_handle_get_always (&ipc_hdb, handle, (void **)&ipc_instance)); if (res != CS_OK) { return (res); } retry_ipc_sem_wait: res = ipc_sem_wait (ipc_instance->control_buffer, SEMAPHORE_DISPATCH, ipc_instance->fd); if (res != CS_OK) { if (res == CS_ERR_TRY_AGAIN) { priv_change_send (ipc_instance); goto retry_ipc_sem_wait; } else { goto error_exit; } } addr = ipc_instance->dispatch_buffer; read_idx = ipc_instance->control_buffer->read; header = (coroipc_response_header_t *) &addr[read_idx]; ipc_instance->control_buffer->read = ((read_idx + header->size + 7) & 0xFFFFFFF8) % ipc_instance->dispatch_size; /* * Put from dispatch get and also from this call's get */ res = CS_OK; error_exit: hdb_handle_put (&ipc_hdb, handle); hdb_handle_put (&ipc_hdb, handle); return (res); }
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; }
int do_futex(uintptr_t uaddr, int op, int val) { int ret = 0; if(FUTEX_WAIT == op) { if(*((int*)uaddr) != val) { panic("FUTEX_WAIT: unexpected val, *uaddr = %d, val = %d\n", *((int*)uaddr), val); } sem_t sem_id = ipc_sem_find_or_init_with_address(uaddr, 0, 1); ret = ipc_sem_wait(sem_id, 100000); } else if(FUTEX_WAKE == op) { sem_t sem_id = ipc_sem_find_or_init_with_address(uaddr, val, 0); if(-E_NO_MEM == sem_id) { } else { ret = ipc_sem_post_max(sem_id, val); } } else { panic("unexpected futex op: %d\n", op); } }
static cs_error_t reply_receive_in_buf ( struct ipc_instance *ipc_instance, void **res_msg) { cs_error_t res; retry_ipc_sem_wait: res = ipc_sem_wait (ipc_instance->control_buffer, SEMAPHORE_RESPONSE, ipc_instance->fd); if (res != CS_OK) { if (res == CS_ERR_TRY_AGAIN) { priv_change_send (ipc_instance); goto retry_ipc_sem_wait; } else { return (res); } } *res_msg = (char *)ipc_instance->response_buffer; return (CS_OK); }
static uint32_t sys_sem_wait(uint32_t arg[]) { sem_t sem_id = (sem_t) arg[0]; unsigned int timeout = (unsigned int)arg[1]; return ipc_sem_wait(sem_id, timeout); }
static uint64_t sys_sem_wait(uint64_t arg[]) { sem_t sem_id = (sem_t)arg[0]; return ipc_sem_wait(sem_id); }
static void *pthread_ipc_consumer (void *conn) { struct conn_info *conn_info = (struct conn_info *)conn; int res; coroipc_request_header_t *header; coroipc_response_header_t coroipc_response_header; int send_ok; unsigned int new_message; int sem_value = 0; #if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX) if (api->sched_policy != 0) { res = pthread_setschedparam (conn_info->thread, api->sched_policy, api->sched_param); } #endif for (;;) { ipc_sem_wait (conn_info->control_buffer, SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT, IPC_SEMWAIT_NOFILE); if (ipc_thread_active (conn_info) == 0) { coroipcs_refcount_dec (conn_info); pthread_exit (0); } outq_flush (conn_info); ipc_sem_getvalue (conn_info->control_buffer, SEMAPHORE_REQUEST, &sem_value); if (sem_value > 0) { res = ipc_sem_wait (conn_info->control_buffer, SEMAPHORE_REQUEST, IPC_SEMWAIT_NOFILE); } else { continue; } zerocopy_operations_process (conn_info, &header, &new_message); /* * There is no new message to process, continue for loop */ if (new_message == 0) { continue; } coroipcs_refcount_inc (conn); send_ok = api->sending_allowed (conn_info->service, header->id, header, conn_info->sending_allowed_private_data); /* * This happens when the message contains some kind of invalid * parameter, such as an invalid size */ if (send_ok == -1) { api->stats_increment_value (conn_info->stats_handle, "invalid_request"); coroipc_response_header.size = sizeof (coroipc_response_header_t); coroipc_response_header.id = 0; coroipc_response_header.error = CS_ERR_INVALID_PARAM; coroipcs_response_send (conn_info, &coroipc_response_header, sizeof (coroipc_response_header_t)); } else if (send_ok) { api->stats_increment_value (conn_info->stats_handle, "requests"); api->serialize_lock(); api->handler_fn_get (conn_info->service, header->id) (conn_info, header); api->serialize_unlock(); } else { /* * Overload, tell library to retry */ api->stats_increment_value (conn_info->stats_handle, "overload"); coroipc_response_header.size = sizeof (coroipc_response_header_t); coroipc_response_header.id = 0; coroipc_response_header.error = CS_ERR_TRY_AGAIN; coroipcs_response_send (conn_info, &coroipc_response_header, sizeof (coroipc_response_header_t)); } api->sending_allowed_release (conn_info->sending_allowed_private_data); coroipcs_refcount_dec (conn); } pthread_exit (0); }