summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/strat.c
blob: fb00d5b7247d5b92c9ba1e15f147e9b42addc631 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
**  strat.c  10-5-91  Robert Mashlan, public domain
**
**   Interface functions to DOS 3.0+ set allocation strategy
**   and get allocation strategy functions via int 21h,
**   function 58h.
**
**   By setting the dos allocation strategy to LAST_FIT_LOW
**   before using DOS the set handle count function int 21h,
**   function 67h, DOS will allocate memory for the extended
**   file handle table at the end of free memory instead of
**   after the last heap allocation, with the benefit of
**   allowing the heap manager make further contiguous
**   allocations from the operating system.
**
*/

#include <stdlib.h>
#include <dos.h>
#include "strat.h"

/*
**   Gets dos memory allocation strategy via function 0x58.
**   Returns  allocation strategy, else returns -1 and sets
**   _doserrno on error.
*/

int get_alloc_strat(void)
{
      union REGS r;

      r.x.ax = 0x5800;              /* DOS "get allocation strategy" */
      int86(0x21,&r,&r);
      if (r.x.cflag)                /* error? */
      {
            _doserrno = r.x.ax;     /* save error code */
            return -1;
      }
      else  return r.x.ax;
}

/*
**   Sets DOS memory allocation strategy
**   returns allocation strategy on success,
**   else returns -1 and sets _doserrno on error
*/

int set_alloc_strat( int strat )
{
      union REGS r;

      r.x.ax = 0x5801;              /* DOS "set allocation strategy" */
      r.x.bx = strat;
      int86(0x21,&r,&r);
      if (r.x.cflag)                /* error? */
      {
            _doserrno = r.x.ax;     /* save error code */
            return -1;
      }
      _doserrno = 0;
      return strat;
}

/*
**   Uses dos function 67h to increase open file handle count.
**   Returns -1 and sets _doserrno on error, 0 otherwise.
*/

int set_handle_count( unsigned nhandles )
{
      union REGS r;

      r.x.ax = 0x6700;
      r.x.bx = nhandles;
      int86(0x21,&r,&r);
      if(r.x.cflag)
      {
            _doserrno = r.x.ax;
            return -1;
      }
      _doserrno = 0;
      return 0;
}

#ifdef DEMO

#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>

/*
**  returns maximum number of files that can be open
*/

int handle_count(void)
{
      int handles[500];
      int i, result;

      /* try allocating as many file handles as possible */

      for (i = 0; i < 500; i++)
      {
            if( (handles[i]=open("NUL",O_WRONLY)) == -1 )
                  break;
      }
      result = i;

      /* close all files opened */

      for (i--; i >= 0; i--)
            close(handles[i]);
      return result;
}


/*
**   Memory test, returns number of kilobytes that
**   can be allocated before failure.
*/

int memtest(void)
{
      static void *mem[1024];
      int i,result;

      /* try allocating as many 1K blocks as possible */

      for(i=0;i<1024;i++)
      {
            if( (mem[i]=malloc(1024)) == NULL )
                  break;
      }
      result = i;                               /* save result */

      /* free memory allocated */

      for(i--; i >= 0; i--)
            free(mem[i]);
      return result;
}

#define checkdoserror(f) \
   ((f==-1)?printf("%s failed, doserror = %#02x\n",#f,_doserrno):(void)0)

int main(void)
{
      int strat;

      /* do pre-test diagnostics */

      printf("allocated %d Kbytes before failure\n",memtest());
      printf("opened %d files\n",handle_count());

      strat = get_alloc_strat();  /* save current allocation strategy */
      checkdoserror(set_alloc_strat(LAST_FIT_LOW));
      puts("setting handle count to 50, with changed allocation strategy");
      checkdoserror(set_handle_count(50));
      checkdoserror(set_alloc_strat(strat)); /* restore strategy */

      /* do post-test diagnostics */

      printf("allocated %d Kbytes before failure\n",memtest());
      printf("opened %d files\n",handle_count());

      return 0;
}

#endif