9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] libthread help ...
@ 2002-12-31 20:48 Philippe Anel
  2003-01-01  4:35 ` Russ Cox
  0 siblings, 1 reply; 4+ messages in thread
From: Philippe Anel @ 2002-12-31 20:48 UTC (permalink / raw)
  To: 9fans


Hi,

	The following program doesn't work when the user
hits the "exit" entry of the menu (by clicking the button 2).
It is derived from /sys/src/libthread/example.c [which doesn't
compile].

	According to acid, all procs are waiting a rendezvous:

At pc:0x00011aa8:rendezvous+0x7 /sys/src/libc/9syscall/rendezvous.s:5
rendezvous() /sys/src/libc/9syscall/rendezvous.s:3
	called from runthread+0x83 /sys/src/libthread/sched.c:127
runthread(p=0x00037dd8) /sys/src/libthread/sched.c:115
	called from _sched+0x99 /sys/src/libthread/sched.c:96
_sched() /sys/src/libthread/sched.c:81
	called from _schedinit+0x1a4 /sys/src/libthread/sched.c:77
_schedinit(arg=0x00037dd8) /sys/src/libthread/sched.c:27
	called from main+0x2a /sys/src/libthread/main.c:32
main(argc=0x00000001,argv=0x7fffefec) /sys/src/libthread/main.c:22
	called from _main+0x31 /sys/src/libc/386/main9.s:16

	Any idea why ?

	Philippe,
	Happy new year.

----------------------------------------------
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <frame.h>

enum
{
	STACKSIZE = 2048,
};

void
clockproc(void *arg)
{
	int t, pid;
	Channel *c;

	pid = getpid();
	c = arg;
	for(t=0;; t++){
		sleep(1000);
		fprint(2, "[%d]clock->%d\n", pid, t);
		sendul(c, t);
		fprint(2, "[%d]clock->sendul\n", pid);
	}
}

struct mh {
	Mousectl *mctl;
	Channel *cmd;
	Channel *res;
};

void
menuhitproc(void *arg)
{
	struct mh *marg;
	int	t, pid;
	char *items[] = {
		"exit",
		nil
	};
	Menu menu = {
		items,
		nil,
		0
	};

	pid = getpid();
	marg = arg;
	for (;;) {
		t = recvul(marg->cmd);
  		t = menuhit(t, marg->mctl, &menu, nil);
		fprint(2, "[%d]menuhit->%d\n", pid, t);
		sendul(marg->res, t);
		fprint(2, "[%d]menu->sendul\n", pid);
	}
}

void
threadmain(int argc, char *argv[])
{
	int t, item;
	Mousectl *mctl;
  	Alt a[] = {
	//	 c		v		op
		{nil,	nil,	CHANRCV},			// 0:	mouse
		{nil,	nil,	CHANRCV},			// 1:	resize
		{nil,	&t,		CHANRCV},			// 2:	clock
		{nil,	&item,	CHANRCV},			// 3:	menuhit
		{nil,	nil,	CHANEND},
	};
	struct mh marg;
	int pid;

	USED(argc);
	USED(argv);

  	initdraw(0, 0, "frame");


	// create mouse event channel and process
	mctl = initmouse(0, screen);
  	a[0].c = mctl->c;
	a[1].c = mctl->resizec;

	// create clock event channel and process
	a[2].c = chancreate(sizeof(ulong), 0);
	proccreate(clockproc, a[2].c, STACKSIZE);

	// create menuhit channel and process
	a[3].c = chancreate(sizeof(ulong), 0);
	marg.mctl = mctl;
	marg.cmd = chancreate(sizeof(ulong), 0);
	marg.res = a[3].c;
	proccreate(menuhitproc, &marg, STACKSIZE);

	pid = getpid();
	for(;;){
		fprint(2, "[%d]main->alt\n", pid);
		switch(alt(a)){
		case 0:	// mouse event
			if (mctl->buttons & 2) {
				sendul(marg.cmd, 2);
				fprint(2, "[%d]main->sendul\n", pid);
			}
			if (mctl->buttons & 4)
				threadexitsall(nil);
			fprint(2, "[%d]main->click\n", pid);
			break;
		case 1: // resize event
			fprint(2, "[%d]main->resize\n", pid);
			break;
		case 2:	// clock event
			fprint(2, "[%d]main->tic\n", pid);
			break;
		case 3: // menu event
			fprint(2, "[%d]main->menu->%d\n", pid, item);
			break;
		default:
			sysfatal("can't happen");
		}
	}
}

----------------------------------------------
Here is the log with libthread compiled with :

	_threaddebuglevel =  DBGAPPL | DBGSCHED | DBGCHAN |
		DBGREND | DBGNOTE | DBGEXEC;

----------------------------------------------
noproc create thread -1.1 name threadmain
noproc readying -1.1
2211._ top of schedinit, _threadexitsallstatus=0
2211._ running 2211.1
2211.1 chancreate 35658
2211.1 chancreate 362d8
2211.1 create thread -1.2 name <nil>
2211.1 readying -1.2
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ readying 2211.1
2211._ running 2211.1
2212._ top of schedinit, _threadexitsallstatus=0
2211.1 chancreate 37d58
2212._ running 2212.2
2211.1 create thread -1.3 name <nil>
2211.1 readying -1.3
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ readying 2211.1
2211._ running 2211.1
2213._ top of schedinit, _threadexitsallstatus=0
2211.1 chancreate 39018
2213._ running 2213.3
2211.1 chancreate 39058
2211.1 create thread -1.4 name <nil>
2211.1 readying -1.4
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ readying 2211.1
2214._ top of schedinit, _threadexitsallstatus=0
2211._ running 2211.1
2214._ running 2214.4
[2211]main->alt
2214.4 Queuing alt 3a370 on channel 39058
2214.4 Rendezvous for tag 238412
2211.1 Queuing alt 23318 on channel 35658
2214.4 pausing, state=Dead
2211.1 Queuing alt 2332c on channel 362d8
2214.4 top of schedinit, _threadexitsallstatus=0
2211.1 Queuing alt 23340 on channel 37d58
2214._ sleeping for more work
2211.1 Queuing alt 23354 on channel 39018
2211.1 Rendezvous for tag 144096
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ sleeping for more work
[2213]clock->0
2213.3 can rendez alt 38f24 chan 37d58
2213.3 rendez send alt 38f24 chan 37d58 alt 23340
2213.3 unlocking the chanlock
2213.3 chanlock is 0
2213.3 Rendezvous with thread 2211.1
2213.3 readying 2211.1
2213.3 waking process 2211
2213.3 pausing, state=Dead
2211._ running 2211.1
2213.3 top of schedinit, _threadexitsallstatus=0
2211.1 Woke after rendezvous; val is 0
2213._ readying 2213.3
2211.1 Dequeuing alt 23318 from channel 35658
2213._ running 2213.3
2211.1 Dequeuing alt 2332c from channel 362d8
[2213]clock->sendul
2211.1 Dequeuing alt 23340 from channel 37d58
2211.1 Dequeuing alt 23354 from channel 39018
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ readying 2211.1
2211._ running 2211.1
[2211]main->tic
[2211]main->alt
2211.1 Queuing alt 23318 on channel 35658
2211.1 Queuing alt 2332c on channel 362d8
2211.1 Queuing alt 23340 on channel 37d58
2211.1 Queuing alt 23354 on channel 39018
2211.1 Rendezvous for tag 144096
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ sleeping for more work
2212.2 can rendez alt 37c64 chan 35658
2212.2 rendez send alt 37c64 chan 35658 alt 23318
2212.2 unlocking the chanlock
2212.2 chanlock is 0
2212.2 Rendezvous with thread 2211.1
2212.2 readying 2211.1
2212.2 waking process 2211
2212.2 pausing, state=Dead
2211._ running 2211.1
2212.2 top of schedinit, _threadexitsallstatus=0
2211.1 Woke after rendezvous; val is 0
2212._ readying 2212.2
2211.1 Dequeuing alt 23318 from channel 35658
2212._ running 2212.2
2211.1 Dequeuing alt 2332c from channel 362d8
2211.1 Dequeuing alt 23340 from channel 37d58
2211.1 Dequeuing alt 23354 from channel 39018
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ readying 2211.1
2211._ running 2211.1
2211.1 can rendez alt 23298 chan 39058
2211.1 rendez send alt 23298 chan 39058 alt 3a370
2211.1 unlocking the chanlock
2211.1 chanlock is 0
2211.1 Rendezvous with thread 2214.4
2211.1 readying 2214.4
2211.1 waking process 2214
2211.1 pausing, state=Dead
2214._ running 2214.4
2211.1 top of schedinit, _threadexitsallstatus=0
2214.4 Woke after rendezvous; val is 0
2211._ readying 2211.1
2214.4 Dequeuing alt 3a370 from channel 39058
2211._ running 2211.1
2214.4 pausing, state=Dead
[2211]main->sendul
2214.4 top of schedinit, _threadexitsallstatus=0
[2211]main->click
2214._ readying 2214.4
[2211]main->alt
2214._ running 2214.4
2211.1 Queuing alt 23318 on channel 35658
2211.1 Queuing alt 2332c on channel 362d8
2211.1 Queuing alt 23340 on channel 37d58
2211.1 Queuing alt 23354 on channel 39018
2211.1 Rendezvous for tag 144096
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ sleeping for more work
2214.4 Queuing alt 3a26c on channel 35658
2214.4 Rendezvous for tag 238152
2212.2 can rendez alt 37c64 chan 35658
2214.4 pausing, state=Dead
2212.2 rendez send alt 37c64 chan 35658 alt 3a26c
2214.4 top of schedinit, _threadexitsallstatus=0
2212.2 unlocking the chanlock
2214._ sleeping for more work
2212.2 chanlock is 0
2212.2 Rendezvous with thread 2214.4
2212.2 readying 2214.4
2212.2 waking process 2214
2212.2 pausing, state=Dead
2214._ running 2214.4
2212.2 top of schedinit, _threadexitsallstatus=0
2214.4 Woke after rendezvous; val is 0
2212._ readying 2212.2
2214.4 Dequeuing alt 3a26c from channel 35658
2212._ running 2212.2
2214.4 pausing, state=Dead
2214.4 top of schedinit, _threadexitsallstatus=0
2214._ readying 2214.4
2214._ running 2214.4
2214.4 Queuing alt 3a26c on channel 35658
2214.4 Rendezvous for tag 238152
2214.4 pausing, state=Dead
2214.4 top of schedinit, _threadexitsallstatus=0
2214._ sleeping for more work
2212.2 can rendez alt 37c64 chan 35658
2212.2 rendez send alt 37c64 chan 35658 alt 23318
2212.2 unlocking the chanlock
2212.2 chanlock is 0
2212.2 Rendezvous with thread 2211.1
2212.2 readying 2211.1
2212.2 waking process 2211
2212.2 pausing, state=Dead
2211._ running 2211.1
2212.2 top of schedinit, _threadexitsallstatus=0
2211.1 Woke after rendezvous; val is 0
2212._ readying 2212.2
2211.1 Dequeuing alt 23318 from channel 35658
2212._ running 2212.2
2211.1 Dequeuing alt 2332c from channel 362d8
2211.1 Dequeuing alt 23340 from channel 37d58
2211.1 Dequeuing alt 23354 from channel 39018
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ readying 2211.1
2211._ running 2211.1
2211.1 Queuing alt 23298 on channel 39058
2211.1 Rendezvous for tag 143988
2211.1 pausing, state=Dead
2211.1 top of schedinit, _threadexitsallstatus=0
2211._ sleeping for more work
[2213]clock->1
2213.3 Queuing alt 38f24 on channel 37d58
2213.3 Rendezvous for tag 233216
2213.3 pausing, state=Dead
2213.3 top of schedinit, _threadexitsallstatus=0
2213._ sleeping for more work
2212.2 can rendez alt 37c64 chan 35658
2212.2 rendez send alt 37c64 chan 35658 alt 3a26c
2212.2 unlocking the chanlock
2212.2 chanlock is 0
2212.2 Rendezvous with thread 2214.4
2212.2 readying 2214.4
2212.2 waking process 2214
2212.2 pausing, state=Dead
2214._ running 2214.4
2212.2 top of schedinit, _threadexitsallstatus=0
2214.4 Woke after rendezvous; val is 0
2212._ readying 2212.2
2214.4 Dequeuing alt 3a26c from channel 35658
2212._ running 2212.2
2214.4 pausing, state=Dead
2214.4 top of schedinit, _threadexitsallstatus=0
2214._ readying 2214.4
2214._ running 2214.4
[2214]menuhit->0
2214.4 Queuing alt 3a378 on channel 39018
2214.4 Rendezvous for tag 238420
2214.4 pausing, state=Dead
2214.4 top of schedinit, _threadexitsallstatus=0
2214._ sleeping for more work
2212.2 Queuing alt 37c64 on channel 35658
2212.2 Rendezvous for tag 228416
2212.2 pausing, state=Dead
2212.2 top of schedinit, _threadexitsallstatus=0
2212._ sleeping for more work
2211._ Got note hangup
2213._ Got note hangup
2212._ Got note hangup
2214._ Got note hangup
2211._ Unhandled note hangup, proc 20998

2213._ Unhandled note hangup, proc 37d98

2212._ Unhandled note hangup, proc 36318

2214._ Unhandled note hangup, proc 39098



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9fans] libthread help ...
  2002-12-31 20:48 [9fans] libthread help Philippe Anel
@ 2003-01-01  4:35 ` Russ Cox
  2003-01-01 13:45   ` Philippe Anel
  0 siblings, 1 reply; 4+ messages in thread
From: Russ Cox @ 2003-01-01  4:35 UTC (permalink / raw)
  To: 9fans

if you run acid -l thread, it loads some
useful functions.  one such function is
"stacks()", which prints the stack for all
the threads in all the procs of the program.

if you run this on your program, you see
(i've deleted all but the relevant lines):

acid: stacks()
------
	threadmain:
	0x00022328	1		Rendezvous 		alt(tag(*148068=0) 0: send(channel(223368)))

sendul(c=0x00036888,v=0x00000002) /sys/src/libthread/channel.c:231
	called from threadmain+0x254 /tmp/a.c:106
------
	mouseproc:
	0x000366c8	2		Rendezvous 		alt(tag(*240176=0) 0: send(channel(222792)))

send(c=0x00036648,v=0x0003aab4) /sys/src/libthread/channel.c:209
	called from _ioproc+0x149 /sys/src/libdraw/mouse.c:85
------
	0x00036788	3		Rendezvous 		alt(tag(*244856=0) 0: send(channel(223048)))

sendul(c=0x00036748,v=0x00000001) /sys/src/libthread/channel.c:231
	called from clockproc+0x63 /tmp/a.c:25
------
	0x000368c8	4		Rendezvous 		alt(tag(*249380=0) 0: send(channel(223304)))

sendul(c=0x00036848,v=0x00000000) /sys/src/libthread/channel.c:231
	called from menuhitproc+0xad /tmp/a.c:57
------

the problem is that the menuhitproc and main are
both reading from the mouse.  main got a new mouse
event to send to menuhitproc, and menuhitproc is
trying to send its result to main at the same time.
perhaps you should wait for the menuhitproc to
send its result before waiting for more mouse ops.

you could change a[0].op to CHANNOP after sending
to menuhitproc and then change it back after getting
the result.

i don't see why it's a separate proc.  you might want
main not to stop processing clock ticks while you
wait for the menu event, i guess, but even then you
could do that with a thread rather than a proc.

russ



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9fans] libthread help ...
  2003-01-01  4:35 ` Russ Cox
