Subject: faster fork.
From: [email-masked] (Tim Newsham)

2 Nov 1997 13:38:31 -0800
Message-ID: <[email-masked]>
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
To: [email-masked]

Hi,

    Here are my diffs for a faster fork.  It makes cygwin
do lazy initialization of sockets and of the password/group databases.
It also assumes that uid/gid does not change across fork.
I have been using these sources for a few days now and it seems
to be working ok.  Note the patches are against a slightly
modified version of the cygwin library so some of the net.cc
changes might have to be done by hand.

                                       Tim N.

diff -c5 -r winsup.970904t4/dcrt0.cc winsup/dcrt0.cc
*** winsup.970904t4/dcrt0.cc	Tue Oct 28 14:10:03 1997
--- winsup/dcrt0.cc	Thu Oct 30 13:40:40 1997
***************
*** 403,415 ****
    hmap_init ();
  
    /* Initialize uid, gid.  */
    uinfo_init ();
  
-   /* Initialize winsock */
-   socket_checkinit ();
- 
    syscall_printf ("Application CYGWIN version: %d.%d\n",
  		  u->version_major, u->version_minor);
    syscall_printf ("CYGWIN DLL version        : %d.%d\n",
  		  cygwin_dll_version_major, cygwin_dll_version_minor);
  
--- 403,412 ----
diff -c5 -r winsup.970904t4/fork.cc winsup/fork.cc
*** winsup.970904t4/fork.cc	Tue Oct 28 14:10:04 1997
--- winsup/fork.cc	Thu Oct 30 13:40:45 1997
***************
*** 445,460 ****
        if (recreate_mmaps_after_fork (u->self->mmap_ptr))
          {
            small_printf ("fork child: recreate_mmaps_after_fork_failed\n");
            ExitProcess (1);
          }
- 
-       /* Initialize uid, gid.  */
-       uinfo_init ();
- 
-       /* Ensure winsock is enabled for the child. */
-       socket_checkinit ();
  #if 0
        print_checksum (4, s->base[0][0], s->base[0][1]);
        print_checksum (5, s->base[1][0], s->base[1][1]);
        print_checksum (6, s->base[2][0], s->base[2][1]);
        print_checksum (7, s->base[3][0], s->base[3][1]);
--- 445,454 ----
diff -c5 -r winsup.970904t4/grp.cc winsup/grp.cc
*** winsup.970904t4/grp.cc	Tue Oct 28 14:10:06 1997
--- winsup/grp.cc	Thu Oct 30 13:22:33 1997
***************
*** 14,23 ****
--- 14,25 ----
  #include <grp.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include "winsup.h"
  
+ /* only read /etc/group on first query */
+ static int grp_init = 0;
  static char *def_group = "everyone";
  static int def_group_id = 500;
  static char *etc_group = "/etc/group";
  static char **group_buf = NULL;
  static int curr_lines = 0;
***************
*** 37,47 ****
          group_buf = new_grp_buf;
      }
      group_buf[curr_lines++] = strdup (line);
  }
  
! void read_etc_group ()
  {
    FILE *f = fopen (etc_group, "r");
  
    if (f)
      {
--- 39,49 ----
          group_buf = new_grp_buf;
      }
      group_buf[curr_lines++] = strdup (line);
  }
  
! static void read_etc_group ()
  {
    FILE *f = fopen (etc_group, "r");
  
    if (f)
      {
***************
*** 53,72 ****
--- 55,78 ----
            add_grp_line (linebuf);
          }
  
        fclose (f);
      }
