Index: ifq.c =================================================================== RCS file: /cvs/src/sys/net/ifq.c,v retrieving revision 1.3 diff -u -p -r1.3 ifq.c --- ifq.c 9 Dec 2015 12:07:42 -0000 1.3 +++ ifq.c 29 Dec 2015 11:19:37 -0000 @@ -83,8 +83,8 @@ ifq_serialize(struct ifqueue *ifq, struc TAILQ_INSERT_TAIL(&ifq->ifq_task_list, t, t_entry); } - if (ifq->ifq_serializer == 0) { - ifq->ifq_serializer = 1; + if (ifq->ifq_serializer == NULL) { + ifq->ifq_serializer = curcpu(); while ((t = TAILQ_FIRST(&ifq->ifq_task_list)) != NULL) { TAILQ_REMOVE(&ifq->ifq_task_list, t, t_entry); @@ -98,11 +98,17 @@ ifq_serialize(struct ifqueue *ifq, struc mtx_enter(&ifq->ifq_task_mtx); } - ifq->ifq_serializer = 0; + ifq->ifq_serializer = NULL; } mtx_leave(&ifq->ifq_task_mtx); } +int +ifq_is_serialized(struct ifqueue *ifq) +{ + return (ifq->ifq_serializer == curcpu()); +} + void ifq_start_task(void *p) { @@ -136,7 +142,7 @@ ifq_barrier(struct ifqueue *ifq) /* this should only be called from converted drivers */ KASSERT(ISSET(ifq->ifq_if->if_xflags, IFXF_MPSAFE)); - if (ifq->ifq_serializer == 0) + if (ifq->ifq_serializer == NULL) return; ifq_serialize(ifq, &t); @@ -176,7 +182,7 @@ ifq_init(struct ifqueue *ifq, struct ifn mtx_init(&ifq->ifq_task_mtx, IPL_NET); TAILQ_INIT(&ifq->ifq_task_list); - ifq->ifq_serializer = 0; + ifq->ifq_serializer = NULL; task_set(&ifq->ifq_start, ifq_start_task, ifq); task_set(&ifq->ifq_restart, ifq_restart_task, ifq); Index: ifq.h =================================================================== RCS file: /cvs/src/sys/net/ifq.h,v retrieving revision 1.3 diff -u -p -r1.3 ifq.h --- ifq.h 10 Dec 2015 03:05:17 -0000 1.3 +++ ifq.h 29 Dec 2015 11:19:37 -0000 @@ -37,7 +37,7 @@ struct ifqueue { /* work serialisation */ struct mutex ifq_task_mtx; struct task_list ifq_task_list; - unsigned int ifq_serializer; + void *ifq_serializer; /* work to be serialised */ struct task ifq_start; @@ -149,8 +149,9 @@ struct ifqueue { * == Network Driver API * * The API used by network drivers is mostly documented in the - * ifq_dequeue(9) manpage except for ifq_serialize(). - * + * ifq_dequeue(9) manpage except for ifq_serialize(), + * ifq_is_serialized(), and IFQ_ASSERT_SERIALIZED(). + * * === ifq_serialize() * * A driver may run arbitrary work in the ifqueue serialiser context @@ -163,6 +164,16 @@ struct ifqueue { * Because the work may be run on another CPU, the lifetime of the * task and the work it represents can extend beyond the end of the * call to ifq_serialize() that dispatched it. + * + * === ifq_is_serialized() + * + * This function returns whether the caller is currently within the + * ifqueue serializer context. + * + * === IFQ_ASSERT_SERIALIZED() + * + * This macro will assert that the caller is currently within the + * specified ifqueue serialiser context. * * * = ifqueue work serialisation @@ -318,6 +329,7 @@ unsigned int ifq_purge(struct ifqueue * void *ifq_q_enter(struct ifqueue *, const struct ifq_ops *); void ifq_q_leave(struct ifqueue *, void *); void ifq_serialize(struct ifqueue *, struct task *); +int ifq_is_serialized(struct ifqueue *); void ifq_barrier(struct ifqueue *); #define ifq_len(_ifq) ((_ifq)->ifq_len) @@ -353,6 +365,8 @@ ifq_restart(struct ifqueue *ifq) { ifq_serialize(ifq, &ifq->ifq_restart); } + +#define IFQ_ASSERT_SERIALIZED(_ifq) KASSERT(ifq_is_serialized(_ifq)) extern const struct ifq_ops * const ifq_priq_ops;