static void memcpyperf(void *src, void *dst, u32 size, u32 cnt) { struct timespec beforets; struct timespec afterts; long val[OUT_TRY_CNT]; long sum = 0; u32 i, j; memset(src, 0xab, size); memset(dst, 0x00, size); for (j = 0; j < OUT_TRY_CNT; j++) { getnstimeofday(&beforets); for (i = 0; i < cnt; i++) memcpy(dst, src, size); getnstimeofday(&afterts); mdelay(100); val[j] = update_timeval(beforets, afterts)/cnt; } for (j = 0; j < OUT_TRY_CNT; j++) sum += val[j]; printk(KERN_ERR "%lu\n", sum/OUT_TRY_CNT); if (buf_compare(src, dst, size)) printk(KERN_ERR "copy err\n"); }
static void cacheperf(void *vbuf, enum cachemaintenance id) { struct timespec beforets; struct timespec afterts; phys_addr_t pbuf = virt_to_phys(vbuf); u32 pbufend, xfer_size, i; long timeval; xfer_size = START_SIZE; while (xfer_size <= END_SIZE) { pbufend = pbuf + xfer_size; timeval = 0; for (i = 0; i < try_cnt; i++) { memset(vbuf, i, xfer_size); getnstimeofday(&beforets); switch (id) { case CM_CLEAN: if (l1) dmac_map_area(vbuf, xfer_size, DMA_TO_DEVICE); if (l2) outer_clean_range(pbuf, pbufend); break; case CM_INV: if (l2) outer_inv_range(pbuf, pbufend); if (l1) dmac_unmap_area(vbuf, xfer_size, DMA_FROM_DEVICE); break; case CM_FLUSH: if (l1) dmac_flush_range(vbuf, (void *)((u32) vbuf + xfer_size)); if (l2) outer_flush_range(pbuf, pbufend); break; case CM_FLUSHALL: if (l1) flush_cache_all(); if (l2) outer_flush_all(); break; } getnstimeofday(&afterts); timeval += update_timeval(beforets, afterts); } printk(KERN_INFO "%lu\n", timeval/try_cnt); xfer_size *= 2; } }
static int cacheperf(void) { u32 xfer_size; int i = 0; void *vbuf; phys_addr_t pbuf; u32 bufend; struct timespec beforets; struct timespec afterts; long timeval; vbuf = kmalloc(END_SIZE, GFP_KERNEL); pbuf = virt_to_phys(vbuf); if (mset) { printk(KERN_INFO "## Memset perf (ns)\n"); xfer_size = START_SIZE; while (xfer_size <= END_SIZE) { bufend = pbuf + xfer_size; getnstimeofday(&beforets); for (i = 0; i < try_cnt; i++) memset(vbuf, i, xfer_size); getnstimeofday(&afterts); print_result(xfer_size, beforets, afterts); xfer_size *= 2; } } if (cops) { printk(KERN_INFO "## Clean perf (ns)\n"); xfer_size = START_SIZE; while (xfer_size <= END_SIZE) { bufend = pbuf + xfer_size; timeval = 0; for (i = 0; i < try_cnt; i++) { memset(vbuf, i, xfer_size); getnstimeofday(&beforets); if (l1) dmac_map_area(vbuf, xfer_size, DMA_TO_DEVICE); if (l2) outer_clean_range(pbuf, bufend); getnstimeofday(&afterts); timeval += update_timeval(beforets, afterts); xfer_size *= 2; } printk(KERN_INFO "%lu\n", timeval); } } if (iops) { printk(KERN_INFO "## Invalidate perf (ns)\n"); xfer_size = START_SIZE; while (xfer_size <= END_SIZE) { bufend = pbuf + xfer_size; timeval = 0; for (i = 0; i < try_cnt; i++) { memset(vbuf, i, xfer_size); getnstimeofday(&beforets); if (l2) outer_inv_range(pbuf, bufend); if (l1) dmac_unmap_area(vbuf, xfer_size, DMA_FROM_DEVICE); getnstimeofday(&afterts); timeval += update_timeval(beforets, afterts); xfer_size *= 2; } printk(KERN_INFO "%lu\n", timeval); } } if (fops) { printk(KERN_INFO "## Flush perf (ns)\n"); xfer_size = START_SIZE; while (xfer_size <= END_SIZE) { bufend = pbuf + xfer_size; timeval = 0; for (i = 0; i < try_cnt; i++) { memset(vbuf, i, xfer_size); getnstimeofday(&beforets); if (l1) dmac_flush_range(vbuf, (void *)((u32) vbuf + xfer_size)); if (l2) outer_flush_range(pbuf, bufend); getnstimeofday(&afterts); timeval += update_timeval(beforets, afterts); xfer_size *= 2; } printk(KERN_INFO "%lu\n", timeval); } } if (all) { printk(KERN_INFO "## Flush all perf (ns)\n"); xfer_size = START_SIZE; while (xfer_size <= END_SIZE) { bufend = pbuf + xfer_size; timeval = 0; for (i = 0; i < try_cnt; i++) { memset(vbuf, i, xfer_size); getnstimeofday(&beforets); if (l1) flush_cache_all(); if (l2) outer_flush_all(); getnstimeofday(&afterts); timeval += update_timeval(beforets, afterts); xfer_size *= 2; } printk(KERN_INFO "%lu\n", timeval); } } kfree(vbuf); return 0; }
int core_readwrite(nc_sock_t *nc_main, nc_sock_t *nc_slave) { int fd_stdin, fd_stdout, fd_sock, fd_max; int read_ret, write_ret; #ifdef __MVS__ /* zosunix01 26.07.2011 */ unsigned char buf[32768]; #else unsigned char buf[1024]; #endif bool inloop = TRUE; fd_set ins, outs; struct timeval delayer; assert(nc_main && nc_slave); debug_v(("core_readwrite(nc_main=%p, nc_slave=%p)", (void *)nc_main, (void *)nc_slave)); /* set the actual input and output fds and find out the max fd + 1 */ fd_sock = nc_main->fd; assert(fd_sock >= 0); /* if the domain is unspecified, it means that this is the standard I/O */ if (nc_slave->domain == PF_UNSPEC) { fd_stdin = STDIN_FILENO; fd_stdout = STDOUT_FILENO; } else { fd_stdin = fd_stdout = nc_slave->fd; assert(fd_stdin >= 0); } fd_max = 1 + (fd_stdin > fd_sock ? fd_stdin : fd_sock); delayer.tv_sec = 0; delayer.tv_usec = 0; /* use the internal signal handler */ signal_handler = FALSE; while (inloop) { bool call_select = TRUE; struct sockaddr_in recv_addr; /* only used by UDP proto */ unsigned int recv_len = sizeof(recv_addr); /* if we received an interrupt signal break this function */ if (got_sigint) { got_sigint = FALSE; break; } /* if we received a terminating signal we must terminate */ if (got_sigterm) break; /* reset the ins and outs events watch because some changes could happen */ FD_ZERO(&ins); FD_ZERO(&outs); /* if the receiving queue is not empty it means that something bad is happening (for example the target sending queue is delaying the output and so requires some more time to free up. */ if (nc_main->recvq.len == 0) { debug_v(("watching main sock for incoming data (recvq is empty)")); FD_SET(fd_sock, &ins); } else call_select = FALSE; /* same thing for the other socket */ if (nc_slave->recvq.len == 0) { /* FIXME: call_select = false but could call it anyway and one of them could be set.. so what happens? */ debug_v(("watching slave sock for incoming data (recvq is empty)")); if (use_stdin || (netcat_mode == NETCAT_TUNNEL)) FD_SET(fd_stdin, &ins); } else call_select = FALSE; /* now the send queue. There are two cases in which the main sendq is not empty. The first one is when we have a delayed output (-i), in which case the delayer is not null, and the socket is writable. The second case is when the socket buffer is full, so the socket is not writable and the delayer is either null or set, depending on the opt_interval variable. */ if (nc_main->sendq.len > 0) { if ((delayer.tv_sec == 0) && (delayer.tv_usec == 0)) { debug_v(("watching main sock for outgoing availability (there is pending data)")); FD_SET(fd_sock, &outs); call_select = TRUE; } } if (call_select || delayer.tv_sec || delayer.tv_usec) { int ret; #ifndef USE_LINUX_SELECT struct timeval dd_saved; dd_saved.tv_sec = delayer.tv_sec; dd_saved.tv_usec = delayer.tv_usec; update_timeval(NULL); #endif debug(("[select] entering with timeout=%d:%d ...", delayer.tv_sec, delayer.tv_usec)); ret = select(fd_max, &ins, &outs, NULL, (delayer.tv_sec || delayer.tv_usec ? &delayer : NULL)); #ifndef USE_LINUX_SELECT delayer.tv_sec = dd_saved.tv_sec; delayer.tv_usec = dd_saved.tv_usec; update_timeval(&delayer); #endif if (ret < 0) { /* something went wrong (maybe a legal signal) */ if (errno == EINTR) goto handle_signal; perror("select(core_readwrite)"); exit(EXIT_FAILURE); } else if (ret == 0) { /* timeout expired */ delayer.tv_sec = 0; delayer.tv_usec = 0; } call_select = TRUE; debug(("ret=%d\n", ret)); } /* reading from stdin the incoming data. The data is currently in the kernel's receiving queue, and in this session we move that data to our own receiving queue, located in the socket object. We can be sure that this queue is empty now because otherwise this fd wouldn't have been watched. */ if (call_select && FD_ISSET(fd_stdin, &ins)) { read_ret = read(fd_stdin, buf, sizeof(buf)); debug_dv(("read(stdin) = %d", read_ret)); if (read_ret < 0) { perror("read(stdin)"); exit(EXIT_FAILURE); } else if (read_ret == 0) { /* when we receive EOF and this is a tunnel say goodbye, otherwise it means that stdin has finished its input. */ if ((netcat_mode == NETCAT_TUNNEL) || opt_eofclose) { debug_v(("EOF Received from stdin! (exiting from loop..)")); inloop = FALSE; } else { debug_v(("EOF Received from stdin! (removing from lookups..)")); use_stdin = FALSE; } } else { /* we can overwrite safely since if the receive queue is busy this fd is not watched at all. */ nc_slave->recvq.len = read_ret; nc_slave->recvq.head = NULL; nc_slave->recvq.pos = buf; } } /* for optimization reasons we have a common buffer for both receiving queues, because of this, handle the data now so the buffer is available for the other socket events. */ if (nc_slave->recvq.len > 0) { nc_buffer_t *my_recvq = &nc_slave->recvq; nc_buffer_t *rem_sendq = &nc_main->sendq; debug_v(("there are %d data bytes in slave->recvq", my_recvq->len)); /* if the remote send queue is empty, move there the entire data block */ if (rem_sendq->len == 0) { debug_v((" moved %d data bytes from slave->recvq to main->sendq", my_recvq->len)); memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq)); memset(my_recvq, 0, sizeof(*my_recvq)); } else if (!my_recvq->head) { /* move the data block in a dedicated allocated space */ debug_v((" reallocating %d data bytes in slave->recvq", my_recvq->len)); my_recvq->head = malloc(my_recvq->len); memcpy(my_recvq->head, my_recvq->pos, my_recvq->len); my_recvq->pos = my_recvq->head; } } /* now handle the nc_slave sendq because of the same reason as above. There could be a common buffer that moves around the queues, so if this is the case handle it so that it can be reused. If we must delay it some more, copy it in a dynamically allocated space. */ if (nc_main->sendq.len > 0) { unsigned char *data = nc_main->sendq.pos; int data_len = nc_main->sendq.len; nc_buffer_t *my_sendq = &nc_main->sendq; debug_v(("there are %d data bytes in main->sendq", my_sendq->len)); /* we have a delayed output, but at this point we might have the send queue pointing to a stack buffer. In this case, allocate a new buffer and copy the data there for the buffered output. */ if (opt_interval) { int i = 0; if (delayer.tv_sec || delayer.tv_usec) goto skip_sect; /* the delay is not yet over! */ /* find the newline character. We are going to output the first line immediately while we allocate and safe the rest of the data for a later output. */ while (i < data_len) if (data[i++] == '\n') break; data_len = i; delayer.tv_sec = opt_interval; } write_ret = write(fd_sock, data, data_len); if (write_ret < 0) { #ifdef __MVS__ /* zosunix01 26.07.2011 */ /* z/OS Unix is Unix V and here the errno */ /* EWOULBBLOCK appears, if the socket is */ /* blocked. */ if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) #else if (errno == EAGAIN) #endif write_ret = 0; /* write would block, append it to select */ else { perror("write(net)"); exit(EXIT_FAILURE); } } /* FIXME: fix the below unhandled exception, and find a way to delay the * tries to call write(2) in case of EAGAIN, i think 100ms would be fine * for most systems. A too high value would not use all the bandwidth on * bigger installations, while a too small value would eat cpu with * kernel overhead. */ bytes_sent += write_ret; /* update statistics */ debug_dv(("write(net) = %d (buf=%p)", write_ret, (void *)data)); if (write_ret < data_len) { debug_v(("Damn! I wanted to send to sock %d bytes but it only sent %d", data_len, write_ret)); data_len = write_ret; } /* if the option is set, hexdump the sent data */ if (opt_hexdump) { #ifndef USE_OLD_HEXDUMP fprintf(output_fp, "Sent %u bytes to the socket\n", write_ret); #endif netcat_fhexdump(output_fp, '>', data, data_len); } /* update the queue */ my_sendq->len -= data_len; my_sendq->pos += data_len; skip_sect: debug_v(("there are %d data bytes left in the queue", my_sendq->len)); if (my_sendq->len == 0) { free(my_sendq->head); memset(my_sendq, 0, sizeof(*my_sendq)); } else if (!my_sendq->head) { my_sendq->head = malloc(my_sendq->len); memcpy(my_sendq->head, my_sendq->pos, my_sendq->len); my_sendq->pos = my_sendq->head; } } /* end of reading from stdin section */ /* reading from the socket (net). */ if (call_select && FD_ISSET(fd_sock, &ins)) { if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero) { memset(&recv_addr, 0, sizeof(recv_addr)); /* this allows us to fetch packets from different addresses */ read_ret = recvfrom(fd_sock, buf, sizeof(buf), 0, (struct sockaddr *)&recv_addr, &recv_len); /* when recvfrom() call fails, recv_addr remains untouched */ debug_dv(("recvfrom(net) = %d (address=%s:%d)", read_ret, netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port))); } else { /* common file read fallback */ read_ret = read(fd_sock, buf, sizeof(buf)); debug_dv(("read(net) = %d", read_ret)); } if (read_ret < 0) { perror("read(net)"); exit(EXIT_FAILURE); } else if (read_ret == 0) { debug_v(("EOF Received from the net")); inloop = FALSE; } else { nc_main->recvq.len = read_ret; nc_main->recvq.head = NULL; nc_main->recvq.pos = buf; } } /* handle net receiving queue */ if (nc_main->recvq.len > 0) { nc_buffer_t *my_recvq = &nc_main->recvq; nc_buffer_t *rem_sendq = &nc_slave->sendq; /* check for telnet codes (if enabled). Note that the buffered output interval does NOT apply to telnet code answers */ if (opt_telnet) netcat_telnet_parse(nc_main); /* the telnet parsing could have returned 0 chars! */ if (my_recvq->len > 0) { /* if the remote send queue is empty, move there the entire data block */ if (rem_sendq->len == 0) { memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq)); memset(my_recvq, 0, sizeof(*my_recvq)); } else if (!my_recvq->head) { /* move the data block in a dedicated allocated space */ my_recvq->head = malloc(my_recvq->len); memcpy(my_recvq->head, my_recvq->pos, my_recvq->len); my_recvq->pos = my_recvq->head; } } } if (nc_slave->sendq.len > 0) { unsigned char *data = nc_slave->sendq.pos; int data_len = nc_slave->sendq.len; nc_buffer_t *my_sendq = &nc_slave->sendq; write_ret = write(fd_stdout, data, data_len); bytes_recv += write_ret; /* update statistics */ debug_dv(("write(stdout) = %d", write_ret)); if (write_ret < 0) { perror("write(stdout)"); exit(EXIT_FAILURE); } /* FIXME: unhandled exception */ assert((write_ret > 0) && (write_ret <= data_len)); if (write_ret < data_len) { debug_v(("Damn! I wanted to send to stdout %d bytes but it only sent %d", data_len, write_ret)); data_len = write_ret; } /* if option is set, hexdump the received data */ if (opt_hexdump) { #ifndef USE_OLD_HEXDUMP if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero) fprintf(output_fp, "Received %d bytes from %s:%d\n", write_ret, netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port)); else fprintf(output_fp, "Received %d bytes from the socket\n", write_ret); #endif netcat_fhexdump(output_fp, '<', data, write_ret); } /* update the queue */ my_sendq->len -= data_len; my_sendq->pos += data_len; debug_v(("there are %d data bytes left in the queue", my_sendq->len)); if (my_sendq->len == 0) { free(my_sendq->head); memset(my_sendq, 0, sizeof(*my_sendq)); } else if (!my_sendq->head) { my_sendq->head = malloc(my_sendq->len); memcpy(my_sendq->head, my_sendq->pos, my_sendq->len); my_sendq->pos = my_sendq->head; } } /* end of reading from the socket section */ handle_signal: /* FIXME: i'm not sure this is the right place */ if (got_sigusr1) { debug_v(("LOCAL printstats!")); netcat_printstats(TRUE); got_sigusr1 = FALSE; } continue; } /* end of while (inloop) */ /* we've got an EOF from the net, close the sockets */ shutdown(fd_sock, SHUT_RDWR); close(fd_sock); nc_main->fd = -1; /* close the slave socket only if it wasn't a simulation */ if (nc_slave->domain != PF_UNSPEC) { shutdown(fd_stdin, SHUT_RDWR); close(fd_stdin); nc_slave->fd = -1; } /* restore the extarnal signal handler */ signal_handler = TRUE; return 0; } /* end of core_readwrite() */