static Npreq * _get_waiting_reqs (Npconn *conn) { Npsrv *srv = conn->srv; Npreq *req, *req1, *preqs; Nptpool *tp; /* assert: srv->lock held */ preqs = NULL; for (tp = srv->tpool; tp != NULL; tp = tp->next) { xpthread_mutex_lock (&tp->lock); req = tp->reqs_first; while (req != NULL) { req1 = req->next; if (req->conn == conn) { np_srv_remove_req(tp, req); req->next = preqs; preqs = req; } req = req1; } xpthread_mutex_unlock (&tp->lock); } return preqs; }
static void np_conn_flush (Npconn *conn) { Nptpool *tp; Npreq *creq, *nextreq; xpthread_mutex_lock(&conn->srv->lock); for (tp = conn->srv->tpool; tp != NULL; tp = tp->next) { for (creq = tp->reqs_first; creq != NULL; creq = nextreq) { nextreq = creq->next; if (creq->conn != conn) continue; np_srv_remove_req(tp, creq); np_req_unref(creq); } for (creq = tp->workreqs; creq != NULL; creq = creq->next) { if (creq->conn != conn) continue; creq->state = REQ_NOREPLY; if (conn->srv->flags & SRV_FLAGS_FLUSHSIG) pthread_kill (creq->wthread->thread, SIGUSR2); } } xpthread_mutex_unlock(&conn->srv->lock); }
static void * np_wthread_proc(void *a) { Npwthread *wt = (Npwthread *)a; Nptpool *tp = wt->tpool; Npreq *req = NULL; Npfcall *rc; xpthread_mutex_lock(&tp->lock); while (!wt->shutdown) { wt->state = WT_IDLE; req = tp->reqs_first; if (!req) { xpthread_cond_wait(&tp->reqcond, &tp->lock); continue; } np_srv_remove_req(tp, req); np_srv_add_workreq(tp, req); xpthread_mutex_unlock(&tp->lock); req->wthread = wt; wt->state = WT_WORK; rc = np_process_request(req, &tp->stats); if (rc) { wt->state = WT_REPLY; np_respond(tp, req, rc); } xpthread_mutex_lock(&tp->lock); } xpthread_mutex_unlock (&tp->lock); wt->state = WT_SHUT; return NULL; }
void np_conn_reset(Npconn *conn, u32 msize, int dotu) { int i, n; Npsrv *srv; Npreq *req, *req1, *preqs, **reqs; Npfcall *fc, *fc1; pthread_mutex_lock(&conn->lock); conn->resetting = 1; pthread_mutex_unlock(&conn->lock); pthread_mutex_lock(&conn->srv->lock); srv = conn->srv; // first flush all outstanding requests preqs = NULL; req = srv->reqs_first; while (req != NULL) { req1 = req->next; if (req->conn == conn) { np_srv_remove_req(srv, req); req->next = preqs; preqs = req; } req = req1; } // then flush all working requests n = 0; req = conn->srv->workreqs; while (req != NULL) { if (req->conn == conn && (msize==0 || req->tcall->type != Tversion)) n++; req = req->next; } reqs = malloc(n * sizeof(Npreq *)); n = 0; req = conn->srv->workreqs; while (req != NULL) { if (req->conn == conn && (msize==0 || req->tcall->type != Tversion)) reqs[n++] = np_req_ref(req); req = req->next; } pthread_mutex_unlock(&conn->srv->lock); req = preqs; while (req != NULL) { req1 = req->next; np_conn_respond(req); np_req_unref(req); req = req1; } for(i = 0; i < n; i++) { req = reqs[i]; if (req->conn->srv->flush) (*req->conn->srv->flush)(req); } /* wait until all working requests finish */ /* pthread_mutex_lock(&conn->lock); while (1) { for(i = 0; i < n; i++) if (!reqs[i]->responded) break; if (i >= n) break; pthread_cond_wait(&conn->resetcond, &conn->lock); } */ pthread_mutex_lock(&srv->lock); while (1) { for(req = srv->workreqs; req != NULL; req = req->next) if (req->conn == conn && (msize==0 || req->tcall->type != Tversion)) break; if (req == NULL) break; while(conn->resetting) pthread_cond_wait(&conn->resetcond, &srv->lock); } pthread_mutex_unlock(&srv->lock); /* free old pool of fcalls */ fc = conn->freerclist; conn->freerclist = NULL; while (fc != NULL) { fc1 = fc->next; free(fc); fc = fc1; } if (conn->fidpool) { np_fidpool_destroy(conn->fidpool); conn->fidpool = NULL; } if (msize) { conn->dotu = dotu; conn->resetting = 0; conn->fidpool = np_fidpool_create(); pthread_cond_broadcast(&conn->resetdonecond); } conn->resetting = 0; pthread_mutex_unlock(&conn->lock); /* free the working requests */ for(i = 0; i < n; i++) np_req_unref(reqs[i]); free(reqs); }
Npfcall* np_flush(Npreq *req, Npfcall *tc) { u16 oldtag = tc->u.tflush.oldtag; Npreq *creq = NULL; Npconn *conn = req->conn; Npfcall *ret = NULL; Nptpool *tp; xpthread_mutex_lock(&conn->srv->lock); // check pending requests for (tp = conn->srv->tpool; tp != NULL; tp = tp->next) { xpthread_mutex_lock(&tp->lock); for(creq = tp->reqs_first; creq != NULL; creq = creq->next) { if (creq->conn==conn && creq->tag==oldtag) { np_srv_remove_req(tp, creq); xpthread_mutex_lock(&creq->lock); np_conn_respond(creq); /* doesn't send anything */ xpthread_mutex_unlock(&creq->lock); np_req_unref(creq); ret = np_create_rflush(); creq = NULL; xpthread_mutex_unlock(&tp->lock); goto done; } } xpthread_mutex_unlock(&tp->lock); } // check working requests for (tp = conn->srv->tpool; tp != NULL; tp = tp->next) { xpthread_mutex_lock(&tp->lock); creq = tp->workreqs; while (creq != NULL) { if (creq->conn==conn && creq->tag==oldtag) { np_req_ref(creq); xpthread_mutex_lock(&creq->lock); req->flushreq = creq->flushreq; creq->flushreq = req; xpthread_mutex_unlock(&creq->lock); xpthread_mutex_unlock(&tp->lock); goto done; } creq = creq->next; } xpthread_mutex_unlock(&tp->lock); } // if not found, return P9_RFLUSH if (!creq) ret = np_create_rflush(); done: xpthread_mutex_unlock(&conn->srv->lock); // if working request found, try to flush it if (creq && req->conn->srv->flush) { (*req->conn->srv->flush)(creq); np_req_unref(creq); } return ret; }