Threaded version 0.7

This commit is contained in:
2026-10-06 23:50:02 -06:00
parent fe5dcbe715
commit 490c9bdc5b
21 changed files with 891 additions and 1010 deletions
+22 -10
View File
@@ -14,8 +14,8 @@
#endif
typedef struct { int fd;uint8_t rx[260],tx[260];size_t received,needed,sent,length;uint64_t deadline; } as_peer;
typedef struct {
int used,enabled,listener,running,error,os_error;uint32_t generation,received,replied,exceptions,retry;
uint32_t ip;uint16_t port,base[4],count[4],values[4][AS_ITEMS];uint64_t retry_at;
int used,enabled,suspended,listener,running,error,os_error;uint32_t generation,received,replied,exceptions,retry;
uint32_t ip;uint16_t port,base[4],count[4],values[4][AS_ITEMS];uint64_t retry_at,heartbeat; uint8_t dirty[4][AS_ITEMS];
as_peer peers[AS_PEERS];
} as_server;
static as_server as_slots[AS_POOL];
@@ -46,13 +46,13 @@ static void as_reply(as_server *s,as_peer *p){
table=f==5?0:2;
if(p->needed!=12 || (f==5 && q!=0 && q!=0xff00)){exception=3;break;}
if(!as_range(s,table,address,1)){exception=2;break;}
s->values[table][address-s->base[table]]=f==5?(q!=0):q;memcpy(p->tx+8,p->rx+8,4);n=12;break;
s->values[table][address-s->base[table]]=f==5?(q!=0):q;s->dirty[table][address-s->base[table]]=1;memcpy(p->tx+8,p->rx+8,4);n=12;break;
case 15:case 16:
table=f==15?0:2;
if(!q || q>(f==15?1968:123) || p->needed<13 || p->rx[12]!=(f==15?(q+7u)/8u:2u*q) || p->needed!=(size_t)(13+p->rx[12])){exception=3;break;}
if(!as_range(s,table,address,q)){exception=2;break;}
index=address-s->base[table];
for(unsigned i=0;i<q;i++)s->values[table][index+i]=f==15?(uint16_t)((p->rx[13+i/8]>>(i%8))&1):as_get16(p->rx+13+2*i);
for(unsigned i=0;i<q;i++){s->values[table][index+i]=f==15?(uint16_t)((p->rx[13+i/8]>>(i%8))&1):as_get16(p->rx+13+2*i);s->dirty[table][index+i]=1;}
memcpy(p->tx+8,p->rx+8,4);n=12;break;
default:exception=1;break;
}
@@ -103,7 +103,7 @@ uint32_t as_call(uint32_t cmd,uint32_t h,uint32_t ip,uint16_t port,uint8_t table
memset(out,0,24*sizeof(*out));if(!port || !retry)return AM_ARGUMENT;
for(i=0;i<AS_POOL;i++)if(!as_slots[i].used && as_slots[i].generation<0xffffffu)break;
if(i==AS_POOL)return 257;
s=&as_slots[i];uint32_t generation=s->generation+1;memset(s,0,sizeof(*s));s->generation=generation;s->used=1;s->listener=-1;s->ip=ip;s->port=port;s->retry=retry;
s=&as_slots[i];uint32_t generation=s->generation+1;memset(s,0,sizeof(*s));s->generation=generation;s->used=1;s->listener=-1;s->ip=ip;s->port=port;s->retry=retry;s->heartbeat=now;
for(unsigned j=0;j<AS_PEERS;j++){s->peers[j].fd=-1;as_peer_close(&s->peers[j]);}
h=(generation<<8)|(i+65u);as_snapshot(s,h,out);return 0;
}
@@ -112,20 +112,32 @@ uint32_t as_call(uint32_t cmd,uint32_t h,uint32_t ip,uint16_t port,uint8_t table
s=&as_slots[i-1];
switch(cmd){
case AS_CLOSE:as_stop(s);s->used=0;as_snapshot(s,0,out);return 0;
case AS_ENABLE:s->enabled=1;break;
case AS_DISABLE:s->enabled=0;as_stop(s);break;
case AS_TICK:as_tick(s,now);break;
case AS_ENABLE:s->enabled=1;s->suspended=0;s->heartbeat=now;break;
case AS_DISABLE:s->suspended=0;s->enabled=0;as_stop(s);break;
case AS_TICK:s->heartbeat=now;if(s->suspended){s->suspended=0;s->enabled=1;s->retry_at=now;}break;
case AS_PUSH:case AS_PULL:
if(table>3 || !q || q>AS_ITEMS || (uint32_t)addr+q>65536u)result=AM_ARGUMENT;
else if(!data || cap<q)result=258;
else if(cmd==AS_PUSH){
if(table<2){for(unsigned j=0;j<q;j++)if(data[j]>1){result=AM_ARGUMENT;break;}}
if(!result){s->base[table]=addr;s->count[table]=q;memcpy(s->values[table],data,q*sizeof(*data));}
if(!result){
if(s->count[table] && (s->base[table]!=addr || s->count[table]!=q)) { result=AM_ARGUMENT;break; }
s->base[table]=addr;s->count[table]=q;
for(unsigned j=0;j<q;j++)if(!s->dirty[table][j])s->values[table][j]=data[j];
}
}else if(s->base[table]!=addr || s->count[table]!=q)result=AM_ARGUMENT;
else memcpy(data,s->values[table],q*sizeof(*data));
else {memcpy(data,s->values[table],q*sizeof(*data));memset(s->dirty[table],0,q);}
break;
default:result=259;break;
}
as_snapshot(s,h,out);return result;
}
void as_shutdown(void){for(unsigned i=0;i<AS_POOL;i++)if(as_slots[i].used){as_stop(&as_slots[i]);as_slots[i].used=0;}}
void as_pump(uint64_t now,uint32_t watchdog_ms){
for(unsigned i=0;i<AS_POOL;i++)if(as_slots[i].used){
as_server *s=&as_slots[i];
if(s->enabled && now-s->heartbeat>=watchdog_ms){as_stop(s);s->enabled=0;s->suspended=1;}
as_tick(s,now);
}
}