From: newsham AT lava DOT net (Tim Newsham) Subject: faster fork. 2 Nov 1997 13:38:31 -0800 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit To: gnu-win32 AT cygnus DOT com 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 #include #include #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 #include #include #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 #include #include #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 + 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 #include #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 "gnu-win32-request AT cygnus DOT com" with one line of text: "help".