void kernel() { unsigned int then, now, delta; PUT32(0x40000054, INT_IRQ); // mboxes 1..3 *do* interrupt, via IRQ PUT32(0x40000058, INT_IRQ); PUT32(0x4000005C, INT_IRQ); flash_lonum(3); then = now_usec(); while (1) { now = now_usec(); delta = usec_diff( now, then ); //if (delta > ONE_MSEC) { if ( delta > (ONE_SEC) ) { //if (delta > ((7 * ONE_SEC) + (500 * ONE_MSEC))) { then = now; // flash_lonum(3); // oldwait(20); interrupt_core(1); // clear_interrupt(1); // while (1) continue; } } }
//归还数据库连接 void release_SC_connect(T_Connect **Connect,int TCBno,int n) { int i,num; pthread_t tid=pthread_self(); pool *pl; resource *rs; T_CLI_Var *clip; //ShowLog(5,"%s:TCB:%d,poolno=%d",__FUNCTION__,TCBno,n); if(!Connect || !scpool || n<0 || n>=SCPOOLNUM) { ShowLog(1,"%s:TCB:%d,poolno=%d,错误的参数",__FUNCTION__,TCBno,n); return; } if(!*Connect) { ShowLog(1,"%s:TCB:%d,Conn is Empty!",__FUNCTION__,TCBno); return; } clip=(T_CLI_Var *)((*Connect)->Var); pl=&scpool[n]; rs=pl->lnk; if(!rs) { ShowLog(1,"%s:无效的连接池[%d]",__FUNCTION__,n); return; } num=pl->resource_num; for(i=0;i<num;i++,rs++) if(TCBno==rs->TCBno) { if(0!=pthread_mutex_lock(&pl->mut)) { ShowLog(1,"%s:pool[%d].%d,TCB:%d,mutex error=%d,%s", __FUNCTION__,n,i,TCBno,errno,strerror(errno)); return; } if(*Connect != &rs->Conn) { ShowLog(1,"%s:TCB:%d,Connect not equal!",__FUNCTION__,TCBno); } if(clip != &rs->cli) { ShowLog(1,"%s:TCB:%d,clip not equal!",__FUNCTION__,TCBno); } if(rs->cli.Errno==-1) { //连接失效 ShowLog(1,"%s:scpool[%d].%d fail!",__FUNCTION__,n,i); disconnect(&rs->Conn); } rs->TCBno=-1; pthread_mutex_unlock(&pl->mut); pthread_cond_signal(&pl->cond); //如果有等待连接的线程就唤醒它 rs->timestamp=now_usec(); clip->Errno=0; *clip->ErrMsg=0; *Connect=NULL; if(log_level) ShowLog(log_level,"%s tid=%lu,TCB:%d,pool[%d].lnk[%d]",__FUNCTION__, tid,TCBno,n,i); return; } ShowLog(1,"%s:在pool[%d]中未发现该TCBno:%d",__FUNCTION__,n,TCBno); clip->Errno=0; *clip->ErrMsg=0; *Connect=NULL; }
//取连接 T_Connect * get_SC_connect(int TCBno,int n,int flg) { int i,num; pool *pl; resource *rs; pthread_t tid=pthread_self(); if(!scpool || n<0 || n>=SCPOOLNUM) return NULL; pl=&scpool[n]; if(!pl->lnk) { ShowLog(1,"%s:无效的连接池[%d]",__FUNCTION__,n); return NULL; } num=pl->resource_num; if(0!=pthread_mutex_lock(&pl->mut)) return NULL; while(1) { rs=pl->lnk; for(i=0;i<num;i++,rs++) if(rs->TCBno<0) { if(rs->Conn.Socket<0 || rs->cli.Errno<0) { switch(sc_connect(pl,rs)) { case -1: case -2: case -3: ShowLog(1,"%s:scpool[%d].%d 连接%s/%s错:err=%d,%s", __FUNCTION__,n,i,pl->log.HOST,pl->log.PORT, rs->cli.Errno, rs->cli.ErrMsg); pthread_mutex_unlock(&pl->mut); return (T_Connect *)-1; case 0: break; default: rs->cli.Errno=-1; ShowLog(1,"%s:scpool[%d].%d 连接%s/%s错:err=%d,%s", __FUNCTION__,n,i,pl->log.HOST,pl->log.PORT, rs->cli.Errno, rs->cli.ErrMsg); continue; } } rs->TCBno=TCBno; rs->timestamp=now_usec(); pthread_mutex_unlock(&pl->mut); if(log_level) ShowLog(log_level,"%s tid=%lu,TCB:%d,pool[%d].lnk[%d]",__FUNCTION__, tid,TCBno,n,i); rs->cli.Errno=0; *rs->cli.ErrMsg=0; return &rs->Conn; } if(flg) { //flg !=0,don't wait pthread_mutex_unlock(&pl->mut); return NULL; } if(log_level) ShowLog(log_level,"%s tid=%lu pool[%d] suspend",__FUNCTION__,pthread_self(),n); pthread_cond_wait(&pl->cond,&pl->mut); //没有资源,等待 if(log_level) ShowLog(log_level,"%s tid=%lu pool[%d] weakup",__FUNCTION__,pthread_self(),n); } }
int scpool_MGR(int TCBno,int poolno,T_Connect **connp,int (*call_back)(T_Connect *,T_NetHead *)) { int ret; pthread_t *tp; if(TCBno<0) { ShowLog(1,"%s:bad TCB no!",__FUNCTION__); return -1; } ShowLog(3,"%s:get pool[%d],TCB_no=%d,tid:%lX,USEC=%llu",__FUNCTION__, poolno,TCBno,pthread_self(),now_usec()); *connp=get_SC_connect(poolno,0); if(*connp == (T_Connect *)-1) { *connp=NULL; return -1; } if(*connp) { if((*connp)->only_do == (sdbcfunc)1) { (*connp)->only_do=call_back; TCB_add(NULL,TCBno); //加入到主任务队列 //ShowLog(5,"%s:tid=%lX,only_do=1,TCB_no=%d",__FUNCTION__,pthread_self(),TCBno); return 1; } return 0; } set_callback(TCBno,call_back,120); if(wpool.poolnum<=0) { ret=get_scpoolnum(); pthread_mutex_lock(&wpool.mut); wpool_init(&wpool,ret); pthread_mutex_unlock(&wpool.mut); } if(poolno < 0 || poolno >= wpool.poolnum) { ShowLog(1,"%s:TCB_no=%d bad poolno %d,poolnum=%d",__FUNCTION__, TCBno,poolno,wpool.poolnum); return -1; } pthread_mutex_lock(&wpool.QP[poolno].mut); TCB_add(&wpool.QP[poolno].queue,TCBno); tp=&wpool.QP[poolno].tid; if(*tp==0) *tp=TCBno+1; pthread_mutex_unlock(&wpool.QP[poolno].mut); //new thread if(*tp==(pthread_t)(TCBno+1)) { pthread_create(&wpool.QP[poolno].tid,&wpool.attr,wait_sc,(void *)(long)poolno); } else pthread_cond_signal(&wpool.QP[poolno].cond); //唤醒工作线程 return 1; }
//连接池监控 void scpool_check() { int n,i,num; pool *pl; resource *rs; INT64 now; char buf[32]; T_Connect *conn=NULL; if(!scpool) return; now=now_usec(); pl=scpool; for(n=0;n<SCPOOLNUM;n++,pl++) { if(!pl->lnk) continue; rs=pl->lnk; num=pl->resource_num; if(log_level) ShowLog(log_level,"%s:scpool[%d],num=%d",__FUNCTION__,n,num); pthread_mutex_lock(&pl->mut); for(i=0;i<num;i++,rs++) if(rs->TCBno<0) { if(rs->Conn.Socket>-1 && (now-rs->timestamp)>299000000) { //空闲时间太长了 disconnect(&rs->Conn); rs->cli.Errno=-1; if(log_level) ShowLog(log_level,"%s:Close SCpool[%d].lnk[%d],since %s",__FUNCTION__, n,i,rusecstrfmt(buf,rs->timestamp,YEAR_TO_USEC)); } } else { if(rs->Conn.Socket>-1 && (now-rs->timestamp)>299000000) { //占用时间太长了 if(-1==get_TCB_status(rs->TCBno)) { //TCB已经结束,释放之 if(log_level) ShowLog(log_level,"%s:scpool[%d].lnk[%d] TCB:%d to be release", __FUNCTION__,n,i,rs->TCBno); rs->cli.Errno=-1; conn=&rs->Conn; release_SC_connect(&conn,rs->TCBno,n); } else { if(log_level) ShowLog(log_level,"%s:scpool[%d].lnk[%d] used by TCB:%d,since %s", __FUNCTION__,n,i,rs->TCBno, rusecstrfmt(buf,rs->timestamp,YEAR_TO_USEC)); } } } pthread_mutex_unlock(&pl->mut); } }
static const struct timespec *sleep_till(utime_t wake_up) { static struct timespec buf; utime_t now_u; now_u = now_usec(); if (wake_up == 0) wake_up = now_u + MAX_SLEEP * TIME_RES; if (now_u >= wake_up) { buf.tv_sec = 0; buf.tv_nsec = 0; return &buf; } if ((wake_up - now_u) > (MAX_SLEEP * TIME_RES)) wake_up = now_u + MAX_SLEEP * TIME_RES; buf.tv_sec = wake_up / TIME_RES; buf.tv_nsec = (wake_up % TIME_RES) * 1000; return &buf; }
static SCM sched_thread(void *data) { SCHED_EVENT *event; utime_t next_wake; utime_t now, early, late; time_t tnow; scheduling = 1; next_wake = 0; pthread_mutex_lock(&qmutex); while (scheduling) { pthread_cond_timedwait(&qcondvar, &qmutex, sleep_till(next_wake)); now = now_usec(); late = now - DISPATCH_WINDOW / 2; early = now + DISPATCH_WINDOW / 2; event = queue; while (event != NULL) { if (event->clock < late) { log_msg("would drop %1.3f < %1.3f\n", event->clock / (double)TIME_RES, late / (double)TIME_RES); // queue = event->link; // release_node(event); // event = queue; // continue; } if (event->clock > early) break; queue = event->link; if (event->state == STATE_PENDING) { scm_spawn_thread(dispatch_event, (void *)&(event->action), NULL, NULL); } release_node(event); event = queue; } queue = sweep_cancellations(queue); if (queue != NULL) next_wake = queue->clock; else next_wake = 0; if (((tnow = time(NULL)) - gc_hit) > GC_HIT_INTERVAL) { gc_hit = tnow; scm_gc(); } } pthread_mutex_unlock(&qmutex); return SCM_BOOL_T; }
job allocate_job(int body_size) { job j; j = malloc(sizeof(struct job) + body_size); if (!j) return twarnx("OOM"), (job) 0; j->id = 0; j->state = JOB_STATE_INVALID; j->created_at = now_usec(); j->reserve_ct = j->timeout_ct = j->release_ct = j->bury_ct = j->kick_ct = 0; j->body_size = body_size; j->next = j->prev = j; /* not in a linked list */ j->ht_next = NULL; j->tube = NULL; j->binlog = NULL; j->heap_index = 0; j->reserved_binlog_space = 0; return j; }
static void sched_at_c(utime_t usec, SCM action, SCM tag) { SCHED_EVENT *event; SCHED_EVENT *node, *prev; if (usec < now_usec()) { // can't schedule in the past return; } event = grab_node(); event->clock = usec; event->state = STATE_PENDING; if (tag == SCM_UNDEFINED) event->tag = NULL; else event->tag = scm_to_locale_string(tag); scm_gc_protect_object(event->action = action); pthread_mutex_lock(&qmutex); node = queue; prev = NULL; while (node != NULL) { if (node->clock >= event->clock) { event->link = node; if (prev == NULL) queue = event; else prev->link = event; break; } prev = node; node = node->link; } if (event->link == NULL) { if (prev == NULL) queue = event; else prev->link = event; } pthread_mutex_unlock(&qmutex); if (pthread_mutex_trylock(&qmutex) == 0) { pthread_cond_signal(&qcondvar); pthread_mutex_unlock(&qmutex); } return; }
//客户端用,与服务器协商并取得密钥 int get_clikey(T_Connect *conn) { int i,kw,a2,b1; u_int x[4],ax[4],ay[4],m[4]; int crymode=0; INT64 tim; char keybuf[52],cmd[256]; ENIGMA2 t; unsigned short crc; tim=now_usec(); x[0]=(0XFFFFFFF&((int)tim )); x[1]=0XFFFFFFFF & (tim>>32); x[2]=getpid(); x[3]=0X7FFFFFFF&conn->family[31&x[0]]; a2=(x[3]^(tim>>31))&0X1F; b1=(x[3]^(tim>>36))&0X1F; kw=conn->family[b1]; n_zero(4,ax); i=conn->family[a2]; if(!i) i=65537; ax[0]=i; ax[1]=kw; m[1]=m[2]=m[3]=0XFFFFFFFF; m[0]=0xFFFFFF61; _e_m_(4,ax,x,m,ay); n2byte(4,ay,keybuf); keybuf[16]=a2&255; keybuf[17]=b1&255; byte_a64(cmd,keybuf,18); crc=gencrc((unsigned char *)cmd,24); *(short *)(cmd+24)=htons(crc); i=SendNet(conn->Socket,cmd,26,0); if(i!=26) { ShowLog(1,"%s:SenNet(%d) i=%d,err=%d,%s",__FUNCTION__,conn->Socket,i,errno,strerror(errno)); } i=RecvNet(conn->Socket,cmd,68,120); if(i!=68) { ShowLog(1,"%s:read(%d) len=%d,Error=%d,%s!",__FUNCTION__, conn->Socket,i,errno,strerror(errno)); return SYSERR; } cmd[68]=0; i=a64_byte(keybuf,cmd); if(i!=50) { ShowLog(1,"%s:%s len=%d can not get ind!\n", __FUNCTION__,cmd,i); return LENGERR; } crymode=keybuf[49]; if(crymode & DO_CRYPT) { byte2n(4,ay,keybuf); _e_m_(4,ay,x,m,ax); prikey128(cmd,ax,conn->family); enigma2_init(&t,cmd,0); enigma2_decrypt(&t,keybuf+16,32); /* char errbuf[72]; strhex(8,(u_int *)(keybuf+16),errbuf); ShowLog(5,"%s:key=%s,len=%d",__FUNCTION__,errbuf,strlen(keybuf+16)); */ enigma2_init(&conn->t,keybuf+16,32); } conn->CryptFlg=crymode; return crymode; }
static SCM sched_in(SCM sec, SCM action, SCM tag) { sched_at_c((utime_t)(scm_to_double(sec) * TIME_RES + 0.5) + now_usec(), action, tag); return SCM_UNSPECIFIED; }
inline usec_t now_boottime_usec(void) { return now_usec(CLOCK_BOOTTIME); }
inline usec_t now_monotonic_usec(void) { return now_usec(CLOCK_MONOTONIC); }
inline usec_t now_realtime_usec(void) { return now_usec(CLOCK_REALTIME); }
//初始化连接池 int scpool_init() { int n,i,ret; char *p,buf[512]; INT64 now; FILE *fd; JSON_OBJECT cfg,json; SCPOOL_stu node; if(scpool) return 0; p=getenv("SCPOOLCFG"); if(!p||!*p) { ShowLog(1,"%s:缺少环境变量SCPOOLCFG!",__FUNCTION__); return -1; } fd=fopen((const char *)p,"r"); if(!fd) { ShowLog(1,"%s:CFGFILE %s open err=%d,%s",__FUNCTION__, p,errno,strerror(errno)); return -2; } cfg=json_object_new_array(); while(!ferror(fd)) { fgets(buf,sizeof(buf),fd); if(feof(fd)) break; TRIM(buf); if(!*buf || *buf=='#') continue; ret=net_dispack(&node,buf,SCPOOL_tpl); if(ret<=0) continue; json=json_object_new_object(); struct_to_json(json,&node,SCPOOL_tpl,0); json_object_array_add(cfg,json); } fclose(fd); SCPOOLNUM=json_object_array_length(cfg); if(SCPOOLNUM <=0 ) { json_object_put(cfg); ShowLog(1,"%s:empty SCPOOL",__FUNCTION__); return -3; } scpool=(pool *)malloc(SCPOOLNUM * sizeof(pool)); if(!scpool) { json_object_put(cfg); SCPOOLNUM=0; return MEMERR; } p=getenv("SCPOOL_LOGLEVEL"); if(p && isdigit(*p)) log_level=atoi(p); now=now_usec(); for(n=0;n<SCPOOLNUM;n++) { if(0!=(i=pthread_mutex_init(&scpool[n].mut,NULL))) { ShowLog(1,"%s:mutex_init err %s",__FUNCTION__, strerror(i)); json_object_put(cfg); return -12; } if(0!=(i=pthread_cond_init(&scpool[n].cond,NULL))) { ShowLog(1,"%s:cond init err %s",__FUNCTION__, strerror(i)); json_object_put(cfg); return -13; } json=json_object_array_get_idx(cfg,n); json_to_struct(&scpool[n].log,json,SCPOOL_tpl); scpool[n].d_node=scpool[n].log.d_node; scpool[n].resource_num=scpool[n].log.NUM>0?scpool[n].log.NUM:1; scpool[n].lnk=(resource *)malloc(scpool[n].resource_num * sizeof(resource)); if(!scpool[n].lnk) { ShowLog(1,"%s:malloc lnk error!",__FUNCTION__); scpool[n].resource_num=0; continue; } scpool[n].free_q=scpool[n].resource_num-1; for(i=0;i<scpool[n].resource_num;i++) { int j; pthread_mutex_init(&scpool[n].lnk[i].mut,NULL); Init_CLI_Var(&scpool[n].lnk[i].cli); scpool[n].lnk[i].cli.Errno=-1; initconnect(&scpool[n].lnk[i].Conn); strcpy(scpool[n].lnk[i].Conn.Host,scpool[n].log.HOST); strcpy(scpool[n].lnk[i].Conn.Service,scpool[n].log.PORT); scpool[n].lnk[i].Conn.timeout=-1; if(*scpool[n].log.family) str_a64n(32,scpool[n].log.family,scpool[n].family); scpool[n].lnk[i].tcb_num=0; if(i<scpool[n].resource_num-1) scpool[n].lnk[i].next=i+1; else scpool[n].lnk[i].next=0; for(j=0;j<TCBNUM;j++) { scpool[n].lnk[i].TCB_q[j]=-1; } scpool[n].lnk[i].timestamp=now; } ShowLog(2,"scpool[%d],link num=%d",n,scpool[n].resource_num); } json_object_put(cfg); return SCPOOLNUM; }
//归还数据库连接 void release_SC_connect(T_Connect **Connect,int TCBno,int n) { int i,j,flg,num; pthread_t tid=pthread_self(); pool *pl; resource *rs; T_CLI_Var *clip; //ShowLog(5,"%s:TCB:%d,poolno=%d",__FUNCTION__,TCBno,n); if(!Connect || !scpool || n<0 || n>=SCPOOLNUM) { ShowLog(1,"%s:TCB:%d,poolno=%d,错误的参数",__FUNCTION__,TCBno,n); return; } if(!*Connect) { ShowLog(1,"%s:TCB:%d,Conn is Empty!",__FUNCTION__,TCBno); return; } clip=(T_CLI_Var *)((*Connect)->Var); pl=&scpool[n]; rs=pl->lnk; if(!rs) { ShowLog(1,"%s:无效的连接池[%d]",__FUNCTION__,n); return; } num=pl->resource_num; for(i=0;i<num;i++,rs++) if(*Connect == &rs->Conn) { if(0!=pthread_mutex_lock(&pl->mut)) { ShowLog(1,"%s:pool[%d].%d,TCB:%d,mutex error=%d,%s", __FUNCTION__,n,i,TCBno,errno,strerror(errno)); return; } if(clip != &rs->cli) { ShowLog(1,"%s:TCB:%d,clip not equal!",__FUNCTION__,TCBno); } flg=0; if(rs->cli.Errno==-1) { //连接失效 ShowLog(1,"%s:scpool[%d].%d fail!",__FUNCTION__,n,i); disconnect(&rs->Conn); for(j=0;j<TCBNUM;j++) { if(rs->TCB_q[j] >= 0 && rs->TCB_q[j]!=TCB_no) { //释放所有使用这个连接的任务 unbind_sc(rs->TCB_q[j]); TCB_add(NULL,rs->tcb_q[j]); } rs->TCB_q[j]=-1; } flg=1; } add_lnk(pl,i); if(!flg) { for(j=0;j<TCBNUM;j++) { if(rs->TCB_q[j] == TCBno){ flg=1; } if(flg) { if(j<TCBNUM-1) rs->TCB_q[j]=rs->TCB_q[j+1]; else rs->TCB_q[j]=-1; } } if(flg) rs->tcb_num--; } else rs->tcb_num=0; pthread_mutex_unlock(&pl->mut); pthread_cond_signal(&pl->cond); //如果有等待连接的线程就唤醒它 rs->timestamp=now_usec(); clip->Errno=0; *clip->ErrMsg=0; *Connect=NULL; if(log_level) ShowLog(log_level,"%s tid=%lu,TCB:%d,pool[%d].lnk[%d]",__FUNCTION__, tid,TCBno,n,i); return; } ShowLog(1,"%s:在pool[%d]中未发现该TCBno:%d",__FUNCTION__,n,TCBno); clip->Errno=0; *clip->ErrMsg=0; *Connect=NULL; }