@ 2003-01-01 13:45   ` Philippe Anel
  2003-01-01 17:00     ` Russ Cox
  0 siblings, 1 reply; 4+ messages in thread
From: Philippe Anel @ 2003-01-01 13:45 UTC (permalink / raw)
  To: 9fans

At 23:35 31/12/02 -0500, you wrote:
>if you run acid -l thread, it loads some
>useful functions.

Is there any doc about these functions/libs ?

>the problem is that the menuhitproc and main are
>both reading from the mouse.  main got a new mouse
>event to send to menuhitproc, and menuhitproc is
>trying to send its result to main at the same time.
>perhaps you should wait for the menuhitproc to
>send its result before waiting for more mouse ops.

With some 'threadsetname()' and the acid function
threads(), I saw the problem. Thanks.

>you could change a[0].op to CHANNOP after sending
>to menuhitproc and then change it back after getting
>the result.

I've just made this fix and now it works.


>i don't see why it's a separate proc.  you might want
>main not to stop processing clock ticks while you
>wait for the menu event, i guess, but even then you
>could do that with a thread rather than a proc.

I didn't realize that my thread/proc 'menuhit' could
yield the the processor waiting the mouseproc channel.
Now, it is a thread.

         Thank you,
         Philippe.

---------------------------------------------th_exmpl.c----

