@@ -346,6 +346,7 @@ struct exp_deref {
346346#define EXP_DEREF_MAGIC 0xb5854b59
347347 unsigned n ;
348348 struct exp_inbox_head remove_head ;
349+ struct exp_inbox_head expire_head ;
349350};
350351
351352/* take lists from src to dsk */
@@ -361,6 +362,8 @@ exp_deref_take(struct exp_deref *dst, struct exp_deref *src)
361362 src -> n = 0 ;
362363 VSTAILQ_INIT (& dst -> remove_head );
363364 VSTAILQ_SWAP (& dst -> remove_head , & src -> remove_head , objcore );
365+ VSTAILQ_INIT (& dst -> expire_head );
366+ VSTAILQ_SWAP (& dst -> expire_head , & src -> expire_head , objcore );
364367}
365368
366369static void
@@ -376,11 +379,17 @@ exp_deref_work(struct worker *wrk, struct exp_deref *deref, vtim_real now)
376379 if (n % 1024 == 0 )
377380 Pool_Sumstat (wrk );
378381 }
382+ VSTAILQ_FOREACH_SAFE (oc , & deref -> expire_head , exp_list , save ) {
383+ exp_expire_oc (wrk , wrk -> vsl , oc , now );
384+ n ++ ;
385+ if (n % 1024 == 0 )
386+ Pool_Sumstat (wrk );
387+ }
379388 assert (deref -> n == n );
380389 memset (deref , 0 , sizeof * deref );
381390}
382391
383- // trivial function to wrap n increment.
392+ // trivial functions to wrap n increment.
384393static void
385394exp_deref_add_remove (struct exp_deref * deref , struct objcore * oc )
386395{
@@ -390,12 +399,22 @@ exp_deref_add_remove(struct exp_deref *deref, struct objcore *oc)
390399 deref -> n ++ ;
391400}
392401
402+ static void
403+ exp_deref_add_expire (struct exp_deref * deref , struct objcore * oc )
404+ {
405+
406+ CHECK_OBJ_NOTNULL (deref , EXP_DEREF_MAGIC );
407+ VSTAILQ_INSERT_TAIL (& deref -> expire_head , oc , exp_list );
408+ deref -> n ++ ;
409+ }
410+
393411static void
394412exp_deref_init (struct exp_deref * deref )
395413{
396414
397415 INIT_OBJ (deref , EXP_DEREF_MAGIC );
398416 VSTAILQ_INIT (& deref -> remove_head );
417+ VSTAILQ_INIT (& deref -> expire_head );
399418}
400419
401420/*--------------------------------------------------------------------
@@ -495,43 +514,50 @@ exp_inbox(struct exp_priv *ep, struct objcore *oc, unsigned flags)
495514 */
496515
497516static vtim_real
498- exp_expire (struct exp_priv * ep , vtim_real now )
517+ exp_expire (struct exp_priv * ep , struct exp_deref * deref , vtim_real now )
499518{
500519 struct objcore * oc ;
520+ vtim_real ret ;
501521
502522 CHECK_OBJ_NOTNULL (ep , EXP_PRIV_MAGIC );
503523
504- oc = VBH_root (ep -> heap );
505- if (oc == NULL )
506- return (now + 355. / 113. );
507- VSLb (& ep -> vsl , SLT_ExpKill , "EXP_Inspect p=%p e=%.6f f=0x%x" , oc ,
508- oc -> timer_when - now , oc -> flags );
524+ Lck_Lock (& ep -> mtx );
525+ while (1 ) {
526+ oc = VBH_root (ep -> heap );
527+ if (oc == NULL ) {
528+ ret = now + 355. / 113. ;
529+ break ;
530+ }
531+ VSLb (& ep -> vsl , SLT_ExpKill , "EXP_Inspect p=%p e=%.6f f=0x%x" ,
532+ oc , oc -> timer_when - now , oc -> flags );
509533
510- CHECK_OBJ_NOTNULL (oc , OBJCORE_MAGIC );
534+ CHECK_OBJ_NOTNULL (oc , OBJCORE_MAGIC );
511535
512- /* Ready ? */
513- if (oc -> timer_when > now )
514- return (oc -> timer_when );
536+ /* Ready ? */
537+ if (oc -> timer_when > now ) {
538+ ret = oc -> timer_when ;
539+ break ;
540+ }
515541
516- VSC_C_main -> n_expired ++ ;
542+ VSC_C_main -> n_expired ++ ;
517543
518- Lck_Lock (& ep -> mtx );
519- if (oc -> exp_flags & OC_EF_POSTED ) {
520- oc -> exp_flags |= OC_EF_REMOVE ;
521- oc = NULL ;
522- } else {
523- oc -> exp_flags &= ~OC_EF_REFD ;
524- }
525- Lck_Unlock (& ep -> mtx );
526- if (oc != NULL ) {
544+ if (oc -> exp_flags & OC_EF_POSTED ) {
545+ VSTAILQ_REMOVE (& ep -> inbox , oc , objcore , exp_list );
546+ oc -> exp_flags = 0 ;
547+ }
548+ else
549+ oc -> exp_flags &= ~OC_EF_REFD ;
527550
551+ exp_deref_add_expire (deref , oc );
528552 /* Remove from binheap */
529553 assert (oc -> timer_idx != VBH_NOIDX );
530554 VBH_delete (ep -> heap , oc -> timer_idx );
531555
532- exp_expire_oc ( ep -> wrk , & ep -> vsl , oc , now );
556+ assert ( oc -> timer_idx == VBH_NOIDX );
533557 }
534- return (0 );
558+ Lck_Unlock (& ep -> mtx );
559+
560+ return (ret );
535561}
536562
537563/*--------------------------------------------------------------------
@@ -625,6 +651,7 @@ exp_thread(struct worker *wrk, void *priv)
625651 VSC_C_main -> exp_received ++ ;
626652 tnext = 0 ;
627653 flags = oc -> exp_flags ;
654+ assert (flags & OC_EF_POSTED );
628655 if (flags & OC_EF_REMOVE ) {
629656 oc -> exp_flags = 0 ;
630657 exp_deref_add_remove (& deref , oc );
@@ -657,7 +684,7 @@ exp_thread(struct worker *wrk, void *priv)
657684 }
658685
659686 t = VTIM_real ();
660- tnext = exp_expire (ep , t );
687+ tnext = exp_expire (ep , & deref , t );
661688
662689 if (deref .n == 0 )
663690 continue ;
@@ -669,6 +696,7 @@ exp_thread(struct worker *wrk, void *priv)
669696 continue ;
670697 }
671698
699+ /* call exp_deref_work() in a task */
672700 Lck_Lock (& ep -> mtx );
673701 while ((task = VTAILQ_FIRST (& ep -> free_tasks )) == NULL ) {
674702 VSL_Flush (& ep -> vsl , 0 );
0 commit comments