From: Claudius Pyka
Subject: AllegroCL & Sun (LWP & RPC)
Date: 
Message-ID: <claude.743277573@nats11>
I have written some C function library using Sun's LWP library and
Sun's RPC library.  The functions I have written enable a Lisp
program (AllegroCL4.1) to communicate with other Unix processes on
a local network.  Basically, this works as follows.  LWP is used
to create a receiver thread that waits for messages from other
processes.  If a message arrives it is accepted by this receiver
thread, decoded from its XDR representation, mapped into a Lisp
representation and finally passed to a Lisp function.  Message
passing is performed by RPC calls.

All worked fine with AllegroCL4.0.1 which I used to develop the
message passing library.  Recently we moved to Allegro4.1 and
a problem appeared.  After a lot of debugging I realized that
the RPC function clnt_create() must create a side effect not
present in the previous ACL version.  After calling clnt_create(),
the LWP function lwp_sleep() blocks Lisp.  I append a test program
at the end of this posting which reproduces this effect when run.
This program behaves as expected with ACL4.0.1, but produces the
failure when executed in ACL4.1.

Is there someone out there having tried similar things?  Do you
have any idea what the underlying problem might be and what a
solution could be?  Basically, there must be some side effect
of clnt_create() which influences LWP functions.  This side effect
did not exist in ACL4.0.1.

After compiling the C source, load the Lisp file and execute the
following:

	(init-threads)
	;; threads are printing one-line messages
	;; enter:
	(make-client)
	;; threads stop executing


Claudius Pyka.

======================================================================
==  Claudius Pyka                  Tel.:  (040) 4123-2574           ==
==  University of Hamburg          Fax :  (040) 4123-6384           ==
==  Computer Science Department    email: ······@nats4.informatik.  ==
==  Natural Language Systems Division     uni-hamburg.de            ==
==                                                                  ==
==  Bodenstedtstr. 16                                               ==
==  W-2000 Hamburg 50                                               ==
======================================================================


This is the C source of the test program:

---------------------------------------------------------------------
/*
 * Testing combination of LWP and ACL.
 */

#include <stdio.h>
#include <lwp/lwp.h>
#include <lwp/stackdep.h>
#include <rpc/rpc.h>

#define MAXPRIO 20

thread_t th1, th2, th3, th4, th5;

static int leave_threads = 0;

int
init_threads()
{
	int f_1(), f_2(), f_3(), f_4();

	(void)pod_setmaxpri(MAXPRIO);

	lwp_setstkcache(64000, 5);

	if(lwp_create(&th1,f_1,12,0,lwp_newstk(),0)!=0)
		{printf("Cannot create th1\n");fflush(stdout);}
	if(lwp_create(&th2,f_2,12,0,lwp_newstk(),0)!=0)
		{printf("Cannot create th2\n");fflush(stdout);}
	if(lwp_create(&th3,f_3,12,0,lwp_newstk(),0)!=0)
		{printf("Cannot create th3\n");fflush(stdout);}
	if(lwp_create(&th4,f_4,12,0,lwp_newstk(),0)!=0)
		{printf("Cannot create th4\n");fflush(stdout);}

	lwp_self(&th5);
	printf("Threads created\n");fflush(stdout);
	lwp_setpri(th5, 10);

	printf("Leaving main thread\n");fflush(stdout);
	return(1);
}

int
make_client()
{
	CLIENT *cli;
	cli = clnt_create("nats11",900900900,1,"tcp");
	printf("------------------------------------\n");
	printf("------------------------------------\n");
	printf("------------------------------------\n");
	printf("------------------------------------\n");
	printf("------------------------------------\n");
	printf("------------ D O N E ---------------\n");
	printf("------------------------------------\n");
	printf("------------------------------------\n");
	printf("------------------------------------\n");
	printf("------------------------------------\n");
	printf("------------------------------------\n");
	fflush(stdout);
	return(111);
}

