From 20fcf38e30af9afeaf4e36771788a0feb8a43432 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Fri, 13 May 2005 09:21:21 +0000 Subject: [PATCH] Recognize Intel Compilers. Add user mode network stack with slirp from qemu. Simply use "ether slirp" in the prefs file, no kernel module required. I could perform up to 450 KB/sec on my DSL line. --- BasiliskII/src/Unix/Makefile.in | 16 ++- BasiliskII/src/Unix/configure.ac | 31 +++++- BasiliskII/src/Unix/ether_unix.cpp | 161 ++++++++++++++++++++++++++--- 3 files changed, 186 insertions(+), 22 deletions(-) diff --git a/BasiliskII/src/Unix/Makefile.in b/BasiliskII/src/Unix/Makefile.in index a9e304e9..326b8f50 100644 --- a/BasiliskII/src/Unix/Makefile.in +++ b/BasiliskII/src/Unix/Makefile.in @@ -19,7 +19,7 @@ CC = @CC@ CXX = @CXX@ CFLAGS = @CFLAGS@ CXXFLAGS = @CXXFLAGS@ -CPPFLAGS = @CPPFLAGS@ -I../include -I. @CPUINCLUDES@ +CPPFLAGS = @CPPFLAGS@ -I../include -I. @CPUINCLUDES@ -I../slirp DEFS = @DEFS@ @DEFINES@ -D_REENTRANT -DDATADIR=\"$(datadir)/$(APP)\" LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ @@ -31,6 +31,16 @@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s INSTALL_DATA = @INSTALL_DATA@ +SLIRP_CFLAGS = @SLIRP_CFLAGS@ +SLIRP_SRCS = \ + ../slirp/bootp.c ../slirp/ip_output.c ../slirp/tcp_input.c \ + ../slirp/cksum.c ../slirp/mbuf.c ../slirp/tcp_output.c \ + ../slirp/debug.c ../slirp/misc.c ../slirp/tcp_subr.c \ + ../slirp/if.c ../slirp/sbuf.c ../slirp/tcp_timer.c \ + ../slirp/ip_icmp.c ../slirp/slirp.c ../slirp/tftp.c \ + ../slirp/ip_input.c ../slirp/socket.c ../slirp/udp.c +SLIRP_OBJS = $(SLIRP_SRCS:../slirp/%.c=obj/%.o) + ## Files SRCS = ../main.cpp main_unix.cpp ../prefs.cpp ../prefs_items.cpp prefs_unix.cpp \ sys_unix.cpp ../rom_patches.cpp ../slot_rom.cpp ../rsrc_patches.cpp \ @@ -39,7 +49,7 @@ SRCS = ../main.cpp main_unix.cpp ../prefs.cpp ../prefs_items.cpp prefs_unix.cpp ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp ../video.cpp video_blit.cpp \ vm_alloc.cpp sigsegv.cpp ../audio.cpp ../extfs.cpp extfs_unix.cpp \ ../user_strings.cpp user_strings_unix.cpp sshpty.c strlcpy.c \ - $(SYSSRCS) $(CPUSRCS) + $(SYSSRCS) $(CPUSRCS) $(SLIRP_SRCS) APP = BasiliskII ## Rules @@ -104,6 +114,8 @@ distclean: clean depend dep: makedepend $(CPPFLAGS) -Y. $(SRCS) 2>/dev/null +$(OBJ_DIR)/%.o : ../slirp/%.c + $(CC) $(CPPFLAGS) $(DEFS) $(SLIRP_CFLAGS) -c $< -o $@ $(OBJ_DIR)/%.o : %.c $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ $(OBJ_DIR)/%.o : %.cpp diff --git a/BasiliskII/src/Unix/configure.ac b/BasiliskII/src/Unix/configure.ac index e3c6bca7..1f00108c 100644 --- a/BasiliskII/src/Unix/configure.ac +++ b/BasiliskII/src/Unix/configure.ac @@ -275,7 +275,8 @@ dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(unistd.h fcntl.h sys/types.h sys/time.h sys/mman.h mach/mach.h) AC_CHECK_HEADERS(readline.h history.h readline/readline.h readline/history.h) -AC_CHECK_HEADERS(sys/socket.h) +AC_CHECK_HEADERS(sys/socket.h sys/ioctl.h sys/filio.h sys/bitypes.h sys/wait.h sys/select.h) +AC_CHECK_HEADERS(arpa/inet.h) AC_CHECK_HEADERS(linux/if.h linux/if_tun.h net/if.h net/if_tun.h, [], [], [ #ifdef HAVE_SYS_SOCKET_H #include @@ -321,11 +322,12 @@ if [[ "x$ac_cv_type_socklen_t" != "xyes" ]]; then fi dnl Checks for library functions. -AC_CHECK_FUNCS(strdup cfmakeraw) +AC_CHECK_FUNCS(strdup strerror cfmakeraw) AC_CHECK_FUNCS(clock_gettime timer_create) AC_CHECK_FUNCS(sigaction signal) AC_CHECK_FUNCS(mmap mprotect munmap) AC_CHECK_FUNCS(vm_allocate vm_deallocate vm_protect) +AC_CHECK_FUNCS(inet_aton) dnl Darwin seems to define mach_task_self() instead of task_self(). AC_CHECK_FUNCS(mach_task_self task_self) @@ -1063,6 +1065,14 @@ AC_EGREP_CPP(xyes, #endif ], [AC_MSG_RESULT(yes); HAVE_GCC30=yes], AC_MSG_RESULT(no)) +dnl Check for ICC. +AC_MSG_CHECKING(for ICC) +HAVE_ICC=no +if $CXX -V -v 2>&1 | grep -q "Intel(R) C++ Compiler"; then + HAVE_ICC=yes +fi +AC_MSG_RESULT($HAVE_ICC) + dnl Set "-fomit-frame-pointer" on i386 GCC 2.7 or higher. dnl Also set "-fno-exceptions" for C++ because exception handling requires dnl the frame pointer. @@ -1076,7 +1086,7 @@ dnl As of 2001/08/02, this affects the following compilers: dnl Official: probably gcc-3.1 (mainline CVS) dnl Mandrake: gcc-2.96 >= 0.59mdk, gcc-3.0.1 >= 0.1mdk dnl Red Hat : gcc-2.96 >= 89, gcc-3.0 >= 1 -if [[ "x$HAVE_GCC27" = "xyes" ]]; then +if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_ICC" = "xno" ]]; then SAVED_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fno-merge-constants" AC_CACHE_CHECK([whether GCC supports constants merging], ac_cv_gcc_constants_merging, [ @@ -1092,7 +1102,7 @@ fi dnl Store motion was introduced in 3.3-hammer branch and any gcc >= 3.4 dnl However, there are some corner cases exposed on x86-64 -if [[ "x$HAVE_GCC27" = "xyes" ]]; then +if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_ICC" = "xno" ]]; then SAVED_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fno-gcse-sm" AC_CACHE_CHECK([whether GCC supports store motion], ac_cv_gcc_store_motion, [ @@ -1106,6 +1116,19 @@ if [[ "x$HAVE_GCC27" = "xyes" ]]; then fi fi +dnl Add -fno-strict-aliasing for slirp sources +if [[ "x$HAVE_GCC30" = "xyes" ]]; then + SAVED_CXXFLAGS="$CXXFLAGS" + CFLAGS="$CFLAGS -fno-strict-aliasing" + AC_CACHE_CHECK([whether the compiler supports -fno-strict-aliasing], + ac_cv_gcc_no_strict_aliasing, [ + AC_TRY_COMPILE([],[], + [ac_cv_gcc_no_strict_aliasing=yes; AC_SUBST(SLIRP_CFLAGS, "$CFLAGS")], + [ac_cv_gcc_no_strict_aliasing=no]) + ]) + CFLAGS="$SAVED_CFLAGS" +fi + dnl Select appropriate CPU source and REGPARAM define. ASM_OPTIMIZATIONS=none CPUSRCS="cpuemu1.cpp cpuemu2.cpp cpuemu3.cpp cpuemu4.cpp cpuemu5.cpp cpuemu6.cpp cpuemu7.cpp cpuemu8.cpp" diff --git a/BasiliskII/src/Unix/ether_unix.cpp b/BasiliskII/src/Unix/ether_unix.cpp index 84e62bad..b16cf985 100644 --- a/BasiliskII/src/Unix/ether_unix.cpp +++ b/BasiliskII/src/Unix/ether_unix.cpp @@ -45,6 +45,11 @@ #include #endif +// XXX: slirp is currently not 64-bit clean +#if SIZEOF_VOID_P == 4 +#define HAVE_SLIRP 1 +#endif + #include "cpu_emulation.h" #include "main.h" #include "macos_util.h" @@ -52,6 +57,7 @@ #include "user_strings.h" #include "ether.h" #include "ether_defs.h" +#include "libslirp.h" #ifndef NO_STD_NAMESPACE using std::map; @@ -68,6 +74,7 @@ enum { NET_IF_SHEEPNET, NET_IF_ETHERTAP, NET_IF_TUNTAP, + NET_IF_SLIRP }; // Constants @@ -83,12 +90,16 @@ static bool udp_tunnel; // Flag: UDP tunnelling active, fd is the socket de static int net_if_type = -1; // Ethernet device type static char *net_if_name = NULL; // TUN/TAP device name static const char *net_if_script = NULL; // Network config script +static pthread_t slirp_thread; // Slirp reception thread +static bool slirp_thread_active = false; // Flag: Slirp reception threadinstalled +static int slirp_output_fd = -1; // fd of slirp output pipe // Attached network protocols, maps protocol type to MacOS handler address static map net_protocols; // Prototypes static void *receive_func(void *arg); +static void *slirp_receive_func(void *arg); /* @@ -109,6 +120,16 @@ static bool start_thread(void) return false; } +#ifdef HAVE_SLIRP + if (net_if_type == NET_IF_SLIRP) { + slirp_thread_active = (pthread_create(&slirp_thread, NULL, slirp_receive_func, NULL) == 0); + if (!slirp_thread_active) { + printf("WARNING: Cannot start slirp reception thread\n"); + return false; + } + } +#endif + return true; } @@ -119,6 +140,14 @@ static bool start_thread(void) static void stop_thread(void) { +#ifdef HAVE_SLIRP + if (slirp_thread_active) { + pthread_cancel(slirp_thread); + pthread_join(slirp_thread, NULL); + slirp_thread_active = false; + } +#endif + if (thread_active) { pthread_cancel(ether_thread); pthread_join(ether_thread, NULL); @@ -178,10 +207,28 @@ bool ether_init(void) #if ENABLE_TUNTAP else if (strcmp(name, "tun") == 0) net_if_type = NET_IF_TUNTAP; +#endif +#ifdef HAVE_SLIRP + else if (strcmp(name, "slirp") == 0) + net_if_type = NET_IF_SLIRP; #endif else net_if_type = NET_IF_SHEEPNET; +#ifdef HAVE_SLIRP + // Initialize slirp library + if (net_if_type == NET_IF_SLIRP) { + slirp_init(); + + // Open slirp output pipe + int fds[2]; + if (pipe(fds) < 0) + return false; + fd = fds[0]; + slirp_output_fd = fds[1]; + } +#endif + // Open sheep_net or ethertap or TUN/TAP device char dev_name[16]; switch (net_if_type) { @@ -195,11 +242,13 @@ bool ether_init(void) strcpy(dev_name, "/dev/sheep_net"); break; } - fd = open(dev_name, O_RDWR); - if (fd < 0) { - sprintf(str, GetString(STR_NO_SHEEP_NET_DRIVER_WARN), dev_name, strerror(errno)); - WarningAlert(str); - goto open_error; + if (net_if_type != NET_IF_SLIRP) { + fd = open(dev_name, O_RDWR); + if (fd < 0) { + sprintf(str, GetString(STR_NO_SHEEP_NET_DRIVER_WARN), dev_name, strerror(errno)); + WarningAlert(str); + goto open_error; + } } #if ENABLE_TUNTAP @@ -257,6 +306,15 @@ bool ether_init(void) ether_addr[3] = p >> 16; ether_addr[4] = p >> 8; ether_addr[5] = p; +#ifdef HAVE_SLIRP + } else if (net_if_type == NET_IF_SLIRP) { + ether_addr[0] = 0x52; + ether_addr[1] = 0x54; + ether_addr[2] = 0x00; + ether_addr[3] = 0x12; + ether_addr[4] = 0x34; + ether_addr[5] = 0x56; +#endif } else ioctl(fd, SIOCGIFADDR, ether_addr); D(bug("Ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); @@ -275,6 +333,10 @@ open_error: close(fd); fd = -1; } + if (slirp_output_fd >= 0) { + close(slirp_output_fd); + slirp_output_fd = -1; + } return false; } @@ -304,6 +366,10 @@ void ether_exit(void) // Close sheep_net device if (fd > 0) close(fd); + + // Close slirp output buffer + if (slirp_output_fd > 0) + close(slirp_output_fd); } @@ -323,14 +389,19 @@ void ether_reset(void) int16 ether_add_multicast(uint32 pb) { - if (net_if_type != NET_IF_TUNTAP && ioctl(fd, SIOCADDMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) { - D(bug("WARNING: Couldn't enable multicast address\n")); - if (net_if_type == NET_IF_ETHERTAP) - return noErr; - else - return eMultiErr; - } else + switch (net_if_type) { + case NET_IF_ETHERTAP: + case NET_IF_SHEEPNET: + if (ioctl(fd, SIOCADDMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) { + D(bug("WARNING: Couldn't enable multicast address\n")); + if (net_if_type == NET_IF_ETHERTAP) + return noErr; + else + return eMultiErr; + } + default: return noErr; + } } @@ -340,11 +411,16 @@ int16 ether_add_multicast(uint32 pb) int16 ether_del_multicast(uint32 pb) { - if (net_if_type != NET_IF_TUNTAP && ioctl(fd, SIOCDELMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) { - D(bug("WARNING: Couldn't disable multicast address\n")); - return eMultiErr; - } else + switch (net_if_type) { + case NET_IF_ETHERTAP: + case NET_IF_SHEEPNET: + if (ioctl(fd, SIOCDELMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) { + D(bug("WARNING: Couldn't disable multicast address\n")); + return eMultiErr; + } + default: return noErr; + } } @@ -400,6 +476,12 @@ int16 ether_write(uint32 wds) #endif // Transmit packet +#ifdef HAVE_SLIRP + if (net_if_type == NET_IF_SLIRP) { + slirp_input(packet, len); + return noErr; + } else +#endif if (write(fd, packet, len) < 0) { D(bug("WARNING: Couldn't transmit packet\n")); return excessCollsns; @@ -431,6 +513,53 @@ void ether_stop_udp_thread(void) } +/* + * SLIRP output buffer glue + */ + +#ifdef HAVE_SLIRP +int slirp_can_output(void) +{ + return 1; +} + +void slirp_output(const uint8 *packet, int len) +{ + write(slirp_output_fd, packet, len); +} + +void *slirp_receive_func(void *arg) +{ + for (;;) { + // Wait for packets to arrive + fd_set rfds, wfds, xfds; + int nfds; + struct timeval tv; + + nfds = -1; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&xfds); + slirp_select_fill(&nfds, &rfds, &wfds, &xfds); + tv.tv_sec = 0; + tv.tv_usec = 16667; + if (select(nfds + 1, &rfds, &wfds, &xfds, &tv) >= 0) + slirp_select_poll(&rfds, &wfds, &xfds); + } + return NULL; +} +#else +int slirp_can_output(void) +{ + return 0; +} + +void slirp_output(const uint8 *packet, int len) +{ +} +#endif + + /* * Packet reception thread */