void message_dispatch(void) { int msg_type; pid_t src; void *buf; size_t len; struct dispatch_fns *dfn; int n_handled; if (!received_signal) return; DEBUG(10,("message_dispatch: received_signal = %d\n", received_signal)); received_signal = 0; while (message_recv(&msg_type, &src, &buf, &len)) { DEBUG(10,("message_dispatch: received msg_type=%d src_pid=%u\n", msg_type, (unsigned int) src)); n_handled = 0; for (dfn = dispatch_fns; dfn; dfn = dfn->next) { if (dfn->msg_type == msg_type) { DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type)); dfn->fn(msg_type, src, buf, len); n_handled++; } } if (!n_handled) { DEBUG(5,("message_dispatch: warning: no handlers registed for " "msg_type %d in pid%u\n", msg_type, (unsigned int)getpid())); } SAFE_FREE(buf); } }
static void * juggling_thread(void *arg) { int fd2, i, j; fd2 = *(int *)arg; if (pthread_mutex_lock(&threaded_mtx) != 0) err(-1, "juggling_thread: pthread_mutex_lock"); threaded_child_ready = 1; if (pthread_cond_signal(&threaded_cond) != 0) err(-1, "juggling_thread: pthread_cond_signal"); if (pthread_mutex_unlock(&threaded_mtx) != 0) err(-1, "juggling_thread: pthread_mutex_unlock"); for (i = 0; i < NUMCYCLES; i++) { for (j = 0; j < threaded_pipeline; j++) { if (message_recv(fd2) < 0) err(-1, "message_recv fd2"); if (message_send(fd2) < 0) err(-1, "message_send fd2"); } } return (NULL); }
static struct timespec thread_juggle(int fd1, int fd2, int pipeline) { struct timespec tstart, tfinish; pthread_t thread; int i, j; threaded_pipeline = pipeline; if (pthread_mutex_init(&threaded_mtx, NULL) != 0) err(-1, "thread_juggle: pthread_mutex_init"); if (pthread_create(&thread, NULL, juggling_thread, &fd2) != 0) err(-1, "thread_juggle: pthread_create"); if (pthread_mutex_lock(&threaded_mtx) != 0) err(-1, "thread_juggle: pthread_mutex_lock"); while (!threaded_child_ready) { if (pthread_cond_wait(&threaded_cond, &threaded_mtx) != 0) err(-1, "thread_juggle: pthread_cond_wait"); } if (pthread_mutex_unlock(&threaded_mtx) != 0) err(-1, "thread_juggle: pthread_mutex_unlock"); if (clock_gettime(CLOCK_REALTIME, &tstart) < 0) err(-1, "thread_juggle: clock_gettime"); for (i = 0; i < NUMCYCLES; i++) { for (j = 0; j < pipeline; j++) { if (message_send(fd1) < 0) err(-1, "message_send fd1"); } for (j = 0; j < pipeline; j++) { if (message_recv(fd1) < 0) err(-1, "message_recv fd1"); } } if (clock_gettime(CLOCK_REALTIME, &tfinish) < 0) err(-1, "thread_juggle: clock_gettime"); if (pthread_join(thread, NULL) != 0) err(-1, "thread_juggle: pthread_join"); timespecsub(&tfinish, &tstart); return (tfinish); }
/* * Juggle messages between two file descriptors in a single thread/process, * so simply a measure of IPC performance. */ static struct timespec juggle(int fd1, int fd2, int pipeline) { struct timespec tstart, tfinish; int i, j; if (clock_gettime(CLOCK_REALTIME, &tstart) < 0) err(-1, "juggle: clock_gettime"); for (i = 0; i < NUMCYCLES; i++) { for (j = 0; j < pipeline; j++) { if (message_send(fd1) < 0) err(-1, "message_send fd1"); } for (j = 0; j < pipeline; j++) { if (message_recv(fd2) < 0) err(-1, "message_recv fd2"); if (message_send(fd2) < 0) err(-1, "message_send fd2"); } for (j = 0; j < pipeline; j++) { if (message_recv(fd1) < 0) err(-1, "message_recv fd1"); } } if (clock_gettime(CLOCK_REALTIME, &tfinish) < 0) err(-1, "juggle: clock_gettime"); timespecsub(&tfinish, &tstart); return (tfinish); }
void message_dispatch(void) { int msg_type; struct process_id src; char *buf; char *msgs_buf; size_t len, total_len; struct dispatch_fns *dfn; int n_handled; if (!received_signal) return; DEBUG(10,("message_dispatch: received_signal = %d\n", received_signal)); received_signal = 0; if (!retrieve_all_messages(&msgs_buf, &total_len)) return; for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) { DEBUG(10,("message_dispatch: received msg_type=%d " "src_pid=%u\n", msg_type, (unsigned int) procid_to_pid(&src))); n_handled = 0; for (dfn = dispatch_fns; dfn; dfn = dfn->next) { if (dfn->msg_type == msg_type) { DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type)); dfn->fn(msg_type, src, len ? (void *)buf : NULL, len); n_handled++; } } if (!n_handled) { DEBUG(5,("message_dispatch: warning: no handlers registed for " "msg_type %d in pid %u\n", msg_type, (unsigned int)sys_getpid())); } } SAFE_FREE(msgs_buf); }
/** * Sends the given class to the remote server for instrumentation. If the * server modified the class, provided class definition structure is updated * and the function returns TRUE. Otherwise, the structure is left unmodified * and FALSE is returned. * * NOTE: The class_name parameter may be NULL -- this is often the case for * anonymous classes. */ static bool __instrument_class ( jint request_flags, const char * class_name, jvmtiClassDefinition * class_def ) { // // Put the class data into a request message, acquire a connection and // send the it to the server. Receive the response and release the // connection again. // struct message request = { .message_flags = request_flags, .control_size = (class_name != NULL) ? strlen (class_name) : 0, .classcode_size = class_def->class_byte_count, .control = (unsigned char *) class_name, .classcode = class_def->class_bytes, }; // struct connection * conn = network_acquire_connection (); message_send (conn, &request); struct message response; message_recv (conn, &response); network_release_connection (conn); // // Check if error occurred on the server. // The control field of the response contains the error message. // if (response.control_size > 0) { fprintf ( stderr, "%sinstrumentation server error:\n%s\n", ERROR_PREFIX, response.control ); exit (ERROR_SERVER); } // // Update the class definition and signal that the class has been // modified if non-empty class code has been returned. Otherwise, // signal that the class has not been modified. // if (response.classcode_size > 0) { class_def->class_byte_count = response.classcode_size; class_def->class_bytes = response.classcode; return true; } else { return false; } } static void __handle_exception (JNIEnv * jni, jthrowable ex_obj) { jclass ex_class = (* jni)->GetObjectClass (jni, ex_obj); jmethodID m_getClass = (* jni)->GetMethodID (jni, ex_class, "getClass", "()Ljava/lang/Class;"); jobject cl_obj = (* jni)->CallObjectMethod (jni, ex_obj, m_getClass); jclass cl_class = (* jni)->GetObjectClass (jni, cl_obj); jmethodID m_getName = (* jni)->GetMethodID (jni, cl_class, "getName", "()Ljava/lang/String;"); jstring cl_name = (* jni)->CallObjectMethod (jni, cl_obj, m_getName); const char * cl_name_chars = (* jni)->GetStringUTFChars (jni, cl_name, NULL); rdaprintf ("\texception %s occured, cleared\n", cl_name_chars); (* jni)->ReleaseStringUTFChars (jni, cl_name, cl_name_chars); }
static void child (int conn, fsp_backend *backend, fs_backend *be) { int auth = 0; while (1) { fs_segment segment; unsigned int length; unsigned char *msg = message_recv(conn, &segment, &length); unsigned char *reply = NULL; unsigned char *content = msg + FS_HEADER; if (!msg) { /* if the connection is in fact closed, this won't matter, but otherwise this error might help */ reply = fsp_error_new(segment, "protocol mismatch"); unsigned int* const l = (unsigned int *) (reply + 4); unsigned int length = *l; if (write(conn, reply, FS_HEADER + length) != (FS_HEADER+length)) { fs_error(LOG_ERR, "write failed: %s", strerror(errno)); } break; } if (auth) { switch (msg[3]) { case FS_NO_OP: reply = fsp_handle_no_op(segment, length, content); break; case FS_RESOLVE: reply = handle(backend->resolve, be, segment, length, content); break; case FS_BIND: reply = handle(backend->bind, be, segment, length, content); break; case FS_PRICE_BIND: reply = handle(backend->price, be, segment, length, content); break; case FS_DELETE_MODEL: reply = handle(backend->delete_models, be, segment, length, content); break; case FS_INSERT_RESOURCE: reply = handle(backend->insert_resource, be, segment, length, content); break; case FS_SEGMENTS: reply = handle(backend->segments, be, segment, length, content); break; case FS_COMMIT_RESOURCE: reply = handle(backend->commit_resource, be, segment, length, content); break; case FS_START_IMPORT: reply = handle(backend->start_import, be, segment, length, content); break; case FS_STOP_IMPORT: reply = handle(backend->stop_import, be, segment, length, content); break; case FS_GET_SIZE: reply = handle(backend->get_data_size, be, segment, length, content); break; case FS_GET_IMPORT_TIMES: reply = handle(backend->get_import_times, be, segment, length, content); break; case FS_INSERT_QUAD: reply = handle(backend->insert_quad, be, segment, length, content); break; case FS_COMMIT_QUAD: reply = handle(backend->commit_quad, be, segment, length, content); break; case FS_GET_QUERY_TIMES: reply = handle(backend->get_query_times, be, segment, length, content); break; case FS_BIND_LIMIT: reply = handle(backend->bind_limit, be, segment, length, content); break; case FS_BNODE_ALLOC: reply = handle(backend->bnode_alloc, be, segment, length, content); break; case FS_RESOLVE_ATTR: reply = handle(backend->resolve_attr, be, segment, length, content); break; case FS_DELETE_MODELS: reply = handle(backend->delete_models, be, segment, length, content); break; case FS_NEW_MODELS: reply = handle(backend->new_models, be, segment, length, content); break; case FS_BIND_FIRST: reply = handle(backend->bind_first, be, segment, length, content); break; case FS_BIND_NEXT: reply = handle(backend->bind_next, be, segment, length, content); break; case FS_BIND_DONE: reply = handle(backend->bind_done, be, segment, length, content); break; case FS_TRANSACTION: reply = handle(backend->transaction, be, segment, length, content); break; case FS_NODE_SEGMENTS: reply = handle(backend->node_segments, be, segment, length, content); break; case FS_REVERSE_BIND: reply = handle(backend->reverse_bind, be, segment, length, content); break; case FS_LOCK: reply = handle(backend->lock, be, segment, length, content); break; case FS_UNLOCK: reply = handle(backend->unlock, be, segment, length, content); break; case FS_GET_SIZE_REVERSE: reply = handle(backend->get_size_reverse, be, segment, length, content); break; case FS_GET_QUAD_FREQ: reply = handle(backend->get_quad_freq, be, segment, length, content); break; case FS_CHOOSE_SEGMENT: reply = handle(backend->choose_segment, be, segment, length, content); break; case FS_DELETE_QUADS: reply = handle(backend->delete_quads, be, segment, length, content); break; case FS_GET_UUID: reply = handle(backend->get_uuid, be, segment, length, content); break; default: kb_error(LOG_WARNING, "unexpected message type (%d)", msg[3]); reply = fsp_error_new(segment, "unexpected message type"); break; } } else if (msg[3] == FS_AUTH) { if (backend->auth) { reply = backend->auth(be, segment, length, content); } else { reply = message_new(FS_DONE_OK, segment, 0); } if (reply[3] == FS_DONE_OK) auth = 1; } else { reply = fsp_error_new(segment, "authenticate before continuing"); } if (reply) { unsigned int* const l = (unsigned int *) (reply + 4); unsigned int length = *l; if (write(conn, reply, FS_HEADER + length) <= 0) { kb_error(LOG_WARNING, "write reply failed"); } free(reply); } free(msg); } }
/* * Juggle messages between two file descriptors in two processes, so measure * the cost of IPC and the cost of a process context switch. * * Since we can't use a mutex between the processes, we simply do an extra * write on the child to let the parent know that it's ready to start. */ static struct timespec process_juggle(int fd1, int fd2, int pipeline) { struct timespec tstart, tfinish; pid_t pid, ppid, wpid; int error, i, j; ppid = getpid(); pid = fork(); if (pid < 0) err(-1, "process_juggle: fork"); if (pid == 0) { if (message_send(fd2) < 0) { error = errno; kill(ppid, SIGTERM); errno = error; err(-1, "process_juggle: child: message_send"); } for (i = 0; i < NUMCYCLES; i++) { for (j = 0; j < pipeline; j++) { if (message_send(fd2) < 0) err(-1, "message_send fd2"); if (message_recv(fd2) < 0) err(-1, "message_recv fd2"); } } exit(0); } else { if (message_recv(fd1) < 0) { error = errno; kill(pid, SIGTERM); errno = error; err(-1, "process_juggle: parent: message_recv"); } if (clock_gettime(CLOCK_REALTIME, &tstart) < 0) err(-1, "process_juggle: clock_gettime"); for (i = 0; i < NUMCYCLES; i++) { for (j = 0; j < pipeline; j++) { if (message_send(fd1) < 0) { error = errno; kill(pid, SIGTERM); errno = error; err(-1, "message_send fd1"); } } for (j = 0; j < pipeline; j++) { if (message_recv(fd1) < 0) { error = errno; kill(pid, SIGTERM); errno = error; err(-1, "message_recv fd1"); } } } if (clock_gettime(CLOCK_REALTIME, &tfinish) < 0) err(-1, "process_juggle: clock_gettime"); } wpid = waitpid(pid, NULL, 0); if (wpid < 0) err(-1, "process_juggle: waitpid"); if (wpid != pid) errx(-1, "process_juggle: waitpid: pid != wpid"); timespecsub(&tfinish, &tstart); return (tfinish); }