+     grp_init = 1;
  }
  
  extern "C"
  struct group *
  getgrgid (gid_t gid)
  {
    static struct group grp;
    static char *namearray[2];
    static char linebuf[100];
  
+   if(!grp_init)
+     read_etc_group();
+ 
    for (int i = 0; i < curr_lines; i++)
    {
      char *id_ptr;
      strcpy (linebuf, group_buf[i]);
      grp.gr_name = strtok (linebuf, ":");
***************
*** 100,109 ****
--- 106,118 ----
  getgrnam (const char *name)
  {
    static struct group grp;
    static char *namearray[2];
    static char linebuf[100];
+ 
+   if(!grp_init)
+     read_etc_group();
  
    for (int i = 0; i < curr_lines; i++)
    {
      char *id_ptr;
      strcpy (linebuf, group_buf[i]);
diff -c5 -r winsup.970904t4/net.cc winsup/net.cc
*** winsup.970904t4/net.cc	Tue Oct 28 14:10:17 1997
--- winsup/net.cc	Thu Oct 30 14:01:36 1997
***************
*** 35,73 ****
  fail (int n)
  {
    debug_printf ("********%d*************\n",n);
  }
  
! int init;
  
  extern "C" {
  int h_errno;
  };
  
  void
! socket_checkinit ()
  {
!   WSADATA p;
!   if (!init) 
!     {
!       int res = WSAStartup ((2<<8) |2, &p);
!       debug_printf ("res %d\n", res);
!       debug_printf ("wVersion %d\n", p.wVersion);
        debug_printf ("wHighVersion %d\n", p.wHighVersion);
!       debug_printf ("szDescription %s\n",p.szDescription);
!       debug_printf ("szSystemStatus %s\n",p.szSystemStatus);
!       debug_printf ("iMaxSockets %d\n", p.iMaxSockets);
!       debug_printf ("iMaxUdpDg %d\n", p.iMaxUdpDg);
!       debug_printf ("lpVendorInfo %d\n", p.lpVendorInfo);
! 
!       if (FIONBIO  != REAL_FIONBIO)
! 	{
! 	  debug_printf ("****************  FIONBIO  != REAL_FIONBIO\n");
! 	}
!     }
!   init = 1;
!   MARK();
  }
  
  extern "C"
  unsigned long int
  htonl (unsigned long int x)
--- 35,69 ----
  fail (int n)
  {
    debug_printf ("********%d*************\n",n);
  }
  
! int socket_init = 0;
  
  extern "C" {
  int h_errno;
  };
  
  void
! initialize_sockets ()
  {
!    WSADATA p;
!    int res = WSAStartup ((2<<8) |2, &p);
!    socket_init = 1;
!    debug_printf ("res %d\n", res);
!    debug_printf ("wVersion %d\n", p.wVersion);
        debug_printf ("wHighVersion %d\n", p.wHighVersion);
!    debug_printf ("szDescription %s\n",p.szDescription);
!    debug_printf ("szSystemStatus %s\n",p.szSystemStatus);
!    debug_printf ("iMaxSockets %d\n", p.iMaxSockets);
!    debug_printf ("iMaxUdpDg %d\n", p.iMaxUdpDg);
!    debug_printf ("lpVendorInfo %d\n", p.lpVendorInfo);
! 
!    if (FIONBIO  != REAL_FIONBIO)
!    {
!      debug_printf ("****************  FIONBIO  != REAL_FIONBIO\n");
!    }
  }
  
  extern "C"
  unsigned long int
  htonl (unsigned long int x)
***************
*** 229,238 ****
--- 225,236 ----
  
  extern "C"
  struct protoent *
  cygwin32_getprotobyname (const char *p)
  {
+   if(!socket_init)
+       initialize_sockets ();
    MARK();
    in ("getprotobyname");
  
    struct protoent *res = getprotobyname (p);
    if (!res)
***************
*** 245,254 ****
--- 243,254 ----
  
  extern "C"
  struct protoent *
  cygwin32_getprotobynumber(int number)
  {
+   if(!socket_init)
+       initialize_sockets ();
    MARK();
    in ("getprotobynumber");
  
    struct protoent *res = getprotobynumber(number);
    if (!res)
***************
*** 261,270 ****
--- 261,272 ----
  
  extern "C"
  int
  cygwin32_socket (int af, int type, int protocol)
  {
+   if(!socket_init)
+       initialize_sockets ();
    int res = -1;
    in ("socket");
    pinfo *p = u->self;
    SOCKET soc, newsock;
  
***************
*** 326,335 ****
--- 328,339 ----
  		 unsigned int flags,
  		 const struct sockaddr *to, 
  		 int tolen)
  {
    fhandler_socket *h = (fhandler_socket *) u->self->hmap.vec[fd].h;
+   if(!socket_init)
+       initialize_sockets ();
    in ("sendto");
    int res = sendto (h->get_socket(), (const char *)buf, len, flags, to, tolen);
    if (res == SOCKET_ERROR) {
      set_winsock_errno ();
      res = -1;
***************
*** 347,356 ****
--- 351,362 ----
  		   struct sockaddr *from,
  		   int *fromlen)
  {
    int res;
    fhandler_socket *h = (fhandler_socket *) u->self->hmap.vec[fd].h;
+   if(!socket_init)
+       initialize_sockets ();
    in ("recvfrom");
  
    debug_printf ("recvfrom %d\n", h->get_socket ());
    res = h->canread(len);
  
***************
*** 382,391 ****
--- 388,399 ----
  		     int level,
  		     int optname,
  		     const void *optval, 
  		     int optlen)
  {
+   if(!socket_init)
+       initialize_sockets ();
    in ("setsockopt");
    fhandler_socket *h = get (fd);
    int res = -1;
    const char *name = "error";
    if (h) 
***************
*** 427,436 ****
--- 435,446 ----
  		     int level,
  		     int optname,
  		     void *optval, 
  		     int *optlen)
  {
+   if(!socket_init)
+       initialize_sockets ();
    in ("getsockopt");
    fhandler_socket *h = get (fd);
    int res = -1;
    const char *name = "error";
    if (h) 
***************
*** 466,475 ****
--- 476,487 ----
  int
  cygwin32_connect (int fd,
  		  const struct sockaddr * name,
  		  int namelen)
  {
+   if(!socket_init)
+       initialize_sockets ();
    in ("connect");
    int res;
    fhandler_socket *s = get (fd);
    if (!s)
      {
***************
*** 491,500 ****
--- 503,514 ----
  
  extern "C"
  struct servent *
  cygwin32_getservbyname (const char *name, const char *proto)
  {
+   if(!socket_init)
+       initialize_sockets ();
    in ("getservbyname");
    struct servent *p = getservbyname (name, proto);
    if (!p)
      set_winsock_errno ();
  
***************
*** 506,515 ****
--- 520,531 ----
  
  extern "C"
  struct servent *
  cygwin32_getservbyport (int port, const char *proto)
  {
+   if(!socket_init)
+       initialize_sockets ();
    in ("getservbyport");
    struct servent *p = getservbyport(port, proto);
    if (!p)
      set_winsock_errno ();
  
***************
*** 522,531 ****
--- 538,549 ----
  extern "C"
  struct hostent *
  cygwin32_gethostbyname (const char *name)
  {
    MARK();
+   if(!socket_init)
+       initialize_sockets ();
    in ("gethostbyname");
    struct hostent *ptr = gethostbyname (name);
    if (!ptr)
      {
        set_winsock_errno ();
***************
*** 543,552 ****
--- 561,572 ----
  extern "C" 
  struct hostent *
  cygwin32_gethostbyaddr (const char *addr, int len, int type)
  {
    MARK();
+   if(!socket_init)
+       initialize_sockets ();
    in ("gethostbyaddr");
    struct hostent *ptr = gethostbyaddr (addr, len, type);
    if (!ptr)
      {
        set_winsock_errno ();
***************
*** 562,571 ****
--- 582,593 ----
  }
  
  int
  fhandler_socket::write (const void *ptr, size_t len)
  {
+   if(!socket_init)
+       initialize_sockets ();
    int res = send (get_socket (), (const char *)ptr, len, 0);
    if (res == SOCKET_ERROR)
      {
        set_winsock_errno ();
        if (get_errno () == ECONNABORTED || get_errno () == ECONNRESET)
***************
*** 575,584 ****
--- 597,608 ----
  }
  
  int
  fhandler_socket::read (void *ptr, size_t len)
  {
+   if(!socket_init)
+       initialize_sockets ();
    in ("read");
    int res = canread(len);
    res = recv (get_socket (), (char *)ptr, res, 0);
    if (res == SOCKET_ERROR)
      {
***************
*** 592,601 ****
--- 616,627 ----
  int
  cygwin32_accept (int fd, struct sockaddr *peer, int *len)
  {
    int res = -1;
    SOCKET newsock;
+   if(!socket_init)
+       initialize_sockets ();
    in ("accept");
    fhandler_socket *s = get (fd);
    if (s)
      {
        pinfo *p = u->self;
***************
*** 639,648 ****
--- 665,676 ----
  extern "C"
  int
  cygwin32_bind (int fd, struct sockaddr *my_addr, int addrlen)
  {
    int res = -1;
+   if(!socket_init)
+       initialize_sockets ();
    in ("bind");
    fhandler_socket *s = get (fd);
    if (s)
      {
        res = bind (s->get_socket (), my_addr, addrlen);
***************
*** 657,666 ****
--- 685,696 ----
  extern "C"
  int
  cygwin32_getsockname (int fd, struct sockaddr *addr, int *namelen)
  {
    int res = -1;
+   if(!socket_init)
+       initialize_sockets ();
    in ("getsockname");
    fhandler_socket *s = get (fd);
    if (s)
      {
        res = getsockname (s->get_socket (), addr, namelen);
***************
*** 676,685 ****
--- 706,717 ----
  extern "C"
  int
  cygwin32_listen (int fd, int backlog)
  {
    int res = -1;
+   if(!socket_init)
+       initialize_sockets ();
    in ("listen");
  
    fhandler_socket *s = get (fd);
    if (s)
      {
***************
*** 695,704 ****
--- 727,738 ----
  extern "C"
  int
  cygwin32_shutdown (int fd, int how)
  {
    int res = -1;
+   if(!socket_init)
+       initialize_sockets ();
    in ("shutdown");
  
    fhandler_socket *s = get (fd);
    if (s)
      {
***************
*** 728,737 ****
--- 762,773 ----
  extern "C"
  int
  cygwin32_send (int fd, const void *buf, int len, unsigned int flags)
  {
    fhandler_socket *h = (fhandler_socket *) u->self->hmap.vec[fd].h;
+   if(!socket_init)
+       initialize_sockets ();
    in ("send");
  
    int res = send (h->get_socket (),(const char *) buf, len, flags);
    if (res == SOCKET_ERROR) {
      set_winsock_errno ();
***************
*** 753,762 ****
--- 789,800 ----
  
  int
  fhandler_socket::close ()
  {
    int res;
+   if(!socket_init)
+       initialize_sockets ();
    if (closesocket (get_socket ())) 
      {
        set_winsock_errno ();
        res = -1;
      }
***************
*** 866,875 ****
--- 904,915 ----
  int
  cygwin32_recv (int fd, void *buf, int len, unsigned int flags)
  {
    int res;
    fhandler_socket *h = (fhandler_socket *) u->self->hmap.vec[fd].h;
+   if(!socket_init)
+       initialize_sockets ();
    in ("recv");
  
    res = h->canread(len);
  
    res = recv (h->get_socket (), (char *)buf, res, flags);
***************
*** 898,907 ****
--- 938,949 ----
  extern "C"
  int
  cygwin32_getpeername (int fd, struct sockaddr *name, int *len)
  {
    fhandler_socket *h = (fhandler_socket *) u->self->hmap.vec[fd].h;
+   if(!socket_init)
+       initialize_sockets ();
    in ("getpeername");
  
    debug_printf ("getpeername %d\n", h->get_socket ());
    int res = getpeername (h->get_socket (), name, len);
    if (res)
***************
*** 1077,1086 ****
--- 1119,1130 ----
  int
  fhandler_socket::ioctl (int cmd, void *p)
  {
    int res;
  
+   if(!socket_init)
+       initialize_sockets ();
    switch (cmd)
      {
      case SIOCGIFCONF:
        {
          struct ifconf *ifc = (struct ifconf *) p;
***************
*** 1147,1154 ****
--- 1191,1200 ----
  }
  
  int
  fhandler_socket::fstat (struct stat *buf)
  {
+   if(!socket_init)
+       initialize_sockets ();
    syscall_printf ("******************** FSTAT!\n");
    return -1;
  }
diff -c5 -r winsup.970904t4/passwd.cc winsup/passwd.cc
*** winsup.970904t4/passwd.cc	Tue Oct 28 14:10:18 1997
--- winsup/passwd.cc	Thu Oct 30 13:23:03 1997
***************
*** 12,26 ****
  #include <pwd.h>
  #include <stdio.h>
  #include <termios.h>
  #include "winsup.h"
  
! /* read the /etc/passwd only once on process startup to improves performance */
  static char **passwd_buf = NULL;
  static int curr_lines = 0;
  static int max_lines = 0;
  
  /* cache the last passwd query */
  static struct passwd last_passwd = { 0, 0, 0, 0, 0, 0, 0, 0 };
  
  static void
  add_pwd_line (char *line)
--- 12,28 ----
  #include <pwd.h>
  #include <stdio.h>
  #include <termios.h>
  #include "winsup.h"
  
! /* read /etc/passwd only on the first query to improve performance */
! static int pw_init = 0;
  static char **passwd_buf = NULL;
  static int curr_lines = 0;
  static int max_lines = 0;
  
+ 
  /* cache the last passwd query */
  static struct passwd last_passwd = { 0, 0, 0, 0, 0, 0, 0, 0 };
  
  static void
  add_pwd_line (char *line)
***************
*** 37,47 ****
          passwd_buf = new_pwd_buf;
      }
      passwd_buf[curr_lines++] = strdup (line);
  }
  
! void
  read_etc_passwd()
  {
      FILE *f = fopen ("/etc/passwd", "r");
      
      if (f)
--- 39,49 ----
          passwd_buf = new_pwd_buf;
      }
      passwd_buf[curr_lines++] = strdup (line);
  }
  
! static void
  read_etc_passwd()
  {
      FILE *f = fopen ("/etc/passwd", "r");
      
      if (f)
***************
*** 54,63 ****
--- 56,66 ----
              add_pwd_line (linebuf);
          }
  
          fclose (f);
      }
+     pw_init = 1;
  }
  
  /* Remove a : teminated string from the buffer, and inc the pointer */
  
  static char *
***************
*** 166,197 ****
  
  extern "C"
  struct passwd *
  getpwuid (uid_t uid)
  {
    return search_for (uid, 0);
  }
  
  extern "C"
  struct passwd *
  getpwnam (const char *name)
  {
    return search_for (0,name);
  }
  
  /* replace any accesses to /etc/passwd by accesses to the passwd cache */
! /* FIXME: i is a very poor naming choice for a global */
! static int i = 0;
  
  extern "C"
  struct passwd *
  getpwent (void)
  {
    char buf[_PASSWORD_LEN];
!   if (i < curr_lines)
      {
!       strcpy (buf, passwd_buf[i++]);
        return parse (buf);
      }
  
    return NULL;
  }
--- 169,207 ----
  
  extern "C"
  struct passwd *
  getpwuid (uid_t uid)
  {
+   if(!pw_init)
+     read_etc_passwd();
    return search_for (uid, 0);
  }
  
  extern "C"
  struct passwd *
  getpwnam (const char *name)
  {
+   if(!pw_init)
+     read_etc_passwd();
    return search_for (0,name);
  }
  
  /* replace any accesses to /etc/passwd by accesses to the passwd cache */
! static int pw_pos = 0;
  
  extern "C"
  struct passwd *
  getpwent (void)
  {
    char buf[_PASSWORD_LEN];
! 
!   if(!pw_init)
!     read_etc_passwd();
! 
!   if (pw_pos < curr_lines)
      {
!       strcpy (buf, passwd_buf[pw_pos++]);
        return parse (buf);
      }
  
    return NULL;
  }
***************
*** 205,222 ****
  
  extern "C"
  void
  setpwent (void)
  {
!   i = curr_lines - 1;
  }
  
  extern "C"
  void
  endpwent (void)
  {
!   i = 0;
  }
  
  extern "C"
  int
  setpassent ()
--- 215,232 ----
  
  extern "C"
  void
  setpwent (void)
  {
!   pw_pos = 0;
  }
  
  extern "C"
  void
  endpwent (void)
  {
!   pw_pos = 0;
  }
  
  extern "C"
  int
  setpassent ()
diff -c5 -r winsup.970904t4/select.cc winsup/select.cc
*** winsup.970904t4/select.cc	Tue Oct 28 14:10:19 1997
--- winsup/select.cc	Thu Oct 30 14:01:25 1997
***************
*** 34,43 ****
--- 34,45 ----
   */
  
  #define __INSIDE_CYGWIN32__
  #include <mywinsock.h>
  
+ extern int socket_init;
+ 
  /*
   * Use this struct to interface to
   * the system provided select.
   */
  
***************
*** 936,945 ****
--- 938,950 ----
    int console_used = (number_of_read_consoles != 0);
    int pipe_used = (number_of_read_pipes != 0);
    int always_ready_used = ((number_of_read_always_ready != 0) ||
                             (number_of_write_always_ready != 0) ||
                             (number_of_except_always_ready != 0));
+ 
+   if(socket_used > 0 && !socket_init)
+       initialize_sockets();
  
  #if 0
    /* Look for easy to handle cases. One is where all
     * given fd's are sockets. In this case create the Win32 fd_set
     * and call win32 select. This should be the most common case.
diff -c5 -r winsup.970904t4/uinfo.cc winsup/uinfo.cc
*** winsup.970904t4/uinfo.cc	Tue Oct 28 14:10:26 1997
--- winsup/uinfo.cc	Wed Oct 29 12:40:11 1997
***************
*** 10,31 ****
  
  #include <pwd.h>
  #include <unistd.h>
  #include "winsup.h"
  
- void read_etc_passwd ();
- void read_etc_group ();
- 
  #define MAX_USER_NAME 20
  
  void
  uinfo_init ()
  {
    struct passwd *p;
- 
-   read_etc_passwd ();
-   read_etc_group ();
  
    if ((p = getpwnam (getlogin ())) != NULL)
      {
        u->self->uid = p->pw_uid;
        u->self->gid = p->pw_gid;
--- 10,25 ----
diff -c5 -r winsup.970904t4/winsup.h winsup/winsup.h
*** winsup.970904t4/winsup.h	Tue Oct 28 14:10:27 1997
--- winsup/winsup.h	Thu Oct 30 13:26:44 1997
***************
*** 533,543 ****
  SECURITY_DESCRIPTOR *get_null_sd ();
  
  int file_exists (const char *);
  
  /* Initialize winsock */
! void socket_checkinit ();
  
  int get_id_from_sid (PSID);
  
  BOOL ctrl_c_handler (DWORD);
  extern "C" void set_process_mask (sigset_t newmask);
--- 533,543 ----
  SECURITY_DESCRIPTOR *get_null_sd ();
  
  int file_exists (const char *);
  
  /* Initialize winsock */
! void initialize_sockets();
  
  int get_id_from_sid (PSID);
  
  BOOL ctrl_c_handler (DWORD);
  extern "C" void set_process_mask (sigset_t newmask);
-
For help on using this list (especially unsubscribing), send a message to
"[email-masked]" with one line of text: "help".