harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From telli...@apache.org
Subject svn commit: r390442 - in /incubator/harmony/enhanced/classlib/trunk/native-src: linux.IA32/ linux.IA32/vmls/ shared/vmls/ win.IA32/ win.IA32/vmls/
Date Fri, 31 Mar 2006 15:24:59 GMT
Author: tellison
Date: Fri Mar 31 07:24:54 2006
New Revision: 390442

URL: http://svn.apache.org/viewcvs?rev=390442&view=rev
Log:
Add a reference implementation of VM local storage.

Added:
    incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/vmls/
    incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/vmls/makefile
    incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/   (with props)
    incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/makefile
    incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.c
    incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.h
    incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/vmls/   (with props)
    incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/vmls/makefile
Modified:
    incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/makefile
    incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/makefile

Modified: incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/makefile
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/makefile?rev=390442&r1=390441&r2=390442&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/makefile (original)
+++ incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/makefile Fri Mar 31 07:24:54
2006
@@ -19,7 +19,7 @@
 all: \
 	_sig _common _pool _thread _port _fdlibm _zip \
 	_zlib _vmi _luni _nio _archive _auth \
-	_math _text _launcher
+	_math _text _vmls _launcher
 
 _auth:
 	(cd auth && $(MAKE) )
@@ -65,7 +65,10 @@
 	
 _text: _sig _zip _zlib _pool _fdlibm _thread _vmi
 	(cd text && $(MAKE) )
-	
+
+_vmls: _thread _port
+	(cd vmls && $(MAKE) )	
+
 _launcher: _thread _port
 	(cd launcher && $(MAKE) )	
 
@@ -85,4 +88,5 @@
 	(cd archive && $(MAKE) clean )
 	(cd math && $(MAKE) clean )
 	(cd text && $(MAKE) clean )
+	(cd vmls && $(MAKE) clean )
 	(cd launcher && $(MAKE) clean )

Added: incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/vmls/makefile
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/vmls/makefile?rev=390442&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/vmls/makefile (added)
+++ incubator/harmony/enhanced/classlib/trunk/native-src/linux.IA32/vmls/makefile Fri Mar
31 07:24:54 2006
@@ -0,0 +1,25 @@
+# Copyright 2006 The Apache Software Foundation or its licensors, as applicable
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+#     http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Makefile for module 'common'
+#
+
+include ../makefile.include
+
+CFLAGS += -I../vmls 
+BUILDFILES = $(SHAREDSUB)vmls.o
+LIBNAME = $(LIBPATH)libhyvmls.a
+
+include ../rules.mk

Propchange: incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Mar 31 07:24:54 2006
@@ -0,0 +1 @@
+*.obj

Added: incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/makefile
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/makefile?rev=390442&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/makefile (added)
+++ incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/makefile Fri Mar 31 07:24:54
2006
@@ -0,0 +1,45 @@
+# Makefile for module 'clear_vmls'
+# (c) Copyright IBM Corp. 1998, 2005 All Rights Reserved
+# File generated in stream: 2.3
+#
+# Autogenerated Code
+
+APPVER=4.0
+TARGETOS=WIN95
+_WIN32_IE=0x0500
+SEHMAP = TRUE
+!include <win32.mak>
+
+LIBNAME=j9clear_vmls.lib# declaration
+
+LIBPATH=..\lib\# declaration
+
+BUILDFILES1 = vmls.obj
+
+
+
+
+
+.c.obj:
+	$(cc) -DWINVER=0x0400 -D_WIN32_WINNT=0x0400 $(cflags) -D_MT -D_DLL -MD -D_WINSOCKAPI_ -DWIN32
-Ogityb1 -Gs -GF -Zm400 -W2 -Zi -Fd$(LIBPATH)j9clear_vmls.pdb /I..\include /I..\oti  $(VMDEBUG)
$*.c
+
+.cpp.obj:
+	$(cc) -DWINVER=0x0400 -D_WIN32_WINNT=0x0400 $(cflags) -D_MT -D_DLL -MD -D_WINSOCKAPI_ -DWIN32
-Ogityb1 -Gs -GF -Zm400 -W2 -Zi -Fd$(LIBPATH)j9clear_vmls.pdb /I..\include /I..\oti  $(VMDEBUG)
$*.cpp
+
+.asm.obj:
+	ml /c /Cp /W3 /nologo /coff /Zm /Zd /Zi /Gd -DJ9VM_MULTI_CODE_CACHE $(VMASMDEBUG) -DWIN32
 $<
