Unix on Mocka, part 2

Many years ago I did some rudimentary tests with running Unix system commands from within Modula-2. They worked, as can be seen in unix.html but it was cumbersome. And I definitely need some sleep for Mocka. Yes I can start and calibrate a timing loop based on an infinite loop, but such a loop is only allowed on single user single tasking systems like "Good Old Dos". On Linux we should not lock up the machine for such a silly task. Therefore the Unix sleep command (which simply HALT the processor for a finite time and then wake it up again.
A sleeping process does noit eat up cpu cycles so it doesn't slow down the rest. With a 'sleep' command around, it is possible to poll I/O's in a sensible way. I decided to name the module 'unix' (lower case letters only) since I want a sleep command and perhaps some other goodies like 'printf' since it works a little bit easier than a series of InOut commands.

Unix functions for Mocka Modula-2

Here is the module that does all the work:

/* Unix functions for Modula-2 */

#define billion 1000000000;

#include <stdio.h>
#include <time.h>


void Printf (char * text)
{
   printf (text);
}


void nSleep (int s, int ns)
{
   struct timespec ts;
   
   ts.tv_sec = (s > 0) ? s : -s;
   ts.tv_nsec = ns % billion;
   nanosleep (&ts, NULL);
}


void uSleep (unsigned int delay)
{
   usleep (delay);
}
   
Compile it to an object module with
gcc unix.c -c -o unix.o
We're half way done now. Just create a DEFINITION MODULE. At least, the file has a 'def' extension, the contents are as follows:
FOREIGN MODULE unix;		(* Unix functions for Modula-2 *)

PROCEDURE Printf ( text : ARRAY OF CHAR);

PROCEDURE nSleep (s, ns : CARDINAL);

PROCEDURE uSleep (delay : CARDINAL);

END unix.
   
Now start mocka and compile the foreign module:
jan@nitrogen ~/Modula/lib$ mocka 
Mocka 0608m
>> s unix
.. Compiling Definition of unix
>> q
   
Done. Now we can IMPORT the functions....

Testing the new unix functions

Below is a small program to test the new functions:

MODULE unto;

IMPORT unix, InOut;

BEGIN
  InOut.WriteString ("testing new Unix module. Going to sleep for 1.5 seconds now");
  InOut.WriteLn;
  unix.uSleep (1500000);
  InOut.WriteString ("Just woke up after an eternity.. still feeling sleepy. Time foe a 5.3 second nap the time.");
  InOut.WriteLn;
  unix.nSleep (5, 300000000);
  unix.Printf ("Done sleeping, time to get some grub.\n")
END unto.
   

See it compile

I always use the mocka 'IDE' since it works so easy.

jan@nitrogen ~/Modula/lib$ mocka
Mocka 0608m
>> i unto
>> p unto
.. Compiling Program Module unto I/0001 II/0001
.. Linking unto
gcc: error: ./m2bin/unix.o: No such file or directory
strip: 'unto': No such file
>> cp unix.o m2bin
>> p unto
.. Linking unto
>> q
jan@nitrogen ~/Modula/lib$ ./unto
   
So far the compiling. As you see, the linker expects the object file in the ./m2bin directory so I help it a little bit. And then it immediately performs a clean compile.

See it run

testing new Unix module. Going to sleep for 1.5 seconds now
Just woke up after an eternity.. still feeling sleepy. Time foe a 5.3 second nap the time.
Done sleeping, time to get some grub.\njan@nitrogen ~/Modula/lib$
Three things:
  1. The 1.5 second delay was as good as it gets
  2. The 5.3 second delay was as good as I could check it too
  3. Printf does not process the '\n' token (apparently this is done by the C preprocessor)
It has no use to leave the Printf function in the unix Module. But the sleeping is handled perfectly. And the trick with the foreign module still works.

Page created 14 May 2015 and