瀏覽代碼

Added missing modules based on I386 counterpart

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7682 8c9fc860-2736-0410-a75d-ab315db34111
negelef 7 年之前
父節點
當前提交
450fa77312
共有 3 個文件被更改,包括 2615 次插入0 次删除
  1. 492 0
      source/Generic.Linux.AMD64.Glue.Mod
  2. 1189 0
      source/Generic.Linux.AMD64.Unix.Mod
  3. 934 0
      source/Generic.Unix.AMD64.Machine.Mod

+ 492 - 0
source/Generic.Linux.AMD64.Glue.Mod

@@ -0,0 +1,492 @@
+(* Minimal ELF header for self contained linux Oberon programs *)
+(* Copyright (c) Felix Friedrich, ETH Zürich *)
+
+MODULE Glue; 
+
+IMPORT SYSTEM, Trace;
+
+CONST 
+	base* = 08048000H;
+	debug* = {};
+VAR
+	last-: RECORD END; (* empty variable linked to end of kernel *)
+	
+	baseAdr*: ADDRESS;
+	endAdr*: ADDRESS;
+	
+	dlsym-	: PROCEDURE {C} ( handle: ADDRESS; name: ADDRESS): ADDRESS;
+	dlopen-	: PROCEDURE {C} ( pathname: ADDRESS; mode: LONGINT ): ADDRESS;
+	dlclose-	: PROCEDURE {C} ( handle: ADDRESS );
+	exit-		: PROCEDURE {C} (status: LONGINT);
+
+	stackBottom-	: ADDRESS;	(* of main thread *)
+
+
+	argc-: WORD; 
+	argv-: ADDRESS;
+	environ-: ADDRESS;
+
+	PROCEDURE {INITIAL, NOPAF} EntryPoint;
+	CODE
+		; ELF header
+		DB 07FH, 'ELF', 1, 1, 1, 0
+		DD 0, 0
+		DW 02, 03
+		DD 01
+		DD entry + base; program entry point
+		DD elfheadersize
+		DD 0
+		DD 0
+		DW elfheadersize
+		DW 20H
+		DW 3 ; #program header table entries
+		DW 0
+		DW 0
+		DW 0
+
+		elfheadersize:
+
+		; program header
+		DD 1
+		DD 0
+		DD base; 
+		DD base; 
+		DD @last - base; segment size (file)
+		DD @last - base; segment size (memory)
+		DD 07
+		DD 1000H; alignment
+		
+		; interpreter header
+		DD 3
+		DD interpretername; interpreter name offset
+		DD interpretername + base; interpreter name 
+		DD interpretername + base; interpreter name
+		DD interpretername_end - interpretername ; interpreter name length
+		DD interpretername_end - interpretername ; interpreter name length
+		DD 4H
+		DD 1H
+
+		; dynamic header
+		DD 02H
+		DD dynamicsection 
+		DD dynamicsection + base
+		DD dynamicsection + base
+		DD dynamicsection_end - dynamicsection ; size of dynamic section
+		DD dynamicsection_end - dynamicsection ; size of dynamic section
+		DD 06H
+		DD 04H
+
+		dynamicsection:
+		DD 05H, base + stringtable
+		DD 06H, symboltablebegin + base
+		DD 07H, dlsymrelocation + base
+		DD 08H, dlsymrelocation_end-dlsymrelocation ; size (relocationtable)
+		DD 09H, 0CH
+		DD 0AH, stringtable_end - stringtable; size (stringtable)
+		DD 0BH, 10H
+		
+		DD 01H, libname - stringtable; position of libname
+		DD 0H, 0H ; sentinel
+		dynamicsection_end:		
+		
+	 	dlsymrelocation:
+		DD @dlsym
+		DB 01H
+		DB 01H, 00H, 00H; index of the symbol
+		DD 0H
+		dlsymrelocation_end:
+
+		stringtable:
+		DB 0H ; sentinel
+
+		libname:
+		DB 'libdl.so.2', 0
+		
+		dlsymname:
+		DB 'dlsym', 0
+		
+		
+		stringtable_end:
+		
+		ALIGN 4
+		symboltablebegin:
+		DD	0;
+		DD	0
+		DD	0
+		DB	0
+		DB	0
+		DW 0
+		
+		; dlsym symbol
+		DD dlsymname - stringtable; position of dlsymname
+		DD	0
+		DD	0
+		DB	12H ; info: global + function
+		DB 0
+		DW	0
+
+		interpretername:
+		DB '/lib/ld-linux.so.2', 0
+		interpretername_end:
+
+		ALIGN 4
+
+		entry:
+	END EntryPoint;
+
+	(*
+	PROCEDURE {FINAL} ExitPoint;
+	BEGIN
+		Trace.String("exiting"); Trace.Ln;
+		exit(0);
+	END ExitPoint;
+	*)
+
+	PROCEDURE {NOPAF} putc*(file: ADDRESS; c: CHAR);
+	CODE
+		PUSH ECX
+		MOV EAX, 4
+		MOV EBX, [ESP + 12]
+		LEA ECX, [ESP+8]	
+		MOV EDX, 1
+		INT 80H
+		POP ECX
+		JNE fail
+		MOV EAX, [ESP + 4]
+		RET
+		fail:
+		MOV EAX, -1
+		RET
+	END putc;
+
+	PROCEDURE Dlsym*(handle: ADDRESS; CONST name: ARRAY OF CHAR; adr: ADDRESS);
+	VAR val: ADDRESS;
+	BEGIN
+		val := dlsym(handle, ADDRESS OF name[0]);
+		SYSTEM.PUT(adr, val);
+	END Dlsym;
+
+	PROCEDURE Char(c: CHAR);
+	BEGIN
+		putc(1, c);
+	END Char;
+ 
+	PROCEDURE Init;
+	VAR i: LONGINT;
+	BEGIN
+		baseAdr := ADDRESS OF EntryPoint;
+		endAdr := ADDRESS OF last;
+		
+		Trace.Init;
+		Trace.Char := Char;
+		
+		stackBottom := ADDRESSOF( i ) + 2*SIZEOF(ADDRESS);
+		ASSERT(dlsym # NIL);
+		Dlsym(0,"dlopen", ADDRESS OF dlopen);
+		ASSERT(dlopen # NIL); 
+		Dlsym( 0, "dlclose", ADDRESS OF dlclose);
+		ASSERT(dlclose # NIL); 
+		Dlsym(0,"exit", ADDRESS OF exit);
+		ASSERT(exit # NIL);
+	END Init;
+	
+	PROCEDURE {INITIAL,NOPAF} Init0;
+	BEGIN
+		(*initial stack layout:
+			argc at esp
+			argv at esp+4
+			0 at esp+4+argc*4
+			env at esp+4+argc*4+4      =   (2+argc)<<2 + esp*)
+		CODE{SYSTEM.i386}
+			MOV EAX, [ESP]
+			MOV argc, EAX
+			LEA EAX, [ESP+4]
+			MOV argv, EAX
+			MOV EAX, [ESP]
+			ADD EAX, 2
+			SHL EAX, 2
+			ADD EAX, ESP
+			MOV environ, EAX
+		END;
+		Init;
+	END Init0;
+	
+	PROCEDURE Initialize*;
+	BEGIN
+		(* nothing, only for compatibility *)
+	END Initialize;
+	
+
+END Glue.
+
+
+
+SystemTools.FreeDownTo FoxIntermediateBackend ~
+
+SystemTools.DoCommands
+	Compiler.Compile -p=Linux32G
+		Runtime.Mod Trace.Mod Generic.Linux.I386.Glue.Mod Generic.Linux.I386.Unix.Mod Generic.Unix.I386.Machine.Mod Heaps.Mod  Generic.Modules.Mod 
+		Generic.Unix.Objects.Mod 
+		Unix.Kernel.Mod KernelLog.Mod Plugins.Mod Streams.Mod 
+		Pipes.Mod Commands.Mod I386.Reals.Mod Generic.Reflection.Mod TrapWriters.Mod CRC.Mod SystemVersion.Mod 
+		Unix.StdIO.Mod Generic.Unix.Traps.Mod Locks.Mod Unix.Clock.Mod Disks.Mod Files.Mod Dates.Mod Strings.Mod 
+		UTF8Strings.Mod FileTrapWriter.Mod Caches.Mod DiskVolumes.Mod OldDiskVolumes.Mod RAMVolumes.Mod 
+		DiskFS.Mod OldDiskFS.Mod OberonFS.Mod FATVolumes.Mod FATFiles.Mod ISO9660Volumes.Mod 
+		ISO9660Files.Mod Unix.UnixFiles.Mod RelativeFileSystem.Mod BitSets.Mod StringPool.Mod DIagnostics.Mod 
+		ObjectFile.Mod GenericLinker.Mod GenericLoader.Mod Unix.BootConsole.Mod 
+	~
+
+	StaticLinker.Link --fileFormat=Raw --fileName=simple_elf --extension=.GofU --displacement=08048000H
+		Runtime Trace Glue Unix Machine Heaps Modules Objects Kernel KernelLog 
+Streams Commands StdIO TrapWriters Traps 
+Files UnixFiles Clock Dates Reals Strings Diagnostics 
+BitSets StringPool ObjectFile GenericLinker Reflection  GenericLoader  
+BootConsole 
+ ~
+
+	FSTools.CloseFiles simple_elf ~
+~ 
+
+MODULE Test;
+
+IMPORT StdIO, Commands, Streams, Modules;
+
+PROCEDURE Execute(context: Commands.Context);
+VAR str, msg: ARRAY 256 OF CHAR;  res: LONGINT;
+BEGIN
+	IF ~context.arg.GetString(str) THEN RETURN END;
+	IF ~context.arg.GetString(str) THEN 
+		context.out.String("no command"); context.out.Ln;
+		RETURN
+	END;
+	Commands.Activate(str, context, {Commands.Wait}, res, msg);
+END Execute;
+
+BEGIN
+	Execute(StdIO.env);
+	Modules.Shutdown(1);
+END Test.
+
+
+#	Release.Build --path="../obg/"  Win32G ~
+#	StaticLinker.Link --fileFormat=PE32 --fileName=A2.exe --extension=GofW --displacement=401000H --path="../obg/" 
+
+Runtime Trace Kernel32 Machine Heaps Modules Objects Kernel KernelLog 
+Streams Commands FIles WinFS Clock Dates Reals Strings Diagnostics 
+BitSets StringPool ObjectFile GenericLinker Reflection  GenericLoader  BootConsole ~
+
+FoxGenericObjectFile.Show Machine.GofU ~
+
+
+# LinuxAos
+# Wednesday, September 7, 2016  18:54:57
+# This file has been automatically generated using Release.Mod.
+# Red colors indicate that a module imports SYSTEM.
+SystemTools.DoCommands
+SystemTools.Timer start ~
+Compiler.Compile  -b=AMD --objectFileExtension=.Obj --symbolFileExtension=.Obj --destPath=NewAos/
+Runtime.Mod Trace.Mod Unix.Glue.Mod Linux.I386.Unix.Mod Unix.I386.Machine.Mod 
+Unix.Heaps.Mod Modules.Mod Unix.Objects.Mod Unix.Kernel.Mod KernelLog.Mod Plugins.Mod Streams.Mod 
+Pipes.Mod Commands.Mod I386.Reals.Mod Reflection.Mod TrapWriters.Mod CRC.Mod SystemVersion.Mod 
+Unix.StdIO.Mod Unix.Traps.Mod Locks.Mod Unix.Clock.Mod Disks.Mod Files.Mod Dates.Mod Strings.Mod 
+UTF8Strings.Mod FileTrapWriter.Mod Caches.Mod DiskVolumes.Mod OldDiskVolumes.Mod RAMVolumes.Mod 
+DiskFS.Mod OldDiskFS.Mod OberonFS.Mod FATVolumes.Mod FATFiles.Mod ISO9660Volumes.Mod 
+ISO9660Files.Mod Unix.UnixFiles.Mod RelativeFileSystem.Mod Loader.Mod Unix.BootConsole.Mod
+
+Compiler.Compile -p=Linux32G
+Displays.Mod Inputs.Mod Options.Mod Events.Mod EventsUtils.Mod EventsKernelLog.Mod 
+EventsFileLog.Mod EventsMemoryLog.Mod DynamicStrings.Mod XMLObjects.Mod XML.Mod XMLScanner.Mod 
+XMLParser.Mod Configuration.Mod FileHandlers.Mod BootShell.Mod I386.Network.Mod ActiveTimers.Mod 
+Unix.IP.Mod Unix.Sockets.Mod Unix.TCP.Mod Unix.UDP.Mod Unix.DNS.Mod Serials.Mod SoundDevices.Mod 
+Joysticks.Mod TVDriver.Mod VirtualDisks.Mod DisplayNull.Mod Unix.V24.Mod Unix.OpenAL.Mod 
+OpenALSound.Mod StringPool.Mod Diagnostics.Mod Debugging.Mod BitSets.Mod ObjectFile.Mod 
+GenericLinker.Mod StaticLinker.Mod FoxBasic.Mod FoxProgTools.Mod FoxScanner.Mod FoxCSharpScanner.Mod 
+FoxSyntaxTree.Mod FoxGlobal.Mod FoxActiveCells.Mod FoxHardware.Mod FoxFormats.Mod FoxPrintout.Mod 
+FoxParser.Mod FoxCSharpParser.Mod FoxSemanticChecker.Mod FoxBackend.Mod FoxSections.Mod 
+FoxFrontend.Mod FoxOberonFrontend.Mod FoxCSharpFrontend.Mod FoxCompiler.Mod FoxFingerPrinter.Mod 
+FoxInterfaceComparison.Mod FoxTextualSymbolFile.Mod FoxBinarySymbolFile.Mod FoxBinaryCode.Mod 
+FoxIntermediateCode.Mod FoxIntermediateBackend.Mod FoxCodeGenerators.Mod FoxBinaryObjectFile.Mod 
+FoxGenericObjectFile.Mod FoxAMD64InstructionSet.Mod FoxAMD64Assembler.Mod FoxAMDBackend.Mod FoxAssembler.Mod 
+FoxIntermediateAssembler.Mod FoxDisassembler.Mod FoxARMInstructionSet.Mod FoxARMAssembler.Mod FoxARMBackend.Mod 
+FoxMinosObjectFile.Mod FoxIntermediateParser.Mod FoxIntermediateObjectFile.Mod FoxIntermediateLinker.Mod 
+FoxTRMInstructionSet.Mod FoxTRMAssembler.Mod FoxTRMBackend.Mod FoxInterpreterBackend.Mod 
+FoxTranspilerBackend.Mod FoxDocumentationScanner.Mod FoxDocumentationTree.Mod FoxDocumentationPrinter.Mod 
+FoxDocumentationHtml.Mod FoxDocumentationParser.Mod FoxDocumentationBackend.Mod FoxProfiler.Mod 
+XMM.I386.Math.Mod XMM.I386.MathL.Mod FoxArrayBase.Mod I386.FoxArrayBaseOptimized.Mod Errors.Mod 
+Unix.ProcessInfo0.Mod ProcessInfo.Mod SystemTools.Mod Reboot.Mod XMM.I386.Math.Mod XMM.I386.MathL.Mod 
+Random.Mod Drand48.Mod SerialsVirtual.Mod Autostart.Mod FSTools.Mod UpTime.Mod CLUTs.Mod 
+I386.Raster.Mod Localization.Mod Archives.Mod WMRectangles.Mod WMEvents.Mod Repositories.Mod 
+FP1616.Mod Texts.Mod UndoManager.Mod CRC.Mod Inflate.Mod Unzip.Mod ZipFS.Mod Codecs.Mod 
+UnicodeProperties.Mod ContextualDependency.Mod UnicodeBidirectionality.Mod I386.WMRasterScale.Mod 
+WMGraphics.Mod TextUtilities.Mod Types.Mod Models.Mod WMProperties.Mod WMMessages.Mod 
+WMWindowManager.Mod WMGraphicUtilities.Mod WMDropTarget.Mod WMComponents.Mod KernelLogger.Mod 
+CompilerInterface.Mod FoxTextCompiler.Mod PCDebug.Mod PCM.Mod PCS.Mod PCT.Mod PCBT.Mod PCLIR.Mod PCO.Mod 
+PCG386.Mod PCC.Mod PCV.Mod PCArrays.Mod PCB.Mod PCP.Mod PCA386.Mod PCOM.Mod PCOF.Mod PCOFPE.Mod 
+PC.Mod PCOARM.Mod PCARMCP.Mod PCARMRegisters.Mod PCAARM.Mod PCGARM.Mod ASMAMD64.Mod 
+PCAAMD64.Mod PCGAMD64.Mod WhitespaceRemover.Mod HostClipboard.Mod Tar.Mod Zlib.Mod ZlibBuffers.Mod 
+ZlibDeflate.Mod ZlibInflate.Mod ZlibWriters.Mod ZlibReaders.Mod Zip.Mod ZipTool.Mod BIT.Mod 
+PNGDecoder.Mod BMPCodec.Mod GIFCodec.Mod JPEGDecoder.Mod AnimationCodec.Mod PartitionsLib.Mod 
+FATScavenger.Mod Partitions.Mod DiskTests.Mod DiskBenchmark.Mod PartitionEditorTable.Mod 
+FTPClient.Mod XYModem.Mod Shell.Mod ShellSerial.Mod Installer.Mod CryptoBigNumbers.Mod 
+CryptoBase64.Mod CryptoUtils.Mod CryptoCiphers.Mod CryptoARC4.Mod CryptoDES.Mod CryptoDES3.Mod 
+CryptoHashes.Mod CryptoMD5.Mod CryptoSHA1.Mod CryptoSHA256.Mod CryptoKeccakF1600.Mod 
+CryptoKeccakSponge.Mod CryptoSHA3.Mod CryptoCSPRNG.Mod CryptoPrimes.Mod CryptoDSA.Mod 
+CryptoDiffieHellman.Mod CryptoAES.Mod CryptoBlowfish.Mod CryptoTwofish.Mod CryptoCAST.Mod CryptoHMAC.Mod 
+CryptoIDEA.Mod CryptoRSA.Mod Checksum.Mod Fido.Mod I386.CPUID.Mod A2Sequencers.Mod PictImages.Mod 
+V24Tracer.Mod XMLGeneratorSchema.Mod CSS2.Mod CSS2Scanner.Mod CSS2Parser.Mod RAWPrinter.Mod LPR.Mod 
+ASN1.Mod PKCS1.Mod X509.Mod TLS.Mod TCPServices.Mod TestServer.Mod TCPTools.Mod 
+Win32.Performance.Mod Bin2Hex.Mod BinToCode.Mod Base64.Mod DisplayGTF.Mod GZip.Mod ShellCommands.Mod 
+Telnet.Mod TFClasses.Mod Mail.Mod SMTPClient.Mod TFLog.Mod WebHTTP.Mod WebHTTPClient.Mod 
+WebHTTPTools.Mod WebHTTPServer.Mod WebHTTPServerTools.Mod WebSSMPPlugin.Mod 
+WebHTTPServerStatistics.Mod POP3Client.Mod RFC865Client.Mod QuoteServer.Mod FTPFS.Mod XModem.Mod SearchTools.Mod 
+DiffLib.Mod TextConverter.Mod TaskScheduler.Mod FTP.Mod DES.Mod VNCServer.Mod WAVCodec.Mod 
+MP3Decoder.Mod I386.IDCT.Mod AVI.Mod DivXTypes.Mod I386.DivXHelper.Mod I386.DivXDecoder.Mod 
+MPEGTables.Mod I386.MPEGUtilities.Mod MPEGVideoDecoder.Mod JPEG2000DecoderUtil.Mod 
+JPEG2000DecoderCS.Mod JPEG2000Decoder.Mod MD5.Mod HTTPSupport.Mod HTTPSession.Mod DynamicWebpage.Mod 
+DynamicWebpagePlugin.Mod PrevalenceSystem.Mod WMDropTarget.Mod GenericSort.Mod WebStd.Mod WebComplex.Mod 
+WMCharCodes.Mod HTMLScanner.Mod HTMLParser.Mod NewHTTPClient.Mod UnihanParser.Mod CSV.Mod 
+ColorModels.Mod WMDefaultWindows.Mod WMDefaultFont.Mod WMFontManager.Mod WMOberonFonts.Mod 
+WMCCGFonts.Mod WMBitmapFont.Mod OpenTypeInt.Mod OpenTypeScan.Mod OpenType.Mod OpenTypeFonts.Mod 
+WMOTFonts.Mod WindowManager.Mod Generic.Unix.X11.Mod Unix.X11Api.Mod Unix.XDisplay.Mod Unix.Beep.Mod 
+Unix.KbdMouse.Mod Unix.Clipboard.Mod Attributes.Mod WMStandardComponents.Mod WMProgressComponents.Mod 
+WMShapes.Mod WMFigures.Mod WMScrollableComponents.Mod WMPieMenu.Mod WMPopups.Mod 
+PositionDebugging.Mod SyntaxHighlighter.Mod WMTextView.Mod WMInputMethods.Mod WMEditors.Mod 
+WMSearchComponents.Mod WMMacros.Mod WMGrids.Mod WMStringGrids.Mod WMTrees.Mod WMMixer.Mod 
+WMTabComponents.Mod WMColorComponents.Mod WMAnimations.Mod WMDropDownLists.Mod WMRestorable.Mod 
+WMApplications.Mod WMDialogs.Mod WMDocumentEditor.Mod WMErrors.Mod WMOSD.Mod WMArchives.Mod 
+WMCharMap.Mod WMUnicodeMarkerTool.Mod Unix.DisplayRefresher.Mod ModuleParser.Mod ModuleTrees.Mod 
+WMXMLTree.Mod WMDiagnostics.Mod PETTrees.Mod PETModuleTree.Mod PETXMLTree.Mod PET.Mod 
+WMArabicIME.Mod WMArmenianIME.Mod WMHebrewIME.Mod WMPinyinIME.Mod WMRussianIME.Mod 
+WMUkrainianIME.Mod WMEthiopicIME.Mod WMUnicodeIME.Mod WMInputMethodTool.Mod WMUtilities.Mod 
+WMTrapWriter.Mod FoxA2Interface.Mod WMMenus.Mod WMDiagramComponents.Mod MainMenu.Mod StartMenu.Mod 
+HotKeys.Mod WMNavigate.Mod WMNavigator.Mod WMDesktops.Mod Notepad.Mod WMSystemComponents.Mod 
+WMFileManager.Mod WMSearchTool.Mod WMFTPClient.Mod SkinLanguage.Mod FNHistories.Mod SkinEngine.Mod 
+WMProcessInfo.Mod WMObjectTracker.Mod WMKernelLog.Mod WMEventLog.Mod WMPartitionsComponents.Mod 
+WMPartitions.Mod PartitionEditorComponents.Mod PartitionEditor.Mod MultiLogger.Mod MemoryReader.Mod 
+Decoder.Mod I386Decoder.Mod ARMDecoder.Mod AMD64Decoder.Mod WMTextTool.Mod WMPerfMonPlugins.Mod 
+WMPerfMonAlerts.Mod WMPerfMonAlertsUtils.Mod Unix.WMPerfMonPluginCpu.Mod 
+ WMPerfMonPluginProcesses.Mod WMPerfMonPluginSerials.Mod WMPerfMonPluginNetwork.Mod 
+WMPerfMonPluginDisks.Mod WMPerfMonPluginPerfMon.Mod WMPerfMonPluginEvents.Mod WMPerfMonPluginMessages.Mod 
+WMPerfMonComponents.Mod WMPerfMonTabSystem.Mod WMPerfMonTabAlerts.Mod WMPerfMon.Mod WMClock.Mod 
+WMCalendar.Mod WMV24Component.Mod WMShell.Mod SSHGlobals.Mod SSHKeys.Mod SSHTransport.Mod 
+SSHAuthorize.Mod SSH.Mod SSHClient.Mod TFStringPool.Mod BimboScanner.Mod TFTypeSys.Mod TFDumpTS.Mod 
+TFScopeTools.Mod TFCheck.Mod TFAOParser.Mod TFModuleTrees.Mod TFPET.Mod TFClasses.Mod 
+TFDocGenerator.Mod TFXRef.Mod CharacterLineup.Mod WMDesktopIcons.Mod WMTextStyleTool.Mod WMVNCView.Mod 
+VNC.Mod WMVT100.Mod SkinEditor.Mod Looks.Mod WMSkinLoader.Mod WMBackdropLoader.Mod 
+WMInspectionComponents.Mod WMInspector.Mod WMRepositories.Mod WMBuilder.Mod WMBuilderTransformer.Mod 
+CyberbitNetInstall.Mod WMDiff.Mod WMTaskScheduler.Mod IMAPUtilities.Mod IMAP.Mod IMAPClient.Mod RMSMTP.Mod 
+IMAPGUI.Mod WMPerfMonPluginHTTPServer.Mod WMPerfMonPluginQuoteServer.Mod 
+WMPerfMonPluginVNCServer.Mod WMPerfMonPluginExample.Mod WMModuleState.Mod WMKeyCode.Mod WMPicView.Mod 
+ComponentViewer.Mod WMScreenShot.Mod WMBackdrop.Mod WMInstaller.Mod HotKeysCommands.Mod 
+I386.VMWareTools.Mod SynergyClient.Mod I386.WMTransitions.Mod MediaPlayer.Mod Presentation.Mod 
+MP3Player.Mod WMPlayer.Mod WAVRecorder.Mod OGGUtilities.Mod OGGVorbisPlayer.Mod WMOGGPlayer.Mod 
+DTPData.Mod DTPUtilities.Mod DTPView.Mod DTPEditor.Mod DTPText.Mod DTPRect.Mod DTPImage.Mod 
+GfxMatrix.Mod GfxImages.Mod GfxPaths.Mod GfxRegions.Mod GfxFonts.Mod Gfx.Mod GfxRaster.Mod 
+GfxBuffer.Mod WMGraphicsGfx.Mod CSS2Properties.Mod XMLComponents.Mod XMLStyle.Mod XMLLoader.Mod 
+SVGUtilities.Mod SVGColors.Mod SVGMatrix.Mod SVG.Mod SVGGradients.Mod SVGFilters.Mod SVGRenderer.Mod 
+SVGLoader.Mod SVGDecoder.Mod WebBrowserComponents.Mod XMLTransformer.Mod HTMLTransformer.Mod 
+WebBrowserPanel.Mod WebBrowser.Mod MailStorage.Mod BimboMail.Mod DebugLog.Mod WMJoysticks.Mod 
+WMTetris.Mod VNCTetrisServer.Mod Bimso.Mod WMScribble.Mod SortDemo.Mod FractalDemo.Mod WMBunny.Mod 
+TuringCoatWnd.Mod W3dVectors.Mod W3dMatrix.Mod W3dGeometry.Mod W3dAbstractWorld.Mod 
+W3dObjectGenerator.Mod W3dRasterizer.Mod W3dWorld.Mod W3dExplorer.Mod W3dMenu.Mod CATServer.Mod 
+W3dClusterWatch.Mod WMSlideshow.Mod Snow.Mod MenuEdit.Mod PresentViewer.Mod TestSuite.Mod PCTest.Mod 
+Versioning.Mod FoxTest.Mod TestFiles.Mod BenchTCP.Mod TestDates.Mod TestStrings.Mod BenchXML.Mod 
+BenchSyntaxHighlighter.Mod CryptoTestBigNumbers.Mod CryptoTestCiphers.Mod CryptoTestDH.Mod CryptoTestDSA.Mod 
+CryptoTestHMAC.Mod CryptoTestHashes.Mod CryptoTestRSA.Mod BeepTest.Mod JoysticksTest.Mod TestMenu.Mod 
+PieTest.Mod TestTrees.Mod TestComponentDragDrop.Mod ComponentInfo.Mod TestComponents.Mod 
+TestXMLPlugins.Mod HelloWorld.Mod HelloWorld1.Mod HelloWorld2.Mod HelloWorld3.Mod Example1.Mod 
+Example2.Mod Example3.Mod Example4.Mod Example5.Mod Example6.Mod Example7.Mod Example8.Mod 
+ExampleTextWriter.Mod JavaLocks.Mod WebAccounts.Mod WebForum.Mod ExerciseGroups.Mod IsoImages.Mod 
+ReleaseThreadPool.Mod Release.Mod PETReleaseTree.Mod Linker0.Mod Linker1.Mod Linker.Mod 
+Unix.BootLinkerHeaps.Mod Unix.BootLinkerModules.Mod Unix.BootLinkerLoader.Mod Unix.BootLinker.Mod 
+BootManager.Mod EFI.Mod I386.EFIMachine.Mod EFIBlockIO.Mod EFIDiskIO.Mod EFIFileProtocol.Mod 
+EFISimpleFS.Mod EFILoadedImage.Mod EFIGraphicsOutput.Mod EFITrace.Mod EFILib.Mod EFITest.Mod 
+EFIGraphicalConsole.Mod EFIA2Loader.Mod Sage.UDPChatBase.Mod Sage.UDPChatServer.Mod Sage.UDPChatClient.Mod 
+CyrillicUtilities.Mod YMF754Util.Mod SambaClient.Mod SambaServer.Mod srBase.Mod srRayEngine.Mod srMath.Mod 
+I386.srE.Mod srGL.Mod srHex.Mod srImage.Mod srVoxel.Mod srVoxel2.Mod srVoxel3.Mod srVolShader.Mod 
+srVoxel4.Mod srVoxel5.Mod srM2Space.Mod srM3Space.Mod srM5Space.Mod srM6Space.Mod 
+srRastermovie.Mod srTexVox.Mod srThermoCell.Mod srTree.Mod sr3DTexture.Mod srLifeVox.Mod srRotaVox.Mod 
+srvoxels.Mod srRender.Mod MenuPages.Mod WMOverlay.Mod PrettyPrint.Mod NbrInt8.Mod NbrInt16.Mod 
+NbrInt32.Mod I386.NbrInt64.Mod NbrInt.Mod NbrRat.Mod I386.NbrRe32.Mod I386.NbrRe64.Mod NbrRe.Mod 
+NbrCplx.Mod NbrStrings.Mod WPM.Mod AlmSmtpReceiver.Mod WMFontCCGConverter.Mod WebCGI.Mod 
+RegisterRFW.Mod WebBimbodot.Mod TFWebForum.Mod PDF.Mod AFM.Mod PDFExample.Mod Visualizer.Mod 
+ReleaseVisualizerScanner.Mod ReleaseVisualizer.Mod OdUtil.Mod OdXml.Mod OdCond.Mod OdAuthBase.Mod OdAuth.Mod 
+OdClient.Mod OdVCSBase.Mod SVNArgument.Mod SVNOutput.Mod SVNUtil.Mod Oberon.Kernel.Mod 
+Oberon.Modules.Mod Oberon.FileDir.Mod Oberon.Files.Mod Oberon.Disks.Mod Oberon.Objects.Mod 
+OberonInput.Mod OberonDisplay.Mod Oberon.Display.Mod Oberon.Input.Mod Oberon.Viewers.Mod 
+Oberon.Fonts.Mod Oberon.Mod Oberon.Texts.Mod Oberon.Oberon.Mod Oberon.MenuViewers.Mod 
+Oberon.TextFrames.Mod Oberon.System.Mod Oberon.In.Mod Oberon.Out.Mod Oberon.Dates.Mod Oberon.Strings.Mod 
+I386.Oberon.Bitmaps.Mod Oberon.Pictures.Mod Oberon.RandomNumbers.Mod Oberon.V24.Mod Unix.Oberon.Printer.Mod 
+Oberon.OPM.Mod Oberon.OPS.Mod Oberon.OPT.Mod Oberon.OPB.Mod Oberon.OPA.Mod Oberon.OPP.Mod 
+Oberon.OPO.Mod Oberon.OPL.Mod Oberon.OPC.Mod Oberon.OPV.Mod Oberon.Compiler.Mod Oberon.OPAData.Mod 
+Oberon.Edit.Mod Oberon.Styles.Mod Oberon.ScriptFrames.Mod Oberon.Script.Mod Oberon.Partitions.Mod 
+Oberon.Browser.Mod Oberon.FATFiles.Mod Oberon.DOS.Mod Oberon.Hello.Mod Oberon.PSPrinter.Mod 
+Oberon.HPLaserPrinter.Mod Oberon.HPPCL.Mod Unix.Oberon.UnixPrinter.Mod Unix.Oberon.NetSystem.Mod 
+Oberon.HelloServer.Mod Oberon.Terminals.Mod Oberon.TerminalFrames.Mod Oberon.Telnet.Mod 
+Oberon.TextMail.Mod Oberon.FTP.Mod Oberon.XYplane.Mod Oberon.IFS.Mod Oberon.ET.Mod Oberon.Menu.Mod 
+Oberon.Decoder.Mod Oberon.V24Log.Mod Oberon.SysLog.Mod Oberon.ZlibWriters.Mod Oberon.ZlibReaders.Mod 
+Oberon.Zip.Mod Oberon.ZipTool.Mod Oberon.GZWriters.Mod Oberon.GZReaders.Mod Oberon.GZip.Mod 
+Oberon.TGZ.Mod Oberon.PCARMDecoder.Mod Oberon.Aos.Mod Oberon.OFSTools.Mod Oberon.CleanupFiles.Mod 
+Oberon.FATTools.Mod Oberon.Colors.Mod Oberon.Display3.Mod Oberon.Effects.Mod Oberon.Printer3.Mod 
+Oberon.Attributes.Mod Oberon.Links.Mod Oberon.Gadgets.Mod Oberon.BasicGadgets.Mod Oberon.TextFields.Mod 
+Oberon.ListRiders.Mod Oberon.ListModels.Mod Oberon.ListDags.Mod Oberon.ListGadgets.Mod Oberon.Lists.Mod 
+Oberon.Panels.Mod Unix.Oberon.TextGadgets0.Mod Unix.Oberon.TextGadgets.Mod Oberon.BasicFigures.Mod 
+Unix.Oberon.Scrollbars.Mod Unix.Oberon.TextSBControl.Mod Oberon.Directories.Mod Oberon.Clocks.Mod 
+Oberon.Organizers.Mod Oberon.Complex.Mod Oberon.SetGadgets.Mod Oberon.TimeStamps.Mod Oberon.Gages.Mod 
+Oberon.AudioGadgets.Mod Oberon.ProgressMeters.Mod Oberon.Sisiphus.Mod Oberon.Documents.Mod Oberon.Views.Mod 
+Oberon.Desktops.Mod Unix.Oberon.TextDocs.Mod Oberon.PanelDocs.Mod Oberon.Icons.Mod 
+Oberon.ColorTools.Mod Oberon.NamePlates.Mod Oberon.Navigators.Mod Oberon.NoteBooks.Mod Oberon.Finder.Mod 
+Oberon.GadgetsIn.Mod Oberon.GadgetsOut.Mod Oberon.ScrollViews.Mod Oberon.RefGadgets.Mod 
+Oberon.Columbus.Mod Oberon.ObjExplorer.Mod Oberon.Compress.Mod Oberon.CompressCrypt.Mod 
+Oberon.AsciiCoder.Mod Oberon.Base64.Mod Oberon.UUDecoder.Mod Oberon.BinHex.Mod Oberon.Rot13.Mod 
+Oberon.Tar.Mod Oberon.QuotedPrintable.Mod Oberon.Builder.Mod Oberon.Watson0.Mod Oberon.Watson.Mod 
+Oberon.EditTools.Mod Oberon.Outlines.Mod Oberon.OFormatterIO.Mod Oberon.OFormatter.Mod 
+Oberon.StyleGadgets.Mod Oberon.ScriptGadgets.Mod Oberon.Rembrandt0.Mod Oberon.Rembrandt.Mod 
+Oberon.RembrandtDocs.Mod Oberon.RembrandtTools.Mod Oberon.ErrorGadgets.Mod Oberon.PC.Mod 
+Unix.Oberon.Clipboard.Mod Oberon.JPEG.Mod Oberon.GIF.Mod Oberon.XBM.Mod Oberon.BMP.Mod Oberon.ICO.Mod 
+Oberon.PCX.Mod Oberon.TGA.Mod Oberon.IFF.Mod Oberon.ColorModels.Mod Oberon.XPM.Mod Oberon.PPM.Mod 
+Oberon.PSD.Mod Oberon.Images.Mod Oberon.ImageGadgets.Mod Oberon.ImageDocs.Mod 
+Oberon.PictImages.Mod Oberon.BMPImages.Mod Oberon.JPEGImages.Mod Oberon.GIFImages.Mod 
+Oberon.PSDImages.Mod Oberon.ColorGadgets.Mod Oberon.PCXImages.Mod Oberon.ColorWells.Mod 
+Oberon.Streams.Mod Oberon.TextStreams.Mod Oberon.BTrees.Mod Oberon.MIME.Mod Oberon.HyperDocs.Mod 
+Oberon.NetTools.Mod Oberon.PasswordFields.Mod Oberon.HyperDocTools.Mod Oberon.Mail.Mod 
+Oberon.FTPDocs.Mod Oberon.Finger.Mod Oberon.News.Mod Oberon.Gopher.Mod Oberon.TerminalGadgets.Mod 
+Oberon.TelnetGadgets.Mod Oberon.HTTPDocs0.Mod Oberon.HTMLDocs.Mod Oberon.HTTPDocs.Mod Oberon.HTMLForms.Mod 
+Oberon.HTMLImages.Mod Oberon.HTMLTables.Mod Oberon.ZipDocs.Mod Oberon.Packages.Mod Oberon.PlugIns.Mod 
+Oberon.HTMLPlugIns.Mod Oberon.Copyright.Mod Oberon.FileDisks.Mod Oberon.OTInt.Mod Oberon.OTScan.Mod 
+Oberon.OType.Mod Oberon.OTFonts.Mod Oberon.GfxMatrix.Mod Oberon.GfxImages.Mod Oberon.GfxPaths.Mod 
+Oberon.GfxRegions.Mod Oberon.GfxFonts0.Mod Oberon.GfxFonts.Mod Oberon.Gfx.Mod Oberon.GfxRaster.Mod 
+Oberon.GfxPrinter.Mod Oberon.GfxBuffer.Mod Oberon.GfxDisplay.Mod Oberon.GfxPS.Mod Oberon.GfxOType.Mod 
+Oberon.GfxPKFonts.Mod Oberon.GfxTest.Mod Oberon.GfxDemo.Mod Oberon.Leonardo.Mod Oberon.LeoFrames.Mod 
+Oberon.LeoTools.Mod Oberon.LeoDocs.Mod Oberon.LeoPanels.Mod Oberon.LeoLists.Mod Oberon.LeoPens.Mod 
+Oberon.LeoOutliners.Mod Oberon.LeoPenEditors.Mod Oberon.LeoPaths.Mod Oberon.LeoPathEditors.Mod 
+Oberon.LeoSplines.Mod Oberon.LeoSplineEditors.Mod Oberon.LeoCaptions.Mod Oberon.LeoCaptionEditors.Mod 
+Oberon.LeoBasic.Mod Oberon.LeoBasicEditors.Mod Oberon.LeoImages.Mod Oberon.LeoImageEditors.Mod 
+Oberon.LeoDraw.Mod Oberon.Scheme.Mod Oberon.SchemeOps.Mod Oberon.Vinci.Mod Oberon.VinciGadgets.Mod 
+Oberon.VinciDocs.Mod Oberon.VinciShapes.Mod Oberon.VinciPens.Mod Oberon.VinciEditors.Mod 
+Oberon.TextPopups.Mod Oberon.V24Gadgets.Mod Oberon.Hex.Mod Oberon.Conversions.Mod Oberon.HPCalc.Mod 
+Oberon.EditKeys.Mod Oberon.Find.Mod Oberon.TeXTools.Mod Oberon.SaveScreen.Mod Oberon.SaveTiles.Mod 
+Oberon.SaveParticles.Mod Oberon.SaveDecay.Mod Oberon.SaveSisyphus.Mod Oberon.SaveSwarm.Mod 
+Oberon.SavePoints.Mod Oberon.MakePoints.Mod Oberon.SaveLife.Mod Oberon.SaveArt.Mod Oberon.DayTime.Mod 
+Oberon.Backdrops.Mod Oberon.LayoutPanels0.Mod Oberon.LayoutPanels.Mod Oberon.Layouts.Mod 
+Oberon.LayLaS.Mod Oberon.LayLa.Mod Oberon.LayLa2S.Mod Oberon.LayLa2.Mod Oberon.LayLaDemo.Mod 
+Oberon.Books0.Mod Oberon.Books.Mod Oberon.BooksHelp.Mod Oberon.BookDocs.Mod Oberon.BookCompiler.Mod 
+Oberon.Sets.Mod Oberon.CRS.Mod Oberon.CRT.Mod Oberon.CRA.Mod Oberon.CRX.Mod Oberon.CRP.Mod 
+Oberon.Coco.Mod Oberon.FontEditor.Mod Oberon.ASCIITab.Mod Oberon.Magnifier.Mod Oberon.Cards.Mod 
+Oberon.Solitaire.Mod Oberon.Spider.Mod Oberon.Freecell.Mod Oberon.MineSweeper.Mod Oberon.Sokoban.Mod 
+Oberon.Scramble.Mod Oberon.Shanghai.Mod Oberon.Tetris.Mod Oberon.Asteroids.Mod Oberon.HTML.Mod 
+Oberon.WTS.Mod Oberon.WTSFold.Mod Oberon.WTSPict.Mod Oberon.WTSStamp.Mod Oberon.WTSDraw.Mod 
+Oberon.CUSM.Mod Oberon.DiffGadgets.Mod Oberon.Diff.Mod Oberon.Sort.Mod Oberon.RXA.Mod Oberon.RX.Mod 
+Oberon.PictConverters.Mod Oberon.PS.Mod Oberon.Histogram.Mod Oberon.MultiMail.Mod Oberon.Calc.Mod 
+Oberon.Calculator.Mod Oberon.CalculatorGadgets.Mod Oberon.DBF.Mod Oberon.DBFDump.Mod Oberon.Swarm.Mod 
+Oberon.DVIFiles.Mod Oberon.DVIViewers.Mod Oberon.DVIDocs.Mod Oberon.ColorSystem.Mod Oberon.PhonePad.Mod 
+Oberon.Plotter.Mod Oberon.Plot.Mod Oberon.Lissajous.Mod Oberon.Graphs.Mod Oberon.Diagrams.Mod 
+Oberon.Simulator.Mod Oberon.Popups.Mod Oberon.BartSimpson.Mod Oberon.Cups.Mod Oberon.Examples.Mod 
+Oberon.Examples1.Mod Oberon.OpenDemo.Mod Oberon.OpenDemo2.Mod Oberon.ExampleOberon.Mod 
+Oberon.Suitcases.Mod Oberon.Skeleton.Mod Oberon.ViewSkeleton.Mod Oberon.ColorDriver.Mod 
+Oberon.DocumentSkeleton.Mod Oberon.Portraits.Mod Oberon.Reminders.Mod Oberon.TaskExample.Mod 
+Oberon.TCPExample.Mod 
+~
+SystemTools.Show Time elapsed: ~ SystemTools.Ln ~
+SystemTools.Timer elapsed ~ SystemTools.Ln ~
+~

+ 1189 - 0
source/Generic.Linux.AMD64.Unix.Mod

@@ -0,0 +1,1189 @@
+MODULE Unix;   (* Josef Templ, 5.3.90	SVR4 system calls *)  (** Linux x86 version, non portable *)
+
+(* Linux PPC version	g.f. 18.04.98	*)
+(* Linux x86 version	g.f 10.11.99 	*)
+(*	2000.09.19	g.f.	'Sigaltstack' added	*)
+(*	2002.06.27	g.f.	TmDesc fixed,  new: Utime, Mktime *)
+(*	2006.07.31	g.f.	shared memory support added *)
+(*	2007.04.13	g.f.	Thread priorities added *)
+
+IMPORT S := SYSTEM, Glue, Trace;
+
+
+CONST
+	Version* = "Linux";
+
+  	libcname* = "libc.so.6";
+	libX11name* = "libX11.so.6";
+	libpthreadname = "libpthread.so.0";
+
+	LittleEndian* = TRUE;   (** byte order of basic types *)
+	LsbIs0* = TRUE;   (** bit order of SET type *)
+
+	PageSize* = 4096;	(* least MMU page size *)
+
+	stdin* = 0;  stdout* = 1;  stderr* = 2;
+
+	(** Unix error codes:	*)
+	EPERM* = 1;   (* Not super-user *)
+	ENOENT* = 2;   (* No such file or directory *)
+	ESRCH* = 3;   (* No such process *)
+	EINTR* = 4;   (* interrupted system call *)
+	EIO* = 5;   (* I/O error *)
+	ENXIO* = 6;   (* No such device or address *)
+	E2BIG* = 7;   (* Arg list too long *)
+	ENOEXEC* = 8;   (* Exec format error *)
+	EBADF* = 9;   (* Bad file number *)
+	ECHILD* = 10;   (* No children *)
+	EAGAIN* = 11;   (* No more processes *)
+	ENOMEM* = 12;   (* Not enough core *)
+	EACCES* = 13;   (* Permission denied *)
+	EFAULT* = 14;   (* Bad address *)
+	ENOTBLK* = 15;   (* Block device required *)
+	EBUSY* = 16;   (* Mount device busy *)
+	EEXIST* = 17;   (* File exists *)
+	EXDEV* = 18;   (* Cross-device link *)
+	ENODEV* = 19;   (* No such device *)
+	ENOTDIR* = 20;   (* Not a directory *)
+	EISDIR* = 21;   (* Is a directory *)
+	EINVAL* = 22;   (* Invalid argument *)
+	ENFILE* = 23;   (* File table overflow *)
+	EMFILE* = 24;   (* Too many open files *)
+	ENOTTY* = 25;   (* Inappropriate ioctl for device *)
+	ETXTBSY* = 26;   (* Text file busy *)
+	EFBIG* = 27;   (* File too large *)
+	ENOSPC* = 28;   (* No space left on device *)
+	ESPIPE* = 29;   (* Illegal seek *)
+	EROFS* = 30;   (* Read only file system *)
+	EMLINK* = 31;   (* Too many links *)
+	EPIPE* = 32;   (* Broken pipe *)
+	EDOM* = 33;   (* Math arg out of domain of func *)
+	ERANGE* = 34;   (* Math result not representable *)
+	ENOMSG* = 42;   (* No message of desired type *)
+	EIDRM* = 43;   (* Identifier removed *)
+	ECHRNG* = 44;   (* Channel number out of range *)
+	EL2NSYNC* = 45;   (* Level 2 not synchronized *)
+	EL3HLT* = 46;   (* Level 3 halted *)
+	EL3RST* = 47;   (* Level 3 reset *)
+	ELNRNG* = 48;   (* Link number out of range *)
+	EUNATCH* = 49;   (* Protocol driver not attached *)
+	ENOCSI* = 50;   (* No CSI structure available *)
+	EL2HLT* = 51;   (* Level 2 halted *)
+	EDEADLK* = 35;   (* Deadlock condition. *)
+	ENOLCK* = 37;   (* No record locks available. *)
+
+	(* open flags *)
+	rdonly* = {};  rdwr* = {1};  creat* = {6};  trunc* = {9};
+
+	(* access modes *)
+	rwrwr* = {2, 4, 5, 7, 8};  rwxrwxrwx* = {0..8};
+
+	F_OK* = {};  X_Ok* = {0};  W_OK* = {1};  R_OK* = {2};
+
+	SCHED_OTHER = 0;
+
+	T_SIGRESUME = SIGUSR1;
+	T_SIGSUSPEND = SIGUSR2;
+
+	SIGHUP*		= 1;
+	SIGINT*		= 2;
+	SIGQUIT*	=3;
+	SIGILL*		= 4;
+	SIGTRAP*	= 5;
+	SIGABRT*	= 6;
+	SIGIOT*		= 6;
+	SIGBUS*		= 7;
+	SIGFPE*		= 8;
+	SIGKILL*		= 9;
+	SIGUSR1*	= 10;
+	SIGSEGV*	= 11;
+	SIGUSR2*	= 12;
+	SIGPIPE*	= 13;
+	SIGALRM*	= 14;
+	SIGTERM*	= 15;
+	SIGSTKFLT*	= 16;
+	SIGCHLD*	= 17;
+	SIGCONT*	= 18;
+	SIGSTOP*	= 19;
+	SIGTSTP*	= 20;
+	SIGTTIN*		= 21;
+	SIGTTOU*	= 22;
+	SIGURG*		= 23;
+	SIGXCPU*	= 24;
+	SIGXFSZ*	= 25;
+	SIGVTALRM*	= 26;
+	SIGPROF*	= 27;
+	SIGWINCH*	=28;
+	SIGIO*		=29;
+	SIGPOLL*	= SIGIO;
+	SIGPWR*	= 30;
+	SIGSYS*		= 31;
+	SIGUNUSED = 31;
+
+	SIG_BLOCK = 0;
+	SIG_UNBLOCK=1;
+	SIG_SETMASK=2;
+
+	SA_NOCLDSTOP	= 0x00000001;
+	SA_SIGINFO			= 0x00000004;
+	SA_ONSTACK		= 0x08000000;
+	SA_RESTART		= 0x10000000;
+	SA_NODEFER		= 0x40000000;
+	SA_RESETHAND	= 0x80000000;
+
+	PTHREAD_CANCEL_ENABLE 	= 0;
+	PTHREAD_CANCEL_DISABLE	= 1;
+
+	PTHREAD_CANCEL_ASYNCHRONOUS	= 0;
+	PTHREAD_CANCEL_DEFERRED	= 1;
+
+	(*--------------------------- Threads -------------------------------*)
+
+TYPE
+	Thread_t* = ADDRESS;
+	Mutex_t* = ADDRESS;
+	MutexType = ARRAY 8 OF ADDRESS;
+	MutexAttributeType = ARRAY 1 OF WORD;
+
+	Condition_t* = ADDRESS;
+	ConditionType = ARRAY 12 OF WORD;
+	
+	Key_t* = ADDRESS;
+
+	Sigset_t= ARRAY 32 OF ADDRESS;
+	SignalTrap = PROCEDURE ( sig: LONGINT; mc: Mcontext );
+	
+	pid_t*		= LONGINT;
+	path_t*	= ARRAY OF CHAR;
+	arg_t*		= ARRAY OF CHAR;
+	argv_t*	= ARRAY OF arg_t;
+	off_t*	= SIZE;
+
+
+CONST
+	(* Thread priorities *)
+	ThreadLow* = 1; ThreadNormal* = 20; ThreadHigh* = 99;
+	NumPriorities* = 99;	(* number of priority levels *)
+
+
+	(*---------------------------- IP -----------------------------------*)
+
+CONST
+	(* domain *)
+		AFINET* = 2;
+		AFINET6* = 26;
+
+		PFINET* = AFINET;
+		PFINET6* = AFINET6;
+
+	(* types of connection*)
+		SockStream*	= 1;
+		SockDGram*	= 2;
+
+	(* Protocols *)
+		IpProtoUDP*	= 17;
+		IpProtoTCP*		=  6;
+
+	(* setsockopt *)
+		SoLSocket*		= 1;			(* socket option level *)
+		SoLinger* 		= 13; 		(* linger (gracefully close the connection)*)
+		SoKeepAlive*	= 9;			(* keep connection alive *)
+		SoNoDelay*	= 1;			(* no delay *)
+
+	(* ioctl *)
+		FioNRead*		= 541BH;	(* something to read ? *)
+
+	(* recv *)
+		MsgPeek*		= 2;
+		MsgDontWait*	= 40H;		(* non blocking read *)
+
+	(* shutdown *)
+		ShutRDWR*	= 2;
+
+	SockAddrSizeV4*	= 16;
+	SockAddrSizeV6*	= 28;
+
+	(*----------------------- seral line, cf Unix.V24.Mod -----------------------*)
+
+	FIONREAD*	= 541BH;
+	TIOCMGET*		= 5415H;
+	TIOCMBIS*		= 5416H;
+	TIOCMBIC*		= 5417H;
+	TIOCMSET*		= 5418H;
+
+	(* speeds *)
+	B0*	= 0;
+	B50*	= 1;
+	B75*	= 2;
+	B110*	= 3;
+	B134*	= 4;
+	B150*	= 5;
+	B200*	= 6;
+	B300*	= 7;
+	B600*	= 8;
+	B1200* 	= 9;
+	B1800* 	= 10;
+	B2400* 	= 11;
+	B4800* 	= 12;
+	B9600* 	= 13;
+	B19200*	= 14;
+	B38400*	= 15;
+
+	B57600* 	= 1001H;
+	B115200*	= 1002H;
+	B230400*	= 1003H;
+
+
+
+	(* tio.cflag bits *)
+	CSIZE*		= {4,5};
+	   CS5*		= {};
+	   CS6*		= {4};
+	   CS7*		= {5};
+	   CS8*		= {4,5};
+	CSTOPB*	= {6};
+	CREAD*		= {7};
+	PARENB*	= {8};
+	PARODD*	= {9};
+	HUPCL*		= {10};
+	CLOCAL*	= {11};
+
+
+TYPE
+	Termios* = RECORD
+		iflags*, oflags*, cflags*, lflags*: SET;
+		line*: CHAR;
+		cc*	: ARRAY 32 OF CHAR;
+		ispeed-, ospeed-: LONGINT
+	END;
+
+	(*------------------------------------------------------------------*)
+
+
+TYPE
+	DevT* = HUGEINT;
+
+	Status* = RECORD
+				dev-		: DevT;
+				unused1-	: LONGINT;
+				ino-		: LONGINT;
+				mode-	: LONGINT;
+				nlink-		: LONGINT;
+				uid-		: LONGINT;
+				gid-		: LONGINT;
+				rdev-		: DevT;
+				unused2-	: LONGINT;
+				size-		: LONGINT;
+				blksize-	: LONGINT;
+				blocks-	: LONGINT;
+				atime-	: Timeval;
+				mtime-	: Timeval;
+				ctime-	: Timeval;
+				unused-	: ARRAY 2 OF LONGINT;
+			END;
+	tvPtr* = POINTER TO Timeval;
+	Timeval* = RECORD
+				sec*	: LONGINT;
+				usec*	: LONGINT
+			END;
+
+	TmPtr* = POINTER TO Tm;
+	Tm* = RECORD
+				sec*, min*, hour*, mday*, mon*, year*, wday*, yday*, isdst*: LONGINT;
+				gmtoff*, tmzone*: LONGINT;
+			END;
+
+	Tms* = POINTER TO RECORD
+				utime*, stime*, cutime*, cstime*: LONGINT
+			END;
+
+	Timezone* = RECORD
+				minuteswest*, dsttime*: LONGINT
+			END;
+
+	Itimerval* = RECORD
+				interval*, value*: Timeval
+			END;
+
+
+CONST
+	FdSetLen* = 32;
+
+TYPE
+	FdSet* = ARRAY FdSetLen OF SET;
+
+
+	Dirent* = POINTER TO RECORD
+				ino-, off-	: LONGINT;   (* these may change to HUGEINT in future Linux releases!! *)
+				reclen-	: INTEGER;
+				typ-		: CHAR;
+				name-	: (*array of*) CHAR;
+			END;
+
+	Stack* = RECORD
+				sp*		: ADDRESS;
+				flags*		: SET;
+				size*		: SIZE
+			END;
+
+	Ucontext* = POINTER TO UcontextDesc;
+	UcontextDesc* = RECORD
+				flags-		: SET;
+				link-		: ADDRESS;
+				stack-	: Stack;
+				mc-		: McontextDesc
+			END;
+
+	Mcontext* = POINTER TO McontextDesc;
+	McontextDesc* = RECORD
+				r_gs-		: ADDRESS;
+				r_fs-		: ADDRESS;
+				r_es-		: ADDRESS;
+				r_ds-		: ADDRESS;
+				r_di-		: ADDRESS;
+				r_si-		: ADDRESS;
+				r_bp *		: ADDRESS;
+				r_sp_x-	: ADDRESS;
+				r_bx-		: ADDRESS;
+				r_dx-		: ADDRESS;
+				r_cx-		: ADDRESS;
+				r_ax-		: ADDRESS;
+				r_trapno-	: LONGINT;
+				r_err-		: LONGINT;
+				r_pc*		: ADDRESS;
+				r_cs-		: ADDRESS;
+				r_flags-	: LONGINT;
+				r_sp*		: ADDRESS;		(* sp at error (signal) *)
+				r_ss-		: LONGINT;
+				fpc-		: ADDRESS; 	(* FPcontext *)
+				oldmask-	: LONGINT;
+				cr2-		: LONGINT
+			END;
+
+	FPcontext* = POINTER TO FPcontextDesc;
+	FPcontextDesc* = RECORD
+				(* ... *)
+			END;
+
+	PThreadAttr = RECORD
+		reserved1-: ARRAY 5 OF ADDRESS;
+		reserved2-: ARRAY 4 OF WORD;
+	END;
+
+
+	Sigaction = RECORD
+		sa_handler: ADDRESS;
+		(*filler1: ADDRESS;*)
+		sa_mask: Sigset_t;
+		sa_flags: ADDRESS;
+		filler: ADDRESS;
+	END;
+
+	Sched_param = RECORD
+		sched_priority: LONGINT;
+		safety: ARRAY 8 OF ADDRESS;
+	END;
+
+
+VAR
+	suspend_mutex: MutexType;
+	mainthread: Thread_t;
+	suspend_done: LONGINT;
+	resume_done: LONGINT;
+	sasuspend, saresume: Sigaction;
+
+	argc-: LONGINT;  argv-: ADDRESS;  environ-: ADDRESS;
+
+	sysinfo-: RECORD
+		sysname-, nodename-, release-, version-, machine-: ARRAY 65 OF CHAR;
+	END;
+
+	sigstack-: ARRAY 32*4096 OF CHAR;
+
+
+	sysconf: PROCEDURE {C} (name: LONGINT):WORD;
+
+	pthread_mutex_init: PROCEDURE {C} (mutex: ADDRESS; mutexattr: ADDRESS): WORD;
+	pthread_mutex_destroy: PROCEDURE {C} (mutex: ADDRESS): WORD;
+	pthread_mutex_lock: PROCEDURE {C} (mutex: ADDRESS): WORD;
+	pthread_mutex_unlock: PROCEDURE {C} (mutex: ADDRESS): WORD;
+
+	pthread_mutexattr_init: PROCEDURE {C} (mutexattr: ADDRESS): WORD;
+	pthread_mutexattr_settype: PROCEDURE {C} (mutexattr: ADDRESS; type: WORD): WORD;
+
+	pthread_cond_init: PROCEDURE {C} (cond: ADDRESS; condAttr: ADDRESS): WORD;
+	pthread_cond_destroy: PROCEDURE {C} (cond: ADDRESS): WORD;
+	pthread_cond_wait: PROCEDURE {C} (cond: ADDRESS; mutex: ADDRESS): WORD;
+	pthread_cond_signal: PROCEDURE {C} (cond: ADDRESS): WORD;
+
+	pthread_create: PROCEDURE {C} (newthread: ADDRESS; attr: ADDRESS; start_routine: PROCEDURE {C} (arg: PROCEDURE):ADDRESS; arg:PROCEDURE): WORD;
+	pthread_exit: PROCEDURE {C} (thr: ADDRESS);
+	pthread_detach: PROCEDURE {C} (thr: ADDRESS);
+	pthread_kill: PROCEDURE {C} (thr: ADDRESS; sigid: LONGINT): LONGINT;
+	pthread_cancel: PROCEDURE {C} (thr: ADDRESS);
+	
+	pthread_key_create	: PROCEDURE {C} ( key: ADDRESS; destructor: PROCEDURE {C} ( param: ADDRESS ) ): WORD;
+	pthread_setspecific	: PROCEDURE {C} ( key: Key_t; value: ADDRESS ): WORD;
+	pthread_getspecific	: PROCEDURE {C} ( key: Key_t ): ADDRESS;
+
+	pthread_attr_init: PROCEDURE {C} (attr: ADDRESS);
+	pthread_attr_setscope: PROCEDURE {C}(attr: ADDRESS; set: WORD);
+	pthread_attr_setdetachstate: PROCEDURE {C}(attr: ADDRESS; set: WORD);
+	pthread_attr_setstacksize: PROCEDURE {C}(attr: ADDRESS; stackSize: SIZE);
+	pthread_self: PROCEDURE {C} (): Thread_t;
+
+	sched_get_priority_max: PROCEDURE {C} (policy: LONGINT): LONGINT;
+	sched_get_priority_min: PROCEDURE {C} (policy: LONGINT): LONGINT;
+	pthread_setschedparam: PROCEDURE {C} (thread: Thread_t; policy: LONGINT; param: ADDRESS): WORD;
+	pthread_getschedparam: PROCEDURE {C} (thread: Thread_t; policy: LONGINT; param: ADDRESS): WORD;
+	pthread_setcancelstate: PROCEDURE {C} (state: LONGINT; oldstate: ADDRESS): LONGINT;
+	pthread_setcanceltype: PROCEDURE {C} (type: LONGINT; oldtype: ADDRESS): LONGINT;
+	sigaction: PROCEDURE {C} (signum: LONGINT; CONST act, oldact: ADDRESS): LONGINT;
+	sigemptyset: PROCEDURE {C} (set: ADDRESS);
+	sigfillset: PROCEDURE {C} (set: ADDRESS): LONGINT;
+	sigsuspend: PROCEDURE {C} (set: ADDRESS): LONGINT;
+	sigaddset: PROCEDURE {C} (set: ADDRESS; signo: LONGINT);
+	sigdelset: PROCEDURE {C} (set: ADDRESS; signo: LONGINT);
+	nanosleep: PROCEDURE {C} (req, rem: ADDRESS): LONGINT;
+	sigaltstack: PROCEDURE {C} (ss, oss: ADDRESS): LONGINT;
+	pthread_sigmask: PROCEDURE {C}(how: LONGINT; set: ADDRESS; oldset: ADDRESS): LONGINT;
+
+	(*pid: return param for process id. Only set if initialized non-null. path: pointer to string denoting the executable. file_actions: modify which files are open for the new process, if NIL it inherits open files from parent process. attrp: sets process groups, scheduler, signals etc, leave NIL. argv, evp: char** to the arguments and env. variables*)
+	posix_spawnp- 	: PROCEDURE{C}(pid: ADDRESS; path: ADDRESS; file_actions: ADDRESS; attrp: ADDRESS; argv: ADDRESS ; envp: ADDRESS): LONGINT;
+	(*more restrictive than spawnp*)
+	posix_spawn- 	: PROCEDURE{C}(pid: ADDRESS; path: ADDRESS; file_actions: ADDRESS; attrp: ADDRESS; argv: ADDRESS ; envp: ADDRESS): LONGINT;
+	waitpid-			: PROCEDURE{C}(pid: pid_t; status: ADDRESS; options: LONGINT): pid_t;
+	pipe-				:PROCEDURE{C}(pipefd: ADDRESS): LONGINT; (*pipefd is assumed to be a pointer to a C array of 2 elements, after pipe creation the array will contain file descriptors for the input and output end of the pipe. returns 0 on success, or -1 on fail*)
+	dup2-				:PROCEDURE{C}(oldfd,newfd: LONGINT): LONGINT; (*overwrites file descriptor newfd with a copy of oldfd. useful for redirecting pipes.*)
+	dup-				:PROCEDURE{C}(oldfd: LONGINT): LONGINT;
+
+	read-			: PROCEDURE {C} ( fd: LONGINT; buf: ADDRESS; n: SIZE ): LONGINT;
+	write-			: PROCEDURE {C} ( fd: LONGINT; buf: ADDRESS; n: SIZE ): LONGINT;
+	open-			: PROCEDURE {C} ( name: ADDRESS;  flags, mode: SET ): LONGINT;
+	close-		: PROCEDURE {C} ( fd: LONGINT ): LONGINT;
+	lseek-		: PROCEDURE {C} ( fd: LONGINT; offset, origin: SIZE ): LONGINT;
+	fsync-		: PROCEDURE {C} ( fd: LONGINT ): LONGINT;
+	ioctl-			: PROCEDURE {C} ( fd: LONGINT; request: LONGINT; arg: ADDRESS ): LONGINT;
+	unlink-		: PROCEDURE {C} ( name: ADDRESS ): LONGINT;
+	rename-		: PROCEDURE {C} ( oldname, newname: ADDRESS ): LONGINT;
+	ftruncate-		: PROCEDURE {C} ( fd: LONGINT;  length: SIZE ): LONGINT;
+	chmod-		: PROCEDURE {C} ( name: ADDRESS;  mode: SET ): LONGINT;
+	utime-		: PROCEDURE {C} ( name: ADDRESS;  tb: ADDRESS ): LONGINT;
+	access-		: PROCEDURE {C} ( name: ADDRESS;  mode: SET ): LONGINT;
+	select-		: PROCEDURE {C} ( width: LONGINT; rd, wr, ex: ADDRESS;  VAR timeout: Timeval ): LONGINT;
+	realpath-	: PROCEDURE {C} (file_name: ADDRESS; resolved_name: ADDRESS): ADDRESS;
+
+	chdir-			: PROCEDURE {C} ( name: ADDRESS ): LONGINT;
+	mkdir-		: PROCEDURE {C} ( name: ADDRESS;  mode: SET ): LONGINT;
+	rmdir-			: PROCEDURE {C} ( path: ADDRESS ): LONGINT;
+
+	xstat-			: PROCEDURE {C} ( ver: LONGINT; name: ADDRESS;  VAR buf: Status ): LONGINT;
+	lxstat-			: PROCEDURE {C} ( ver: LONGINT; name: ADDRESS;  VAR buf: Status ): LONGINT;
+	fxstat-			: PROCEDURE {C} ( ver: LONGINT; fd: LONGINT;  VAR buf: Status ): LONGINT;
+
+	getpid-		: PROCEDURE {C} ( ): LONGINT;
+	getuid-		: PROCEDURE {C} ( ): LONGINT;
+
+	malloc-		: PROCEDURE {C} ( size: SIZE ): ADDRESS;
+	posix_memalign-	: PROCEDURE {C} ( VAR p: ADDRESS;  alignment, size: SIZE ): LONGINT;
+	free-			: PROCEDURE {C} ( p: ADDRESS );
+	mprotect-	: PROCEDURE {C} ( p: ADDRESS; len: SIZE; prot: LONGINT ): LONGINT;
+
+	alarm-		: PROCEDURE {C} ( ms: LONGINT ): LONGINT;
+	setitimer-		: PROCEDURE {C} ( which: LONGINT;  VAR value, ovalue: Itimerval ): LONGINT;
+	getitimer-		: PROCEDURE {C} ( which: LONGINT;  VAR value: Itimerval ): LONGINT;
+	clock_gettime-	: PROCEDURE{C}	(clk_id: LONGINT; tp: tvPtr): LONGINT;
+
+	gettimeofday-	: PROCEDURE {C} ( VAR tv: Timeval;  VAR tz: Timezone ): LONGINT;
+	mktime-			: PROCEDURE {C} ( VAR tm: Tm ): LONGINT;
+	localtime-		: PROCEDURE {C} ( CONST tv: Timeval ): TmPtr;
+	time-				: PROCEDURE {C} ( VAR tv: Timeval ): LONGINT;
+	times-			: PROCEDURE {C} ( VAR tms: Tms ): LONGINT;
+
+	system-		: PROCEDURE {C} ( cmd: ADDRESS );
+	uname-		: PROCEDURE {C} ( utsname: ADDRESS ): LONGINT;
+
+	getcwd-		: PROCEDURE {C} ( buf: ADDRESS;  len: SIZE ): ADDRESS;
+	getenv-		: PROCEDURE {C} ( name: ADDRESS ): ADDRESS;
+
+	opendir-		: PROCEDURE {C} ( name: ADDRESS ): ADDRESS;
+	readdir-		: PROCEDURE {C} ( dir: ADDRESS ): Dirent;
+	closedir-		: PROCEDURE {C} ( dir: ADDRESS );
+
+	sigsetjmp-	: PROCEDURE {C} ( env: ADDRESS;  savemask: LONGINT ): LONGINT;
+	siglongjmp-	: PROCEDURE {C} ( env: ADDRESS;  val: LONGINT );
+
+	kill-			: PROCEDURE {C} ( pid, sig: LONGINT ): LONGINT;
+	exit-			: PROCEDURE {C} ( status: LONGINT );
+	perror-		: PROCEDURE {C} ( msg: ADDRESS );
+	errno_location: PROCEDURE {C} ( ): ADDRESS;
+
+	xSetErrorHandler: PROCEDURE {C} (h: ADDRESS): WORD;
+	xSetIOErrorHandler: PROCEDURE {C} (h: ADDRESS): WORD;
+
+	libc-: LONGINT;
+	libp-: LONGINT;
+	libx-: LONGINT;
+
+	libraryPaths: ARRAY 8 OF ARRAY 32 OF CHAR;
+	noPaths: LONGINT;
+
+
+
+	PROCEDURE getnprocs* (): LONGINT;
+	BEGIN
+		RETURN sysconf( 0x54 ); (*0x53 for number of processors configured, 0x54 for number of processors online *)
+	END getnprocs;
+ 
+	PROCEDURE NewKey*( ): Key_t;
+	VAR
+		key: Key_t;
+	BEGIN
+		ASSERT(pthread_key_create(ADDRESSOF(key), NIL) = 0);
+		RETURN key;
+	END NewKey;
+ 
+	PROCEDURE ReadKey* (key: Key_t): ADDRESS;
+	BEGIN
+		RETURN pthread_getspecific(key);
+	END ReadKey;
+
+	PROCEDURE WriteKey* (key: Key_t; value: ADDRESS);
+	BEGIN
+		ASSERT(pthread_setspecific(key, value) = 0);
+	END WriteKey;
+
+
+	PROCEDURE NewMtx*( ): Mutex_t;
+	VAR
+		mtx: Mutex_t;
+	BEGIN
+		mtx := malloc( SIZEOF(MutexType) );
+		ASSERT(mtx # 0);
+		ASSERT(pthread_mutex_init(mtx, NIL) = 0);
+		RETURN mtx;
+	END NewMtx;
+
+	PROCEDURE NewRecursiveMtx*( ): Mutex_t;
+	VAR
+		mtx: Mutex_t;
+		attr: MutexAttributeType;
+		res: WORD;
+	CONST
+		Recursive = 1;
+	BEGIN
+		mtx := malloc( SIZEOF(MutexType) );
+		res := pthread_mutexattr_init(ADDRESS OF attr);
+		res := pthread_mutexattr_settype(ADDRESS OF attr, Recursive);
+
+		ASSERT(mtx # 0);
+		ASSERT(pthread_mutex_init(mtx, ADDRESS OF attr) = 0);
+		RETURN mtx;
+	END NewRecursiveMtx;
+
+
+
+	PROCEDURE MtxDestroy*(mtx: Mutex_t);
+	BEGIN
+		ASSERT(pthread_mutex_destroy(mtx) = 0);
+	END MtxDestroy;
+
+	PROCEDURE MtxLock*(mtx: Mutex_t);
+	BEGIN
+		ASSERT(pthread_mutex_lock(mtx) = 0);
+	END MtxLock;
+
+	PROCEDURE MtxUnlock*(mtx: Mutex_t);
+	BEGIN
+		ASSERT(pthread_mutex_unlock(mtx) = 0);
+	END MtxUnlock;
+
+	PROCEDURE NewCond* ( ): Condition_t;
+	VAR cond: Condition_t;
+	BEGIN
+		cond := malloc( SIZEOF(ConditionType) );
+		ASSERT(cond # 0);
+		ASSERT(pthread_cond_init(cond, NIL)=0);
+		RETURN cond;
+	END NewCond;
+
+	PROCEDURE CondDestroy*(con: Condition_t);
+	BEGIN
+		ASSERT(pthread_cond_destroy(con) = 0);
+	END CondDestroy;
+
+	PROCEDURE CondWait*(con: Condition_t; mtx: Mutex_t);
+	BEGIN
+		ASSERT(pthread_cond_wait(con, mtx) = 0);
+	END CondWait;
+
+	PROCEDURE CondSignal*(cond: Condition_t);
+	BEGIN
+		ASSERT(pthread_cond_signal(cond) = 0);
+	END CondSignal;
+
+	PROCEDURE ThrThis*(): Thread_t;
+	BEGIN
+		RETURN pthread_self( );
+	END ThrThis;
+
+	PROCEDURE ThrYield*( );
+	BEGIN
+		ThrSleep(1);
+	END ThrYield;
+
+	PROCEDURE ThrExit*( );
+	BEGIN
+		pthread_exit( 0 );
+	END ThrExit;
+
+	PROCEDURE ThrSetPriority*(thr: Thread_t; prio: LONGINT);
+	VAR
+		param: Sched_param;
+		policy: LONGINT;
+	BEGIN
+		IF pthread_getschedparam( thr, ADDRESS OF policy, ADDRESS OF param ) # 0 THEN END;
+		param.sched_priority := prio;
+		IF pthread_setschedparam( thr, SCHED_OTHER, ADDRESS OF param ) # 0 THEN
+			Perror("pthread_setschedparam");
+		END
+	END ThrSetPriority;
+
+	PROCEDURE ThrGetPriority*(thr: Thread_t):LONGINT;
+	VAR
+		param: Sched_param;
+		policy: LONGINT;
+	BEGIN
+	    IF pthread_getschedparam( thr, ADDRESS OF policy, ADDRESS OF param ) # 0 THEN END;
+	    RETURN  param.sched_priority;
+	END ThrGetPriority;
+
+	VAR
+		sigstk: Stack;
+
+	PROCEDURE SetSigaltstack;
+	BEGIN
+		IF sigaltstack(ADDRESS OF sigstk, NIL) < 0 THEN
+			Perror("sigaltstack")
+		END;
+	END SetSigaltstack;
+
+	PROCEDURE {C} Starter(proc: PROCEDURE): ADDRESS;
+	VAR
+		me: Thread_t;
+		old, new: Sigset_t;
+		param: Sched_param;
+		res: LONGINT;
+	BEGIN
+		me := pthread_self();
+		SetSigaltstack();
+
+		IF sigfillset( ADDRESS OF new ) < 0 THEN
+			Perror("sigfillset");
+		END;
+		sigdelset( ADDRESS OF new, SIGILL );
+		sigdelset( ADDRESS OF new, SIGTRAP );
+		sigdelset( ADDRESS OF new, SIGFPE );
+		sigdelset( ADDRESS OF new, SIGBUS );
+		sigdelset( ADDRESS OF new, SIGSEGV );
+		sigdelset( ADDRESS OF new, SIGTERM );
+		sigdelset( ADDRESS OF new, T_SIGSUSPEND );
+
+		res := pthread_sigmask( SIG_SETMASK, ADDRESS OF new, ADDRESS OF old );
+		res := pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NIL );
+		res := pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NIL );
+		param.sched_priority := 0;
+		res := pthread_setschedparam( me, SCHED_OTHER, ADDRESS OF param );
+		proc();
+
+		pthread_exit( NIL );
+		RETURN NIL;
+	END Starter;
+
+	PROCEDURE ThrStart*(p: PROCEDURE; stackSize: SIZE): Thread_t;
+	VAR
+		attr: PThreadAttr;
+		id: Thread_t;
+		res,i: LONGINT;
+	CONST
+		PTHREAD_SCOPE_SYSTEM = 0;
+		PTHREAD_CREATE_DETACHED = 1;
+	BEGIN
+		pthread_attr_init(ADDRESS OF attr);
+		pthread_attr_setscope(ADDRESS OF attr, PTHREAD_SCOPE_SYSTEM);
+		pthread_attr_setdetachstate(ADDRESS OF attr, PTHREAD_CREATE_DETACHED);
+		(*pthread_attr_setdetachstate(ADDRESS OF attr, 0);*)
+		pthread_attr_setstacksize(ADDRESS OF attr, stackSize);
+		res := pthread_create(ADDRESS OF id, ADDRESS OF attr, Starter, p);
+		RETURN id;
+	END ThrStart;
+
+	PROCEDURE ThrSleep*(ms: LONGINT);
+	VAR
+		sltime,rem: RECORD
+			tv_sec: WORD;        (* seconds *)
+			tv_nsec: WORD;       (* nanoseconds *)
+     	END;
+	BEGIN
+		sltime.tv_sec := ms DIV 1000;
+		sltime.tv_nsec := 1000000*(ms MOD 1000);
+		WHILE (nanosleep(ADDRESS OF sltime, ADDRESS OF rem) < 0) DO
+			(* check error ! *)
+			sltime := rem;
+		END;
+	END ThrSleep;
+
+	PROCEDURE ThrKill*(thr: Thread_t);
+	BEGIN
+		IF (thr # mainthread) THEN
+	    		pthread_detach( thr );
+    			IF (thr = pthread_self()) THEN
+				pthread_exit( 0 );
+			ELSE
+				pthread_cancel( thr );
+			END
+		END;
+    END ThrKill;
+
+
+	PROCEDURE {C} resume_handler( sig: LONGINT );
+	BEGIN
+	END resume_handler;
+
+	PROCEDURE ThrResume*( thr: Thread_t );
+	VAR  res: LONGINT;
+	BEGIN
+		res := pthread_mutex_lock( ADDRESS OF suspend_mutex );
+		resume_done := 0; 
+		res := pthread_kill( thr, T_SIGRESUME );
+
+		WHILE (resume_done # 1)  DO ThrSleep(1); END;
+
+		res := pthread_mutex_unlock( ADDRESS OF suspend_mutex );
+	END ThrResume;
+
+	VAR suspendHandler*: PROCEDURE(c: Ucontext);
+
+	PROCEDURE {C} suspend_handler(sig: LONGINT; scp: ADDRESS; ucp: ADDRESS);
+	VAR block: Sigset_t; res: LONGINT;
+	BEGIN
+		IF suspendHandler # NIL THEN suspendHandler( S.VAL( Ucontext, ucp) ) END;
+	    res := sigfillset( ADDRESS OF block );
+	    sigdelset(  ADDRESS OF block, T_SIGRESUME );
+	    suspend_done := 1;   (*this is ok because ThrSuspend is protected by a mutex, so no race condidtion. It may alert the ThrSuspend too early though!*)
+	    res := sigsuspend(  ADDRESS OF block ); (* await T_SIGRESUME *)
+	    resume_done := 1; (*makes no difference if we do that here or in the resume handler*)
+	END suspend_handler;
+
+	PROCEDURE ThrSuspend*(thr: Thread_t; saveContext: BOOLEAN);
+	VAR res: LONGINT;
+	BEGIN
+	    res := pthread_mutex_lock(ADDRESS OF suspend_mutex );
+	    suspend_done := 0;
+	    res := pthread_kill( thr, T_SIGSUSPEND );
+	    WHILE (suspend_done # 1) DO ThrSleep( 1 ) END; (*this should bettr check the actual thread status!*)
+	    ThrSleep( 1 ); (*improves the probability of the suspednd actually being done*)
+	    
+	    res := pthread_mutex_unlock( ADDRESS OF suspend_mutex );
+	END ThrSuspend;
+
+
+
+
+
+	PROCEDURE ThrInitialize*( VAR low, high: LONGINT ): BOOLEAN;
+	VAR
+		param: Sched_param;
+	BEGIN
+		ASSERT(pthread_mutex_init( ADDRESS OF suspend_mutex, NIL ) = 0);
+		mainthread := pthread_self();
+		high := sched_get_priority_max(SCHED_OTHER);
+		low := sched_get_priority_min(SCHED_OTHER);
+
+		param.sched_priority := high;
+		IF pthread_setschedparam( mainthread, SCHED_OTHER, ADDRESS OF param)#0 THEN
+			Perror("ThrInitialize: setparam");
+		END;
+
+		sigemptyset( ADDRESS OF sasuspend.sa_mask );
+		sigaddset(  ADDRESS OF sasuspend.sa_mask, T_SIGRESUME );
+		sasuspend.sa_flags := SA_SIGINFO + (*SA_ONSTACK +*) SA_NODEFER;
+		sasuspend.sa_handler := suspend_handler;
+		ASSERT(sigaction( T_SIGSUSPEND, ADDRESS OF sasuspend, NIL ) = 0);
+
+		sigemptyset( ADDRESS OF saresume.sa_mask );
+		saresume.sa_flags := 0;
+		saresume.sa_handler := resume_handler;
+		ASSERT(sigaction( T_SIGRESUME, ADDRESS OF saresume, NIL ) = 0);
+
+		RETURN TRUE;
+	END ThrInitialize;
+
+	PROCEDURE CopyContext*(CONST from: McontextDesc; VAR to: McontextDesc);
+	BEGIN
+		S.MOVE(ADDRESS OF from, ADDRESS OF to, SIZE OF McontextDesc);
+	END CopyContext;
+
+
+	PROCEDURE ModifyContext*( cont: Mcontext;  pc, bp, sp: LONGINT );
+	BEGIN
+		cont.r_pc := pc;
+		cont.r_bp := bp;
+		cont.r_sp := sp;
+	END ModifyContext;
+
+	PROCEDURE Perror*( CONST msg: ARRAY OF CHAR );
+	BEGIN
+		perror( ADDRESSOF( msg ) )
+	END Perror;
+
+	PROCEDURE Dlsym*( lib: ADDRESS;  CONST sym: ARRAY OF CHAR;  objAddr: ADDRESS );
+	VAR val: LONGINT;
+	BEGIN
+		Glue.Dlsym( lib, sym, objAddr );
+		S.GET( objAddr, val );
+		IF val = 0 THEN
+			Trace.String( "Unix.Dlsym:  entry '" );  Trace.String( sym );  Trace.String( "' not found" );
+			Trace.Ln;
+		(*	exit(0);	*)
+		END
+	END Dlsym;
+
+	PROCEDURE Dlopen*( CONST libname: ARRAY OF CHAR;  mode: LONGINT ): ADDRESS;
+	VAR h: ADDRESS;  i, j, k: INTEGER;
+		p: ARRAY 256 OF CHAR;
+	BEGIN
+		IF libname[0] = '/' THEN  h := Glue.dlopen( ADDRESSOF( libname ), mode );
+		ELSE
+			i := 0;  h := 0;
+			WHILE (h = 0) & (i < noPaths) DO
+				COPY( libraryPaths[i], p );  j := 0;
+				WHILE p[j] # 0X DO  INC( j )  END;
+				p[j] := '/';  k := 0;
+				REPEAT  INC( j );  p[j] := libname[k];  INC( k )  UNTIL p[j] = 0X;
+				h := Glue.dlopen( ADDRESSOF( p ), mode );  INC( i );
+			END
+		END;
+		IF h = 0 THEN
+			Trace.String( "Unix.Dlopen: loading library " );
+			Trace.String( libname );  Trace.String( " failed" );  Trace.Ln;
+			LOOP END;
+		END;
+		RETURN h
+	END Dlopen;
+
+	PROCEDURE Dlclose*( lib: ADDRESS );
+	BEGIN
+		Glue.dlclose( lib )
+	END Dlclose;
+
+	PROCEDURE GetArg*( no: LONGINT;  VAR val: ARRAY OF CHAR );
+	VAR ch: CHAR;  adr: ADDRESS;  i: LONGINT;
+	BEGIN
+		IF no >= argc THEN  val[0] := 0X
+		ELSE
+			S.GET( argv + SIZEOF(ADDRESS)*no, adr );  i := 0;
+			REPEAT  S.GET( adr, ch );  val[i] := ch;  INC( adr );  INC( i );   UNTIL (ch = 0X) OR (i >= LEN( val ));
+		END
+	END GetArg;
+
+	PROCEDURE GetArgval*(  CONST argName: ARRAY OF CHAR;  VAR val: ARRAY OF CHAR );
+	VAR i: INTEGER;
+		buf: ARRAY 40 OF CHAR;
+	BEGIN
+		i := 1;
+		WHILE i < argc - 1 DO
+			GetArg( i, buf );
+			IF buf = argName THEN  GetArg( i + 1, val );  RETURN   END;
+			INC( i )
+		END;
+		val[0] := 0X
+	END GetArgval;
+
+
+
+	PROCEDURE getSysinfo;
+	VAR res: LONGINT;  p: INTEGER;
+		buf: ARRAY 4096 OF CHAR;
+
+		PROCEDURE copy( VAR p: INTEGER;  VAR dest: ARRAY OF CHAR );
+		VAR i: INTEGER;
+		BEGIN
+			WHILE buf[p] <= ' ' DO  INC( p )  END;
+			i := 0;
+			REPEAT  dest[i] := buf[p];  INC( i );  INC( p )  UNTIL (buf[p - 1] = 0X) OR (i >= LEN( dest ));
+			dest[i - 1] := 0X
+		END copy;
+
+	BEGIN
+		FOR p := 0 TO 4096 - 1 DO  buf[p] := 0X  END;
+		res := uname( ADDRESSOF( buf ) );
+		p := 0;
+		copy( p, sysinfo.sysname );
+		copy( p, sysinfo.nodename );
+		copy( p, sysinfo.release );
+		copy( p, sysinfo.version );
+		copy( p, sysinfo.machine );
+	END getSysinfo;
+
+	PROCEDURE CreateSignalStack;
+	BEGIN
+		sigstk.sp := ADDRESS OF sigstack;
+		sigstk.size := LEN(sigstack);
+		sigstk.flags := {};
+	END CreateSignalStack;
+
+
+
+	VAR trap: SignalTrap;
+
+	PROCEDURE {C} SigHandler  ( sig: LONGINT; scp: ADDRESS; ucp: Ucontext ); (* reversed arguments !! *)
+	BEGIN
+		IF trap # NIL THEN
+			trap( sig, S.VAL( Mcontext, ADDRESSOF( ucp.mc ) ) )
+		ELSE
+			Trace.String( "Unix.SigHandler: sig = " ); Trace.Int( sig, 0 ); Trace.Ln;  exit( -1 );
+		END;
+	END SigHandler;
+
+	PROCEDURE InstallTrap* ( h: SignalTrap );
+	BEGIN
+		trap := h;
+	END InstallTrap;
+
+
+
+	PROCEDURE InstallHandler(sig: LONGINT);
+	VAR
+		act: Sigaction;
+		mask: Sigset_t;
+	BEGIN
+		sigemptyset(ADDRESS OF mask);
+		act.sa_mask := mask;
+		IF sig = SIGSEGV THEN (* segmentation violation *)
+			act.sa_flags :=  SA_SIGINFO +  SA_ONSTACK +  SA_NODEFER;
+		ELSE
+			act.sa_flags :=  SA_SIGINFO + SA_NODEFER;
+		END;
+		act.sa_handler := ADDRESS OF SigHandler;
+		IF sigaction( sig, ADDRESS OF act, 0 ) # 0 THEN
+			Perror("sigaction");
+		END
+	END InstallHandler;
+
+	PROCEDURE fstat*  ( fd: LONGINT;  VAR buf: Status ): LONGINT;
+	BEGIN
+		RETURN  fxstat( 3, fd, buf );
+	END fstat;
+
+	PROCEDURE stat*  ( path: ADDRESS;  VAR buf: Status ): LONGINT;
+	BEGIN
+		RETURN  xstat( 3, path, buf );
+	END stat;
+
+	
+	PROCEDURE HandleSignal*( sig: LONGINT );
+	BEGIN
+		InstallHandler( sig )
+	END HandleSignal;
+
+	PROCEDURE errno*(): LONGINT;
+	VAR loc: ADDRESS;
+	BEGIN
+		loc := errno_location();
+		RETURN S.GET32(loc);
+	END errno;
+
+	TYPE OberonXErrorHandler* = PROCEDURE (disp, err: ADDRESS): LONGINT;
+	TYPE OberonXIOErrorHandler* = PROCEDURE (disp: ADDRESS): LONGINT;
+	VAR oberonXErrorHandler: OberonXErrorHandler;
+	VAR oberonXIOErrorHandler: OberonXIOErrorHandler;
+
+
+	PROCEDURE {C} X11ErrorHandler(d: ADDRESS; err: ADDRESS): WORD;
+	VAR res: LONGINT;
+	BEGIN
+		TRACE(d,err);
+		IF oberonXErrorHandler # NIL THEN
+			res := oberonXErrorHandler(d, err);
+		END;
+		RETURN 0;
+	END X11ErrorHandler;
+
+	PROCEDURE X11IOErrorHandler(d: ADDRESS): WORD;
+	VAR res: LONGINT;
+	BEGIN
+		TRACE(d);
+		IF oberonXIOErrorHandler # NIL THEN
+			res := oberonXIOErrorHandler(d);
+		END;
+		RETURN 0;
+	END X11IOErrorHandler;
+
+	PROCEDURE InitXErrorHandlers*(xErrorHandler: OberonXErrorHandler; xIOErrorHandler: OberonXIOErrorHandler);
+	VAR res: WORD;
+	BEGIN
+		oberonXErrorHandler := xErrorHandler;
+		oberonXIOErrorHandler := xIOErrorHandler;
+		res := xSetErrorHandler(ADDRESS OF X11ErrorHandler);
+		res := xSetIOErrorHandler(ADDRESS OF X11IOErrorHandler);
+	END InitXErrorHandlers;
+
+	PROCEDURE Init;
+	VAR test: ADDRESS; i: LONGINT; s: ARRAY 256 OF CHAR;
+	BEGIN
+		argc := Glue.argc;
+		argv := Glue.argv;
+		environ := Glue.environ;
+
+		libraryPaths[0] := "/lib/i386-linux-gnu/i686/cmov";
+		libraryPaths[1] := "/usr/lib/i386-linux-gnu";
+		libraryPaths[2] := "/lib/i386-linux-gnu";
+		libraryPaths[3] := "/lib";
+		libraryPaths[4] := "/usr/lib";
+		libraryPaths[5] := "/usr/lib32";
+		noPaths := 6;
+
+		libc := Dlopen( libcname, 2 );
+		libp := Dlopen( libpthreadname, 2 );
+
+		Dlsym( libc, "exit",		ADDRESSOF(exit) );
+
+		Dlsym( libc, "sysconf", ADDRESSOF(sysconf) );
+
+		Dlsym( libc, "pthread_mutex_init", ADDRESSOF(pthread_mutex_init) );
+		Dlsym( libc, "pthread_mutex_destroy", ADDRESSOF(pthread_mutex_destroy) );
+		Dlsym( libc, "pthread_mutex_lock", ADDRESSOF(pthread_mutex_lock) );
+		Dlsym( libc, "pthread_mutex_unlock", ADDRESSOF(pthread_mutex_unlock) );
+
+		Dlsym( libp, "pthread_mutexattr_init", ADDRESSOF(pthread_mutexattr_init) );
+		Dlsym( libp, "pthread_mutexattr_settype", ADDRESSOF(pthread_mutexattr_settype) );
+
+
+		Dlsym( libc, "pthread_cond_init", ADDRESSOF(pthread_cond_init) );
+		Dlsym( libc, "pthread_cond_destroy", ADDRESSOF(pthread_cond_destroy) );
+		Dlsym( libc, "pthread_cond_wait", ADDRESSOF(pthread_cond_wait) );
+		Dlsym( libc, "pthread_cond_signal", ADDRESSOF(pthread_cond_signal) );
+
+		Dlsym( libp, "pthread_create", ADDRESSOF(pthread_create) );
+		Dlsym( libp, "pthread_exit", ADDRESSOF(pthread_exit) );
+		Dlsym( libp, "pthread_detach", ADDRESSOF(pthread_detach) );
+		Dlsym( libp, "pthread_cancel", ADDRESSOF(pthread_cancel) );
+		Dlsym( libp, "pthread_kill", ADDRESSOF(pthread_kill) );
+		
+		Dlsym( libp, "pthread_key_create", ADDRESSOF( pthread_key_create ) );
+		Dlsym( libp, "pthread_getspecific", ADDRESSOF( pthread_getspecific ) );
+		Dlsym( libp, "pthread_setspecific", ADDRESSOF( pthread_setspecific ) );
+
+		Dlsym( libp, "pthread_sigmask", ADDRESSOF(pthread_sigmask) );
+		Dlsym( libp, "pthread_setcancelstate", ADDRESSOF(pthread_setcancelstate) );
+		Dlsym( libp, "pthread_setcanceltype", ADDRESSOF(pthread_setcanceltype) );
+		Dlsym( libp, "pthread_attr_init", ADDRESSOF(pthread_attr_init) );
+		Dlsym( libp, "pthread_attr_setscope", ADDRESSOF(pthread_attr_setscope) );
+		Dlsym( libp, "pthread_attr_setdetachstate", ADDRESSOF(pthread_attr_setdetachstate) );
+		Dlsym( libp, "pthread_attr_setstacksize", ADDRESSOF(pthread_attr_setstacksize) );
+		Dlsym( libp, "pthread_self", ADDRESSOF(pthread_self) );
+
+		Dlsym( libc, "posix_spawnp", ADDRESSOF(posix_spawnp) );
+		Dlsym( libc, "posix_spawn", ADDRESSOF(posix_spawn) );
+
+		Dlsym( libc, "waitpid", ADDRESSOF(waitpid) );
+		Dlsym( libc, "pipe", ADDRESSOF(pipe) );
+		Dlsym( libc, "dup2",ADDRESSOF(dup2) );
+		Dlsym( libc, "dup", ADDRESSOF(dup) );
+
+		Dlsym( libc, "sched_get_priority_max", ADDRESSOF(sched_get_priority_max) );
+		Dlsym( libc, "sched_get_priority_min", ADDRESSOF(sched_get_priority_min) );
+		Dlsym( libc, "pthread_setschedparam", ADDRESSOF(pthread_setschedparam) );
+		Dlsym( libc, "pthread_getschedparam", ADDRESSOF(pthread_getschedparam) );
+		Dlsym( libc, "sigaction", ADDRESSOF(sigaction) );
+		Dlsym( libc, "sigemptyset", ADDRESSOF(sigemptyset) );
+		Dlsym( libc, "sigfillset", ADDRESSOF(sigfillset) );
+		Dlsym( libc, "sigaddset", ADDRESSOF(sigaddset) );
+		Dlsym( libc, "sigdelset", ADDRESSOF(sigdelset) );
+		Dlsym( libc, "nanosleep", ADDRESSOF(nanosleep) );
+		Dlsym( libc, "sigaltstack", ADDRESSOF(sigaltstack) );
+		Dlsym( libc, "sigsuspend", ADDRESSOF(sigsuspend) );
+
+		Dlsym( libc, "read",		ADDRESSOF( read ) );
+		Dlsym( libc, "write",	ADDRESSOF( write ) );
+		Dlsym( libc, "open",		ADDRESSOF( open ) );
+		Dlsym( libc, "close",	ADDRESSOF( close ) );
+		Dlsym( libc, "lseek",	ADDRESSOF( lseek ) );
+		Dlsym( libc, "realpath",	ADDRESSOF( realpath ) );
+		Dlsym( libc, "fsync",	ADDRESSOF( fsync ) );
+		Dlsym( libc, "ioctl",	ADDRESSOF( ioctl ) );
+		Dlsym( libc, "unlink",	ADDRESSOF( unlink ) );
+		Dlsym( libc, "rename",	ADDRESSOF( rename ) );
+		Dlsym( libc, "ftruncate",	ADDRESSOF( ftruncate ) );
+		Dlsym( libc, "chmod",	ADDRESSOF( chmod ) );
+		Dlsym( libc, "utime",	ADDRESSOF( utime ) );
+		Dlsym( libc, "access",	ADDRESSOF( access ) );
+		Dlsym( libc, "select",	ADDRESSOF( select ) );
+
+		Dlsym( libc, "chdir",	ADDRESSOF( chdir ) );
+		Dlsym( libc, "mkdir",	ADDRESSOF( mkdir ) );
+		Dlsym( libc, "rmdir",	ADDRESSOF( rmdir ) );
+
+		Dlsym( libc, "__xstat",		ADDRESSOF( xstat ) );
+		Dlsym( libc, "__lxstat",	ADDRESSOF( lxstat ) );
+		Dlsym( libc, "__fxstat",	ADDRESSOF( fxstat ) );
+
+		Dlsym( libc, "getpid",	ADDRESSOF( getpid ) );
+		Dlsym( libc, "getuid",	ADDRESSOF( getuid ) );
+
+		Dlsym( libc, "alarm",	ADDRESSOF( alarm ) );
+		Dlsym( libc, "setitimer",	ADDRESSOF( setitimer ) );
+		Dlsym( libc, "getitimer",	ADDRESSOF( getitimer ) );
+		Dlsym( libc, "clock_gettime", ADDRESSOF(clock_gettime) );
+
+		Dlsym( libc, "gettimeofday", ADDRESSOF( gettimeofday ) );
+		Dlsym( libc, "mktime",		ADDRESSOF( mktime ) );
+		Dlsym( libc, "localtime",	ADDRESSOF( localtime ) );
+		Dlsym( libc, "time",			ADDRESSOF( time ) );
+		Dlsym( libc, "times",		ADDRESSOF( times ) );
+
+		Dlsym( libc, "getcwd",		ADDRESSOF( getcwd ) );
+		Dlsym( libc, "getenv",		ADDRESSOF( getenv ) );
+
+		Dlsym( libc, "opendir",		ADDRESSOF( opendir ) );
+		Dlsym( libc, "readdir",		ADDRESSOF( readdir ) );
+		Dlsym( libc, "closedir",	ADDRESSOF( closedir ) );
+
+
+		Dlsym( libc, "__sigsetjmp",	ADDRESSOF( sigsetjmp ) );
+		Dlsym( libc, "siglongjmp",	ADDRESSOF( siglongjmp ) );
+
+
+		Dlsym( libc, "malloc",		ADDRESSOF( malloc ) );
+		Dlsym( libc, "posix_memalign",	ADDRESSOF( posix_memalign ) );
+		Dlsym( libc, "free",			ADDRESSOF( free ) );
+		Dlsym( libc, "mprotect",	ADDRESSOF( mprotect ) );
+
+		Dlsym( libc, "system",	ADDRESSOF( system ) );
+		Dlsym( libc, "uname",	ADDRESSOF( uname ) );
+
+		Dlsym( libc, "kill",		ADDRESSOF( kill ) );
+		Dlsym( libc, "perror",	ADDRESSOF( perror ) );
+		Dlsym( libc, "__errno_location",	ADDRESSOF(errno_location ) );
+
+		getSysinfo;
+
+		CreateSignalStack;
+	END Init;
+
+	(* load X11 related libaries only on demand *)
+	PROCEDURE LinkToX*;
+	BEGIN
+		libx := Dlopen( libX11name, 2 );
+
+		Dlsym( libx, "XSetErrorHandler", ADDRESS OF xSetErrorHandler);
+		Dlsym( libx, "XSetIOErrorHandler", ADDRESS OF xSetIOErrorHandler);
+	END LinkToX;
+
+
+	PROCEDURE {INITIAL} Init0;
+	BEGIN
+		Init;
+	END Init0;
+END Unix.

+ 934 - 0
source/Generic.Unix.AMD64.Machine.Mod

@@ -0,0 +1,934 @@
+MODULE Machine;	(** AUTHOR "pjm, G.F."; PURPOSE "Bootstrapping, configuration and machine interface"; *)
+
+IMPORT S := SYSTEM, Trace, Unix, Glue;
+
+CONST
+	DefaultConfig = "Color 0  StackSize 128";
+	
+	Version = "A2 Generic, ";
+
+	DefaultObjectFileExtension* = ".GofUu";
+	
+	Second* = 1000; (* frequency of ticks increments in Hz *)
+
+	(** bits in features variable *)
+	MTTR* = 12;  MMX* = 23; 
+	
+	AddrSize = SIZEOF( ADDRESS );
+	SizeSize = SIZEOF( SIZE );
+	
+	AddressSize = SIZEOF(ADDRESS);
+	BlockHeaderSize = 2 * AddressSize;
+	RecordDescSize = 4 * AddressSize;  (* needs to be adapted in case Heaps.RecordBlockDesc is changed *)
+	StaticBlockSize = 32;		(* static heap block size *)
+
+	BlockSize = 32;
+	MemBlockSize* = 64*1024*1024;
+	
+	TraceOutput* = 0;	(* Trace output *)
+	Memory* = 1;		(*!  Virtual memory management, stack and page allocation,  not used in UnixAos *)
+	Heaps* = 2;   		(* Storage allocation and Garbage collection *)
+	Interrupts* = 3;		(*!  Interrupt handling,  not used in UnixAos *)
+	Modules* = 4;		(* Module list *)
+	Objects* = 5;		(*!  Ready queue,  not used in UnixAos *)
+	Processors* = 6;	(*!  Interprocessor interrupts,  not used in UnixAos *)
+	KernelLog* = 7;		(* Atomic output *)
+	X11* = 8;				(* XWindows I/O *)
+	MaxLocks* = 9;   (* { <= 32 } *)
+	
+	MaxCPU* = 4;
+	IsCooperative* = FALSE;
+
+	TraceMemBlocks = FALSE;
+
+TYPE	
+	Vendor* = ARRAY 13 OF CHAR;	
+
+	MemoryBlock* = POINTER TO MemoryBlockDesc;
+	MemoryBlockDesc* = RECORD
+		next- {UNTRACED}: MemoryBlock;
+		startAdr-: ADDRESS; 		(* sort key in linked list of memory blocks *)
+		size-: SIZE; 					
+		beginBlockAdr-, endBlockAdr-: ADDRESS
+	END;
+	
+	(** processor state *)
+	State* = RECORD	
+		PC*, BP*, SP*: ADDRESS
+	END;
+	
+	
+VAR
+	mtx	: ARRAY MaxLocks OF Unix.Mutex_t;
+	
+	version-: ARRAY 64 OF CHAR;	(** Aos version *)
+	
+	features-, features2 : SET;
+	MMXSupport-	: BOOLEAN;
+	SSESupport-	: BOOLEAN;
+	SSE2Support-	: BOOLEAN;
+	SSE3Support-	: BOOLEAN;
+	SSSE3Support-	: BOOLEAN;
+	SSE41Support-	: BOOLEAN;
+	SSE42Support-	: BOOLEAN;
+	SSE5Support-	: BOOLEAN;
+	AVXSupport-		: BOOLEAN;
+		
+	ticks-: LONGINT;	(** timer ticks. Use Kernel.GetTicks() to read, don't write *)
+	
+	prioLow-, prioHigh-: LONGINT;	(* permitted thread priorities *)
+	
+	fcr-: SET;	(** default floating-point control register value (default rounding mode is towards -infinity, for ENTIER) *)
+	mhz-: HUGEINT;	(** clock rate of GetTimer in MHz, or 0 if not known *)
+	
+	gcThreshold-: SIZE;
+	memBlockHead-{UNTRACED}, memBlockTail-{UNTRACED}: MemoryBlock; (* head and tail of sorted list of memory blocks *)
+	
+	config: ARRAY 2048 OF CHAR;	(* config strings *)
+	
+	logname: ARRAY 32 OF CHAR;
+	logfile: LONGINT;
+	traceHeap: BOOLEAN;
+
+	timer0	: HUGEINT;
+
+	(** Return current processor ID (0 to MaxNum-1). *)
+	PROCEDURE  ID* (): LONGINT;
+	BEGIN
+		RETURN 0
+	END ID;
+
+	(**
+	 * Flush Data Cache for the specified virtual address range. If len is negative, flushes the whole cache.
+	 * This is used on some architecture to interact with DMA hardware (e.g. Ethernet and USB. It can be
+	 * left empty on Intel architecture.
+	 *)
+	PROCEDURE FlushDCacheRange * (adr: ADDRESS; len: LONGINT);
+	END FlushDCacheRange;
+
+	(**
+	 * Invalidate Data Cache for the specified virtual address range. If len is negative, flushes the whole cache.
+	 * This is used on some architecture to interact with DMA hardware (e.g. Ethernet and USB. It can be
+	 * left empty on Intel architecture.
+	 *)
+	PROCEDURE InvalidateDCacheRange * (adr: ADDRESS; len: LONGINT);
+	END InvalidateDCacheRange;
+
+	(**
+	 * Invalidate Instruction Cache for the specified virtual address range. If len is negative, flushes the whole cache.
+	 * This is used on some architecture to interact with DMA hardware (e.g. Ethernet and USB. It can be
+	 * left empty on Intel architecture.
+	 *)
+	PROCEDURE InvalidateICacheRange * (adr: ADDRESS; len: LONGINT);
+	END InvalidateICacheRange;
+	
+	(* insert given memory block in sorted list of memory blocks, sort key is startAdr field - called during GC *)
+	PROCEDURE InsertMemoryBlock(memBlock: MemoryBlock);
+	VAR cur {UNTRACED}, prev {UNTRACED}: MemoryBlock;
+	BEGIN
+		cur := memBlockHead;
+		prev := NIL;
+		WHILE (cur # NIL) & (cur.startAdr < memBlock.startAdr) DO
+			prev := cur;
+			cur := cur.next
+		END;
+		IF prev = NIL THEN (* insert at head of list *)
+			memBlock.next := memBlockHead;
+			memBlockHead := memBlock
+		ELSE (* insert in middle or at end of list *)
+			prev.next := memBlock;
+			memBlock.next := cur;
+			IF cur = NIL THEN
+				memBlockTail := memBlock
+			END
+		END
+	END InsertMemoryBlock;
+
+		
+	(* Free unused memory block - called during GC *)
+	PROCEDURE FreeMemBlock*(memBlock: MemoryBlock);
+	VAR cur {UNTRACED}, prev {UNTRACED}: MemoryBlock;
+	BEGIN
+		cur := memBlockHead;
+		prev := NIL;
+		WHILE (cur # NIL) & (cur # memBlock) DO
+			prev := cur;
+			cur := cur.next
+		END;
+		IF cur = memBlock THEN 
+			IF traceHeap THEN  
+				Trace.String( "Release memory block " );  Trace.Hex( memBlock.startAdr, -8 );  Trace.Ln
+			END;
+			IF prev = NIL THEN
+				memBlockHead := cur.next
+			ELSE
+				prev.next := cur.next;
+				IF cur.next = NIL THEN
+					memBlockTail := prev
+				END
+			END;
+			Unix.free( memBlock.startAdr )
+		ELSE
+			HALT(535)	(* error in memory block management *)
+		END;
+	END FreeMemBlock;
+
+	
+
+	(* expand heap by allocating a new memory block *)
+	PROCEDURE ExpandHeap*( dummy: LONGINT; size: SIZE; VAR memoryBlock: MemoryBlock; VAR beginBlockAdr, endBlockAdr: ADDRESS );
+	VAR mBlock: MemoryBlock;  alloc, s: SIZE;  a, adr: ADDRESS; 
+	BEGIN 
+		IF size < (MemBlockSize - (2*BlockSize))  THEN  alloc := MemBlockSize  
+		ELSE  alloc := size + (2*BlockSize);
+		END;  
+		INC( alloc, (-alloc) MOD Unix.PageSize );
+		
+		IF Unix.posix_memalign( adr, Unix.PageSize, alloc ) # 0 THEN
+			Unix.Perror( "Machine.ExpandHeap: posix_memalign" );
+			beginBlockAdr := 0;
+			endBlockAdr := 0
+		ELSE
+			IF Unix.mprotect( adr, alloc, 7 (* READ WRITE EXEC *) ) # 0 THEN
+				Unix.Perror( "Machine.ExpandHeap: mprotect" )
+			END;
+			
+			mBlock := S.VAL( MemoryBlock, adr );  
+			mBlock.next := NIL;  
+			mBlock.startAdr := adr;
+			mBlock.size := alloc;  
+			mBlock.beginBlockAdr := adr + BlockSize - AddrSize;  
+			
+			ASSERT( (mBlock.beginBlockAdr + AddrSize) MOD BlockSize = 0 );  
+
+			s := adr + alloc - mBlock.beginBlockAdr - BlockSize; 
+			DEC( s, s MOD BlockSize );  
+			ASSERT( s >= size );  
+			mBlock.endBlockAdr := mBlock.beginBlockAdr + s; 
+			
+			InsertMemoryBlock( mBlock );
+			IF traceHeap THEN TraceHeap( mBlock )  END;
+			
+			a := mBlock.beginBlockAdr;
+			S.PUT( a, a + AddrSize );	(* tag *)
+			S.PUT( a + AddrSize, s - AddrSize );  (* size *)
+			S.PUT( a + AddrSize + SizeSize, S.VAL( ADDRESS, 0 ) ); (* next *)
+			
+			beginBlockAdr := mBlock.beginBlockAdr;
+			endBlockAdr := mBlock.endBlockAdr;
+			memoryBlock := mBlock;
+		END  
+	END ExpandHeap;
+		
+	(* Set memory block end address *)
+	PROCEDURE SetMemoryBlockEndAddress*(memBlock: MemoryBlock; endBlockAdr: ADDRESS);
+	BEGIN
+		ASSERT(endBlockAdr >= memBlock.beginBlockAdr);
+		memBlock.endBlockAdr := endBlockAdr
+	END SetMemoryBlockEndAddress;
+
+	PROCEDURE TraceHeap( new: MemoryBlock );
+	VAR cur{UNTRACED}: MemoryBlock;
+	BEGIN
+		Trace.Ln;
+		Trace.String( "Heap expanded" );  Trace.Ln;
+		Trace.String("Static Heap: "); Trace.Hex(Glue.baseAdr, -8); Trace.String(" - "); Trace.Hex(Glue.endAdr, -8); 
+		Trace.Ln;
+		cur := memBlockHead;
+		WHILE cur # NIL DO
+			Trace.Hex( cur.startAdr, -8 );  Trace.String( "   " );  Trace.Hex( cur.startAdr + cur.size, -8 );
+			IF cur = new THEN  Trace.String( "  (new)" )  END;
+			Trace.Ln;
+			cur := cur.next
+		END
+	END TraceHeap;
+
+	(** Get first memory block and first free address, the first free address is identical to memBlockHead.endBlockAdr *)
+	PROCEDURE GetStaticHeap*(VAR beginBlockAdr, endBlockAdr, freeBlockAdr: ADDRESS);
+	BEGIN
+		InitHeap(memBlockHead,beginBlockAdr, endBlockAdr);
+		memBlockTail := memBlockHead;
+
+		beginBlockAdr := memBlockHead.beginBlockAdr;
+		endBlockAdr := memBlockHead.endBlockAdr;
+		freeBlockAdr := beginBlockAdr;
+	END GetStaticHeap;
+	
+	VAR Last: RECORD END; (* linked to the end *)
+
+	(* returns if an address is a currently allocated heap address *)
+	PROCEDURE ValidHeapAddress*( p: ADDRESS ): BOOLEAN;
+	VAR mb: MemoryBlock; 
+	BEGIN
+		IF (p>=Glue.baseAdr) & (p<=Glue.endAdr) THEN RETURN TRUE END;
+		mb := memBlockHead;  
+		WHILE mb # NIL DO
+			IF (p >= mb.beginBlockAdr) & (p <= mb.endBlockAdr) THEN  RETURN TRUE  END;  
+			mb := mb.next;  
+		END;  
+		RETURN FALSE;
+	END ValidHeapAddress;
+	
+
+	(** Return information on free memory in Kbytes. *)
+	PROCEDURE GetFreeK*(VAR total, lowFree, highFree: SIZE);
+	BEGIN
+		(*! meaningless in Unix port, for interface compatibility only *)
+		total := 0;
+		lowFree := 0;
+		highFree := 0
+	END GetFreeK;
+	
+	
+
+	(** Fill "size" bytes at "destAdr" with "filler". "size" must be multiple of 4. *)
+	PROCEDURE  Fill32* (destAdr: ADDRESS; size: SIZE; filler: LONGINT);
+	CODE {SYSTEM.i386}
+		MOV EDI, [EBP+destAdr]
+		MOV ECX, [EBP+size]
+		MOV EAX, [EBP+filler]
+		TEST ECX, 3
+		JZ ok
+		PUSH 8	; ASSERT failure
+		INT 3
+	ok:
+		SHR ECX, 2
+		CLD
+		REP STOSD
+	END Fill32;
+
+PROCEDURE  Portin8*(port: LONGINT; VAR val: CHAR);
+END Portin8;
+
+PROCEDURE  Portin16*(port: LONGINT; VAR val: INTEGER);
+END Portin16;
+
+PROCEDURE  Portin32*(port: LONGINT; VAR val: LONGINT);
+END Portin32;
+
+PROCEDURE  Portout8*(port: LONGINT; val: CHAR);
+END Portout8;
+
+PROCEDURE  Portout16*(port: LONGINT; val: INTEGER);
+END Portout16;
+
+PROCEDURE  Portout32*(port: LONGINT; val: LONGINT);
+END Portout32;
+
+
+(** -- Atomic operations -- *)
+
+(** Atomic INC(x). *)
+PROCEDURE -AtomicInc*(VAR x: LONGINT);
+CODE {SYSTEM.i386}
+	POP EAX
+	LOCK
+	INC DWORD [EAX]
+END AtomicInc;
+
+(** Atomic DEC(x). *)
+PROCEDURE -AtomicDec*(VAR x: LONGINT);
+CODE {SYSTEM.i386}
+	POP EAX
+	LOCK
+	DEC DWORD [EAX]
+END AtomicDec;
+
+(** Atomic INC(x, y). *)
+PROCEDURE -AtomicAdd*(VAR x: LONGINT; y: LONGINT);
+CODE {SYSTEM.i386}
+	POP EBX
+	POP EAX
+	LOCK
+	ADD DWORD [EAX], EBX
+END AtomicAdd;
+
+
+(** Atomic EXCL. *)
+PROCEDURE AtomicExcl* (VAR s: SET; bit: LONGINT);
+CODE {SYSTEM.i386}
+	MOV EAX, [EBP+bit]
+	MOV EBX, [EBP+s]
+	LOCK
+	BTR [EBX], EAX
+END AtomicExcl;
+
+
+(** Atomic test-and-set. Set x = TRUE and return old value of x. *)
+PROCEDURE -AtomicTestSet*(VAR x: BOOLEAN): BOOLEAN;
+CODE {SYSTEM.i386}
+	POP EBX
+	MOV AL, 1
+	XCHG [EBX], AL
+END AtomicTestSet;
+
+(* Atomic compare-and-swap. Set x = new if x = old and return old value of x *)
+PROCEDURE  -AtomicCAS* (VAR x: LONGINT; old, new: LONGINT): LONGINT;
+CODE {SYSTEM.i386}
+	POP EBX		; new
+	POP EAX		; old
+	POP ECX		; address of x
+	DB 0F0X, 00FX, 0B1X, 019X	; LOCK CMPXCHG [ECX], EBX; atomicly compare x with old and set it to new if equal
+END AtomicCAS;
+
+
+(* Return current instruction pointer *)
+PROCEDURE  CurrentPC* (): ADDRESS;
+CODE {SYSTEM.i386}
+	MOV EAX, [EBP+4]
+END CurrentPC;
+
+(* Return current frame pointer *)
+PROCEDURE  -CurrentBP* (): ADDRESS;
+CODE {SYSTEM.i386}
+	MOV EAX, EBP
+END CurrentBP;
+
+(* Set current frame pointer *)
+PROCEDURE  -SetBP* (bp: ADDRESS);
+CODE {SYSTEM.i386}
+	POP EBP
+END SetBP;
+
+(* Return current stack pointer *)
+PROCEDURE  -CurrentSP* (): ADDRESS;
+CODE {SYSTEM.i386}
+	MOV EAX, ESP
+END CurrentSP;
+
+(* Set current stack pointer *)
+PROCEDURE  -SetSP* (sp: ADDRESS);
+CODE {SYSTEM.i386}
+	POP ESP
+END SetSP;
+
+PROCEDURE  -GetEAX*(): LONGINT;
+CODE{SYSTEM.i386}
+END GetEAX;
+
+PROCEDURE  -GetECX*(): LONGINT;
+CODE{SYSTEM.i386}
+	MOV EAX,ECX	
+END GetECX;
+
+PROCEDURE  -GetESI*(): LONGINT;
+CODE{SYSTEM.i386}
+	MOV EAX,ESI	
+END GetESI;
+
+PROCEDURE  -GetEDI*(): LONGINT;
+CODE{SYSTEM.i386}
+	MOV EAX,EDI	
+END GetEDI;
+
+
+PROCEDURE  -SetEAX*(n: LONGINT);
+CODE{SYSTEM.i386}	
+	POP EAX
+END SetEAX;
+
+PROCEDURE  -SetEBX*(n: LONGINT);
+CODE{SYSTEM.i386}
+	POP EBX
+END SetEBX;
+
+PROCEDURE  -SetECX*(n: LONGINT);
+CODE{SYSTEM.i386}
+	POP ECX
+END SetECX;
+
+PROCEDURE  -SetEDX*(n: LONGINT);
+CODE{SYSTEM.i386}
+	POP EDX
+END SetEDX;
+
+PROCEDURE  -SetESI*(n: LONGINT);
+CODE{SYSTEM.i386}
+	POP ESI
+END SetESI;
+
+PROCEDURE  -SetEDI*(n: LONGINT);
+CODE{SYSTEM.i386}
+	POP EDI
+END SetEDI;
+
+
+PROCEDURE -GetTimer* (): HUGEINT;
+CODE {SYSTEM.Pentium}
+	RDTSC	; set EDX:EAX
+END GetTimer;
+
+
+	(** -- Configuration and bootstrapping -- *)
+
+	(** Return the value of the configuration string specified by parameter name in parameter val. Returns val = "" if the string was not found, or has an empty value. *)
+	PROCEDURE GetConfig* (CONST name: ARRAY OF CHAR; VAR val: ARRAY OF CHAR);
+	VAR i, src: LONGINT; ch: CHAR;
+	BEGIN
+		ASSERT (name[0] # "=");	(* no longer supported, use GetInit instead *)
+		
+		src := -1;  val := "";
+		LOOP
+			REPEAT
+				INC( src );  ch := config[src]; 
+				IF ch = 0X THEN EXIT END;
+			UNTIL ch > ' ';
+			i := 0;
+			LOOP
+				ch := config[src];
+				IF (ch # name[i]) OR (name[i] = 0X) THEN EXIT END;
+				INC (i); INC (src)
+			END;
+			IF (ch <= ' ') & (name[i] = 0X) THEN	(* found *)
+				i := 0;
+				REPEAT
+					INC (src); ch := config[src]; val[i] := ch; INC (i);
+					IF i = LEN(val) THEN val[i - 1] := 0X; RETURN END	(* val too short *)
+				UNTIL ch <= ' ';
+				IF ch = ' ' THEN val[i -1] := 0X END; 
+				RETURN
+			ELSE
+				WHILE ch > ' ' DO	(* skip to end of name *)
+					INC (src); ch := config[src]
+				END;
+				INC (src);
+				REPEAT	(* skip to end of value *)
+					ch := config[src]; INC (src)
+				UNTIL ch <= ' '
+			END
+		END;
+		IF (name = "ObjectFileExtension") & (val = "") THEN  
+			val := DefaultObjectFileExtension
+		END;
+	END GetConfig;
+
+
+	(** Convert a string to an integer. Parameter i specifies where in the string scanning should begin (usually 0 in the first call). Scanning stops at the first non-valid character, and i returns the updated position. Parameter s is the string to be scanned. The value is returned as result, or 0 if not valid. Syntax: number = ["-"] digit {digit} ["H" | "h"] . digit = "0" | ... "9" | "A" .. "F" | "a" .. "f" . If the number contains any hexdecimal letter, or if it ends in "H" or "h", it is interpreted as hexadecimal. *)
+	PROCEDURE StrToInt* (VAR i: LONGINT; CONST s: ARRAY OF CHAR): LONGINT;
+	VAR vd, vh, sgn, d: LONGINT; hex: BOOLEAN;
+	BEGIN
+		vd := 0; vh := 0; hex := FALSE;
+		IF s[i] = "-" THEN sgn := -1; INC (i) ELSE sgn := 1 END;
+		LOOP
+			IF (s[i] >= "0") & (s[i] <= "9") THEN d := ORD (s[i])-ORD ("0")
+			ELSIF (CAP (s[i]) >= "A") & (CAP (s[i]) <= "F") THEN d := ORD (CAP (s[i]))-ORD ("A") + 10; hex := TRUE
+			ELSE EXIT
+			END;
+			vd := 10*vd + d; vh := 16*vh + d;
+			INC (i)
+		END;
+		IF CAP (s[i]) = "H" THEN hex := TRUE; INC (i) END;	(* optional H *)
+		IF hex THEN vd := vh END;
+		RETURN sgn * vd
+	END StrToInt;
+	
+
+	(* function returning the number of processors that are available to Aos *)
+	PROCEDURE NumberOfProcessors*( ): LONGINT;
+	VAR res: LONGINT;
+	BEGIN
+		res := Unix.getnprocs();
+		RETURN res;
+	END NumberOfProcessors;
+
+	(*! non portable code, for native Aos only *)
+	PROCEDURE SetNumberOfProcessors*( num: LONGINT );
+	BEGIN
+		(* numberOfProcessors := num; *)
+	END SetNumberOfProcessors;
+
+	(* function for changing byte order *)
+	PROCEDURE ChangeByteOrder* (n: LONGINT): LONGINT;
+	CODE { SYSTEM.i486 }
+		MOV EAX, [EBP+n]				; load n in eax
+		BSWAP EAX						; swap byte order
+	END ChangeByteOrder;
+
+
+	(* Send and print character *)
+	PROCEDURE TraceChar *(c: CHAR);
+	BEGIN
+		Trace.Char( c )
+	END TraceChar;
+
+
+	(** CPU identification *)
+
+	PROCEDURE CPUID*( VAR vendor: Vendor;  VAR version: LONGINT;  VAR features1,features2: SET );
+	CODE {SYSTEM.i386, SYSTEM.Pentium}
+		MOV	EAX, 0
+		CPUID
+		CMP	EAX, 0
+		JNE	ok
+		MOV	ESI, [EBP+vendor]
+		MOV	[ESI], AL	;  AL = 0
+		MOV	ESI, [EBP+version]
+		MOV	[ESI], EAX	;  EAX = 0
+		MOV	ESI, [EBP+features1]
+		MOV	[ESI], EAX
+		MOV	ESI, [EBP+features2]
+		MOV	[ESI], EAX
+		JMP	end
+	ok:
+		MOV	ESI, [EBP+vendor]
+		MOV	[ESI], EBX
+		MOV	[ESI+4], EDX
+		MOV	[ESI+8], ECX
+		MOV	BYTE [ESI+12], 0
+		MOV	EAX, 1
+		CPUID
+		MOV	ESI, [EBP+version]
+		MOV	[ESI], EAX
+		MOV	ESI, [EBP+features1]
+		MOV	[ESI], EDX
+		MOV	ESI, [EBP+features2]
+		MOV	[ESI], ECX
+	end:
+	END CPUID;
+	
+
+	(* If the CPUID instruction is supported, the ID flag (bit 21) of the EFLAGS register is r/w *)
+	PROCEDURE CpuIdSupported( ) : BOOLEAN;
+	CODE {SYSTEM.i386}	
+		PUSHFD				; save EFLAGS
+		POP EAX				; store EFLAGS in EAX
+		MOV EBX, EAX		; save EBX for later testing
+		XOR EAX, 00200000H	; toggle bit 21
+		PUSH EAX				; push to stack
+		POPFD					; save changed EAX to EFLAGS
+		PUSHFD				; push EFLAGS to TOS
+		POP EAX				; store EFLAGS in EAX
+		CMP EAX, EBX		; see if bit 21 has changed
+		SETNE AL;			; return TRUE if bit 21 has changed, FALSE otherwise
+	END CpuIdSupported;
+
+	
+	(* setup MMX, SSE and SSE2..SSE5 and AVX extension *)
+
+	PROCEDURE SetupSSE2Ext;
+	CONST
+		MMXFlag=23;(*IN features from EBX*)
+		FXSRFlag = 24;
+		SSEFlag = 25;
+		SSE2Flag = 26;
+		SSE3Flag = 0; (*IN features2 from ECX*) (*PH 04/11*)
+		SSSE3Flag =9;
+		SSE41Flag =19;
+		SSE42Flag =20;
+		SSE5Flag = 11;
+		AVXFlag = 28;
+	BEGIN
+		MMXSupport := MMXFlag IN features;
+		SSESupport := SSEFlag IN features;
+		SSE2Support := SSESupport & (SSE2Flag IN features);
+		SSE3Support := SSE2Support & (SSE3Flag IN features2);
+		SSSE3Support := SSE3Support & (SSSE3Flag IN features2); (* PH 04/11*)
+		SSE41Support := SSE3Support & (SSE41Flag IN features2);
+		SSE42Support := SSE3Support & (SSE42Flag IN features2);
+		SSE5Support := SSE3Support & (SSE5Flag IN features2);
+		AVXSupport := SSE3Support & (AVXFlag IN features2);
+
+		IF SSESupport & (FXSRFlag IN features) THEN
+			(* InitSSE(); *) (*! not privileged mode in Windows and Unix, not allowed *)
+		END;
+	END SetupSSE2Ext;
+	
+
+	(** -- Processor initialization -- *)
+	PROCEDURE -SetFCR( s: SET );
+	CODE {SYSTEM.i386, SYSTEM.FPU}
+		FLDCW	[ESP]	;  parameter s
+		POP	EAX
+	END SetFCR;
+
+	PROCEDURE -FCR( ): SET;
+	CODE {SYSTEM.i386, SYSTEM.FPU}
+		PUSH	0
+		FNSTCW	[ESP]
+		FWAIT
+		POP	EAX
+	END FCR;
+
+	PROCEDURE -InitFPU;
+	CODE {SYSTEM.i386, SYSTEM.FPU}
+		FNINIT
+	END InitFPU;
+
+	(** Setup FPU control word of current processor. *)
+	PROCEDURE SetupFPU*;
+	BEGIN
+		InitFPU;  SetFCR( fcr )
+	END SetupFPU;
+
+
+	(* Initialize locks. *)
+	PROCEDURE InitLocks;  
+	VAR i: LONGINT; 
+	BEGIN 
+		i := 0;  
+		WHILE i < MaxLocks DO  mtx[i] := Unix.NewMtx( );  INC( i )  END;   
+	END InitLocks;  
+
+	PROCEDURE CleanupLocks*;  
+	VAR i: LONGINT;  
+	BEGIN 
+		i := 0;  
+		WHILE i < MaxLocks DO  Unix.MtxDestroy( mtx[i] );  INC( i ) END;  	
+	END CleanupLocks;  
+	
+	(** Acquire a spin-lock. *)
+	PROCEDURE  Acquire*( level: LONGINT );   (* non reentrant lock *)
+	BEGIN 
+		Unix.MtxLock( mtx[level] );
+	END Acquire;  
+
+	(** Release a spin-lock. *)
+	PROCEDURE  Release*( level: LONGINT );   
+	BEGIN 
+		Unix.MtxUnlock( mtx[level] );
+	END Release;  
+	
+	
+	PROCEDURE Shutdown*( reboot: BOOLEAN );
+	VAR r: LONGINT;  logstat: Unix.Status;
+	BEGIN
+		r := Unix.fstat( logfile, logstat );
+		r := Unix.close( logfile );
+		IF logstat.size = 0 THEN  r := Unix.unlink( ADDRESSOF( logname) )  END;
+		IF reboot THEN  Unix.exit( 0 )  ELSE  Unix.exit( 1 )  END;
+	END Shutdown;
+		
+
+		
+
+	(* Set machine-dependent parameter gcThreshold *)
+	PROCEDURE SetGCParams*;
+	BEGIN
+		gcThreshold := 10*1024*1024; (* 10 MB *)
+	END SetGCParams;
+
+	(* expand heap by allocating a new memory block - called during GC *)
+	PROCEDURE InitHeap(VAR memoryBlock: MemoryBlock; VAR beginBlockAdr, endBlockAdr: ADDRESS);
+	CONST MemBlockHeaderSize = BlockHeaderSize + RecordDescSize + BlockHeaderSize;
+		TypeDescOffset = -AddressSize; (* see Heaps.Mod *)
+		HeapBlockOffset = - 2 * AddressSize; (* see Heaps.Mod *)
+		DataAdrOffset = AddressSize; (* offset of dataAdr field in Heaps.HeapBlockDesc *)
+	VAR memDescSize, memBlkSize, alignOffset: SIZE; adr, memHeaderAdr, memBlockAdr: ADDRESS;
+		memBlock {UNTRACED}: MemoryBlock; size: LONGINT;
+		initVal: LONGINT;
+	BEGIN
+
+		(*
+			HeapBlockPtr -- bootHeapAdr
+		4	Type
+		8	Mark
+		12	DataAdr
+		16	Size
+		20	HeapBlockPtr
+		24	Type
+		28	next  -- MemoryBlock
+		32	startAdr
+		36	size
+		40	beginBlockAdr
+		44	endBlockAdr
+		48		--beginBlockAdr
+		....
+				--endBlockAdr
+
+		*)
+		size := 1;
+		memDescSize := MemBlockHeaderSize + SIZEOF(MemoryBlockDesc);
+		INC(memDescSize, (-memDescSize) MOD StaticBlockSize); 	(* round up to multiple of StaticBlockSize *)
+		INC(size, (-size) MOD StaticBlockSize); (* round up to multiple of StaticBlockSize *)
+		memBlkSize := memDescSize + size + StaticBlockSize; 		(* add StaticBlockSize to account for alignments different from multiples of StaticBlockSize *)
+		IF memBlkSize < MemBlockSize THEN memBlkSize := MemBlockSize END; 	(* MemBlockSize implicitly multiple of StaticBlockSize *)
+
+		IF Unix.posix_memalign( adr, Unix.PageSize, memBlkSize ) # 0 THEN
+			Unix.Perror( "Machine.ExpandHeap: posix_memalign" );
+			beginBlockAdr := 0;
+			endBlockAdr := 0
+		ELSE
+			IF Unix.mprotect( adr, memBlkSize, 7 (* READ WRITE EXEC *) ) # 0 THEN
+				Unix.Perror( "Machine.ExpandHeap: mprotect" )
+			END;
+			IF TraceMemBlocks THEN TRACE(adr, memBlkSize) END;
+		END;
+
+		IF TraceMemBlocks THEN
+			Trace.String("first heap block intVal "); Trace.Int(initVal,1); Trace.Ln;
+			Trace.String("first heap block memBlkSize "); Trace.Int(memBlkSize,1); Trace.Ln;
+			Trace.String("first heap block adr "); Trace.Int(adr,1); Trace.Ln;
+		END;
+		ASSERT(adr # 0);
+
+		alignOffset := (-adr) MOD StaticBlockSize;
+
+		memHeaderAdr := adr + alignOffset;  	(* force alignment of memory block start *)
+		memBlockAdr := memHeaderAdr + MemBlockHeaderSize;
+		memBlock := S.VAL(MemoryBlock, memBlockAdr);
+		beginBlockAdr := memHeaderAdr + memDescSize;
+
+		memBlock.next := NIL;
+		memBlock.startAdr := adr;
+		memBlock.size := memBlkSize;
+
+		beginBlockAdr := memHeaderAdr + memDescSize;
+		endBlockAdr := adr + memBlkSize - alignOffset;
+		memBlock.beginBlockAdr := beginBlockAdr;
+		memBlock.endBlockAdr := endBlockAdr;
+
+		(* correct fields *)
+		S.PUT(memBlockAdr + HeapBlockOffset, memHeaderAdr + BlockHeaderSize);	(* set reference to header part of memory block correctly *)
+		S.PUT(memBlockAdr + TypeDescOffset, 0);										(* set type descriptor field of memory block to default value, memory blocks are not traced by GC *)
+		S.PUT(memHeaderAdr + BlockHeaderSize + DataAdrOffset, memBlockAdr);		(* set dataAdr of RecordBlockDesc to correct value *)
+		S.PUT(memHeaderAdr + BlockHeaderSize + 2*AddressSize , memBlkSize);
+
+		(* fill first heap block *)
+		S.PUT(beginBlockAdr,0);
+		S.PUT(beginBlockAdr+AddressSize,0);
+		S.PUT(beginBlockAdr+2*AddressSize,0);
+		S.PUT(beginBlockAdr+3*AddressSize,beginBlockAdr+7*AddressSize);
+		S.PUT(beginBlockAdr+4*AddressSize,endBlockAdr-beginBlockAdr);
+		S.PUT(beginBlockAdr+5*AddressSize,beginBlockAdr+2*AddressSize);
+		S.PUT(beginBlockAdr+6*AddressSize,0);
+
+		memoryBlock := memBlock;
+	END InitHeap;
+
+
+	PROCEDURE InitConfig;
+	VAR a: ADDRESS;  i: LONGINT;  c: CHAR;
+	BEGIN
+		a := Unix.getenv( ADDRESSOF( "AOSCONFIG" ) );
+		IF a = 0 THEN  config := DefaultConfig
+		ELSE
+			REPEAT
+				S.GET( a, c );  INC( a );  config[i] := c;  INC( i )
+			UNTIL c = 0X
+		END
+	END InitConfig;
+	
+	
+	PROCEDURE UpdateTicks*;
+	BEGIN
+		ticks := SHORT( (GetTimer() - timer0) DIV (mhz * 1000) );
+	END UpdateTicks;
+	
+	
+	PROCEDURE InitThreads;
+	VAR res: BOOLEAN; 
+	BEGIN
+		res := Unix.ThrInitialize( prioLow, prioHigh );
+		IF ~res THEN
+			Trace.StringLn( "Machine.InitThreads: no threads support in boot environment.  teminating" ); 
+			Unix.exit( 1 )
+		END;
+		IF Glue.debug # {} THEN
+			Trace.String( "Threads initialized, priorities low, high: " ); 
+			Trace.Int( prioLow, 0 ); Trace.String( ", " ); Trace.Int( prioHigh, 0 );
+			Trace.Ln
+		END
+	END InitThreads;
+	
+	PROCEDURE CPUSpeed;
+	VAR t0, t1: HUGEINT; 
+	BEGIN
+		t0 := GetTimer();  Unix.ThrSleep( 100 );  t1 := GetTimer();
+		mhz := (t1 - t0) DIV 100000;
+		IF Glue.debug # {} THEN
+			Trace.String( "CPU speed: ~" );  Trace.Int( SHORT( mhz ), 0);  Trace.String( " MHz" );  Trace.Ln
+		END
+	END CPUSpeed;
+	
+	PROCEDURE Log( c: CHAR );
+	VAR ignore: LONGINT;
+	BEGIN
+		ignore := Unix.write( 1, ADDRESSOF( c ), 1 );
+		ignore := Unix.write( logfile, ADDRESSOF( c ), 1 );
+	END Log;
+	
+	PROCEDURE LogFileOnly( c: CHAR );
+	VAR ignore: LONGINT;
+	BEGIN
+		ignore := Unix.write( logfile, ADDRESSOF( c ), 1 );
+	END LogFileOnly;
+	
+	
+	PROCEDURE InitLog;
+	VAR pid, i: LONGINT; 
+	BEGIN
+		logname := "AOS.xxxxx.Log";
+		pid := Unix.getpid();  i := 8;
+		REPEAT
+			logname[i] := CHR( pid MOD 10 + ORD( '0' ) );  DEC( i );
+			pid := pid DIV 10;		
+		UNTIL i = 3;
+		logfile := Unix.open( ADDRESSOF( logname ), Unix.rdwr + Unix.creat + Unix.trunc, Unix.rwrwr );
+		VerboseLog;	
+	END InitLog;
+	
+	PROCEDURE SilentLog*;
+	BEGIN
+		Trace.Char := LogFileOnly
+	END SilentLog;
+	
+	PROCEDURE VerboseLog*;
+	BEGIN
+		Trace.Char := Log
+	END VerboseLog;
+
+	
+	PROCEDURE Append( VAR a: ARRAY OF CHAR; CONST this: ARRAY OF CHAR );
+	VAR i, j: LONGINT;
+	BEGIN
+		i := 0;  j := 0;  
+		WHILE a[i] # 0X DO  INC( i )  END;
+		WHILE (i < LEN( a ) - 1) & (this[j] # 0X) DO a[i] := this[j];  INC( i );  INC( j )  END;
+		a[i] := 0X
+	END Append;
+	
+
+	PROCEDURE Init;
+	VAR vendor: Vendor; ver: LONGINT;
+	BEGIN		
+		COPY( Unix.Version, version );  Append( version, Version ); Append(version, S.Date);
+		
+		timer0 := GetTimer( );  ticks := 0;
+		InitThreads;
+		InitLocks;
+		traceHeap := 1 IN Glue.debug;
+		InitConfig;
+		InitLog;
+		CPUSpeed;
+		IF CpuIdSupported() THEN
+			CPUID( vendor, ver, features, features2 );	 SetupSSE2Ext
+		END;
+		fcr := (FCR() - {0,2,3,10,11}) + {0..5,8,9};	(* default FCR RC=00B *)
+	END Init;
+
+	PROCEDURE {INITIAL} Init0;
+	BEGIN
+		Init;
+	END Init0;
+	
+END Machine.
+
+(*
+03.03.1998	pjm	First version
+30.06.1999	pjm	ProcessorID moved to AosProcessor
+*)
+
+(**
+Notes
+
+This module defines an interface to the boot environment of the system. The facilities provided here are only intended for the lowest levels of the system, and should never be directly imported by user modules (exceptions are noted below). They are highly specific to the system hardware and firmware architecture.
+
+Typically a machine has some type of firmware that performs initial testing and setup of the system. The firmware initiates the operating system bootstrap loader, which loads the boot file. This module is the first module in the statically linked boot file that gets control.
+
+There are two more-or-less general procedures in this module: GetConfig and StrToInt. GetConfig is used to query low-level system settings, e.g., the location of the boot file system. StrToInt is a utility procedure that parses numeric strings.
+
+Config strings:
+
+ExtMemSize	Specifies size of extended memory (above 1MB) in MB. This value is not checked for validity. Setting it false may cause the system to fail, possible after running for some time. The memory size is usually detected automatically, but if the detection does not work for some reason, or if you want to limit the amount of memory detected, this string can be set. For example, if the machine has 64MB of memory, this value can be set as ExtMemSize="63".
+*)
+