Merge for v0.1.1 #57
							
								
								
									
										358
									
								
								engine/api.c
									
									
									
									
									
								
							
							
						
						
									
										358
									
								
								engine/api.c
									
									
									
									
									
								
							@@ -27,47 +27,18 @@
 | 
			
		||||
 */
 | 
			
		||||
static struct Global_Data {
 | 
			
		||||
	SyMemBackend sAllocator;                /* Global low level memory allocator */
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	const SyMutexMethods *pMutexMethods;   /* Mutex methods */
 | 
			
		||||
	SyMutex *pMutex;                       /* Global mutex */
 | 
			
		||||
	sxu32 nThreadingLevel;                 /* Threading level: 0 == Single threaded/1 == Multi-Threaded
 | 
			
		||||
										    * The threading level can be set using the [ph7_lib_config()]
 | 
			
		||||
											* interface with a configuration verb set to
 | 
			
		||||
											* PH7_LIB_CONFIG_THREAD_LEVEL_SINGLE or
 | 
			
		||||
											* PH7_LIB_CONFIG_THREAD_LEVEL_MULTI
 | 
			
		||||
											*/
 | 
			
		||||
#endif
 | 
			
		||||
	const ph7_vfs *pVfs;                    /* Underlying virtual file system */
 | 
			
		||||
	sxi32 nEngine;                          /* Total number of active engines */
 | 
			
		||||
	ph7 *pEngines;                          /* List of active engine */
 | 
			
		||||
	sxu32 nMagic;                           /* Sanity check against library misuse */
 | 
			
		||||
} sMPGlobal = {
 | 
			
		||||
	{0, 0, 0, 0, 0, 0, 0, 0, 0, {0}},
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	0,
 | 
			
		||||
	0,
 | 
			
		||||
	0,
 | 
			
		||||
#endif
 | 
			
		||||
	0,
 | 
			
		||||
	0,
 | 
			
		||||
	0,
 | 
			
		||||
	0
 | 
			
		||||
};
 | 
			
		||||
#define PH7_LIB_MAGIC  0xEA1495BA
 | 
			
		||||
/*
 | 
			
		||||
 * Supported threading level.
 | 
			
		||||
 * These options have meaning only when the library is compiled with multi-threading
 | 
			
		||||
 * support.That is,the PH7_ENABLE_THREADS compile time directive must be defined
 | 
			
		||||
 * when PH7 is built.
 | 
			
		||||
 * PH7_THREAD_LEVEL_SINGLE:
 | 
			
		||||
 * In this mode,mutexing is disabled and the library can only be used by a single thread.
 | 
			
		||||
 * PH7_THREAD_LEVEL_MULTI
 | 
			
		||||
 * In this mode, all mutexes including the recursive mutexes on [ph7] objects
 | 
			
		||||
 * are enabled so that the application is free to share the same engine
 | 
			
		||||
 * between different threads at the same time.
 | 
			
		||||
 */
 | 
			
		||||
#define PH7_THREAD_LEVEL_SINGLE 1
 | 
			
		||||
#define PH7_THREAD_LEVEL_MULTI  2
 | 
			
		||||
