From 4e6452445e56432b71d4c1d2312d114da3dcde8b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 1 Nov 2016 21:38:48 -0400 Subject: [PATCH] More work on getting Java to run. Still not there. --- lx_loader.h | 2 + native/doscalls.c | 136 +++++++++++++++++++++++++++++++++++++++++++++- native/nls.c | 41 ++++++++++++++ native/nls.h | 21 ++++++- native/sesmgr.c | 8 +++ native/sesmgr.h | 27 +++++++++ 6 files changed, 233 insertions(+), 2 deletions(-) diff --git a/lx_loader.h b/lx_loader.h index 43c61de..dadbdf9 100644 --- a/lx_loader.h +++ b/lx_loader.h @@ -13,10 +13,12 @@ typedef uint8_t uint8; typedef uint16_t uint16; typedef uint32_t uint32; +typedef uint64_t uint64; typedef int8_t sint8; typedef int16_t sint16; typedef int32_t sint32; +typedef int64_t sint64; typedef unsigned int uint; diff --git a/native/doscalls.c b/native/doscalls.c index dc67b2c..ce4b80e 100644 --- a/native/doscalls.c +++ b/native/doscalls.c @@ -1,4 +1,4 @@ -#include "os2native.h" +#include "os2native16.h" #include "doscalls.h" #include @@ -36,6 +36,17 @@ APIRET OS2API DosQuerySysState(ULONG func, ULONG arg1, ULONG pid, ULONG _res_, P // This is also undocumented (no idea about this at all, including function params). Of course, Java uses it. APIRET DosR3ExitAddr(void); +// These are 16-bit APIs that aren't in the 4.5 toolkit headers. Yeah, Java uses them! Winging it. +typedef int HSEM16, *PHSEM16; +static APIRET16 DosSemRequest(PHSEM16 sem, LONG ms); +static APIRET16 DosSemClear(PHSEM16 sem); +static APIRET16 DosSemWait(PHSEM16 sem, LONG ms); +static APIRET16 DosSemSet(PHSEM16 sem); +static APIRET16 bridge16to32_DosSemRequest(uint8 *args); +static APIRET16 bridge16to32_DosSemClear(uint8 *args); +static APIRET16 bridge16to32_DosSemWait(uint8 *args); +static APIRET16 bridge16to32_DosSemSet(uint8 *args); + static pthread_mutex_t GMutexDosCalls; @@ -117,6 +128,13 @@ typedef struct static DirFinder GHDir1; +LX_NATIVE_MODULE_16BIT_SUPPORT() + LX_NATIVE_MODULE_16BIT_API(DosSemRequest) + LX_NATIVE_MODULE_16BIT_API(DosSemClear) + LX_NATIVE_MODULE_16BIT_API(DosSemWait) + LX_NATIVE_MODULE_16BIT_API(DosSemSet) +LX_NATIVE_MODULE_16BIT_SUPPORT_END() + LX_NATIVE_MODULE_DEINIT({ GLoaderState->dosExit = NULL; @@ -137,10 +155,19 @@ LX_NATIVE_MODULE_DEINIT({ MaxHFiles = 0; pthread_mutex_destroy(&GMutexDosCalls); + + LX_NATIVE_MODULE_DEINIT_16BIT_SUPPORT(); }) static int initDoscalls(void) { + LX_NATIVE_MODULE_INIT_16BIT_SUPPORT() + LX_NATIVE_INIT_16BIT_BRIDGE(DosSemRequest, 8) + LX_NATIVE_INIT_16BIT_BRIDGE(DosSemClear, 4) + LX_NATIVE_INIT_16BIT_BRIDGE(DosSemWait, 8) + LX_NATIVE_INIT_16BIT_BRIDGE(DosSemSet, 4) + LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END() + GLoaderState->dosExit = DosExit; if (pthread_mutex_init(&GMutexDosCalls, NULL) == -1) { @@ -183,6 +210,10 @@ static int initDoscalls(void) } // initDoscalls LX_NATIVE_MODULE_INIT({ if (!initDoscalls()) return NULL; }) + LX_NATIVE_EXPORT16(DosSemRequest, 140), + LX_NATIVE_EXPORT16(DosSemClear, 141), + LX_NATIVE_EXPORT16(DosSemWait, 142), + LX_NATIVE_EXPORT16(DosSemSet, 143), LX_NATIVE_EXPORT(DosSetMaxFH, 209), LX_NATIVE_EXPORT(DosSetPathInfo, 219), LX_NATIVE_EXPORT(DosQueryPathInfo, 223), @@ -2861,5 +2892,108 @@ __asm__ ( ".size _DosSelToFlat, .-_DosSelToFlat \n\t" ); +static inline int trySpinLock(int *lock) +{ + return (__sync_lock_test_and_set(lock, 1) == 0); +} // trySpinLock + +static APIRET16 DosSemRequest(PHSEM16 sem, LONG ms) +{ + TRACE_NATIVE("DosSemRequest(%p, %u)", sem, (uint) ms); + if (ms == 0) { + return !trySpinLock(sem) ? ERROR_TIMEOUT : NO_ERROR; + } else if (ms < 0) { + while (!trySpinLock(sem)) + usleep(1000); + return NO_ERROR; + } + + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + const uint64 end = (((uint64) ts.tv_sec) * 1000) + (((uint64) ts.tv_nsec) / 1000000) + ms; + + while (1) { + if (trySpinLock(sem)) + return NO_ERROR; + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + const uint64 now = (((uint64) ts.tv_sec) * 1000) + (((uint64) ts.tv_nsec) / 1000000); + if (now >= end) + return ERROR_TIMEOUT; + usleep(1000); + } // while + + return NO_ERROR; +} // DosSemRequest + +static APIRET16 DosSemClear(PHSEM16 sem) +{ + TRACE_NATIVE("DosSemClear(%p)", sem); + __sync_lock_release(sem); + return NO_ERROR; +} // DosSemClear + +static APIRET16 DosSemWait(PHSEM16 sem, LONG ms) +{ + TRACE_NATIVE("DosSemWait(%p, %u)", sem, (uint) ms); + if (ms == 0) { + return __sync_bool_compare_and_swap(sem, 0, 1) ? NO_ERROR : ERROR_TIMEOUT; + } else if (ms < 0) { + while (!__sync_bool_compare_and_swap(sem, 0, 1)) + usleep(1000); + return NO_ERROR; + } + + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + const uint64 end = (((uint64) ts.tv_sec) * 1000) + (((uint64) ts.tv_nsec) / 1000000) + ms; + + while (1) { + if (__sync_bool_compare_and_swap(sem, 0, 1)) + return NO_ERROR; + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + const uint64 now = (((uint64) ts.tv_sec) * 1000) + (((uint64) ts.tv_nsec) / 1000000); + if (now >= end) + return ERROR_TIMEOUT; + usleep(1000); + } // while + + return NO_ERROR; +} // DosSemWait + +static APIRET16 DosSemSet(PHSEM16 sem) +{ + TRACE_NATIVE("DosSemSet(%p)", sem); + __sync_bool_compare_and_swap(sem, 1, 0); + return NO_ERROR; +} // DosSemSet + +static APIRET16 bridge16to32_DosSemRequest(uint8 *args) +{ + LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(LONG, ms); + LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PHSEM16, sem); + return DosSemRequest(sem, ms); +} // bridge16to32_DosSemRequest + +static APIRET16 bridge16to32_DosSemClear(uint8 *args) +{ + LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PHSEM16, sem); + return DosSemClear(sem); +} // bridge16to32_DosSemClear + +static APIRET16 bridge16to32_DosSemWait(uint8 *args) +{ + LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(LONG, ms); + LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PHSEM16, sem); + return DosSemWait(sem, ms); +} // bridge16to32_DosSemWait + +static APIRET16 bridge16to32_DosSemSet(uint8 *args) +{ + LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PHSEM16, sem); + return DosSemSet(sem); +} // bridge16to32_DosSemSet + // end of doscalls.c ... diff --git a/native/nls.c b/native/nls.c index 5265e12..059428a 100644 --- a/native/nls.c +++ b/native/nls.c @@ -26,8 +26,49 @@ APIRET DosMapCase(ULONG cb, PCOUNTRYCODE pcc, PCHAR pch) return NO_ERROR; } // DosMapCase +APIRET DosQueryCtryInfo(ULONG cb, PCOUNTRYCODE pcc, PCOUNTRYINFO pci, PULONG pcbActual) +{ + // From the 4.5 toolkit docs: "If this area is too small to hold all of + // the available information, then as much information as possible is + // provided in the available space (in the order in which the data would + // appear)." ...so we fill in a local struct and memcpy it at the end. + COUNTRYINFO ci; + memset(&ci, '\0', sizeof (ci)); + + // From the 4.5 toolkit docs: "If the amount of data returned is not + // enough to fill the memory area provided by the caller, then the memory + // that is unaltered by the available data is zeroed out." ...so blank + // it all out now. + memset(pci, '\0', cb); + + if ((pcc->country != 0) || (pcc->codepage != 0)) + return ERROR_CODE_PAGE_NOT_FOUND; + + // !!! FIXME: this is just what OS/2 Warp 4.52 returns by default for my USA system. + ci.country = 1; + ci.codepage = 437; + ci.fsDateFmt = 0; + ci.szCurrency[0] = '$'; + ci.szThousandsSeparator[0] = ','; + ci.szDecimal[0] = '.'; + ci.szDateSeparator[0] = '-'; + ci.szTimeSeparator[0] = ':'; + ci.fsCurrencyFmt = 0;; + ci.cDecimalPlace = 2; + ci.fsTimeFmt = 0; + //USHORT abReserved1[2]; + ci.szDataSeparator[0] = ','; + //USHORT abReserved2[5]; + + if (pcbActual) + *pcbActual = 38; // OS/2 Warp 4.52 doesn't count the abReserved[5] at the end. + + return NO_ERROR; +} // DosQueryCtryInfo + LX_NATIVE_MODULE_INIT() LX_NATIVE_EXPORT(DosQueryDBCSEnv, 6), + LX_NATIVE_EXPORT(DosQueryCtryInfo, 5), LX_NATIVE_EXPORT(DosMapCase, 7) LX_NATIVE_MODULE_INIT_END() diff --git a/native/nls.h b/native/nls.h index b46c93a..eaff051 100644 --- a/native/nls.h +++ b/native/nls.h @@ -7,14 +7,33 @@ extern "C" { #endif -typedef struct COUNTRYCODE +typedef struct { ULONG country; ULONG codepage; } COUNTRYCODE, *PCOUNTRYCODE; +typedef struct +{ + ULONG country; + ULONG codepage; + ULONG fsDateFmt; + CHAR szCurrency[5]; + CHAR szThousandsSeparator[2]; + CHAR szDecimal[2]; + CHAR szDateSeparator[2]; + CHAR szTimeSeparator[2]; + UCHAR fsCurrencyFmt; + UCHAR cDecimalPlace; + UCHAR fsTimeFmt; + USHORT abReserved1[2]; + CHAR szDataSeparator[2]; + USHORT abReserved2[5]; +} COUNTRYINFO, *PCOUNTRYINFO; + APIRET OS2API DosQueryDBCSEnv(ULONG cb, PCOUNTRYCODE pcc, PCHAR pBuf); APIRET OS2API DosMapCase(ULONG cb, PCOUNTRYCODE pcc, PCHAR pch); +APIRET OS2API DosQueryCtryInfo(ULONG cb, PCOUNTRYCODE pcc, PCOUNTRYINFO pci, PULONG pcbActual); #ifdef __cplusplus } diff --git a/native/sesmgr.c b/native/sesmgr.c index 8d66dab..e388cef 100644 --- a/native/sesmgr.c +++ b/native/sesmgr.c @@ -2,7 +2,15 @@ #include "sesmgr.h" LX_NATIVE_MODULE_INIT() + LX_NATIVE_EXPORT(DosStartSession, 37) LX_NATIVE_MODULE_INIT_END() +APIRET DosStartSession(PSTARTDATA psd, PULONG pidSession, PPID ppid) +{ + TRACE_NATIVE("DosStartSession(%p, %p, %p)", psd, pidSession, ppid); +printf("'%s', '%s', '%s'\n", psd->PgmTitle, psd->PgmName, psd->IconFile); + return ERROR_NOT_ENOUGH_MEMORY; +} // DosStartSession + // end of sesmgr.c ... diff --git a/native/sesmgr.h b/native/sesmgr.h index 2fa8045..26a40c4 100644 --- a/native/sesmgr.h +++ b/native/sesmgr.h @@ -7,6 +7,33 @@ extern "C" { #endif +typedef struct +{ + USHORT Length; + USHORT Related; + USHORT FgBg; + USHORT TraceOpt; + PSZ PgmTitle; + PSZ PgmName; + PBYTE PgmInputs; + PBYTE TermQ; + PBYTE Environment; + USHORT InheritOpt; + USHORT SessionType; + PSZ IconFile; + ULONG PgmHandle; + USHORT PgmControl; + USHORT InitXPos; + USHORT InitYPos; + USHORT InitXSize; + USHORT InitYSize; + USHORT Reserved; + PSZ ObjectBuffer; + ULONG ObjectBuffLen; +} STARTDATA, *PSTARTDATA; + +APIRET OS2API DosStartSession(PSTARTDATA psd, PULONG pidSession, PPID ppid); + #ifdef __cplusplus } #endif