#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <frame.h>

enum
{
         STACKSIZE = 2048,
};

static void
clockproc(void *arg)
{
         int t;
         Channel *c;

         threadsetname("clockproc");
         c = arg;
         for(t=0;; t++){
                 sleep(1000);
                 sendul(c, t);
         }
}

struct mh {
         Mousectl *mctl;
         Channel *cmd;
         Channel *res;
};

static void
menuhitthread(void *arg)
{
         struct mh *marg;
         int     t;
         char *items[] = {
                 "exit",
                 nil
         };
         Menu menu = {
                 items,
                 nil,
                 0
         };

         threadsetname("menuhitthread");
         marg = arg;
         for (;;) {
                 t = recvul(marg->cmd);
                 t = menuhit(t, marg->mctl, &menu, nil);
                 sendul(marg->res, t);
         }
}

void
threadmain(int argc, char *argv[])
{
         int tick, item;
         Mousectl *mctl;
         Alt a[] = {
         //       c              v               op
                 {nil,   nil,    CHANRCV},                       // 0:   mouse
                 {nil,   nil,    CHANRCV},                       // 1:   resize
                 {nil,   &tick,  CHANRCV},                       // 2:   clock
                 {nil,   &item,  CHANRCV},                       // 
3:   menuhit
                 {nil,   nil,    CHANEND},
         };
         struct mh marg;

         USED(argc);
         USED(argv);

         initdraw(0, 0, "frame");

         // create mouse event channel and process
         mctl = initmouse(0, screen);
         a[0].c = mctl->c;
         a[1].c = mctl->resizec;

         // create clock event channel and process
         a[2].c = chancreate(sizeof(ulong), 0);
         proccreate(clockproc, a[2].c, STACKSIZE);

         // create menuhit channel and process
         a[3].c = chancreate(sizeof(ulong), 0);
         marg.mctl = mctl;
         marg.cmd = chancreate(sizeof(ulong), 0);
         marg.res = a[3].c;
         threadcreate(menuhitthread, &marg, STACKSIZE);

         for(;;){
                 switch(alt(a)){
                 case 0: // mouse event
                         if (mctl->buttons & 2) {
                                 a[0].op = CHANNOP;
                                 sendul(marg.cmd, 2);
                         }
                         if (mctl->buttons & 1)
                                 fprint(2, "button1 ");
                         if (mctl->buttons & 4)
                                 fprint(2, "button4 ");
                         break;
                 case 1: // resize event
                         fprint(2, "resize ");
                         break;
                 case 2: // clock event
                         fprint(2, "tic%d ", tick);
                         break;
                 case 3: // menu event
                         a[0].op = CHANRCV;
                         fprint(2, "menu%d ", item);
                         if (item == 0)
                                 threadexitsall(nil);
                         break;
                 default:
                         sysfatal("can't happen");
                 }
         }
}
---------------------------------------------------------------- 



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9fans] libthread help ...
  2003-01-01 13:45   ` Philippe Anel
@ 2003-01-01 17:00     ` Russ Cox
  0 siblings, 0 replies; 4+ messages in thread
From: Russ Cox @ 2003-01-01 17:00 UTC (permalink / raw)
  To: 9fans

> Is there any doc about these functions/libs ?

no, just look at /sys/lib/acid/thread.



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2003-01-01 17:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-12-31 20:48 [9fans] libthread help Philippe Anel
2003-01-01  4:35 ` Russ Cox
2003-01-01 13:45   ` Philippe Anel
2003-01-01 17:00     ` Russ Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).