source: vendor/emx/current/src/os2/profil.c

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 5.7 KB
Line 
1/* profil.c -- Sampling profiler
2 Copyright (c) 1995-1996 by Eberhard Mattes
3
4This file is part of emx.
5
6emx is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11emx is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with emx; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.
20
21As special exception, emx.dll can be distributed without source code
22unless it has been changed. If you modify emx.dll, this exception
23no longer applies and you must remove this paragraph from all source
24files for emx.dll. */
25
26
27#define INCL_DOSMODULEMGR
28#define INCL_DOSERRORS
29#include <os2emx.h>
30#include <emx/syscalls.h>
31#include "emxdll.h"
32#include "profil.h"
33#include "clib.h"
34
35static enum
36{
37 PS_INIT,
38 PS_FAIL,
39 PS_STOP,
40 PS_RUN
41} profil_state;
42
43static void *profil_buf;
44static unsigned profil_bufsiz;
45static unsigned profil_offset;
46static ULONG (*dosprofile)(ULONG, ULONG, PRFCMD *, PRFRET *);
47
48
49static int xdosprofile (ULONG func, ULONG pid, PRFCMD *cmd, PRFRET *ret)
50{
51 ULONG rc;
52
53 rc = dosprofile (func, pid, cmd, ret);
54 if (rc != 0)
55 return set_error (rc);
56 return 0;
57}
58
59
60static int profil_init (void)
61{
62 char obj[9];
63 HMODULE hmod;
64 ULONG rc;
65
66 profil_state = PS_FAIL;
67 rc = DosLoadModule (obj, sizeof (obj), "DOSCALLS", &hmod);
68 if (rc != 0)
69 return set_error (rc);
70 rc = DosQueryProcAddr (hmod, 377, NULL, (PPFN)&dosprofile);
71 if (rc != 0)
72 return set_error (rc);
73 profil_state = PS_STOP;
74 return 0;
75}
76
77
78static int profil_result (void)
79{
80 PRFRET prof_ret;
81 PRFRET3 *ret3;
82 ULONG ret3_size, rc;
83#ifdef DEBUG
84 PRFRET0 prof_ret0;
85 unsigned shift, i;
86#endif
87 int r;
88
89 if (profil_state != PS_RUN)
90 return set_error (ERROR_PRF_NOT_STARTED);
91 memset (profil_buf, 0, profil_bufsiz);
92 r = xdosprofile (PRF_CM_STOP, my_pid, NULL, NULL);
93 if (r != 0) return r;
94 profil_state = PS_STOP;
95
96#ifdef DEBUG
97 memset (&prof_ret0, 0, sizeof (prof_ret0));
98 prof_ret.us_cmd = PRF_RET_GLOBAL;
99 prof_ret.us_thrdno = 1;
100 prof_ret.us_vaddr = 0;
101 prof_ret.us_bufsz = sizeof (prof_ret0);
102 prof_ret.us_buf = &prof_ret0;
103 r = xdosprofile (PRF_CM_DUMP, my_pid, NULL, &prof_ret);
104 if (r != 0) return r;
105 shift = prof_ret0.r0_shift;
106 oprintf ("r0_shift=%u\r\n", shift);
107#endif
108
109 /* TODO: Overlay data preceding *profil_buff, if posible. */
110
111 ret3_size = profil_bufsiz + sizeof (PRFRET3);
112 rc = DosAllocMem ((PPVOID)&ret3, ret3_size,
113 PAG_READ | PAG_WRITE | PAG_COMMIT);
114 if (rc != 0)
115 return set_error (rc);
116 memset (ret3, 0, ret3_size);
117
118 memset (&prof_ret, 0, sizeof (prof_ret));
119 prof_ret.us_cmd = PRF_RET_VADETAIL;
120 prof_ret.us_thrdno = 1;
121 prof_ret.us_vaddr = profil_offset;
122 prof_ret.us_bufsz = ret3_size;
123 prof_ret.us_buf = ret3;
124 r = xdosprofile (PRF_CM_DUMP, my_pid, NULL, &prof_ret);
125 if (r != 0)
126 {
127 DosFreeMem (ret3);
128 return r;
129 }
130 memcpy (profil_buf, ret3->r3_cnts, profil_bufsiz);
131#ifdef DEBUG
132 for (i = 0; i < ret3->r3_ncnts; ++i)
133 oprintf ("%#.8x: %u\r\n",
134 profil_offset + (i << shift), ret3->r3_cnts[i]);
135#endif
136 DosFreeMem (ret3);
137 return xdosprofile (PRF_CM_EXIT, my_pid, NULL, NULL);
138}
139
140
141static int profil_start (const struct _profil *p)
142{
143 int r;
144
145 profil_buf = p->buff; profil_bufsiz = p->bufsiz; profil_offset = p->offset;
146 memset (profil_buf, 0, profil_bufsiz);
147 if (profil_state == PS_RUN)
148 {
149 r = xdosprofile (PRF_CM_STOP, my_pid, NULL, NULL);
150 if (r != 0) return r;
151 profil_state = PS_STOP;
152 r = xdosprofile (PRF_CM_CLEAR, my_pid, NULL, NULL);
153 if (r != 0) return r;
154 }
155 if (p->scale == 2)
156 {
157 /* TODO */
158 return set_error (ERROR_INVALID_PARAMETER);
159 }
160 else if (p->scale == 0x10000 || p->scale == 0x8000 || p->scale == 0x4000)
161 {
162 PRFCMD prof_cmd;
163 PRFSLOT prof_slots[1];
164
165 memset (&prof_slots, 0, sizeof (prof_slots));
166 memset (&prof_cmd, 0, sizeof (prof_cmd));
167
168 prof_slots[0].sl_vaddr = profil_offset;
169 prof_slots[0].sl_size = p->bufsiz * (0x10000 / p->scale);
170 prof_slots[0].sl_mode = PRF_SL_PRFVA;
171
172#ifdef DEBUG
173 oprintf ("bufsiz=%#.8x\r\n", profil_bufsiz);
174 oprintf ("scale=%#.8x\r\n", p->scale);
175 oprintf ("sl_vaddr=%#.8x\r\n", prof_slots[0].sl_vaddr);
176 oprintf ("sl_size=%#.8x\r\n", prof_slots[0].sl_size);
177#endif
178
179 prof_cmd.cm_slots = prof_slots;
180 prof_cmd.cm_nslots = 1;
181 prof_cmd.cm_flags = PRF_PROCESS_ST | PRF_VADETAIL;
182 prof_cmd.cm_bufsz = profil_bufsiz;
183 prof_cmd.cm_timval = 1000;
184 prof_cmd.cm_flgbits = NULL;
185 prof_cmd.cm_nflgs = 0;
186
187 r = xdosprofile (PRF_CM_INIT, my_pid, &prof_cmd, NULL);
188 if (r != 0) return r;
189 }
190 r = xdosprofile (PRF_CM_START, my_pid, NULL, NULL);
191 if (r != 0) return r;
192 profil_state = PS_RUN;
193 return 0;
194}
195
196
197int do_profil (const struct _profil *p, int *errnop)
198{
199 int r;
200
201 if (p->cb < sizeof (struct _profil))
202 {
203 *errnop = set_error (ERROR_INVALID_PARAMETER);
204 return -1;
205 }
206
207 if (profil_state == PS_INIT)
208 {
209 r = profil_init ();
210 if (r != 0)
211 {
212 *errnop = r;
213 return -1;
214 }
215 }
216 if (profil_state == PS_FAIL)
217 {
218 *errnop = set_error (ERROR_CALL_NOT_IMPLEMENTED);
219 return -1;
220 }
221
222 if (p->scale == 0 || p->scale == 1)
223 r = profil_result ();
224 else
225 r = profil_start (p);
226 if (r != 0)
227 {
228 *errnop = r;
229 return -1;
230 }
231 *errnop = 0;
232 return 0;
233}
Note: See TracBrowser for help on using the repository browser.