int qthread_fork_remote_sinc(qthread_f f, const void *arg, qt_sinc_t *ret, int rank, size_t arg_len) { struct fork_msg_t msg; qthread_debug(MULTINODE_CALLS, "[%d] begin qthread_fork_remote_sinc(0x%lx, 0x%lx, 0x%lx, %d, %ld)\n", my_rank, (unsigned long)f, (unsigned long)arg, (unsigned long)ret, rank, arg_len); if (arg_len <= sizeof(msg.args)) { msg.uid = (uint64_t)qt_hash_get(ptr_to_uid_hash, f); if (qt_hash_get(uid_to_ptr_hash, (qt_key_t)(uintptr_t)msg.uid) != f) { fprintf(stderr, "action not registered at source\n"); abort(); } msg.return_addr = (uint64_t)ret; msg.origin_node = my_rank; msg.arg_len = arg_len; memcpy(msg.args, arg, arg_len); qthread_debug(MULTINODE_DETAILS, "[%d] remote fork %d %d 0x%lx %d\n", my_rank, rank, msg.uid, msg.return_addr, msg.arg_len); return qthread_internal_net_driver_send(rank, SHORT_MSG_SINC_TAG, &msg, sizeof(msg)); } fprintf(stderr, "long remote fork unsupported\n"); abort(); }
int qthread_fork_remote(qthread_f f, const void *arg, aligned_t *ret, int rank, size_t arg_len) { qthread_debug(MULTINODE_CALLS, "[%d] begin f=0x%lx, arg=0x%lx, ret=0x%lx, rank=%d, arg_len=%ld)\n", my_rank, (unsigned long)f, (unsigned long)arg, (unsigned long)ret, rank, arg_len); uint64_t const uid = (uint64_t)qt_hash_get(ptr_to_uid_hash, f); if (qt_hash_get(uid_to_ptr_hash, (qt_key_t)(uintptr_t)uid) != f) { fprintf(stderr, "action not registered at source\n"); abort(); } if (NULL != ret) { qthread_empty(ret); } if (arg_len <= FORK_MSG_PAYLOAD) { struct fork_msg_t msg; msg.uid = uid; msg.return_addr = (uint64_t)ret; msg.origin_node = my_rank; msg.arg_len = arg_len; memcpy(msg.args, arg, arg_len); qthread_debug(MULTINODE_DETAILS, "[%d] remote fork %d %d 0x%lx %d\n", my_rank, rank, msg.uid, msg.return_addr, msg.arg_len); return qthread_internal_net_driver_send(rank, SHORT_MSG_TAG, &msg, sizeof(msg)); } else { struct fork_long_msg_t * long_msg; size_t long_msg_size = sizeof(struct fork_long_msg_t) + arg_len; long_msg = malloc(long_msg_size); assert(NULL != long_msg); long_msg->uid = uid; long_msg->return_addr = (uint64_t)ret; long_msg->origin_node = my_rank; long_msg->arg_len = arg_len; memcpy(&long_msg->args, arg, arg_len); qthread_debug(MULTINODE_DETAILS, "[%d] remote long fork rank=%d uid=%d return_addr=0x%lx arg_len=%d\n", my_rank, rank, long_msg->uid, long_msg->return_addr, long_msg->arg_len); int const rc = qthread_internal_net_driver_send(rank, LONG_MSG_TAG, long_msg, long_msg_size); free(long_msg); return rc; } }
int qthread_multinode_register(uint32_t uid, qthread_f f) { int ret = 0; if (0 == initialized) { return 1; } qthread_debug(MULTINODE_CALLS, "[%d] begin qthread_multinode_register(uid=%d, ptr=0x%lx)\n", my_rank, uid, (unsigned long)f); // Check that UID is strictly positive if (0 == uid) { fprintf(stderr, "invalid action id %d: must be > 0", uid); return 1; } // Check that UID is not used more than once if (NULL != qt_hash_get(uid_to_ptr_hash, (qt_key_t)(uintptr_t)uid)) { fprintf(stderr, "duplicate registration of action uid %d\n", uid); return 1; } ret = qt_hash_put(uid_to_ptr_hash, (qt_key_t)(uintptr_t)uid, f); if (ret != 1) { qthread_debug(MULTINODE_DETAILS, "[%d] uid -> ptr registration failed\n", my_rank); return 1; } // Check that function pointer is not used more than once if (NULL != qt_hash_get(ptr_to_uid_hash, f)) { fprintf(stderr, "duplicate registration of action function 0x%lx\n", (unsigned long)f); return 1; } ret = qt_hash_put(ptr_to_uid_hash, f, (void *)(uintptr_t)uid); if (ret != 1) { qthread_debug(MULTINODE_DETAILS, "[%d] ptr -> uid registration failed\n", my_rank); return 1; } qthread_debug(MULTINODE_CALLS, "[%d] end qthread_multinode_register\n", my_rank); return 0; }
static aligned_t fork_helper(void *info) { struct fork_msg_t *msg = (struct fork_msg_t *)info; aligned_t ret; qthread_f f; qthread_debug(MULTINODE_FUNCTIONS, "[%d] begin fork_helper\n", my_rank); f = qt_hash_get(uid_to_ptr_hash, (qt_key_t)(uintptr_t)msg->uid); if (NULL != f) { ret = f(msg->args); if (0 != msg->return_addr) { struct return_msg_t ret_msg; ret_msg.return_addr = msg->return_addr; ret_msg.return_val = ret; qthread_debug(MULTINODE_DETAILS, "[%d] sending return msg 0x%lx, %ld\n", my_rank, ret_msg.return_addr, ret_msg.return_val); qthread_internal_net_driver_send(msg->origin_node, RETURN_MSG_TAG, &ret_msg, sizeof(ret_msg)); } } else { fprintf(stderr, "action uid %d not registered at destination\n", msg->uid); abort(); } qthread_debug(MULTINODE_FUNCTIONS, "[%d] end fork_helper\n", my_rank); return 0; }
void *qt_dictionary_delete(qt_dictionary *dict, void *key) { void *val = qt_hash_get(dict, key); // TODO : this is inefficient! int ret = qt_hash_remove(dict, key); if(ret) { return val; } else { return NULL; } }
int qthread_multinode_action_ptr(uint32_t uid, qthread_f *f) { int ret = 0; if (0 == initialized) { return 1; } *f = qt_hash_get(uid_to_ptr_hash, (qt_key_t)(uintptr_t)uid); return ret; }
int qthread_multinode_action_uid(qthread_f f, uint32_t *uid) { int ret = 0; if (0 == initialized) { return 1; } *uid = (uint64_t)qt_hash_get(ptr_to_uid_hash, f); return ret; }
void *qt_dictionary_get(qt_dictionary *dict, void *key) { return qt_hash_get(dict, key); }