Changeset 2830 for trunk/kLdr/kLdrHlp.c
- Timestamp:
- Oct 23, 2006, 10:53:11 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrHlp.c
r2828 r2830 41 41 #include <kLdr.h> 42 42 #include "kLdrHlp.h" 43 44 45 /******************************************************************************* 46 * Global Variables * 47 *******************************************************************************/ 48 #ifdef __OS2__ 49 /** The loader sempahore. */ 50 static HMTX g_hmtx; 51 /** The base of the stub object. 52 * The OS/2 exe stub consists of a single data object. When allocating memory 53 * for an executable, we'll have to reuse this. */ 54 static void *g_pvStub = NULL; 55 /** The size of the stub object - 0 if no stub. */ 56 static size_t g_cbStub = 0; 57 58 #elif defined(__WIN__) 59 /** The loader sempahore. */ 60 static CRITICAL_SECTION g_CritSect; 61 /** The system info. */ 62 static SYSTEM_INFO g_SystemInfo; 63 #else 64 # error "port me" 65 #endif 66 67 68 /** 69 * Initializes the loader semaphore. 70 * 71 * @returns 0 on success, non-zero OS status code on failure. 72 */ 73 int kldrHlpSemInit(void) 74 { 75 #ifdef __OS2__ 76 APIRET rc; 77 g_hmtx = NULLHANDLE; 78 rc = DosCreateMutexSem(NULL, &g_hmtx, 0, FALSE); 79 if (rc) 80 return rc; 81 82 #elif defined(__WIN__) 83 InitializeCriticalSection(&g_CritSect); 84 85 #else 86 # error "port me" 87 #endif 88 return 0; 89 } 90 91 92 /** 93 * Terminates the loader semaphore. 94 */ 95 void kldrHlpSemTerm(void) 96 { 97 #ifdef __OS2__ 98 APIRET rc; 99 HMTX hmtx = g_hmtx; 100 g_hmtx = NULLHANDLE; 101 rc = DosCloseMutexSem(hmtx); 102 if (rc) 103 return rc; 104 105 #elif defined(__WIN__) 106 DeleteCriticalSection(&g_CritSect); 107 108 #else 109 # error "port me" 110 #endif 111 } 112 113 114 /** 115 * Requests the loader sempahore ownership. 116 * This can be done recursivly. 117 * 118 * @returns 0 on success, non-zero OS status code on failure. 119 */ 120 int kldrHlpSemRequest(void) 121 { 122 #ifdef __OS2__ 123 APIRET rc = DosRequestMutexSem(g_hmtx, 5000); 124 if (rc == ERROR_TIMEOUT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_INTERRUPT) 125 { 126 unsigned i = 0; 127 do 128 { 129 /** @todo check for deadlocks etc. */ 130 rc = DosRequestMutexSem(g_hmtx, 1000); 131 } while ( ( rc == ERROR_TIMEOUT 132 || rc == ERROR_SEM_TIMEOUT 133 || rc == ERROR_INTERRUPT) 134 && i++ < 120); 135 } 136 return rc; 137 138 #elif defined(__WIN__) 139 EnterCriticalSection(&g_CritSect); 140 return 0; 141 142 #else 143 # error "port me" 144 #endif 145 } 146 147 148 /** 149 * Releases the loader semaphore ownership. 150 * The caller is responsible for making sure it's the semaphore owner! 151 */ 152 void kldrHlpSemRelease(void) 153 { 154 #ifdef __OS2__ 155 APIRET rc = DosReleaseMutexSem(g_hmtx); 156 kldrHlpAssert(!rc); (void)rc; 157 158 #elif defined(__WIN__) 159 LeaveCriticalSection(&g_CritSect); 160 161 #else 162 # error "port me" 163 #endif 164 165 } 166 167 #ifdef __OS2__ 168 static ULONG kldrHlpPageProtToNative(KLDRPROT enmProt) 169 { 170 switch (enmProt) 171 { 172 case KLDRPROT_NOACCESS: return PAG_EXECUTE | PAG_READ | PAG_WRITE; 173 case KLDRPROT_READONLY: return PAG_COMMIT | PAG_READ; 174 case KLDRPROT_READWRITE: return PAG_COMMIT | PAG_READ | PAG_WRITE; 175 case KLDRPROT_EXECUTE: return PAG_COMMIT | PAG_EXECUTE; 176 case KLDRPROT_EXECUTE_READ: return PAG_COMMIT | PAG_EXECUTE | PAG_READ; 177 case KLDRPROT_EXECUTE_READWRITE: return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE; 178 default: 179 kldrHlpAssert(0); 180 return ~0U; 181 } 182 } 183 #elif defined(__WIN__) 184 static DWORD kldrHlpPageProtToNative(KLDRPROT enmProt) 185 { 186 switch (enmProt) 187 { 188 case KLDRPROT_NOACCESS: return PAGE_NOACCESS; 189 case KLDRPROT_READONLY: return PAGE_READONLY; 190 case KLDRPROT_READWRITE: return PAGE_READWRITE; 191 case KLDRPROT_EXECUTE: return PAGE_EXECUTE; 192 case KLDRPROT_EXECUTE_READ: return PAGE_EXECUTE_READ; 193 case KLDRPROT_EXECUTE_READWRITE: return PAGE_EXECUTE_READWRITE; 194 default: 195 kldrHlpAssert(0); 196 return ~0U; 197 } 198 } 199 #endif 200 201 202 /** 203 * Allocate a chunk of memory with page granularity. 204 * 205 * @returns 0 on success, non-zero OS status code on failure. 206 * @param ppv Where to store the address of the allocated memory. 207 * If fFixed is set, *ppv will on entry contain the desired address (page aligned). 208 * @param cb Number of bytes. Page aligned. 209 * @param enmProt The new protection. Copy-on-write is invalid. 210 */ 211 int kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed) 212 { 213 #ifdef __OS2__ 214 APIRET rc; 215 ULONG fFlags = kldrHlpPageProtToNative(enmProt);; 216 217 if (!fFixed) 218 { 219 /* simple */ 220 rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY); 221 if (rc == ERROR_INVALID_PARAMETER) 222 rc = DosAllocMem(ppv, cb, fFlags); 223 } 224 else 225 { 226 /* not so simple. */ 227 /** @todo I've got code for this in libc somewhere. */ 228 } 229 if (!rc) 230 return 0; 231 kldrHlpAssert(0); 232 return rc; 233 234 #elif defined(__WIN__) 235 int rc; 236 DWORD fProt = kldrHlpPageProtToNative(enmProt); 237 238 if (!g_SystemInfo.dwPageSize) 239 GetSystemInfo(&g_SystemInfo); 240 241 *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt); 242 if (*ppv == NULL) 243 { 244 rc = GetLastError(); 245 kldrHlpAssert(0); 246 } 247 return rc; 248 249 #else 250 # error "port me" 251 #endif 252 } 253 254 255 /** 256 * Change the protection of one or more pages in an allocation. 257 * 258 * (This will of course only work correctly on memory allocated by kldrHlpPageAlloc().) 259 * 260 * @returns 0 on success, non-zero OS status code on failure. 261 * @param pv First page. Page aligned. 262 * @param cb Number of bytes. Page aligned. 263 * @param enmProt The new protection. Copy-on-write is invalid. 264 */ 265 int kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt) 266 { 267 #ifdef __OS2__ 268 APIRET rc; 269 uintptr_t offStub; 270 ULONG fFlags = kldrHlpPageProtToNative(enmProt);; 271 272 /* 273 * The non-stub pages. 274 */ 275 rc = DosSetMem(pv, cb, fFlags); 276 if (rc && fFlags != PAG_DECOMMIT) 277 rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT); 278 if (rc) 279 { 280 /* Try page by page. */ 281 while (cb > 0) 282 { 283 rc = DosSetMem(pv, 0x1000, fFlags); 284 if (rc && fFlags != PAG_DECOMMIT) 285 rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT); 286 if (rc) 287 return rc; 288 pv = (void *)((uintptr_t)pv + 0x1000); 289 cb -= 0x1000; 290 } 291 } 292 kldrHlpAssert(!rc); 293 return rc; 294 295 #elif defined(__WIN__) 296 DWORD fOldProt = 0; 297 DWORD fProt = kldrHlpPageProtToNative(enmProt); 298 int rc = 0; 299 300 if (!VirtualProtect(pv, cb, fProt, &fOldProt)) 301 { 302 rc = GetLastError(); 303 kldrHlpAssert(0); 304 } 305 return rc; 306 #else 307 # error "port me" 308 #endif 309 } 310 311 312 /** 313 * Free memory allocated by kldrHlpPageAlloc(). 314 * 315 * @returns 0 on success, non-zero OS status code on failure. 316 * @param pv The address returned by kldrHlpPageAlloc(). 317 * @param cb The byte count requested from kldrHlpPageAlloc(). 318 */ 319 int kldrHlpPageFree(void *pv, size_t cb) 320 { 321 #ifdef __OS2__ 322 APIRET rc; 323 324 /* 325 * Deal with any portion overlapping with the stub. 326 */ 327 uintptr_t offStub = (uintptr_t)pv - (uintptr_t)g_pvStub; 328 if (offStub < g_cbStub) 329 { 330 /* decommit the pages in the stub. */ 331 size_t cbSub = KLDR_MIN(g_cbStub - offStub, cb); 332 rc = DosSetMem(pv, cbStub, PAG_DECOMMIT); 333 if (rc) 334 { 335 /* Page by page, ignoring errors after the first success. */ 336 while (cbSub > 0) 337 { 338 if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT)) 339 rc = 0; 340 pv = (void *)((uintptr_t)pv + 0x1000); 341 cbSub -= 0x1000; 342 cb -= 0x1000; 343 } 344 if (rc) 345 { 346 kldrHlpAssert(!rc); 347 return rc; 348 } 349 } 350 else 351 { 352 cb -= cbSub; 353 if (!cb) 354 return 0; 355 pv = (void *)((uintptr_t)pv + cbSub); 356 } 357 } 358 359 /* 360 * Free the object. 361 */ 362 rc = DosFreeMem(pv); 363 kldrHlpAssert(!rc); 364 return rc; 365 366 #elif defined(__WIN__) 367 /* 368 * Free the object. 369 */ 370 int rc = 0; 371 if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE)) 372 { 373 rc = GetLastError(); 374 kldrHlpAssert(0); 375 } 376 return rc; 377 378 #else 379 # error "port me" 380 #endif 381 } 43 382 44 383 … … 137 476 } 138 477 478 479 /** 480 * Sleep for a number of milliseconds. 481 * @param cMillies Number of milliseconds to sleep. 482 */ 483 void kldrHlpSleep(unsigned cMillies) 484 { 485 #ifdef __OS2__ 486 DosSleep(cMillies); 487 #elif defined(__WIN__) 488 Sleep(cMillies); 489 #else 490 usleep(cMillies * 1000); 491 #endif 492 } 493 494 139 495 /** Internal worker for kldrHlpAssertMsg. */ 140 496 static void int2dec(char *pszLine, unsigned iLine)
Note:
See TracChangeset
for help on using the changeset viewer.