ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/ether_unix.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/ether_unix.cpp (file contents):
Revision 1.24 by nigel, 2005-12-29T13:40:25Z vs.
Revision 1.32 by asvitkine, 2011-12-28T20:22:25Z

# Line 1 | Line 1
1   /*
2   *  ether_unix.cpp - Ethernet device driver, Unix specific stuff (Linux and FreeBSD)
3   *
4 < *  Basilisk II (C) 1997-2005 Christian Bauer
4 > *  Basilisk II (C) 1997-2008 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 20 | Line 20
20  
21   #include "sysdeps.h"
22  
23 + /*
24 + *  NOTES concerning MacOS X issues:
25 + *  - poll() does not exist in 10.2.8, but is available in 10.4.4
26 + *  - select(), and very likely poll(), are not cancellation points. So
27 + *    the ethernet thread doesn't stop on exit. An explicit check is
28 + *    performed to workaround this problem.
29 + */
30 + #if (defined __APPLE__ && defined __MACH__) || ! defined HAVE_POLL
31 + #define USE_POLL 0
32 + #else
33 + #define USE_POLL 1
34 + #endif
35 +
36 + // Define to let the slirp library determine the right timeout for select()
37 + #define USE_SLIRP_TIMEOUT 1
38 +
39   #ifdef HAVE_SYS_POLL_H
40   #include <sys/poll.h>
41   #endif
# Line 31 | Line 47
47   #include <semaphore.h>
48   #include <errno.h>
49   #include <stdio.h>
50 + #include <signal.h>
51   #include <map>
52  
53   #if defined(__FreeBSD__) || defined(sgi) || (defined(__APPLE__) && defined(__MACH__))
# Line 108 | Line 125 | static map<uint16, uint32> net_protocols
125   // Prototypes
126   static void *receive_func(void *arg);
127   static void *slirp_receive_func(void *arg);
111 static int poll_fd(int fd);
128   static int16 ether_do_add_multicast(uint8 *addr);
129   static int16 ether_do_del_multicast(uint8 *addr);
130   static int16 ether_do_write(uint32 arg);
# Line 167 | Line 183 | static void stop_thread(void)
183   #ifdef HAVE_PTHREAD_CANCEL
184                  pthread_cancel(ether_thread);
185   #endif
170 #ifdef AQUA
171                // This call, which waits for ether_thread to terminate,
172                // never returns when used in Nigel's OS X port.
173 #else
186                  pthread_join(ether_thread, NULL);
175 #endif
187                  sem_destroy(&int_ack);
188                  thread_active = false;
189          }
# Line 214 | Line 225 | static bool execute_network_script(const
225  
226   bool ether_init(void)
227   {
228 <        int nonblock = 1;
228 >        int val, nonblock = 1;
229          char str[256];
230  
231          // Do nothing if no Ethernet device specified
# Line 237 | Line 248 | bool ether_init(void)
248          else
249                  net_if_type = NET_IF_SHEEPNET;
250  
251 +        // Don't raise SIGPIPE, let errno be set to EPIPE
252 +        struct sigaction sigpipe_sa;
253 +        if (sigaction(SIGPIPE, NULL, &sigpipe_sa) == 0) {
254 +                assert(sigpipe_sa.sa_handler == SIG_DFL || sigpipe_sa.sa_handler == SIG_IGN);
255 +                sigfillset(&sigpipe_sa.sa_mask);
256 +                sigpipe_sa.sa_flags = 0;
257 +                sigpipe_sa.sa_handler = SIG_IGN;
258 +                sigaction(SIGPIPE, &sigpipe_sa, NULL);
259 +        }
260 +
261   #ifdef HAVE_SLIRP
262          // Initialize slirp library
263          if (net_if_type == NET_IF_SLIRP) {
# Line 325 | Line 346 | bool ether_init(void)
346   #endif
347  
348          // Set nonblocking I/O
349 <        ioctl(fd, FIONBIO, &nonblock);
349 > #ifdef USE_FIONBIO
350 >        if (ioctl(fd, FIONBIO, &nonblock) < 0) {
351 >                sprintf(str, GetString(STR_BLOCKING_NET_SOCKET_WARN), strerror(errno));
352 >                WarningAlert(str);
353 >                goto open_error;
354 >        }
355 > #else
356 >        val = fcntl(fd, F_GETFL, 0);
357 >        if (val < 0 || fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) {
358 >                sprintf(str, GetString(STR_BLOCKING_NET_SOCKET_WARN), strerror(errno));
359 >                WarningAlert(str);
360 >                goto open_error;
361 >        }
362 > #endif
363  
364          // Get Ethernet address
365          if (net_if_type == NET_IF_ETHERTAP) {
# Line 780 | Line 814 | void *slirp_receive_func(void *arg)
814                  FD_ZERO(&rfds);
815                  FD_ZERO(&wfds);
816                  FD_ZERO(&xfds);
817 <                slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
817 >                int timeout = slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
818 > #if ! USE_SLIRP_TIMEOUT
819 >                timeout = 10000;
820 > #endif
821                  tv.tv_sec = 0;
822 <                tv.tv_usec = 10000;
822 >                tv.tv_usec = timeout;
823                  if (select(nfds + 1, &rfds, &wfds, &xfds, &tv) >= 0)
824                          slirp_select_poll(&rfds, &wfds, &xfds);
825  
# Line 815 | Line 852 | static void *receive_func(void *arg)
852          for (;;) {
853  
854                  // Wait for packets to arrive
855 < #if HAVE_POLL
855 > #if USE_POLL
856                  struct pollfd pf = {fd, POLLIN, 0};
857                  int res = poll(&pf, 1, -1);
858   #else
# Line 844 | Line 881 | static void *receive_func(void *arg)
881                          // Wait for interrupt acknowledge by EtherInterrupt()
882                          sem_wait(&int_ack);
883                  } else
884 <                        usleep(20000);
884 >                        Delay_usec(20000);
885          }
886          return NULL;
887   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines