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.