* Taking into account the current state of the queue and node, possibly take * the next entry off the queue and return it. Return NULL if there was * nothing we could return, either because there really was nothing there, or * because the node was in a state where it cannot yet process the next item * on the queue. */
| 1941 | * on the queue. |
| 1942 | */ |
| 1943 | static __inline item_p |
| 1944 | ng_dequeue(node_p node, int *rw) |
| 1945 | { |
| 1946 | item_p item; |
| 1947 | struct ng_queue *ngq = &node->nd_input_queue; |
| 1948 | |
| 1949 | /* This MUST be called with the mutex held. */ |
| 1950 | mtx_assert(&ngq->q_mtx, MA_OWNED); |
| 1951 | |
| 1952 | /* If there is nothing queued, then just return. */ |
| 1953 | if (!QUEUE_ACTIVE(ngq)) { |
| 1954 | CTR4(KTR_NET, "%20s: node [%x] (%p) queue empty; " |
| 1955 | "queue flags 0x%lx", __func__, |
| 1956 | node->nd_ID, node, ngq->q_flags); |
| 1957 | return (NULL); |
| 1958 | } |
| 1959 | |
| 1960 | /* |
| 1961 | * From here, we can assume there is a head item. |
| 1962 | * We need to find out what it is and if it can be dequeued, given |
| 1963 | * the current state of the node. |
| 1964 | */ |
| 1965 | if (HEAD_IS_READER(ngq)) { |
| 1966 | while (1) { |
| 1967 | long t = ngq->q_flags; |
| 1968 | if (t & WRITER_ACTIVE) { |
| 1969 | /* There is writer, reader can't proceed. */ |
| 1970 | CTR4(KTR_NET, "%20s: node [%x] (%p) queued " |
| 1971 | "reader can't proceed; queue flags 0x%lx", |
| 1972 | __func__, node->nd_ID, node, t); |
| 1973 | return (NULL); |
| 1974 | } |
| 1975 | if (atomic_cmpset_acq_int(&ngq->q_flags, t, |
| 1976 | t + READER_INCREMENT)) |
| 1977 | break; |
| 1978 | cpu_spinwait(); |
| 1979 | } |
| 1980 | /* We have got reader lock for the node. */ |
| 1981 | *rw = NGQRW_R; |
| 1982 | } else if (atomic_cmpset_acq_int(&ngq->q_flags, OP_PENDING, |
| 1983 | OP_PENDING + WRITER_ACTIVE)) { |
| 1984 | /* We have got writer lock for the node. */ |
| 1985 | *rw = NGQRW_W; |
| 1986 | } else { |
| 1987 | /* There is somebody other, writer can't proceed. */ |
| 1988 | CTR4(KTR_NET, "%20s: node [%x] (%p) queued writer can't " |
| 1989 | "proceed; queue flags 0x%lx", __func__, node->nd_ID, node, |
| 1990 | ngq->q_flags); |
| 1991 | return (NULL); |
| 1992 | } |
| 1993 | |
| 1994 | /* |
| 1995 | * Now we dequeue the request (whatever it may be) and correct the |
| 1996 | * pending flags and the next and last pointers. |
| 1997 | */ |
| 1998 | item = STAILQ_FIRST(&ngq->queue); |
| 1999 | STAILQ_REMOVE_HEAD(&ngq->queue, el_next); |
| 2000 | if (STAILQ_EMPTY(&ngq->queue)) |
no test coverage detected