/* Precreate an objhead and object for later use */ static void hsh_prealloc(struct worker *wrk) { struct objhead *oh; struct waitinglist *wl; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); if (wrk->nobjcore == NULL) wrk->nobjcore = HSH_NewObjCore(wrk); CHECK_OBJ_NOTNULL(wrk->nobjcore, OBJCORE_MAGIC); if (wrk->nobjhead == NULL) { ALLOC_OBJ(oh, OBJHEAD_MAGIC); XXXAN(oh); oh->refcnt = 1; VTAILQ_INIT(&oh->objcs); Lck_New(&oh->mtx, lck_objhdr); wrk->nobjhead = oh; wrk->stats.n_objecthead++; } CHECK_OBJ_NOTNULL(wrk->nobjhead, OBJHEAD_MAGIC); if (wrk->nwaitinglist == NULL) { ALLOC_OBJ(wl, WAITINGLIST_MAGIC); XXXAN(wl); VTAILQ_INIT(&wl->list); wrk->nwaitinglist = wl; wrk->stats.n_waitinglist++; } CHECK_OBJ_NOTNULL(wrk->nwaitinglist, WAITINGLIST_MAGIC); if (hash->prep != NULL) hash->prep(wrk); }
static struct pool * pool_mkpool(unsigned pool_no) { struct pool *pp; ALLOC_OBJ(pp, POOL_MAGIC); if (pp == NULL) return (NULL); pp->a_stat = calloc(1, sizeof *pp->a_stat); AN(pp->a_stat); pp->b_stat = calloc(1, sizeof *pp->b_stat); AN(pp->b_stat); Lck_New(&pp->mtx, lck_wq); VTAILQ_INIT(&pp->idle_queue); VTAILQ_INIT(&pp->front_queue); VTAILQ_INIT(&pp->back_queue); AZ(pthread_cond_init(&pp->herder_cond, NULL)); AZ(pthread_create(&pp->herder_thr, NULL, pool_herder, pp)); while (VTAILQ_EMPTY(&pp->idle_queue)) (void)usleep(10000); pp->sesspool = SES_NewPool(pp, pool_no); AN(pp->sesspool); return (pp); }
static struct objhead * hsh_newobjhead(void) { struct objhead *oh; ALLOC_OBJ(oh, OBJHEAD_MAGIC); XXXAN(oh); oh->refcnt = 1; VTAILQ_INIT(&oh->objcs); VTAILQ_INIT(&oh->waitinglist); Lck_New(&oh->mtx, lck_objhdr); return (oh); }
static struct vxp * vxp_New(struct vsb *sb) { struct vxp *vxp; AN(sb); ALLOC_OBJ(vxp, VXP_MAGIC); AN(vxp); VTAILQ_INIT(&vxp->membits); VTAILQ_INIT(&vxp->tokens); vxp->sb = sb; return (vxp); }
/* Precreate an objhead and object for later use */ static void hsh_prealloc(struct worker *wrk) { struct waitinglist *wl; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); if (wrk->nobjcore == NULL) wrk->nobjcore = hsh_NewObjCore(wrk); CHECK_OBJ_NOTNULL(wrk->nobjcore, OBJCORE_MAGIC); if (wrk->nobjhead == NULL) { wrk->nobjhead = hsh_newobjhead(); wrk->stats->n_objecthead++; } CHECK_OBJ_NOTNULL(wrk->nobjhead, OBJHEAD_MAGIC); if (wrk->nwaitinglist == NULL) { ALLOC_OBJ(wl, WAITINGLIST_MAGIC); XXXAN(wl); VTAILQ_INIT(&wl->list); wrk->nwaitinglist = wl; wrk->stats->n_waitinglist++; } CHECK_OBJ_NOTNULL(wrk->nwaitinglist, WAITINGLIST_MAGIC); if (hash->prep != NULL) hash->prep(wrk); }
static void * vwe_init(void) { int i; struct vwe *vwe; ALLOC_OBJ(vwe, VWE_MAGIC); AN(vwe); VTAILQ_INIT(&vwe->sesshead); AZ(pipe(vwe->pipes)); AZ(pipe(vwe->timer_pipes)); i = fcntl(vwe->pipes[0], F_GETFL); assert(i != -1); i |= O_NONBLOCK; i = fcntl(vwe->pipes[0], F_SETFL, i); assert(i != -1); i = fcntl(vwe->timer_pipes[0], F_GETFL); assert(i != -1); i |= O_NONBLOCK; i = fcntl(vwe->timer_pipes[0], F_SETFL, i); assert(i != -1); AZ(pthread_create(&vwe->timer_thread, NULL, vwe_sess_timeout_ticker, vwe)); AZ(pthread_create(&vwe->epoll_thread, NULL, vwe_thread, vwe)); return(vwe); }
struct VSL_data * VSL_New(void) { struct VSL_data *vsl; ALLOC_OBJ(vsl, VSL_MAGIC); if (vsl == NULL) return (NULL); vsl->vbm_select = vbit_init(256); vsl->vbm_supress = vbit_init(256); VTAILQ_INIT(&vsl->vslf_select); VTAILQ_INIT(&vsl->vslf_suppress); return (vsl); }
struct VSL_data * VSL_New(void) { struct VSL_data *vsl; ALLOC_OBJ(vsl, VSL_MAGIC); if (vsl == NULL) return (NULL); vsl->L_opt = 1000; vsl->T_opt = 120.; vsl->vbm_select = vbit_new(SLT__MAX); vsl->vbm_supress = vbit_new(SLT__MAX); VTAILQ_INIT(&vsl->vslf_select); VTAILQ_INIT(&vsl->vslf_suppress); return (vsl); }
/* Precreate an objhead and object for later use */ void HSH_Prealloc(const struct sess *sp) { struct worker *wrk; struct objhead *oh; struct objcore *oc; struct waitinglist *wl; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); wrk = sp->wrk; if (wrk->nobjcore == NULL) { ALLOC_OBJ(oc, OBJCORE_MAGIC); XXXAN(oc); wrk->nobjcore = oc; wrk->stats.n_objectcore++; oc->flags |= OC_F_BUSY; } CHECK_OBJ_NOTNULL(wrk->nobjcore, OBJCORE_MAGIC); if (wrk->nobjhead == NULL) { ALLOC_OBJ(oh, OBJHEAD_MAGIC); XXXAN(oh); oh->refcnt = 1; VTAILQ_INIT(&oh->objcs); Lck_New(&oh->mtx, lck_objhdr); wrk->nobjhead = oh; wrk->stats.n_objecthead++; } CHECK_OBJ_NOTNULL(wrk->nobjhead, OBJHEAD_MAGIC); if (wrk->nwaitinglist == NULL) { ALLOC_OBJ(wl, WAITINGLIST_MAGIC); XXXAN(wl); VTAILQ_INIT(&wl->list); wrk->nwaitinglist = wl; wrk->stats.n_waitinglist++; } CHECK_OBJ_NOTNULL(wrk->nwaitinglist, WAITINGLIST_MAGIC); if (hash->prep != NULL) hash->prep(sp); }
static void * vws_init(void) { struct vws *vws; ALLOC_OBJ(vws, VWS_MAGIC); AN(vws); VTAILQ_INIT(&vws->sesshead); AZ(pthread_create(&vws->ports_thread, NULL, vws_thread, vws)); return (vws); }
struct sesspool * SES_NewPool(struct pool *pp) { struct sesspool *sp; ALLOC_OBJ(sp, SESSPOOL_MAGIC); AN(sp); sp->pool = pp; VTAILQ_INIT(&sp->freelist); Lck_New(&sp->mtx, lck_sessmem); return (sp); }
struct mempool * MPL_New(const char *name, volatile struct poolparam *pp, volatile unsigned *cur_size) { struct mempool *mpl; ALLOC_OBJ(mpl, MEMPOOL_MAGIC); AN(mpl); bprintf(mpl->name, "%s", name); mpl->param = pp; mpl->cur_size = cur_size; VTAILQ_INIT(&mpl->list); VTAILQ_INIT(&mpl->surplus); Lck_New(&mpl->mtx, lck_mempool); /* XXX: prealloc min_pool */ mpl->vsc = VSM_Alloc(sizeof *mpl->vsc, VSC_CLASS, VSC_type_mempool, mpl->name); AN(mpl->vsc); AZ(pthread_create(&mpl->thread, NULL, mpl_guard, mpl)); AZ(pthread_detach(mpl->thread)); return (mpl); }
void COT_init(struct callout_block *cb) { struct tms tms; int i; bzero(cb, sizeof(struct callout_block)); cb->ncallout = 16; /* FIXME: with proper value */ cot_callwhell_alloc(cb); cb->ticks = cb->softticks = times(&tms); for (i = 0; i < cb->callwheelsize; i++) { VTAILQ_INIT(&cb->callwheel[i]); } }
struct sesspool * SES_NewPool(struct pool *wp, unsigned pool_no) { struct sesspool *pp; char nb[8]; ALLOC_OBJ(pp, SESSPOOL_MAGIC); AN(pp); pp->pool = wp; VTAILQ_INIT(&pp->freelist); Lck_New(&pp->mtx, lck_sessmem); bprintf(nb, "req%u", pool_no); pp->req_size = sizeof (struct req); pp->mpl_req = MPL_New(nb, &cache_param->req_pool, &pp->req_size); return (pp); }
static void * vwk_init(void) { struct vwk *vwk; ALLOC_OBJ(vwk, VWK_MAGIC); AN(vwk); VTAILQ_INIT(&vwk->sesshead); AZ(pipe(vwk->pipes)); AZ(VFIL_nonblocking(vwk->pipes[0])); AZ(VFIL_nonblocking(vwk->pipes[1])); AZ(pthread_create(&vwk->thread, NULL, vwk_thread, vwk)); return (vwk); }
static double ban_lurker_work(struct worker *wrk, struct vsl_log *vsl) { struct ban *b, *bd; struct banhead_s obans; double d, dt, n; dt = 49.62; // Random, non-magic if (cache_param->ban_lurker_sleep == 0) return (dt); Lck_Lock(&ban_mtx); b = ban_start; Lck_Unlock(&ban_mtx); d = VTIM_real() - cache_param->ban_lurker_age; bd = NULL; VTAILQ_INIT(&obans); for (; b != NULL; b = VTAILQ_NEXT(b, list)) { if (bd != NULL) ban_lurker_test_ban(wrk, vsl, b, &obans, bd); if (b->flags & BANS_FLAG_COMPLETED) continue; if (b->flags & BANS_FLAG_REQ) { bd = VTAILQ_NEXT(b, list); continue; } n = ban_time(b->spec) - d; if (n < 0) { VTAILQ_INSERT_TAIL(&obans, b, l_list); if (bd == NULL) bd = b; } else if (n < dt) { dt = n; } } Lck_Lock(&ban_mtx); VTAILQ_FOREACH(b, &obans, l_list) ban_mark_completed(b); Lck_Unlock(&ban_mtx); return (dt); }
static void * vwe_init(void) { struct vwe *vwe; ALLOC_OBJ(vwe, VWE_MAGIC); AN(vwe); VTAILQ_INIT(&vwe->sesshead); AZ(pipe(vwe->pipes)); AZ(pipe(vwe->timer_pipes)); AZ(VFIL_nonblocking(vwe->pipes[0])); AZ(VFIL_nonblocking(vwe->pipes[1])); AZ(VFIL_nonblocking(vwe->timer_pipes[0])); AZ(pthread_create(&vwe->timer_thread, NULL, vwe_timeout_idle_ticker, vwe)); AZ(pthread_create(&vwe->epoll_thread, NULL, vwe_thread, vwe)); return(vwe); }
static void * vwk_init(void) { int i; struct vwk *vwk; ALLOC_OBJ(vwk, VWK_MAGIC); AN(vwk); VTAILQ_INIT(&vwk->sesshead); AZ(pipe(vwk->pipes)); i = fcntl(vwk->pipes[0], F_GETFL); assert(i != -1); i |= O_NONBLOCK; i = fcntl(vwk->pipes[0], F_SETFL, i); assert(i != -1); AZ(pthread_create(&vwk->thread, NULL, vwk_thread, vwk)); return (vwk); }
struct waiter * Waiter_New(void) { struct waiter *w; AN(waiter); AN(waiter->name); AN(waiter->init); AN(waiter->enter); AN(waiter->fini); w = calloc(1, sizeof (struct waiter) + waiter->size); AN(w); INIT_OBJ(w, WAITER_MAGIC); w->priv = (void*)(w + 1); w->impl = waiter; VTAILQ_INIT(&w->waithead); w->heap = binheap_new(w, waited_cmp, waited_update); waiter->init(w); return (w); }
struct req * SES_GetReq(struct worker *wrk, struct sess *sp) { struct sesspool *pp; struct req *req; uint16_t nhttp; unsigned sz, hl; char *p, *e; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); pp = sp->sesspool; CHECK_OBJ_NOTNULL(pp, SESSPOOL_MAGIC); AN(pp->pool); req = MPL_Get(pp->mpl_req, &sz); AN(req); req->magic = REQ_MAGIC; req->sp = sp; e = (char*)req + sz; p = (char*)(req + 1); p = (void*)PRNDUP(p); assert(p < e); nhttp = (uint16_t)cache_param->http_max_hdr; hl = HTTP_estimate(nhttp); req->http = HTTP_create(p, nhttp); p += hl; p = (void*)PRNDUP(p); assert(p < e); req->http0 = HTTP_create(p, nhttp); p += hl; p = (void*)PRNDUP(p); assert(p < e); req->resp = HTTP_create(p, nhttp); p += hl; p = (void*)PRNDUP(p); assert(p < e); sz = cache_param->vsl_buffer; VSL_Setup(req->vsl, p, sz); req->vsl->wid = VXID_Get(&wrk->vxid_pool) | VSL_CLIENTMARKER; VSLb(req->vsl, SLT_Begin, "req %u", sp->vxid & VSL_IDENTMASK); VSL(SLT_Link, req->sp->vxid, "req %u", req->vsl->wid & VSL_IDENTMASK); p += sz; p = (void*)PRNDUP(p); assert(p < e); WS_Init(req->ws, "req", p, e - p); req->t_req = NAN; req->t_resp = NAN; VTAILQ_INIT(&req->body); return (req); }
vmod_event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e ev) { struct vmod_disco *vd; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); switch(ev) { case VCL_EVENT_LOAD: AZ(pthread_mutex_lock(&global_mtx)); if (global_load_count == 0) { ALLOC_OBJ(vd, VMOD_DISCO_MAGIC); AN(vd); priv->len = sizeof(*vd); priv->free = free_func; VTAILQ_INIT(&vd->dirs); update_rwlock_new(&vd->mtx); AN(vd->mtx); default_mod = vd; } else { vd = priv->priv; CHECK_OBJ_ORNULL(vd, VMOD_DISCO_MAGIC); if (!vd) { struct vmod_disco *dvd = default_mod ? default_mod : warmed_mod; if (dvd) { update_rwlock_wrlock(dvd->mtx); } ALLOC_OBJ(vd, VMOD_DISCO_MAGIC); AN(vd); priv->len = sizeof(*vd); priv->free = free_func; VTAILQ_INIT(&vd->dirs); update_rwlock_new(&vd->mtx); AN(vd->mtx); default_mod = vd; if (dvd) { update_rwlock_unlock(dvd->mtx, NULL); } } } CHECK_OBJ_NOTNULL(vd, VMOD_DISCO_MAGIC); priv->priv = vd; global_load_count++; AZ(pthread_mutex_unlock(&global_mtx)); break; case VCL_EVENT_DISCARD: AZ(pthread_mutex_lock(&global_mtx)); AN(global_load_count); global_load_count--; AZ(pthread_mutex_unlock(&global_mtx)); break; case VCL_EVENT_WARM: AZ(pthread_mutex_lock(&global_mtx)); vd = priv->priv; CHECK_OBJ_NOTNULL(vd, VMOD_DISCO_MAGIC); AZ(vd->wrk); update_rwlock_wrlock(vd->mtx); if (default_mod == NULL && warmed_mod != NULL) default_mod = warmed_mod; warmed_mod = vd; vmod_disco_bgthread_start(&vd->wrk, vd, 10); update_rwlock_unlock(vd->mtx, NULL); AZ(pthread_mutex_unlock(&global_mtx)); break; case VCL_EVENT_COLD: AZ(pthread_mutex_lock(&global_mtx)); CAST_OBJ_NOTNULL(vd, priv->priv, VMOD_DISCO_MAGIC); CHECK_OBJ_NOTNULL(vd->wrk, VMOD_DISCO_BGTHREAD_MAGIC); vmod_disco_bgthread_delete(&vd->wrk); AZ(vd->wrk); if (vd == default_mod && warmed_mod != NULL) default_mod = warmed_mod; AZ(pthread_mutex_unlock(&global_mtx)); break; case VCL_EVENT_USE: AZ(pthread_mutex_lock(&global_mtx)); CAST_OBJ_NOTNULL(vd, priv->priv, VMOD_DISCO_MAGIC); if (vd != default_mod) default_mod = vd; AZ(pthread_mutex_unlock(&global_mtx)); default: break; } return 0; }
void smp_mgt_init(struct stevedore *parent, int ac, char * const *av) { struct smp_sc *sc; struct smp_sign sgn; void *target; int i; ASSERT_MGT(); AZ(av[ac]); /* Necessary alignment. See also smp_object::__filler__ */ assert(sizeof(struct smp_object) % 8 == 0); #define SIZOF(foo) fprintf(stderr, \ "sizeof(%s) = %zu = 0x%zx\n", #foo, sizeof(foo), sizeof(foo)); SIZOF(struct smp_ident); SIZOF(struct smp_sign); SIZOF(struct smp_segptr); SIZOF(struct smp_object); #undef SIZOF /* See comments in storage_persistent.h */ assert(sizeof(struct smp_ident) == SMP_IDENT_SIZE); /* Allocate softc */ ALLOC_OBJ(sc, SMP_SC_MAGIC); XXXAN(sc); sc->parent = parent; sc->fd = -1; VTAILQ_INIT(&sc->segments); /* Argument processing */ if (ac != 2) ARGV_ERR("(-spersistent) wrong number of arguments\n"); i = STV_GetFile(av[0], &sc->fd, &sc->filename, "-spersistent"); if (i == 2) ARGV_ERR("(-spersistent) need filename (not directory)\n"); sc->align = sizeof(void*) * 2; sc->granularity = getpagesize(); sc->mediasize = STV_FileSize(sc->fd, av[1], &sc->granularity, "-spersistent"); AZ(ftruncate(sc->fd, sc->mediasize)); /* Try to determine correct mmap address */ i = read(sc->fd, &sgn, sizeof sgn); assert(i == sizeof sgn); if (!strcmp(sgn.ident, "SILO")) target = (void*)(uintptr_t)sgn.mapped; else target = NULL; sc->base = (void*)mmap(target, sc->mediasize, PROT_READ|PROT_WRITE, MAP_NOCORE | MAP_NOSYNC | MAP_SHARED, sc->fd, 0); if (sc->base == MAP_FAILED) ARGV_ERR("(-spersistent) failed to mmap (%s)\n", strerror(errno)); smp_def_sign(sc, &sc->idn, 0, "SILO"); sc->ident = SIGN_DATA(&sc->idn); i = smp_valid_silo(sc); if (i) { printf("Warning SILO (%s) not reloaded (reason=%d)\n", sc->filename, i); smp_newsilo(sc); } AZ(smp_valid_silo(sc)); smp_metrics(sc); parent->priv = sc; /* XXX: only for sendfile I guess... */ mgt_child_inherit(sc->fd, "storage_persistent"); }
const char * BAN_Commit(struct ban_proto *bp) { struct ban *b, *bi; ssize_t ln; double t0; CHECK_OBJ_NOTNULL(bp, BAN_PROTO_MAGIC); AN(bp->vsb); if (ban_shutdown) return (ban_error(bp, "Shutting down")); AZ(VSB_finish(bp->vsb)); ln = VSB_len(bp->vsb); assert(ln >= 0); ALLOC_OBJ(b, BAN_MAGIC); if (b == NULL) return (ban_error(bp, ban_build_err_no_mem)); VTAILQ_INIT(&b->objcore); b->spec = malloc(ln + BANS_HEAD_LEN); if (b->spec == NULL) { free(b); return (ban_error(bp, ban_build_err_no_mem)); } b->flags = bp->flags; memset(b->spec, 0, BANS_HEAD_LEN); t0 = VTIM_real(); memcpy(b->spec + BANS_TIMESTAMP, &t0, sizeof t0); b->spec[BANS_FLAGS] = b->flags & 0xff; memcpy(b->spec + BANS_HEAD_LEN, VSB_data(bp->vsb), ln); ln += BANS_HEAD_LEN; vbe32enc(b->spec + BANS_LENGTH, ln); Lck_Lock(&ban_mtx); if (ban_shutdown) { /* We could have raced a shutdown */ Lck_Unlock(&ban_mtx); BAN_Free(b); return (ban_error(bp, "Shutting down")); } bi = VTAILQ_FIRST(&ban_head); VTAILQ_INSERT_HEAD(&ban_head, b, list); ban_start = b; VSC_C_main->bans++; VSC_C_main->bans_added++; VSC_C_main->bans_persisted_bytes += ln; if (b->flags & BANS_FLAG_OBJ) VSC_C_main->bans_obj++; if (b->flags & BANS_FLAG_REQ) VSC_C_main->bans_req++; if (bi != NULL) ban_info_new(b->spec, ln); /* Notify stevedores */ if (cache_param->ban_dups) { /* Hunt down duplicates, and mark them as completed */ for (bi = VTAILQ_NEXT(b, list); bi != NULL; bi = VTAILQ_NEXT(bi, list)) { if (!(bi->flags & BANS_FLAG_COMPLETED) && ban_equal(b->spec, bi->spec)) { ban_mark_completed(bi); VSC_C_main->bans_dups++; } } } if (!(b->flags & BANS_FLAG_REQ)) ban_kick_lurker(); Lck_Unlock(&ban_mtx); BAN_Abandon(bp); return (NULL); }
struct req * Req_New(const struct worker *wrk, struct sess *sp) { struct pool *pp; struct req *req; uint16_t nhttp; unsigned sz, hl; char *p, *e; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); pp = sp->pool; CHECK_OBJ_NOTNULL(pp, POOL_MAGIC); req = MPL_Get(pp->mpl_req, &sz); AN(req); req->magic = REQ_MAGIC; req->sp = sp; e = (char*)req + sz; p = (char*)(req + 1); p = (void*)PRNDUP(p); assert(p < e); nhttp = (uint16_t)cache_param->http_max_hdr; hl = HTTP_estimate(nhttp); req->http = HTTP_create(p, nhttp, hl); p += hl; p = (void*)PRNDUP(p); assert(p < e); req->http0 = HTTP_create(p, nhttp, hl); p += hl; p = (void*)PRNDUP(p); assert(p < e); req->resp = HTTP_create(p, nhttp, hl); p += hl; p = (void*)PRNDUP(p); assert(p < e); sz = cache_param->vsl_buffer; VSL_Setup(req->vsl, p, sz); p += sz; p = (void*)PRNDUP(p); req->vfc = (void*)p; INIT_OBJ(req->vfc, VFP_CTX_MAGIC); p = (void*)PRNDUP(p + sizeof(*req->vfc)); req->htc = (void*)p; p = (void*)PRNDUP(p + sizeof(*req->htc)); req->vdc = (void*)p; INIT_OBJ(req->vdc, VDP_CTX_MAGIC); VTAILQ_INIT(&req->vdc->vdp); p = (void*)PRNDUP(p + sizeof(*req->vdc)); req->htc = (void*)p; INIT_OBJ(req->htc, HTTP_CONN_MAGIC); p = (void*)PRNDUP(p + sizeof(*req->htc)); assert(p < e); WS_Init(req->ws, "req", p, e - p); req->t_first = NAN; req->t_prev = NAN; req->t_req = NAN; req->topreq = req; return (req); }