/*
 | 
			
		||||
 * Configure a running PH7 engine instance.
 | 
			
		||||
 * return PH7_OK on success.Any other return
 | 
			
		||||
@@ -193,69 +164,6 @@ static sxi32 PH7CoreConfigure(sxi32 nOp, va_list ap) {
 | 
			
		||||
				sMPGlobal.sAllocator.pUserData = pUserData;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		case PH7_LIB_CONFIG_USER_MUTEX: {
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
				/* Use an alternative low-level mutex subsystem */
 | 
			
		||||
				const SyMutexMethods *pMethods = va_arg(ap, const SyMutexMethods *);
 | 
			
		||||
				if(pMethods == 0) {
 | 
			
		||||
					rc = PH7_CORRUPT;
 | 
			
		||||
				}
 | 
			
		||||
				/* Sanity check */
 | 
			
		||||
				if(pMethods->xEnter == 0 || pMethods->xLeave == 0 || pMethods->xNew == 0) {
 | 
			
		||||
					/* At least three criticial callbacks xEnter(),xLeave() and xNew() must be supplied */
 | 
			
		||||
					rc = PH7_CORRUPT;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				if(sMPGlobal.pMutexMethods) {
 | 
			
		||||
					/* Overwrite the previous mutex subsystem */
 | 
			
		||||
					SyMutexRelease(sMPGlobal.pMutexMethods, sMPGlobal.pMutex);
 | 
			
		||||
					if(sMPGlobal.pMutexMethods->xGlobalRelease) {
 | 
			
		||||
						sMPGlobal.pMutexMethods->xGlobalRelease();
 | 
			
		||||
					}
 | 
			
		||||
					sMPGlobal.pMutex = 0;
 | 
			
		||||
				}
 | 
			
		||||
				/* Initialize and install the new mutex subsystem */
 | 
			
		||||
				if(pMethods->xGlobalInit) {
 | 
			
		||||
					rc = pMethods->xGlobalInit();
 | 
			
		||||
					if(rc != PH7_OK) {
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				/* Create the global mutex */
 | 
			
		||||
				sMPGlobal.pMutex = pMethods->xNew(SXMUTEX_TYPE_FAST);
 | 
			
		||||
				if(sMPGlobal.pMutex == 0) {
 | 
			
		||||
					/*
 | 
			
		||||
					 * If the supplied mutex subsystem is so sick that we are unable to
 | 
			
		||||
					 * create a single mutex,there is no much we can do here.
 | 
			
		||||
					 */
 | 
			
		||||
					if(pMethods->xGlobalRelease) {
 | 
			
		||||
						pMethods->xGlobalRelease();
 | 
			
		||||
					}
 | 
			
		||||
					rc = PH7_CORRUPT;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				sMPGlobal.pMutexMethods = pMethods;
 | 
			
		||||
				if(sMPGlobal.nThreadingLevel == 0) {
 | 
			
		||||
					/* Set a default threading level */
 | 
			
		||||
					sMPGlobal.nThreadingLevel = PH7_THREAD_LEVEL_MULTI;
 | 
			
		||||
				}
 | 
			
		||||
#endif
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		case PH7_LIB_CONFIG_THREAD_LEVEL_SINGLE:
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
			/* Single thread mode(Only one thread is allowed to play with the library) */
 | 
			
		||||
			sMPGlobal.nThreadingLevel = PH7_THREAD_LEVEL_SINGLE;
 | 
			
		||||
#endif
 | 
			
		||||
			break;
 | 
			
		||||
		case PH7_LIB_CONFIG_THREAD_LEVEL_MULTI:
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
			/* Multi-threading mode (library is thread safe and PH7 engines and virtual machines
 | 
			
		||||
			 * may be shared between multiple threads).
 | 
			
		||||
			 */
 | 
			
		||||
			sMPGlobal.nThreadingLevel = PH7_THREAD_LEVEL_MULTI;
 | 
			
		||||
#endif
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			/* Unknown configuration option */
 | 
			
		||||
			rc = PH7_CORRUPT;
 | 
			
		||||
@@ -291,10 +199,6 @@ int ph7_lib_config(int nConfigOp, ...) {
 | 
			
		||||
 */
 | 
			
		||||
static sxi32 PH7CoreInitialize(void) {
 | 
			
		||||
	const ph7_vfs *pVfs; /* Built-in vfs */
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	const SyMutexMethods *pMutexMethods = 0;
 | 
			
		||||
	SyMutex *pMaster = 0;
 | 
			
		||||
#endif
 | 
			
		||||
	int rc;
 | 
			
		||||
	/*
 | 
			
		||||
	 * If the library is already initialized,then a call to this routine
 | 
			
		||||
@@ -307,32 +211,6 @@ static sxi32 PH7CoreInitialize(void) {
 | 
			
		||||
	pVfs = PH7_ExportBuiltinVfs();
 | 
			
		||||
	/* Install it */
 | 
			
		||||
	ph7_lib_config(PH7_LIB_CONFIG_VFS, pVfs);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_SINGLE) {
 | 
			
		||||
		pMutexMethods = sMPGlobal.pMutexMethods;
 | 
			
		||||
		if(pMutexMethods == 0) {
 | 
			
		||||
			/* Use the built-in mutex subsystem */
 | 
			
		||||
			pMutexMethods = SyMutexExportMethods();
 | 
			
		||||
			if(pMutexMethods == 0) {
 | 
			
		||||
				return PH7_CORRUPT; /* Can't happen */
 | 
			
		||||
			}
 | 
			
		||||
			/* Install the mutex subsystem */
 | 
			
		||||
			rc = ph7_lib_config(PH7_LIB_CONFIG_USER_MUTEX, pMutexMethods);
 | 
			
		||||
			if(rc != PH7_OK) {
 | 
			
		||||
				return rc;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/* Obtain a static mutex so we can initialize the library without calling malloc() */
 | 
			
		||||
		pMaster = SyMutexNew(pMutexMethods, SXMUTEX_TYPE_STATIC_1);
 | 
			
		||||
		if(pMaster == 0) {
 | 
			
		||||
			return PH7_CORRUPT; /* Can't happen */
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	/* Lock the master mutex */
 | 
			
		||||
	rc = PH7_OK;
 | 
			
		||||
	SyMutexEnter(pMutexMethods, pMaster); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
			
		||||
	if(sMPGlobal.nMagic != PH7_LIB_MAGIC) {
 | 
			
		||||
#endif
 | 
			
		||||
		if(sMPGlobal.sAllocator.pMethods == 0) {
 | 
			
		||||
			/* Install a memory subsystem */
 | 
			
		||||
			rc = ph7_lib_config(PH7_LIB_CONFIG_USER_MALLOC, 0); /* zero mean use the built-in memory backend */
 | 
			
		||||
@@ -341,26 +219,10 @@ static sxi32 PH7CoreInitialize(void) {
 | 
			
		||||
				goto End;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
		if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
 | 
			
		||||
			/* Protect the memory allocation subsystem */
 | 
			
		||||
			rc = SyMemBackendMakeThreadSafe(&sMPGlobal.sAllocator, sMPGlobal.pMutexMethods);
 | 
			
		||||
			if(rc != PH7_OK) {
 | 
			
		||||
				goto End;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
		/* Our library is initialized,set the magic number */
 | 
			
		||||
		sMPGlobal.nMagic = PH7_LIB_MAGIC;
 | 
			
		||||
		rc = PH7_OK;
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	} /* sMPGlobal.nMagic != PH7_LIB_MAGIC */
 | 
			
		||||
#endif
 | 
			
		||||
End:
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Unlock the master mutex */
 | 
			
		||||
	SyMutexLeave(pMutexMethods, pMaster); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
			
		||||
#endif
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
@@ -414,20 +276,6 @@ static void PH7CoreShutdown(void) {
 | 
			
		||||
		pEngine = pNext;
 | 
			
		||||
		sMPGlobal.nEngine--;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Release the mutex subsystem */
 | 
			
		||||
	if(sMPGlobal.pMutexMethods) {
 | 
			
		||||
		if(sMPGlobal.pMutex) {
 | 
			
		||||
			SyMutexRelease(sMPGlobal.pMutexMethods, sMPGlobal.pMutex);
 | 
			
		||||
			sMPGlobal.pMutex = 0;
 | 
			
		||||
		}
 | 
			
		||||
		if(sMPGlobal.pMutexMethods->xGlobalRelease) {
 | 
			
		||||
			sMPGlobal.pMutexMethods->xGlobalRelease();
 | 
			
		||||
		}
 | 
			
		||||
		sMPGlobal.pMutexMethods = 0;
 | 
			
		||||
	}
 | 
			
		||||
	sMPGlobal.nThreadingLevel = 0;
 | 
			
		||||
#endif
 | 
			
		||||
	if(sMPGlobal.sAllocator.pMethods) {
 | 
			
		||||
		/* Release the memory backend */
 | 
			
		||||
		SyMemBackendRelease(&sMPGlobal.sAllocator);
 | 
			
		||||
@@ -454,17 +302,7 @@ int ph7_lib_is_threadsafe(void) {
 | 
			
		||||
	if(sMPGlobal.nMagic != PH7_LIB_MAGIC) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
 | 
			
		||||
		/* Muli-threading support is enabled */
 | 
			
		||||
		return 1;
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Single-threading */
 | 
			
		||||
	return 0;
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	return 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * [CAPIREF: ph7_lib_version()]
 | 
			
		||||
@@ -497,21 +335,9 @@ int ph7_config(ph7 *pEngine, int nConfigOp, ...) {
 | 
			
		||||
	if(PH7_ENGINE_MISUSE(pEngine)) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire engine mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_ENGINE_RELEASE(pEngine)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	va_start(ap, nConfigOp);
 | 
			
		||||
	rc = EngineConfig(&(*pEngine), nConfigOp, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave engine mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
@@ -543,36 +369,15 @@ int ph7_init(ph7 **ppEngine) {
 | 
			
		||||
	if(rc != PH7_OK) {
 | 
			
		||||
		goto Release;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	SyMemBackendDisbaleMutexing(&pEngine->sAllocator);
 | 
			
		||||
#endif
 | 
			
		||||
	/* Default configuration */
 | 
			
		||||
	SyBlobInit(&pEngine->xConf.sErrConsumer, &pEngine->sAllocator);
 | 
			
		||||
	/* Install a default compile-time error consumer routine */
 | 
			
		||||
	ph7_config(pEngine, PH7_CONFIG_ERR_OUTPUT, PH7_VmBlobConsumer, &pEngine->xConf.sErrConsumer);
 | 
			
		||||
	/* Built-in vfs */
 | 
			
		||||
	pEngine->pVfs = sMPGlobal.pVfs;
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
 | 
			
		||||
		/* Associate a recursive mutex with this instance */
 | 
			
		||||
		pEngine->pMutex = SyMutexNew(sMPGlobal.pMutexMethods, SXMUTEX_TYPE_RECURSIVE);
 | 
			
		||||
		if(pEngine->pMutex == 0) {
 | 
			
		||||
			rc = PH7_NOMEM;
 | 
			
		||||
			goto Release;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Link to the list of active engines */
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Enter the global mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
			
		||||
#endif
 | 
			
		||||
	MACRO_LD_PUSH(sMPGlobal.pEngines, pEngine);
 | 
			
		||||
	sMPGlobal.nEngine++;
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave the global mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
			
		||||
#endif
 | 
			
		||||
	/* Write a pointer to the new instance */
 | 
			
		||||
	*ppEngine = pEngine;
 | 
			
		||||
	return PH7_OK;
 | 
			
		||||
@@ -590,31 +395,11 @@ int ph7_release(ph7 *pEngine) {
 | 
			
		||||
	if(PH7_ENGINE_MISUSE(pEngine)) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire engine mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_ENGINE_RELEASE(pEngine)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Release the engine */
 | 
			
		||||
	rc = EngineRelease(&(*pEngine));
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave engine mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	/* Release engine mutex */
 | 
			
		||||
	SyMutexRelease(sMPGlobal.pMutexMethods, pEngine->pMutex) /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	/* Enter the global mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
			
		||||
#endif
 | 
			
		||||
	/* Unlink from the list of active engines */
 | 
			
		||||
	MACRO_LD_REMOVE(sMPGlobal.pEngines, pEngine);
 | 
			
		||||
	sMPGlobal.nEngine--;
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave the global mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
			
		||||
#endif
 | 
			
		||||
	/* Release the memory chunk allocated to this engine */
 | 
			
		||||
	SyMemBackendPoolFree(&sMPGlobal.sAllocator, pEngine);
 | 
			
		||||
	return rc;
 | 
			
		||||
@@ -711,15 +496,6 @@ static sxi32 ProcessSourceFile(
 | 
			
		||||
	if(rc != PH7_OK) {
 | 
			
		||||
		goto Release;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
 | 
			
		||||
		/* Associate a recursive mutex with this instance */
 | 
			
		||||
		pVm->pMutex = SyMutexNew(sMPGlobal.pMutexMethods, SXMUTEX_TYPE_RECURSIVE);
 | 
			
		||||
		if(pVm->pMutex == 0) {
 | 
			
		||||
			goto Release;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Script successfully compiled,link to the list of active virtual machines */
 | 
			
		||||
	MACRO_LD_PUSH(pEngine->pVms, pVm);
 | 
			
		||||
	pEngine->iVm++;
 | 
			
		||||
@@ -746,20 +522,8 @@ int ph7_compile_code(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOut
 | 
			
		||||
		nLen = (int)SyStrlen(zSource);
 | 
			
		||||
	}
 | 
			
		||||
	SyStringInitFromBuf(&sScript, zSource, nLen);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire engine mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_ENGINE_RELEASE(pEngine)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Compile the script */
 | 
			
		||||
	rc = ProcessSourceFile(&(*pEngine), ppOutVm, &sScript, 0);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave engine mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	/* Compilation result */
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
@@ -774,14 +538,6 @@ int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm) {
 | 
			
		||||
	if(PH7_ENGINE_MISUSE(pEngine) || SX_EMPTY_STR(zFilePath)) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire engine mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_ENGINE_RELEASE(pEngine)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/*
 | 
			
		||||
	 * Check if the underlying vfs implement the memory map
 | 
			
		||||
	 * [i.e: mmap() under UNIX/MapViewOfFile() under windows] function.
 | 
			
		||||
@@ -809,10 +565,6 @@ int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm) {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave engine mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	/* Compilation result */
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
@@ -844,22 +596,10 @@ int ph7_vm_config(ph7_vm *pVm, int iConfigOp, ...) {
 | 
			
		||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire VM mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Configure the virtual machine */
 | 
			
		||||
	va_start(ap, iConfigOp);
 | 
			
		||||
	rc = PH7_VmConfigure(&(*pVm), iConfigOp, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave VM mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
@@ -872,24 +612,12 @@ int ph7_vm_exec(ph7_vm *pVm, int *pExitStatus) {
 | 
			
		||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire VM mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Execute PH7 byte-code */
 | 
			
		||||
	rc = PH7_VmByteCodeExec(&(*pVm));
 | 
			
		||||
	if(pExitStatus) {
 | 
			
		||||
		/* Exit status */
 | 
			
		||||
		*pExitStatus = pVm->iExitStatus;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave VM mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	/* Execution result */
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
@@ -903,19 +631,7 @@ int ph7_vm_reset(ph7_vm *pVm) {
 | 
			
		||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire VM mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	rc = PH7_VmReset(&(*pVm));
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave VM mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
@@ -929,40 +645,14 @@ int ph7_vm_release(ph7_vm *pVm) {
 | 
			
		||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire VM mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	pEngine = pVm->pEngine;
 | 
			
		||||
	rc = PH7_VmRelease(&(*pVm));
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave VM mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	/* free VM mutex */
 | 
			
		||||
	SyMutexRelease(sMPGlobal.pMutexMethods, pVm->pMutex);
 | 
			
		||||
#endif
 | 
			
		||||
	if(rc == PH7_OK) {
 | 
			
		||||
		/* Unlink from the list of active VM */
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
		/* Acquire engine mutex */
 | 
			
		||||
		SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
		if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
				PH7_THRD_ENGINE_RELEASE(pEngine)) {
 | 
			
		||||
			return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
		MACRO_LD_REMOVE(pEngine->pVms, pVm);
 | 
			
		||||
		pEngine->iVm--;
 | 
			
		||||
		/* Release the memory chunk allocated to this VM */
 | 
			
		||||
		SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
		/* Leave engine mutex */
 | 
			
		||||
		SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
@@ -984,20 +674,8 @@ int ph7_create_function(ph7_vm *pVm, const char *zName, int (*xFunc)(ph7_context
 | 
			
		||||
	if(sName.nByte < 1 || xFunc == 0) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire VM mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Install the foreign function */
 | 
			
		||||
	rc = PH7_VmInstallForeignFunction(&(*pVm), &sName, xFunc, pUserData);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave VM mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
@@ -1011,14 +689,6 @@ int ph7_delete_function(ph7_vm *pVm, const char *zName) {
 | 
			
		||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire VM mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Perform the deletion */
 | 
			
		||||
	rc = SyHashDeleteEntry(&pVm->hHostFunction, (const void *)zName, SyStrlen(zName), (void **)&pFunc);
 | 
			
		||||
	if(rc == PH7_OK) {
 | 
			
		||||
@@ -1027,10 +697,6 @@ int ph7_delete_function(ph7_vm *pVm, const char *zName) {
 | 
			
		||||
		SyMemBackendFree(&pVm->sAllocator, (void *)SyStringData(&pFunc->sName));
 | 
			
		||||
		SyMemBackendPoolFree(&pVm->sAllocator, pFunc);
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave VM mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
@@ -1055,20 +721,8 @@ int ph7_create_constant(ph7_vm *pVm, const char *zName, void (*xExpand)(ph7_valu
 | 
			
		||||
	if(xExpand == 0) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire VM mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Perform the registration */
 | 
			
		||||
	rc = PH7_VmRegisterConstant(&(*pVm), &sName, xExpand, pUserData, TRUE);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave VM mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
@@ -1082,14 +736,6 @@ int ph7_delete_constant(ph7_vm *pVm, const char *zName) {
 | 
			
		||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
			
		||||
		return PH7_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Acquire VM mutex */
 | 
			
		||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
			
		||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
			
		||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	/* Query the constant hashtable */
 | 
			
		||||
	rc = SyHashDeleteEntry(&pVm->hConstant, (const void *)zName, SyStrlen(zName), (void **)&pCons);
 | 
			
		||||
	if(rc == PH7_OK) {
 | 
			
		||||
@@ -1097,10 +743,6 @@ int ph7_delete_constant(ph7_vm *pVm, const char *zName) {
 | 
			
		||||
		SyMemBackendFree(&pVm->sAllocator, (void *)SyStringData(&pCons->sName));
 | 
			
		||||
		SyMemBackendPoolFree(&pVm->sAllocator, pCons);
 | 
			
		||||
	}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	/* Leave VM mutex */
 | 
			
		||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
			
		||||
#endif
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -273,35 +273,6 @@ PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk) {
 | 
			
		||||
	}
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
PH7_PRIVATE sxi32 SyMemBackendMakeThreadSafe(SyMemBackend *pBackend, const SyMutexMethods *pMethods) {
 | 
			
		||||
	SyMutex *pMutex;
 | 
			
		||||
	if(SXMEM_BACKEND_CORRUPT(pBackend) || pMethods == 0 || pMethods->xNew == 0) {
 | 
			
		||||
		return SXERR_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
	pMutex = pMethods->xNew(SXMUTEX_TYPE_FAST);
 | 
			
		||||
	if(pMutex == 0) {
 | 
			
		||||
		return SXERR_OS;
 | 
			
		||||
	}
 | 
			
		||||
	/* Attach the mutex to the memory backend */
 | 
			
		||||
	pBackend->pMutex = pMutex;
 | 
			
		||||
	pBackend->pMutexMethods = pMethods;
 | 
			
		||||
	return SXRET_OK;
 | 
			
		||||
}
 | 
			
		||||
PH7_PRIVATE sxi32 SyMemBackendDisbaleMutexing(SyMemBackend *pBackend) {
 | 
			
		||||
	if(SXMEM_BACKEND_CORRUPT(pBackend)) {
 | 
			
		||||
		return SXERR_CORRUPT;
 | 
			
		||||
	}
 | 
			
		||||
	if(pBackend->pMutex == 0) {
 | 
			
		||||
		/* There is no mutex subsystem at all */
 | 
			
		||||
		return SXRET_OK;
 | 
			
		||||
	}
 | 
			
		||||
	SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex);
 | 
			
		||||
	pBackend->pMutexMethods = 0;
 | 
			
		||||
	pBackend->pMutex = 0;
 | 
			
		||||
	return SXRET_OK;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
/*
 | 
			
		||||
 * Memory pool allocator
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,224 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @PROJECT     PH7 Engine for the AerScript Interpreter
 | 
			
		||||
 * @COPYRIGHT   See COPYING in the top level directory
 | 
			
		||||
 * @FILE        engine/lib/mutex.c
 | 
			
		||||
 * @DESCRIPTION Thread safe MUTEX implementation for the PH7 Engine
 | 
			
		||||
 * @DEVELOPERS  Symisc Systems <devel@symisc.net>
 | 
			
		||||
 *              Rafal Kupiec <belliash@codingworkshop.eu.org>
 | 
			
		||||
 */
 | 
			
		||||
#include "ph7int.h"
 | 
			
		||||
#if defined(__WINNT__)
 | 
			
		||||
	#include <Windows.h>
 | 
			
		||||
#else
 | 
			
		||||
	#include <stdlib.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
#if defined(__WINNT__)
 | 
			
		||||
struct SyMutex {
 | 
			
		||||
	CRITICAL_SECTION sMutex;
 | 
			
		||||
	sxu32 nType; /* Mutex type,one of SXMUTEX_TYPE_* */
 | 
			
		||||
};
 | 
			
		||||
/* Preallocated static mutex */
 | 
			
		||||
static SyMutex aStaticMutexes[] = {
 | 
			
		||||
	{{0}, SXMUTEX_TYPE_STATIC_1},
 | 
			
		||||
	{{0}, SXMUTEX_TYPE_STATIC_2},
 | 
			
		||||
	{{0}, SXMUTEX_TYPE_STATIC_3},
 | 
			
		||||
	{{0}, SXMUTEX_TYPE_STATIC_4},
 | 
			
		||||
	{{0}, SXMUTEX_TYPE_STATIC_5},
 | 
			
		||||
	{{0}, SXMUTEX_TYPE_STATIC_6}
 | 
			
		||||
};
 | 
			
		||||
static BOOL winMutexInit = FALSE;
 | 
			
		||||
static LONG winMutexLock = 0;
 | 
			
		||||
 | 
			
		||||
static sxi32 WinMutexGlobaInit(void) {
 | 
			
		||||
	LONG rc;
 | 
			
		||||
	rc = InterlockedCompareExchange(&winMutexLock, 1, 0);
 | 
			
		||||
	if(rc == 0) {
 | 
			
		||||
		sxu32 n;
 | 
			
		||||
		for(n = 0 ; n  < SX_ARRAYSIZE(aStaticMutexes) ; ++n) {
 | 
			
		||||
			InitializeCriticalSection(&aStaticMutexes[n].sMutex);
 | 
			
		||||
		}
 | 
			
		||||
		winMutexInit = TRUE;
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Someone else is doing this for us */
 | 
			
		||||
		while(winMutexInit == FALSE) {
 | 
			
		||||
			Sleep(1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return SXRET_OK;
 | 
			
		||||
}
 | 
			
		||||
static void WinMutexGlobalRelease(void) {
 | 
			
		||||
	LONG rc;
 | 
			
		||||
	rc = InterlockedCompareExchange(&winMutexLock, 0, 1);
 | 
			
		||||
	if(rc == 1) {
 | 
			
		||||
		/* The first to decrement to zero does the actual global release */
 | 
			
		||||
		if(winMutexInit == TRUE) {
 | 
			
		||||
			sxu32 n;
 | 
			
		||||
			for(n = 0 ; n < SX_ARRAYSIZE(aStaticMutexes) ; ++n) {
 | 
			
		||||
				DeleteCriticalSection(&aStaticMutexes[n].sMutex);
 | 
			
		||||
			}
 | 
			
		||||
			winMutexInit = FALSE;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
static SyMutex *WinMutexNew(int nType) {
 | 
			
		||||
	SyMutex *pMutex = 0;
 | 
			
		||||
	if(nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
			
		||||
		/* Allocate a new mutex */
 | 
			
		||||
		pMutex = (SyMutex *)HeapAlloc(GetProcessHeap(), 0, sizeof(SyMutex));
 | 
			
		||||
		if(pMutex == 0) {
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		InitializeCriticalSection(&pMutex->sMutex);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Use a pre-allocated static mutex */
 | 
			
		||||
		if(nType > SXMUTEX_TYPE_STATIC_6) {
 | 
			
		||||
			nType = SXMUTEX_TYPE_STATIC_6;
 | 
			
		||||
		}
 | 
			
		||||
		pMutex = &aStaticMutexes[nType - 3];
 | 
			
		||||
	}
 | 
			
		||||
	pMutex->nType = nType;
 | 
			
		||||
	return pMutex;
 | 
			
		||||
}
 | 
			
		||||
static void WinMutexRelease(SyMutex *pMutex) {
 | 
			
		||||
	if(pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
			
		||||
		DeleteCriticalSection(&pMutex->sMutex);
 | 
			
		||||
		HeapFree(GetProcessHeap(), 0, pMutex);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
static void WinMutexEnter(SyMutex *pMutex) {
 | 
			
		||||
	EnterCriticalSection(&pMutex->sMutex);
 | 
			
		||||
}
 | 
			
		||||
static sxi32 WinMutexTryEnter(SyMutex *pMutex) {
 | 
			
		||||
#ifdef _WIN32_WINNT
 | 
			
		||||
	BOOL rc;
 | 
			
		||||
	/* Only WindowsNT platforms */
 | 
			
		||||
	rc = TryEnterCriticalSection(&pMutex->sMutex);
 | 
			
		||||
	if(rc) {
 | 
			
		||||
		return SXRET_OK;
 | 
			
		||||
	} else {
 | 
			
		||||
		return SXERR_BUSY;
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	return SXERR_NOTIMPLEMENTED;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
static void WinMutexLeave(SyMutex *pMutex) {
 | 
			
		||||
	LeaveCriticalSection(&pMutex->sMutex);
 | 
			
		||||
}
 | 
			
		||||
/* Export Windows mutex interfaces */
 | 
			
		||||
static const SyMutexMethods sWinMutexMethods = {
 | 
			
		||||
	WinMutexGlobaInit,  /* xGlobalInit() */
 | 
			
		||||
	WinMutexGlobalRelease, /* xGlobalRelease() */
 | 
			
		||||
	WinMutexNew,     /* xNew() */
 | 
			
		||||
	WinMutexRelease, /* xRelease() */
 | 
			
		||||
	WinMutexEnter,   /* xEnter() */
 | 
			
		||||
	WinMutexTryEnter, /* xTryEnter() */
 | 
			
		||||
	WinMutexLeave     /* xLeave() */
 | 
			
		||||
};
 | 
			
		||||
PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) {
 | 
			
		||||
	return &sWinMutexMethods;
 | 
			
		||||
}
 | 
			
		||||
#elif defined(__UNIXES__)
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
struct SyMutex {
 | 
			
		||||
	pthread_mutex_t sMutex;
 | 
			
		||||
	sxu32 nType;
 | 
			
		||||
};
 | 
			
		||||
static SyMutex *UnixMutexNew(int nType) {
 | 
			
		||||
	static SyMutex aStaticMutexes[] = {
 | 
			
		||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_1},
 | 
			
		||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_2},
 | 
			
		||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_3},
 | 
			
		||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_4},
 | 
			
		||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_5},
 | 
			
		||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_6}
 | 
			
		||||
	};
 | 
			
		||||
	SyMutex *pMutex;
 | 
			
		||||
	if(nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
			
		||||
		pthread_mutexattr_t sRecursiveAttr;
 | 
			
		||||
		/* Allocate a new mutex */
 | 
			
		||||
		pMutex = (SyMutex *)malloc(sizeof(SyMutex));
 | 
			
		||||
		if(pMutex == 0) {
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		if(nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
			
		||||
			pthread_mutexattr_init(&sRecursiveAttr);
 | 
			
		||||
			pthread_mutexattr_settype(&sRecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
 | 
			
		||||
		}
 | 
			
		||||
		pthread_mutex_init(&pMutex->sMutex, nType == SXMUTEX_TYPE_RECURSIVE ? &sRecursiveAttr : 0);
 | 
			
		||||
		if(nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
			
		||||
			pthread_mutexattr_destroy(&sRecursiveAttr);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Use a pre-allocated static mutex */
 | 
			
		||||
		if(nType > SXMUTEX_TYPE_STATIC_6) {
 | 
			
		||||
			nType = SXMUTEX_TYPE_STATIC_6;
 | 
			
		||||
		}
 | 
			
		||||
		pMutex = &aStaticMutexes[nType - 3];
 | 
			
		||||
	}
 | 
			
		||||
	pMutex->nType = nType;
 | 
			
		||||
	return pMutex;
 | 
			
		||||
}
 | 
			
		||||
static void UnixMutexRelease(SyMutex *pMutex) {
 | 
			
		||||
	if(pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
			
		||||
		pthread_mutex_destroy(&pMutex->sMutex);
 | 
			
		||||
		free(pMutex);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
static void UnixMutexEnter(SyMutex *pMutex) {
 | 
			
		||||
	pthread_mutex_lock(&pMutex->sMutex);
 | 
			
		||||
}
 | 
			
		||||
static void UnixMutexLeave(SyMutex *pMutex) {
 | 
			
		||||
	pthread_mutex_unlock(&pMutex->sMutex);
 | 
			
		||||
}
 | 
			
		||||
/* Export pthread mutex interfaces */
 | 
			
		||||
static const SyMutexMethods sPthreadMutexMethods = {
 | 
			
		||||
	0, /* xGlobalInit() */
 | 
			
		||||
	0, /* xGlobalRelease() */
 | 
			
		||||
	UnixMutexNew,      /* xNew() */
 | 
			
		||||
	UnixMutexRelease,  /* xRelease() */
 | 
			
		||||
	UnixMutexEnter,    /* xEnter() */
 | 
			
		||||
	0,                 /* xTryEnter() */
 | 
			
		||||
	UnixMutexLeave     /* xLeave() */
 | 
			
		||||
};
 | 
			
		||||
PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) {
 | 
			
		||||
	return &sPthreadMutexMethods;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
/* Host application must register their own mutex subsystem if the target
 | 
			
		||||
 * platform is not an UNIX-like or windows systems.
 | 
			
		||||
 */
 | 
			
		||||
struct SyMutex {
 | 
			
		||||
	sxu32 nType;
 | 
			
		||||
};
 | 
			
		||||
static SyMutex *DummyMutexNew(int nType) {
 | 
			
		||||
	static SyMutex sMutex;
 | 
			
		||||
	SXUNUSED(nType);
 | 
			
		||||
	return &sMutex;
 | 
			
		||||
}
 | 
			
		||||
static void DummyMutexRelease(SyMutex *pMutex) {
 | 
			
		||||
	SXUNUSED(pMutex);
 | 
			
		||||
}
 | 
			
		||||
static void DummyMutexEnter(SyMutex *pMutex) {
 | 
			
		||||
	SXUNUSED(pMutex);
 | 
			
		||||
}
 | 
			
		||||
static void DummyMutexLeave(SyMutex *pMutex) {
 | 
			
		||||
	SXUNUSED(pMutex);
 | 
			
		||||
}
 | 
			
		||||
/* Export the dummy mutex interfaces */
 | 
			
		||||
static const SyMutexMethods sDummyMutexMethods = {
 | 
			
		||||
	0, /* xGlobalInit() */
 | 
			
		||||
	0, /* xGlobalRelease() */
 | 
			
		||||
	DummyMutexNew,      /* xNew() */
 | 
			
		||||
	DummyMutexRelease,  /* xRelease() */
 | 
			
		||||
	DummyMutexEnter,    /* xEnter() */
 | 
			
		||||
	0,                  /* xTryEnter() */
 | 
			
		||||
	DummyMutexLeave     /* xLeave() */
 | 
			
		||||
};
 | 
			
		||||
PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) {
 | 
			
		||||
	return &sDummyMutexMethods;
 | 
			
		||||
}
 | 
			
		||||
#endif /* __WINNT__ */
 | 
			
		||||
#endif /* PH7_ENABLE_THREADS */
 | 
			
		||||
@@ -806,10 +806,6 @@ struct ph7 {
 | 
			
		||||
	SyMemBackend sAllocator;     /* Low level memory allocation subsystem */
 | 
			
		||||
	const ph7_vfs *pVfs;         /* Underlying Virtual File System */
 | 
			
		||||
	ph7_conf xConf;              /* Configuration */
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	const SyMutexMethods *pMethods;  /* Mutex methods */
 | 
			
		||||
	SyMutex *pMutex;                 /* Per-engine mutex */
 | 
			
		||||
#endif
 | 
			
		||||
	ph7_vm *pVms;      /* List of active VM */
 | 
			
		||||
	sxi32 iVm;         /* Total number of active VM */
 | 
			
		||||
	ph7 *pNext, *pPrev; /* List of active engines */
 | 
			
		||||
@@ -1185,9 +1181,6 @@ struct ph7_switch {
 | 
			
		||||
 */
 | 
			
		||||
struct ph7_vm {
 | 
			
		||||
	SyMemBackend sAllocator;	/* Memory backend */
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	SyMutex *pMutex;           /* Recursive mutex associated with VM. */
 | 
			
		||||
#endif
 | 
			
		||||
	ph7 *pEngine;               /* Interpreter that own this VM */
 | 
			
		||||
	SySet aInstrSet;            /* Instructions debugging container */
 | 
			
		||||
	SySet aByteCode;            /* Default bytecode container */
 | 
			
		||||
@@ -1876,10 +1869,6 @@ PH7_PRIVATE void *SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes);
 | 
			
		||||
PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk);
 | 
			
		||||
PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes);
 | 
			
		||||
PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	PH7_PRIVATE sxi32 SyMemBackendMakeThreadSafe(SyMemBackend *pBackend, const SyMutexMethods *pMethods);
 | 
			
		||||
	PH7_PRIVATE sxi32 SyMemBackendDisbaleMutexing(SyMemBackend *pBackend);
 | 
			
		||||
#endif
 | 
			
		||||
PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen);
 | 
			
		||||
PH7_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize);
 | 
			
		||||
PH7_PRIVATE void SyZero(void *pSrc, sxu32 nSize);
 | 
			
		||||
@@ -1893,9 +1882,4 @@ PH7_PRIVATE sxu32 SyStrlen(const char *zSrc);
 | 
			
		||||
PH7_PRIVATE sxu32 Systrcpy(char *zDest, sxu32 nDestLen, const char *zSrc, sxu32 nLen);
 | 
			
		||||
PH7_PRIVATE char *SyStrtok(char *str, const char *sep);
 | 
			
		||||
PH7_PRIVATE sxi32 SyAsciiToHex(sxi32 c);
 | 
			
		||||
#if defined(PH7_ENABLE_THREADS)
 | 
			
		||||
	PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void);
 | 
			
		||||
	PH7_PRIVATE sxi32 SyMemBackendMakeThreadSafe(SyMemBackend *pBackend, const SyMutexMethods *pMethods);
 | 
			
		||||
	PH7_PRIVATE sxi32 SyMemBackendDisbaleMutexing(SyMemBackend *pBackend);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* __PH7INT_H__ */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user