Eli Green [mailto:eli.green / codedogs.ca] wrote:

> 	I've been trying to get Ruby to compile/run under QNX's
> RTOS (the free
> download one), and it's remarkable how easy it's been so far... =)

> The interpreter itself works just fine:

Did you try "make test"?

> However, the minute
> I try and load a .so:
>
> manhattan ~% ruby
> require 'socket'
> unknown symbol: rb_eSecurityError
> unknown symbol: rb_cSymbol
> ... it goes on like this for a while ...

I ported ruby to QNX a while ago (using QNX 6.0B, I'll give the new 6.1 a
try in a few days), applying only some minor changes. I'm using this version
of ruby for nearly two months now without problems.

Matz: Could you please have a look at the change notes at the end of this
message and include them in the next release? Thanks in advance...

Roland



================================

Changes to ruby-1.6.4 (2001-06-04)


config.guess/config.sub:

Updated with a more recent version (the ones supplied with QNX RTP).


dir.c:

fnmatch already defined in C library (fnmatch.h). Renamed static function
fnmatch to _rb_fnmatch. Maybe the version from the C library can be used
instead. It has the same signature, but there may be subtle differences.


io.c:

Added (somewhere at the top):

#ifdef __QNXNTO__
#include "unix.h"
#endif

This is needed to define NOFILES.


signal.c:

Signal handlers are not properly set if SA_RESTART is used ("make test"
fails).
Added at line 296:

#ifdef SA_RESTART
  #ifndef __QNXNTO__
    sigact.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
  #endif
#endif


eval.c:

somewhere at the beginning (around line 100) added:

#ifdef __QNXNTO__
#include <time.h>
#include <sys/siginfo.h>
#endif


defines.h

line 76:

add ||defined(__QNXNTO__):

#if defined(DJGPP) || defined(__BOW__) || defined(__QNXNTO__)
#undef HAVE_SETITIMER
#endif

setitimer() only supports ITIMER_REAL in QNX 6.0, which cannot be used. I
tried to simulate ITIMER_VIRTUAL with POSIX timers (see below), but this
does not work reliably.


ext/socket.c

line 1517:

#if !defined(NT) && !defined(__BEOS__) && !defined(__EMX__) &&
!defined(__QNXNTO__)

Up to now socketpair() is not support in QNX 6 (although it might be soon).



configure:

line 4674:

added:

	nto-qnx*)		DLDFLAGS="-L/lib -L/usr/lib -L/usr/local/lib"
			LDSHARED='ld -Bshareable -x'
			LDFLAGS="-L/lib -L/usr/lib -L/usr/local/lib"
			rb_cv_dlopen=yes;;


Note: This change should really go into configure.in, but I don't know
enough about autoconf to mess with that file.


lib/irb/locale.rb

line 132:

Change
      tmp_base = path.tr("./:", "___")
to
      tmp_base = path.tr("./:", "___")[1..30]

This is necessary because the QNX filesystem only supports filenames with up
to 48 characters.


=====================


Here is my try to simulate ITIMER_VIRTUAL to make thread switching more
efficient. This seems to work on principle, but can make blocking system
calls return prematurely (with EINTR result). Ruby doesn't like this...

eval.c:

around lines 8110 / 8122:  (rb_thread_start_timer and rb_thread_stop_timer)

Only TIMER_REAL is supported by setitimer on QNX RTP, so the ITIMER
functionality has to be
simulated by using POSIX timers. Change thread_start_timer /
thread_stop_timer like this:


#if defined(HAVE_SETITIMER)
static int thread_init = 0;

#ifdef __QNXNTO__
static timer_t thread_qnx6_timer_id = 0;
#endif

void
rb_thread_start_timer()
{
#ifdef __QNXNTO__

    struct sigevent sigevt;
    struct itimerspec tval;

    if (!thread_init) return;

    if (!thread_qnx6_timer_id) {
        SIGEV_SIGNAL_INIT (&sigevt, SIGVTALRM);
        timer_create (CLOCK_REALTIME, &sigevt, &thread_qnx6_timer_id);
    }

    tval.it_interval.tv_sec = 0;
    tval.it_interval.tv_nsec = 10000000;
    tval.it_value = tval.it_interval;
    timer_settime (thread_qnx6_timer_id, 0, &tval, NULL);

#else

    struct itimerval tval;

    if (!thread_init) return;
    tval.it_interval.tv_sec = 0;
    tval.it_interval.tv_usec = 10000;
    tval.it_value = tval.it_interval;
    setitimer(ITIMER_VIRTUAL, &tval, NULL);

#endif
}

void
rb_thread_stop_timer()
{
#ifdef __QNXNTO__

    struct itimerspec tval;

    if (!thread_init) return;
    if (!thread_qnx6_timer_id) return;

    tval.it_interval.tv_sec = 0;
    tval.it_interval.tv_nsec = 0;
    tval.it_value = tval.it_interval;
    timer_settime (thread_qnx6_timer_id, 0, &tval, NULL);

#else

    struct itimerval tval;

    if (!thread_init) return;
    tval.it_interval.tv_sec = 0;
    tval.it_interval.tv_usec = 0;
    tval.it_value = tval.it_interval;
    setitimer(ITIMER_VIRTUAL, &tval, NULL);

#endif
}
#endif