On Mon, 20 Jun 2022, adr wrote:
But I have something in mind for a case like
this, when all the processes are going to use the same handler
(that's why I was asking). Let me play with it a litle before I
share it.
Ok, the idea is this: If in is bigger than zero in
threadnotify(int (*f)(void*, char*), int in), the handler is register
for the calling process. If in is 0, then the handler is cleared
for the calling process. If in is -1, the handler is register for
all processes and if in is less than -1, it is cleared for all
processes (expect for those who have already registered it for themselves).
Now back to your example, as all the processes are going to use the same
handler,
you just have to register it once in threadmain:
#include <u.h>
#include <libc.h>
#include <thread.h>
static int
handler_alarm(void *, char *msg)
{
if(strstr(msg, "alarm"))
return 1;
return 0;
}
static void
proc_udp(void *)
{
char resp[512];
char req[] = "request";
int fd;
if((fd = dial("udp!185.157.221.201!5678", nil, nil, nil)) >= 0){
if(write(fd, req, strlen(req)) == strlen(req)){
fprint(1, "start\n");
alarm(2000);
read(fd, resp, sizeof(resp));
alarm(0);
fprint(1, "end\n");
}
close(fd);
}
threadexits(nil);
}
int mainstacksize = 5242880;
void
threadmain(int argc, char *argv[])
{
threadnotify(handler_alarm, -1);
for(int i = 0; i < 80; i++)
proccreate(proc_udp, nil, 10240);
sleep(5000);
threadexitsall(nil);
}
Now,
; ./5.out | grep end | wc -l
80
Are you happy Andrej?
adr.
/sys/src/libthread/sched.c:
[...]
if(t == nil){
_threaddebug(DBGSCHED, "all threads gone; exiting");
cancelnotes(p->pid);
_schedexit(p);
}
[...]
/sys/src/libthread/note.c
[...]
int
threadnotify(int (*f)(void*, char*), int in)
{
int i, frompid, topid;
int (*from)(void*, char*), (*to)(void*, char*);
if(in && in>-2){
from = nil;
frompid = 0;
to = f;
topid = (in == -1)? -1 : _threadgetproc()->pid;
lock(&onnotelock);
for(i=0; i<NFN; i++)
if(onnote[i]==to && onnotepid[i]==topid){
unlock(&onnotelock);
return i<NFN;
}
unlock(&onnotelock);
}else{
from = f;
frompid = (in < -1)? -1 : _threadgetproc()->pid;
to = nil;
topid = 0;
}
lock(&onnotelock);
for(i=0; i<NFN; i++)
if(onnote[i]==from && onnotepid[i]==frompid){
onnote[i] = to;
onnotepid[i] = topid;
break;
}
unlock(&onnotelock);
return i<NFN;
}
void
cancelnotes(int pid)
{
int i;
lock(&onnotelock);
for(i=0; i<NFN; i++)
if(onnotepid[i] == pid){
onnote[i] = nil;
onnotepid[i] = 0;
}
unlock(&onnotelock);
return;
}
static void
delayednotes(Proc *p, void *v)
{
int i;
Note *n;
int (*fn)(void*, char*);
if(!p->pending)
return;
p->pending = 0;
for(n=notes; n<enotes; n++){
if(n->proc == p){
for(i=0; i<NFN; i++){
if((onnotepid[i]!=p->pid && onnotepid[i]!=-1) ||
(fn = onnote[i])==nil)
continue;
if((*fn)(v, n->s))
break;
[...]
/sys/include/thread.h
[...]
void cancelnotes(int pid);
[...]
------------------------------------------
9fans: 9fans
Permalink:
https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-Meda7cacd5cce9cc74c1ddaf8
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription