static gboolean plain_sockets_client_side_watch (GIOChannel *source, GIOCondition condition, gpointer data) { ClientData *cd = data; int fd = g_io_channel_unix_get_fd (source); if (condition & G_IO_IN) { read_and_drop_on_floor (fd, echo_return_size, cd->vtable->fake_malloc_overhead); } else if (condition & G_IO_OUT) { cd->iterations += 1; if (cd->iterations >= N_ITERATIONS) { g_printerr ("\nCompleted %d iterations\n", N_ITERATIONS); g_main_loop_quit (cd->loop); } else if (cd->iterations % (N_ITERATIONS/N_PROGRESS_UPDATES) == 0) { g_printerr ("%d%% ", (int) (cd->iterations/(double)N_ITERATIONS * 100.0)); } write_junk (fd, echo_call_size, cd->vtable->fake_malloc_overhead); } else { g_printerr ("Unexpected IO condition in client thread\n"); exit (1); } return TRUE; }
static gboolean plain_sockets_talk_to_client_watch (GIOChannel *source, GIOCondition condition, gpointer data) { PlainSocketServer *server = data; int client_fd = g_io_channel_unix_get_fd (source); if (condition & G_IO_HUP) { g_printerr ("Client disconnected from server\n"); server->sd->n_clients -= 1; if (server->sd->n_clients == 0) g_main_loop_quit (server->sd->loop); return FALSE; /* remove watch */ } else if (condition & G_IO_IN) { server->sd->handled += 1; read_and_drop_on_floor (client_fd, echo_call_size, server->vtable->fake_malloc_overhead); write_junk (client_fd, echo_return_size, server->vtable->fake_malloc_overhead); } else { g_printerr ("Unexpected IO condition in server thread\n"); exit (1); } return TRUE; }
int main(int argc, char *argv[]) { int opt, fd; unsigned long i, mthreads = 0, nthreads = 1; char *fname = NULL; int flags = 0, sync_options = 0; uint64_t file_size = 0; pid_t pid; int status; while ((opt = getopt(argc, argv, "b:dn:l:srfm:")) != -1) { switch (opt) { case 'd': flags |= O_DIRECT; break; case 'n': nthreads = strtoul(optarg, NULL, 0); break; case 'm': mthreads = strtoul(optarg, NULL, 0); break; case 'l': file_size = strtoull(optarg, NULL, 0); break; case 's': flags |= O_SYNC; break; case 'b': bufsize = strtoul(optarg, NULL, 0); break; case 'r': sync_options |= SYNC_RANGE; break; case 'f': sync_options |= SYNC_FILE; break; default: help(argv[0]); return 4; } } if (optind != argc - 1 || file_size < 1) { help(argv[0]); return 1; } fname = argv[optind]; if (!seed_random()) return 2; // truncate first fd = open(fname, flags | O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) { perror(fname); return 3; } status = posix_fallocate(fd, 0, file_size); #if 0 if (status) { perror(fname); return 4; } #endif close(fd); // spawn threads and go to town if (nthreads == 1) return write_junk(fname, flags, sync_options, file_size); for (i = 0; i < nthreads; i++) { pid = fork(); if (!pid) return write_junk(fname, flags, sync_options, file_size); } for (i = 0; i < mthreads; i++) { pid = fork(); if (!pid) return mmap_junk(fname, flags, sync_options, file_size); } for (i = 0; i < mthreads + nthreads; i++) { pid = wait(&status); if (WIFEXITED(status)) printf("Child %d exited with status %d\n", pid, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) printf("Child %d exited with signal %d\n", pid, WTERMSIG(status)); } return 0; }
static void* plain_sockets_thread_func (void *data) { GMainContext *context; ClientData cd; int fd; struct sockaddr_un addr; GIOChannel *channel; GSource *gsource; g_printerr ("Starting client thread %p\n", g_thread_self()); fd = socket (PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { g_printerr ("Failed to create socket: %s", strerror (errno)); exit (1); } _DBUS_ZERO (addr); addr.sun_family = AF_UNIX; #ifdef HAVE_ABSTRACT_SOCKETS /* remember that abstract names aren't nul-terminated so we rely * on sun_path being filled in with zeroes above. */ addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ strncpy (&addr.sun_path[1], plain_sockets_address, _DBUS_MAX_SUN_PATH_LENGTH - 2); /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ #else /* HAVE_ABSTRACT_SOCKETS */ strncpy (addr.sun_path, plain_sockets_address, _DBUS_MAX_SUN_PATH_LENGTH - 1); #endif /* ! HAVE_ABSTRACT_SOCKETS */ if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0) { g_printerr ("Failed to connect to socket %s: %s", plain_sockets_address, strerror (errno)); exit (1); } context = g_main_context_new (); cd.iterations = 1; cd.loop = g_main_loop_new (context, FALSE); cd.vtable = data; channel = g_io_channel_unix_new (fd); gsource = g_io_create_watch (channel, G_IO_IN | G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_PRI); g_source_set_callback (gsource, (GSourceFunc)plain_sockets_client_side_watch, &cd, NULL); g_source_attach (gsource, context); g_io_channel_unref (channel); g_printerr ("Client thread writing to prime pingpong\n"); write_junk (fd, echo_call_size, cd.vtable->fake_malloc_overhead); g_printerr ("Client thread done writing primer\n"); g_printerr ("Client thread entering main loop\n"); g_main_loop_run (cd.loop); g_printerr ("Client thread %p exiting main loop\n", g_thread_self()); g_source_destroy (gsource); close (fd); g_main_loop_unref (cd.loop); g_main_context_unref (context); return NULL; }