+
+all: $(LIBPATH)$(LIBNAME)
+
+$(LIBPATH)$(LIBNAME):\
+	$(BUILDFILES1) 
+	echo -out:$(LIBPATH)$(LIBNAME) >templrf
+	echo $(BUILDFILES1) >>templrf
+	$(implib) @templrf
+	del templrf
+
+static:
+	$(MAKE) -f makefile.static
+
+quick:
+	$(MAKE)

Added: incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.c?rev=390442&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.c (added)
+++ incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.c Fri Mar 31 07:24:54
2006
@@ -0,0 +1,348 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * @ingroup Reference
+ * @brief Reference implementation of VM-local storage.  
+ *
+ * @detail VM-local storage (VMLS) is similar to thread-local storage (TLS) in that it provides

+ * key-value storage slots that can hold arbitrary data.  While TLS provides per-thread
+ * slots associated with a fixed key, VMLS provides per-JavaVM space associated with a fixed
key.
+ * 
+ * VMLS is used as replacement for static variables which would otherwise prevent multiple
+ * JavaVM instances from co-existing in the same process.  Instead of storing values (such
as
+ * JNI method/field ID's) in static variables -- allocate a VMLS key and use the VMI functions
+ * to get/set it's value on a per-vm basis.
+ */
+
+#define USING_VMI
+
+#include "jni.h"			/* for definitions of JavaVM */
+#include "hycomp.h"			/* for portable types (UDATA,etc...) */
+#include "hythread.h"		/* for synchronization */
+#include "hyport.h"			/* for port library */
+#include "vmi.h"			/* for VMI functions */
+
+/* A constant that bounds the number of keys available. */
+#define VMLS_MAX_KEYS 256
+
+/**
+ * A structure to hold per-vm data.
+ */
+typedef struct VMLSContainer {
+	JavaVM* javaVM;
+	void** vmLocalStorage[VMLS_MAX_KEYS];
+	struct VMLSContainer* linkNext;
+} VMLSContainer;
+
+/**
+  * A structure used to hold process-level VMLS information.
+  */
+typedef struct HyVMLSTable {
+ 	UDATA initialized;
+ 	UDATA head;
+ 	UDATA freeKeys;
+ 	UDATA keys[VMLS_MAX_KEYS];
+	VMLSContainer* containerHead;
+} HyVMLSTable;
+
+/* An instance of the VMLS data shared by all JavaVMs */
+static HyVMLSTable VMLSTable;
+
+
+/**
+ * Destroy one or more slots of VM local storage. 
+ *
+ * @code void  JNICALL HyVMLSFreeKeys(JNIEnv * env, UDATA * pInitCount, ...); @endcode
+ *
+ * @param[in] env  A JNIEnv pointer
+ * @param[in] pInitCount  Pointer to the reference count for these slots
+ * @param[out] ...  Pointers to the allocated keys
+ */
+void JNICALL HyVMLSFreeKeys(JNIEnv * env, UDATA * pInitCount, ...)
+{
+	va_list args;
+	HyVMLSTable* vmls = GLOBAL_DATA(VMLSTable);
+
+	/* Obtain a process-level lock */
+	hythread_monitor_t globalMonitor = hythread_global_monitor();
+	hythread_monitor_enter(globalMonitor);
+
+	if (--(*pInitCount) == 0) {
+		void ** pKey;
+
+		va_start(args, pInitCount);
+		while ((pKey = va_arg(args, void *)) != NULL) {
+			UDATA	key;
+
+			key = (UDATA) *pKey;
+			*pKey = NULL;
+			if (vmls->keys[key] == (UDATA) -1) {
+				vmls->keys[key] = vmls->head;
+				vmls->head = key;
+				++vmls->freeKeys;
+			}
+		}
+		va_end(args);
+	}
+
+	/* Release the lock */
+	hythread_monitor_exit(globalMonitor);
+}
+
+
+/**
+ * Allocate one or more slots of VM local storage. 
+ *
+ * @code UDATA  JNICALL HyVMLSAllocKeys(JNIEnv * env, UDATA * pInitCount, ...); @endcode
+ *
+ * @param[in] env  A JNIEnv pointer
+ * @param[in/out] pInitCount  Pointer to the reference count for these slots
+ * @param[out] ...  Locations to store the allocated keys
+ *
+ * @return 0 on success, 1 on failure.
+ *
+ * @note Newly allocated VMLS slots contain NULL in all VMs.
+ */
+UDATA JNICALL HyVMLSAllocKeys(JNIEnv * env, UDATA * pInitCount, ...)
+{
+	va_list args;
+	HyVMLSTable *vmls = GLOBAL_DATA(VMLSTable);
+
+	/* Obtain a process-level lock */
+	hythread_monitor_t globalMonitor = hythread_global_monitor();
+	hythread_monitor_enter(globalMonitor);
+
+	if (++(*pInitCount) == 1) {
+		JavaVM *javaVM = NULL;
+		void **pKey;
+		UDATA count = 0;
+
+		/* Count the number of keys being initialized */
+		va_start(args, pInitCount);
+		while ((pKey = va_arg(args, void *)) != NULL) {
+			++count;
+		}
+		va_end(args);
+
+		/* Fail if there are not enough free keys left */
+		if (count > vmls->freeKeys) {
+			/* Free the lock */
+			hythread_monitor_exit(globalMonitor);
+			return 1;
+		}
+
+		/* Allocate the keys */
+		va_start(args, pInitCount);
+		while ((pKey = va_arg(args, void *)) != NULL) {
+			UDATA key;
+			VMLSContainer* cursor;
+
+			key = vmls->head;
+			vmls->head = vmls->keys[key];
+			vmls->keys[key] = (UDATA) - 1;
+			*pKey = (void *) key;
+
+			/* Initialize the value of the key to NULL this VM and all other known VMs.
+			   VMs which are being created (i.e. not in the list yet) will have all VMLS
+			   values set to NULL already.  The current VM may or may not be in the list,
+			   which means that the list may be empty.  The global monitor protects the
+			   VM list as well as the key list. */
+
+			/* Iterate through all vms */
+			cursor = vmls->containerHead;
+			while (cursor) {
+				cursor->vmLocalStorage[key - 1] = NULL;
+				cursor = cursor->linkNext;
+			}
+		}
+		va_end(args);
+		vmls->freeKeys -= count;
+	}
+
+	/* Release the lock */
+	hythread_monitor_exit(globalMonitor);
+	return 0;
+}
+
+
+/**
+ * Retrieve the value in a VM local storage slot. 
+ *
+ * @code void*  JNICALL HyVMLSGet(JNIEnv * env, void * key); @endcode
+ *
+ * @param[in] env  JNIEnv pointer
+ * @param[in] key  The VMLS key
+ *
+ * @return The contents of the VM local storage slot in the VM that contains the specified
env
+ */
+void * JNICALL HyVMLSGet(JNIEnv * env, void * key)
+{
+	HyVMLSTable* vmls = GLOBAL_DATA(VMLSTable);
+	JavaVM *javaVM = NULL;
+	VMLSContainer* cursor = vmls->containerHead;
+
+	/* Fetch the javaVM */
+	(*env)->GetJavaVM(env,&javaVM);
+
+	/* Iterate all containers */
+	while (cursor) {
+		/* Locate the correct container identified by javaVM */
+		if (cursor->javaVM == javaVM) {
+			return cursor->vmLocalStorage[((UDATA) key) - 1];
+		}
+		cursor = cursor->linkNext;
+	}
+
+	return NULL;
+}
+
+
+/**
+ * Store a value into a VM local storage slot.  Note the extra level of indirection on
+ * the key parameter.  This indirection enables the use of these functions even when
+ * multi-vm is not supported.  In these cases pKey is a pointer to the raw memory where
+ * the value will be stored.
+ *
+ * @code void*  JNICALL HyVMLSSet(JNIEnv * env, void ** pKey, void * value); @endcode
+ *
+ * @param[in] env  JNIEnv pointer
+ * @param[in] pKey  Pointer to the VM local storage key (NOTE: the extra level of indirection).
+ * @param[in] value  Value to store
+ *
+ * @return The value stored
+ */
+void * JNICALL HyVMLSSet(JNIEnv * env, void ** pKey, void * value)
+{
+	HyVMLSTable* vmls = GLOBAL_DATA(VMLSTable);
+	JavaVM *javaVM = NULL;
+	VMLSContainer* cursor = vmls->containerHead;
+
+	/* Fetch the javaVM */
+	(*env)->GetJavaVM(env,&javaVM);
+
+	/* Iterate all containers */
+	while (cursor) {
+		/* Locate the correct container identified by javaVM */
+		if (cursor->javaVM == javaVM) {
+			cursor->vmLocalStorage[((UDATA) *pKey) - 1] = value;
+			return value;
+		}
+	}
+
+	return value;
+}
+
+
+/** 
+ * This method must be called each time a JavaVM is created.  On the
+ * first invocation this method will allocate the global structures
+ * needed for book-keeping.
+ *
+ * @param[in] vm The JavaVM.
+ */	
+void initializeVMLocalStorage(JavaVM * vm)
+{
+	HyVMLSTable* vmls = GLOBAL_DATA(VMLSTable);
+	VMLSContainer* container = NULL;
+
+	/* Reach for the VM interface */
+	PORT_ACCESS_FROM_JAVAVM(vm);
+
+	if (!vmls->initialized) {
+		UDATA i;
+
+		/* Obtain the global lock */
+		hythread_monitor_t globalMonitor = hythread_global_monitor();
+		hythread_monitor_enter(globalMonitor);
+
+		/* Test again now that we own the lock */
+		if (!vmls->initialized) {
+
+			/* Initialize keys */
+			for (i = 1; i < VMLS_MAX_KEYS-1; ++i) {
+				vmls->keys[i] = i + 1;
+			}
+
+			vmls->keys[0] = 0;
+			vmls->keys[VMLS_MAX_KEYS-1] = 0;
+			vmls->head = 1;
+			vmls->freeKeys = VMLS_MAX_KEYS-1;
+			vmls->initialized = TRUE;
+			vmls->head = 1;
+			vmls->containerHead = NULL;
+		}
+
+		/* Allocate a new container */
+		container = hymem_allocate_memory(sizeof(VMLSContainer));
+		if (container) {
+			memset(container,0,sizeof(VMLSContainer));
+			container->javaVM = vm;
+		}
+
+		/* Insert it into the list */
+		container->linkNext = vmls->containerHead;
+		vmls->containerHead = container;
+		
+		/* Release the global lock */
+		hythread_monitor_exit(globalMonitor);
+	}
+}
+
+
+/** 
+ * This method must be called each time a JavaVM is destroyed.
+ *
+ * @param[in] vm The JavaVM.
+ */	
+void freeVMLocalStorage(JavaVM * vm)
+{
+	HyVMLSTable* vmls = GLOBAL_DATA(VMLSTable);
+	VMLSContainer* cursor = vmls->containerHead;
+	VMLSContainer* previous = NULL;
+
+	/* Reach for the VM interface */
+	PORT_ACCESS_FROM_JAVAVM(vm);
+
+	/* Obtain the global lock */
+	hythread_monitor_t globalMonitor = hythread_global_monitor();
+	hythread_monitor_enter(globalMonitor);
+
+	/* Iterate all containers */
+	while (cursor) {
+
+		/* Locate the correct container identified by javaVM */
+		if (cursor->javaVM == vm) {
+			
+			/* Unlink the container from the list */
+			if (previous) {
+				previous->linkNext = cursor->linkNext;
+			} else {
+				vmls->containerHead = cursor->linkNext;
+			}
+
+			hymem_free_memory(cursor);
+			break;
+		}
+
+		/* Move to the next element */
+		previous = cursor;
+		cursor = cursor->linkNext;
+	}
+		
+	/* Release the global lock */
+	hythread_monitor_exit(globalMonitor);
+}

Added: incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.h
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.h?rev=390442&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.h (added)
+++ incubator/harmony/enhanced/classlib/trunk/native-src/shared/vmls/vmls.h Fri Mar 31 07:24:54
2006
@@ -0,0 +1,26 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef vmls_h
+#define vmls_h
+
+void   initializeVMLocalStorage PROTOTYPE((JavaVM * vm));
+void   freeVMLocalStorage PROTOTYPE((JavaVM * vm));
+UDATA  JNICALL HyVMLSAllocKeys PROTOTYPE((JNIEnv * env, UDATA * pInitCount, ...));
+void * JNICALL HyVMLSSet PROTOTYPE((JNIEnv * env, void ** pKey, void * value));
+void * JNICALL HyVMLSGet PROTOTYPE((JNIEnv * env, void * key));
+void   JNICALL HyVMLSFreeKeys PROTOTYPE((JNIEnv * env, UDATA * pInitCount, ...));
+
+#endif     /* vmls_h */

Modified: incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/makefile
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/makefile?rev=390442&r1=390441&r2=390442&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/makefile (original)
+++ incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/makefile Fri Mar 31 07:24:54
2006
@@ -21,7 +21,8 @@
 all: \
 	_sig _pool _thread _port _fdlibm _zip \
 	_zlib _common _nio _luni _vmi _auth \
-	_archive _math _launcher _text _prefs
+	_archive _math _launcher _text _prefs \
+	_vmls
 
 _auth:
 	cd auth
@@ -103,6 +104,11 @@
 	$(MAKE) /NOLOGO
 	cd ..
 
+_vmls: _thread _port
+	cd vmls
+	$(MAKE) /NOLOGO
+	cd ..
+
 _launcher: _port _thread
 	cd launcher
 	$(MAKE) /NOLOGO
@@ -158,5 +164,8 @@
 	$(MAKE) /NOLOGO clean
 	cd ..
 	cd prefs
+	$(MAKE) /NOLOGO clean
+	cd ..
+	cd vmls
 	$(MAKE) /NOLOGO clean
 	cd ..

Propchange: incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/vmls/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Mar 31 07:24:54 2006
@@ -0,0 +1 @@
+*.pdb

Added: incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/vmls/makefile
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/vmls/makefile?rev=390442&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/vmls/makefile (added)
+++ incubator/harmony/enhanced/classlib/trunk/native-src/win.IA32/vmls/makefile Fri Mar 31
07:24:54 2006
@@ -0,0 +1,29 @@
+# Copyright 2006 The Apache Software Foundation or its licensors, as applicable
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+#     http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Makefile for module 'vmls'
+#
+
+!include <..\defines.mak>
+
+SHAREDSUB=$(SHARED)vmls\# comment to avoid \ being treated as continuation
+LIBNAME=$(LIBPATH)hyvmls.lib
+
+BUILDFILES = \
+	$(SHAREDSUB)vmls.obj
+
+HYCFLAGS = $(HYCFLAGS) /I$(SHAREDSUB) /I..\vmls
+
+!include <..\rules.mak>



Mime
View raw message