int
f_1()
{
	int i;
	struct timeval tout;
	tout.tv_sec  = 0;
	tout.tv_usec = 10000;

	while(leave_threads==0) {
	    printf("\t===> Entering thread 1\n");fflush(stdout);
	    for(i=0; i<1000; i++) ;
	    printf("\t<=== Leaving thread 1\n");fflush(stdout);
	    lwp_sleep(&tout);
	}

	printf("##### Exiting thread 1\n");fflush(stdout);
	return(1);
}

int
f_2()
{
	int i;
	struct timeval tout;
	tout.tv_sec  = 0;
	tout.tv_usec = 10000;

	while(leave_threads==0) {
	    printf("\t===> Entering thread 2\n");fflush(stdout);
	    for(i=0; i<1000; i++) ;
	    printf("\t<=== Leaving thread 2\n");fflush(stdout);
	    lwp_sleep(&tout);
	}

	printf("##### Exiting thread 2\n");fflush(stdout);
	return(1);
}

int
f_3()
{
	int i;
	struct timeval tout;
	tout.tv_sec  = 0;
	tout.tv_usec = 10000;

	while(leave_threads==0) {
	    printf("\t===> Entering thread 3\n");fflush(stdout);
	    for(i=0; i<1000; i++) ;
	    printf("\t<=== Leaving thread 3\n");fflush(stdout);
	    lwp_sleep(&tout);
	}

	printf("##### Exiting thread 3\n");fflush(stdout);
	return(1);
}

int
f_4()
{
	int i;
	struct timeval tout;
	tout.tv_sec  = 0;
	tout.tv_usec = 10000;

	while(leave_threads==0) {
	    printf("\t===> Entering thread 4\n");fflush(stdout);
	    for(i=0; i<1000; i++) ;
	    printf("\t<=== Leaving thread 4\n");fflush(stdout);
	    lwp_sleep(&tout);
	}

	printf("##### Exiting thread 4\n");fflush(stdout);
	return(1);
}

int
delay_thread(d)
	int d;
{
	struct timeval tout;

	tout.tv_sec  = d * 1000 / 1000000;
	tout.tv_usec = d * 1000 % 1000000;
	lwp_sleep(&tout);

	return(99);
}

int
finish_threads()
{
	leave_threads = 1;
	return(1);
}

int
loop_a_little(l)
	int l;
{
	int i;
	for(i=0; i<l; i++) ;
	printf("---------- loop done -----\n");fflush(stdout);
/*	printf("    push RETURN to continue ... ");fflush(stdout);
	scanf("%d",&i);
*/	return(22);
}

/*
 * End of file
 */

/*

(load "aclthreads.cl")
(init-threads)
(finish-threads)
(delay-thread 10)
(loop-thread 100000)
(loop-thread 10000000)
(make-client)
(tumble 200)

*/

----------------------------------------------------------------------

And this is the Lisp source:

----------------------------------------------------------------------
;;;
;;; ACL interface to somethreads.c
;;;

(remove-entry-point "_exit")
(remove-entry-point "__unpacked_to_decimal")
(remove-entry-point "__unpack_quadruple")
(remove-entry-point "__prod_b10000")
(remove-entry-point "__carry_out_b10000")
(remove-entry-point "__prod_65536_b10000")

(load "somethreads.o"
	:system-libraries '("lwp") )

(defforeign 'init-threads
	:entry-point (convert-to-lang "init_threads")
	:return-type :integer)

(defforeign 'finish-threads
	:entry-point (convert-to-lang "finish_threads")
	:return-type :integer)

(defforeign 'make-client
	:entry-point (convert-to-lang "make_client")
	:return-type :integer)

(defforeign 'delay-thread
	:entry-point (convert-to-lang "delay_thread")
	:arguments '(integer)
	:return-type :integer)

(defforeign 'loop-thread
	:entry-point (convert-to-lang "loop_a_little")
	:arguments '(integer)
	:return-type :integer)

(defun tumble (i)
	(loop for x from 1 to i
		do (format t "=== ~A~%" x))
)

----------------------------------------------------------------------