delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/08/19/00:30:22

From: sandmann AT clio DOT rice DOT edu (Charles Sandmann)
Message-Id: <10108190425.AA12230@clio.rice.edu>
Subject: Selector exhaustion code update
To: djgpp-workers AT delorie DOT com (DJGPP developers)
Date: Sat, 18 Aug 2001 23:25:18 -0500 (CDT)
X-Mailer: ELM [version 2.5 PL2]
Mime-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com

Included below is my version of the selector code based on Andris code
and my test code.

In the initialization section it tests which selector characteristics
change on a selector allocation.  Option 1, LAR, is Andris' discovery.
Option 2 is how I've found to do the same on Windows NT/2K/XP.  In both
cases I scan a relatively small area of the selector space, so the 
number of calls will not be a performance issue.  A map is kept for the
working area.  If nothing seems to be able to detect the change in
selector status, we do nothing (Option 3, blindly deallocate, is left in
the cleanup code but it cannot be actived currently.)

The code below is willing to leak a few selectors if the default scan 
zone is not large enough - it will then increase this area.  For all
images compiled with this code it never happens since we only leak 5
for each spawn.  If you have a nested non-cvs image, you might need 
to loose a few and then expand (so building make alone should work).

Comments?  Since the new code is rather conservative, I didn't see
a reason to disable it.


*** dosexec.c_	Sat Jul 28 17:54:04 2001
--- test3.c	Sat Aug 18 23:11:00 2001
*************** size_t __cmdline_str_len = sizeof(__cmdl
*** 157,163 ****
     if LFN is 2, there is a possiblity that the contents of the
     transfer buffer will be overrun!  */
  static int
! direct_exec_tail(const char *program, const char *args,
  		 char * const envp[], const char *proxy, int lfn,
  		 const char *cmdline_var)
  {
--- 157,163 ----
     if LFN is 2, there is a possiblity that the contents of the
     transfer buffer will be overrun!  */
  static int
! direct_exec_tail_1 (const char *program, const char *args,
  		 char * const envp[], const char *proxy, int lfn,
  		 const char *cmdline_var)
  {
*************** direct_exec_tail(const char *program, co
*** 413,418 ****
--- 413,532 ----
    return r.h.al;	/* AL holds the child exit code */
  }
  
+ static int direct_exec_tail (const char *program, const char *args,
+ 		 char * const envp[], const char *proxy, int lfn,
+ 		 const char *cmdline_var)
+ {
+   int i, ret;
+   int sel1, sel2;
+   static char first_call = 1;
+   static char workaround_descriptor_leaks = 0;
+   static unsigned char larbyte = 0;
+   static int how_deep = 12;
+   static char *desc_map = NULL;
+ 
+   sel1 = sel2 = 0;			/* Warnings */
+ 
+   if (first_call)
+   {
+     int flags;
+     char dpmi_vendor[128];
+     unsigned char desc_buf1[8], desc_buf2[8];
+ 
+     /* Disable descriptors leak workaround when CWSDPMI is being used */
+     /* since not needed.  Does not work with CWSDPMI versions before  */
+     /* r5 as corresponding DPMI call is supported beginning with v5.  */
+ 
+     ret = __dpmi_get_capabilities(&flags,dpmi_vendor);
+     if (ret == 0 && strcmp(dpmi_vendor+2,"CWSDPMI") == 0)
+       workaround_descriptor_leaks = 0;
+     else {
+       sel1 = __dpmi_allocate_ldt_descriptors(1);
+       larbyte = 0xf0 & __dpmi_get_descriptor_access_rights(sel1);
+       __dpmi_get_descriptor(sel1, &desc_buf1);
+       __dpmi_free_ldt_descriptor(sel1);
+       flags = __dpmi_get_descriptor_access_rights(sel1);	/* freed */
+ 
+       if (larbyte != (flags & 0xf0)) {	/* present+ring+sys changed */
+         workaround_descriptor_leaks = 1;
+ 
+       } else {				/* Win NT/2K/XP lie about lar */
+         larbyte = desc_buf1[5] & 0xf0;
+         ret = __dpmi_get_descriptor(sel1, &desc_buf2);
+         if (ret == -1 || (larbyte != (desc_buf2[5] & 0xf0))) {
+           workaround_descriptor_leaks = 2;
+         } else
+           workaround_descriptor_leaks = 0;	/* Don't do anything */
+       }
+     }
+     if (workaround_descriptor_leaks)
+       desc_map = (char *)malloc(how_deep);
+     first_call = 0;
+   }
+ 
+   if (workaround_descriptor_leaks)		/* Create the unused map */
+   {
+     unsigned char desc_buf[8];
+     char * map = desc_map;
+      
+     sel1 = __dpmi_allocate_ldt_descriptors(1);
+     if(sel1 < _dos_ds) {			/* Failure -1 also matches */
+       sel1 = _dos_ds;
+       *map++ = 0;				/* don't free it */
+     } else
+       *map++ = 1;				/* sel1 always released */
+     sel2 = sel1 + 8 * how_deep - 8;
+ 
+     if (workaround_descriptor_leaks == 1) {
+       for (i=sel1+8; i<=sel2; i+=8)
+         *map++ = (__dpmi_get_descriptor_access_rights(i) & 0xf0) != larbyte;
+ 
+     } else if (workaround_descriptor_leaks == 2) {
+       for (i=sel1+8; i<=sel2; i+=8)		/* Optimize here using lar */
+         if (__dpmi_get_descriptor(i, &desc_buf) == -1)
+           *map++ = 1;
+         else
+           *map++ = (desc_buf[5] & 0xf0) != larbyte;
+     }
+   }
+ 
+   ret = direct_exec_tail_1 ( program, args, envp, proxy, lfn, cmdline_var );
+ 
+   if (workaround_descriptor_leaks)		/* Free the unused map */
+   {
+     int endsel;
+     char * map;
+      
+     map = desc_map + how_deep;
+   
+     endsel = __dpmi_allocate_ldt_descriptors(1);
+     __dpmi_free_ldt_descriptor (endsel);
+ 
+     if (workaround_descriptor_leaks == 1) {
+       for (i=sel2; i>=sel1; i-=8)
+         if (*--map)
+           if ((__dpmi_get_descriptor_access_rights(i) & 0xf0) == larbyte)
+             __dpmi_free_ldt_descriptor(i);
+ 
+     } else if (workaround_descriptor_leaks == 2) {
+       for (i=sel2; i>=sel1; i-=8)
+         if (*--map)			/* No checking, doing faster */
+           __dpmi_free_ldt_descriptor(i);
+ 
+     } else if (workaround_descriptor_leaks == 3) {
+       for (i=endsel-8; i>=sel1; i-=8)
+         __dpmi_free_ldt_descriptor(i);
+     }
+     
+     if (endsel > sel2) {
+       free(desc_map);
+       how_deep = (endsel - sel1) / 4;			/* Twice what's needed */
+       desc_map = (char *)malloc(how_deep);
+     }
+   }
+   return ret;
+ }
+ 
  int
  _dos_exec(const char *program, const char *args, char * const envp[],
  	  const char *cmdline_var)

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019