@@ -639,23 +639,23 @@ static void unasync_await_conn(void *data1, void *data2)
639
639
}
640
640
641
641
static enum lwan_connection_coro_yield
642
- resume_async (const struct lwan * l ,
643
- enum lwan_connection_coro_yield yield_result ,
644
- int await_fd ,
645
- struct lwan_connection * conn ,
646
- int epoll_fd )
642
+ prepare_await (const struct lwan * l ,
643
+ enum lwan_connection_coro_yield yield_result ,
644
+ int await_fd ,
645
+ struct lwan_connection * conn ,
646
+ int epoll_fd )
647
647
{
648
648
static const enum lwan_connection_flags to_connection_flags [] = {
649
- [CONN_CORO_ASYNC_AWAIT_READ ] = CONN_EVENTS_READ ,
650
- [CONN_CORO_ASYNC_AWAIT_WRITE ] = CONN_EVENTS_WRITE ,
651
- [CONN_CORO_ASYNC_AWAIT_READ_WRITE ] = CONN_EVENTS_READ_WRITE ,
649
+ [CONN_CORO_WANT_READ ] = CONN_EVENTS_READ ,
650
+ [CONN_CORO_WANT_WRITE ] = CONN_EVENTS_WRITE ,
651
+ [CONN_CORO_WANT_READ_WRITE ] = CONN_EVENTS_READ_WRITE ,
652
652
};
653
653
enum lwan_connection_flags flags ;
654
654
int op ;
655
655
656
656
assert (await_fd >= 0 );
657
- assert (yield_result >= CONN_CORO_ASYNC_AWAIT_READ &&
658
- yield_result <= CONN_CORO_ASYNC_AWAIT_READ_WRITE );
657
+ assert (yield_result >= CONN_CORO_WANT_READ &&
658
+ yield_result <= CONN_CORO_WANT_READ_WRITE );
659
659
660
660
flags = to_connection_flags [yield_result ];
661
661
@@ -700,160 +700,181 @@ resume_async(const struct lwan *l,
700
700
return CONN_CORO_ABORT ;
701
701
}
702
702
703
- struct flag_update {
704
- unsigned int num_awaiting ;
705
- enum lwan_connection_coro_yield request_conn_yield ;
706
- };
707
-
708
- static void reset_conn_async_awaitv_flag (struct lwan_connection * conns ,
709
- va_list ap_orig )
703
+ static void clear_awaitv_flags (struct lwan_connection * conns , va_list ap_orig )
710
704
{
711
705
va_list ap ;
712
706
713
707
va_copy (ap , ap_orig );
714
-
715
- while (true) {
716
- int await_fd = va_arg (ap , int );
717
- if (await_fd < 0 ) {
718
- va_end (ap );
719
- break ;
720
- }
721
-
722
- conns [await_fd ].flags &= ~CONN_ASYNC_AWAITV ;
723
-
708
+ for (int fd = va_arg (ap , int ); fd >= 0 ; fd = va_arg (ap , int )) {
709
+ conns [fd ].flags &= ~CONN_ASYNC_AWAITV ;
724
710
LWAN_NO_DISCARD (va_arg (ap , enum lwan_connection_coro_yield ));
725
711
}
712
+ va_end (ap );
726
713
}
727
714
728
- static struct flag_update
729
- update_flags_for_async_awaitv (struct lwan_request * r , struct lwan * l , va_list ap )
715
+ struct awaitv_state {
716
+ unsigned int num_awaiting ;
717
+ enum lwan_connection_coro_yield request_conn_yield ;
718
+ };
719
+
720
+ static int prepare_awaitv (struct lwan_request * r ,
721
+ struct lwan * l ,
722
+ va_list ap ,
723
+ struct awaitv_state * state )
730
724
{
731
725
int epoll_fd = r -> conn -> thread -> epoll_fd ;
732
- struct flag_update update = {.num_awaiting = 0 ,
733
- .request_conn_yield = CONN_CORO_YIELD };
734
726
735
- reset_conn_async_awaitv_flag (l -> conns , ap );
727
+ * state = (struct awaitv_state ){
728
+ .num_awaiting = 0 ,
729
+ .request_conn_yield = CONN_CORO_YIELD ,
730
+ };
736
731
737
- while (true) {
738
- int await_fd = va_arg (ap , int );
739
- if (await_fd < 0 ) {
740
- return update ;
741
- }
732
+ clear_awaitv_flags (l -> conns , ap );
742
733
734
+ for (int await_fd = va_arg (ap , int ); await_fd >= 0 ;
735
+ await_fd = va_arg (ap , int )) {
736
+ struct lwan_connection * conn = & l -> conns [await_fd ];
743
737
enum lwan_connection_coro_yield events =
744
738
va_arg (ap , enum lwan_connection_coro_yield );
745
- if (UNLIKELY (events < CONN_CORO_ASYNC_AWAIT_READ ||
746
- events > CONN_CORO_ASYNC_AWAIT_READ_WRITE )) {
747
- lwan_status_error ("awaitv() called with invalid events" );
748
- coro_yield (r -> conn -> coro , CONN_CORO_ABORT );
749
- __builtin_unreachable ();
750
- }
751
-
752
- struct lwan_connection * conn = & l -> conns [await_fd ];
753
739
740
+ if (UNLIKELY (events < CONN_CORO_WANT_READ ||
741
+ events > CONN_CORO_WANT_READ_WRITE )) {
742
+ return - EINVAL ;
743
+ }
754
744
if (UNLIKELY (conn -> flags & CONN_ASYNC_AWAITV )) {
755
745
lwan_status_debug ("ignoring second awaitv call on same fd: %d" ,
756
746
await_fd );
757
747
continue ;
758
748
}
759
749
760
750
conn -> flags |= CONN_ASYNC_AWAITV ;
761
- update . num_awaiting ++ ;
751
+ state -> num_awaiting ++ ;
762
752
763
753
if (await_fd == r -> fd ) {
764
- static const enum lwan_connection_coro_yield to_request_yield [] = {
765
- [CONN_CORO_ASYNC_AWAIT_READ ] = CONN_CORO_WANT_READ ,
766
- [CONN_CORO_ASYNC_AWAIT_WRITE ] = CONN_CORO_WANT_WRITE ,
767
- [CONN_CORO_ASYNC_AWAIT_READ_WRITE ] = CONN_CORO_WANT_READ_WRITE ,
768
- };
769
-
770
- update .request_conn_yield = to_request_yield [events ];
754
+ state -> request_conn_yield = events ;
771
755
continue ;
772
756
}
773
-
774
- events = resume_async (l , events , await_fd , r -> conn , epoll_fd );
775
- if (UNLIKELY (events == CONN_CORO_ABORT )) {
757
+ if (UNLIKELY (prepare_await (l , events , await_fd , r -> conn , epoll_fd ) ==
758
+ CONN_CORO_ABORT )) {
776
759
lwan_status_error ("could not register fd for async operation" );
777
- coro_yield (r -> conn -> coro , CONN_CORO_ABORT );
778
- __builtin_unreachable ();
760
+ return - EIO ;
779
761
}
780
762
}
763
+
764
+ return 0 ;
781
765
}
782
766
783
767
int lwan_request_awaitv_any (struct lwan_request * r , ...)
784
768
{
785
769
struct lwan * l = r -> conn -> thread -> lwan ;
770
+ struct awaitv_state state ;
786
771
va_list ap ;
787
772
788
773
va_start (ap , r );
789
- struct flag_update update = update_flags_for_async_awaitv (r , l , ap );
774
+ int ret = prepare_awaitv (r , l , ap , & state );
790
775
va_end (ap );
791
776
777
+ if (UNLIKELY (ret < 0 )) {
778
+ errno = - ret ;
779
+ lwan_status_critical_perror ("prepare_awaitv()" );
780
+ coro_yield (r -> conn -> coro , CONN_CORO_ABORT );
781
+ __builtin_unreachable ();
782
+ }
783
+
792
784
while (true) {
793
- int64_t v = coro_yield (r -> conn -> coro , update .request_conn_yield );
785
+ int64_t v = coro_yield (r -> conn -> coro , state .request_conn_yield );
794
786
struct lwan_connection * conn = (struct lwan_connection * )(uintptr_t )v ;
795
787
796
- if (conn -> flags & CONN_ASYNC_AWAITV )
797
- return lwan_connection_get_fd (l , conn );
788
+ if (conn -> flags & CONN_ASYNC_AWAITV ) {
789
+ /* Ensure flags are unset in case awaitv_any() is called with
790
+ * a different set of file descriptors. */
791
+ va_start (ap , r );
792
+ clear_awaitv_flags (l -> conns , ap );
793
+ va_end (ap );
794
+
795
+ int fd = lwan_connection_get_fd (l , conn );
796
+ return UNLIKELY (conn -> flags & CONN_HUNG_UP ) ? - fd : fd ;
797
+ }
798
798
}
799
799
}
800
800
801
- void lwan_request_awaitv_all (struct lwan_request * r , ...)
801
+ int lwan_request_awaitv_all (struct lwan_request * r , ...)
802
802
{
803
803
struct lwan * l = r -> conn -> thread -> lwan ;
804
+ struct awaitv_state state ;
804
805
va_list ap ;
805
806
806
807
va_start (ap , r );
807
- struct flag_update update = update_flags_for_async_awaitv (r , l , ap );
808
+ int ret = prepare_awaitv (r , l , ap , & state );
808
809
va_end (ap );
809
810
810
- while (update .num_awaiting ) {
811
- int64_t v = coro_yield (r -> conn -> coro , update .request_conn_yield );
811
+ if (UNLIKELY (ret < 0 )) {
812
+ errno = - ret ;
813
+ lwan_status_critical_perror ("prepare_awaitv()" );
814
+ coro_yield (r -> conn -> coro , CONN_CORO_ABORT );
815
+ __builtin_unreachable ();
816
+ }
817
+
818
+ for (ret = 0 ; state .num_awaiting ;) {
819
+ int64_t v = coro_yield (r -> conn -> coro , state .request_conn_yield );
812
820
struct lwan_connection * conn = (struct lwan_connection * )(uintptr_t )v ;
813
821
814
822
if (conn -> flags & CONN_ASYNC_AWAITV ) {
815
823
conn -> flags &= ~CONN_ASYNC_AWAITV ;
816
- update .num_awaiting -- ;
824
+
825
+ if (UNLIKELY (conn -> flags & CONN_HUNG_UP )) {
826
+ /* Ensure flags are unset in case awaitv_any() is called with
827
+ * a different set of file descriptors. */
828
+ va_start (ap , r );
829
+ clear_awaitv_flags (l -> conns , ap );
830
+ va_end (ap );
831
+
832
+ return lwan_connection_get_fd (l , conn );
833
+ }
834
+
835
+ state .num_awaiting -- ;
817
836
}
818
837
}
819
- }
820
-
821
- static inline int64_t
822
- make_async_yield_value (int fd , enum lwan_connection_coro_yield event )
823
- {
824
- assert (event >= CONN_CORO_ASYNC_AWAIT_READ &&
825
- event <= CONN_CORO_ASYNC_AWAIT_READ_WRITE );
826
838
827
- return ( int64_t )((( uint64_t ) fd << 32 | event )) ;
839
+ return -1 ;
828
840
}
829
841
830
842
static inline int async_await_fd (struct lwan_connection * conn ,
831
843
int fd ,
832
844
enum lwan_connection_coro_yield events )
833
845
{
834
- int64_t yield_value = make_async_yield_value ( fd , events ) ;
835
- int64_t from_coro = coro_yield ( conn -> coro , yield_value ) ;
836
- struct lwan_connection * conn_from_coro =
837
- ( struct lwan_connection * )( intptr_t ) from_coro ;
846
+ struct lwan_thread * thread = conn -> thread ;
847
+ struct lwan * lwan = thread -> lwan ;
848
+ enum lwan_connection_coro_yield yield =
849
+ prepare_await ( lwan , events , fd , conn , thread -> epoll_fd ) ;
838
850
839
- assert (conn_from_coro -> flags & CONN_ASYNC_AWAIT );
851
+ if (LIKELY (yield == CONN_CORO_SUSPEND )) {
852
+ int64_t v = coro_yield (conn -> coro , yield );
840
853
841
- return lwan_connection_get_fd (conn -> thread -> lwan , conn_from_coro );
854
+ fd =
855
+ lwan_connection_get_fd (lwan , (struct lwan_connection * )(intptr_t )v );
856
+
857
+ return UNLIKELY (conn -> flags & CONN_HUNG_UP ) ? - fd : fd ;
858
+ }
859
+
860
+ lwan_status_critical_perror ("prepare_await(%d)" , fd );
861
+ coro_yield (conn -> coro , CONN_CORO_ABORT );
862
+ __builtin_unreachable ();
842
863
}
843
864
844
- inline int lwan_request_await_read (struct lwan_request * r , int fd )
865
+ int lwan_request_await_read (struct lwan_request * r , int fd )
845
866
{
846
- return async_await_fd (r -> conn , fd , CONN_CORO_ASYNC_AWAIT_READ );
867
+ return async_await_fd (r -> conn , fd , CONN_CORO_WANT_READ );
847
868
}
848
869
849
- inline int lwan_request_await_write (struct lwan_request * r , int fd )
870
+ int lwan_request_await_write (struct lwan_request * r , int fd )
850
871
{
851
- return async_await_fd (r -> conn , fd , CONN_CORO_ASYNC_AWAIT_WRITE );
872
+ return async_await_fd (r -> conn , fd , CONN_CORO_WANT_WRITE );
852
873
}
853
874
854
- inline int lwan_request_await_read_write (struct lwan_request * r , int fd )
875
+ int lwan_request_await_read_write (struct lwan_request * r , int fd )
855
876
{
856
- return async_await_fd (r -> conn , fd , CONN_CORO_ASYNC_AWAIT_READ_WRITE );
877
+ return async_await_fd (r -> conn , fd , CONN_CORO_WANT_READ_WRITE );
857
878
}
858
879
859
880
static ALWAYS_INLINE void resume_coro (struct timeout_queue * tq ,
@@ -864,20 +885,12 @@ static ALWAYS_INLINE void resume_coro(struct timeout_queue *tq,
864
885
assert (conn_to_resume -> coro );
865
886
assert (conn_to_yield -> coro );
866
887
867
- int64_t from_coro = coro_resume_value (conn_to_resume -> coro ,
868
- (int64_t )(intptr_t )conn_to_yield );
869
- enum lwan_connection_coro_yield yield_result = from_coro & 0xffffffff ;
870
-
871
- if (UNLIKELY (yield_result >= CONN_CORO_ASYNC )) {
872
- int await_fd = (int )((uint64_t )from_coro >> 32 );
873
- yield_result = resume_async (tq -> lwan , yield_result , await_fd ,
874
- conn_to_resume , epoll_fd );
875
- }
876
-
877
- if (UNLIKELY (yield_result == CONN_CORO_ABORT )) {
888
+ enum lwan_connection_coro_yield from_coro = coro_resume_value (
889
+ conn_to_resume -> coro , (int64_t )(intptr_t )conn_to_yield );
890
+ if (UNLIKELY (from_coro == CONN_CORO_ABORT )) {
878
891
timeout_queue_expire (tq , conn_to_resume );
879
892
} else {
880
- update_epoll_flags (tq -> lwan , conn_to_resume , epoll_fd , yield_result );
893
+ update_epoll_flags (tq -> lwan , conn_to_resume , epoll_fd , from_coro );
881
894
timeout_queue_move_to_last (tq , conn_to_resume );
882
895
}
883
896
}
0 commit comments