subr_sleepqueue.c (0269ae4c19ad779b43b0d6e2416ac7386945d692) | subr_sleepqueue.c (f91aa773bea2bd0dff2d021c2d78fe78da78d52d) |
---|---|
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2004 John Baldwin <jhb@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 109 unchanged lines hidden (view full) --- 118 * of the sleep queue API (e.g. sleep/wakeup and condition variables). 119 * The lock pointer is only used when invariants are enabled for various 120 * debugging checks. 121 * 122 * Locking key: 123 * c - sleep queue chain lock 124 */ 125struct sleepqueue { | 1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2004 John Baldwin <jhb@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 109 unchanged lines hidden (view full) --- 118 * of the sleep queue API (e.g. sleep/wakeup and condition variables). 119 * The lock pointer is only used when invariants are enabled for various 120 * debugging checks. 121 * 122 * Locking key: 123 * c - sleep queue chain lock 124 */ 125struct sleepqueue { |
126 TAILQ_HEAD(, thread) sq_blocked[NR_SLEEPQS]; /* (c) Blocked threads. */ | 126 struct threadqueue sq_blocked[NR_SLEEPQS]; /* (c) Blocked threads. */ |
127 u_int sq_blockedcnt[NR_SLEEPQS]; /* (c) N. of blocked threads. */ 128 LIST_ENTRY(sleepqueue) sq_hash; /* (c) Chain and free list. */ 129 LIST_HEAD(, sleepqueue) sq_free; /* (c) Free queues. */ 130 void *sq_wchan; /* (c) Wait channel. */ 131 int sq_type; /* (c) Queue type. */ 132#ifdef INVARIANTS 133 struct lock_object *sq_lock; /* (c) Associated lock. */ 134#endif --- 749 unchanged lines hidden (view full) --- 884 TAILQ_INIT(&sq->sq_blocked[i]); 885 sq->sq_blockedcnt[i] = 0; 886 } 887 LIST_INIT(&sq->sq_free); 888 return (0); 889} 890 891/* | 127 u_int sq_blockedcnt[NR_SLEEPQS]; /* (c) N. of blocked threads. */ 128 LIST_ENTRY(sleepqueue) sq_hash; /* (c) Chain and free list. */ 129 LIST_HEAD(, sleepqueue) sq_free; /* (c) Free queues. */ 130 void *sq_wchan; /* (c) Wait channel. */ 131 int sq_type; /* (c) Queue type. */ 132#ifdef INVARIANTS 133 struct lock_object *sq_lock; /* (c) Associated lock. */ 134#endif --- 749 unchanged lines hidden (view full) --- 884 TAILQ_INIT(&sq->sq_blocked[i]); 885 sq->sq_blockedcnt[i] = 0; 886 } 887 LIST_INIT(&sq->sq_free); 888 return (0); 889} 890 891/* |
892 * Find the highest priority thread sleeping on a wait channel and resume it. | 892 * Find thread sleeping on a wait channel and resume it. |
893 */ 894int 895sleepq_signal(void *wchan, int flags, int pri, int queue) 896{ | 893 */ 894int 895sleepq_signal(void *wchan, int flags, int pri, int queue) 896{ |
897 struct sleepqueue_chain *sc; |
|
897 struct sleepqueue *sq; | 898 struct sleepqueue *sq; |
899 struct threadqueue *head; |
|
898 struct thread *td, *besttd; 899 int wakeup_swapper; 900 901 CTR2(KTR_PROC, "sleepq_signal(%p, %d)", wchan, flags); 902 KASSERT(wchan != NULL, ("%s: invalid NULL wait channel", __func__)); 903 MPASS((queue >= 0) && (queue < NR_SLEEPQS)); 904 sq = sleepq_lookup(wchan); 905 if (sq == NULL) 906 return (0); 907 KASSERT(sq->sq_type == (flags & SLEEPQ_TYPE), 908 ("%s: mismatch between sleep/wakeup and cv_*", __func__)); 909 | 900 struct thread *td, *besttd; 901 int wakeup_swapper; 902 903 CTR2(KTR_PROC, "sleepq_signal(%p, %d)", wchan, flags); 904 KASSERT(wchan != NULL, ("%s: invalid NULL wait channel", __func__)); 905 MPASS((queue >= 0) && (queue < NR_SLEEPQS)); 906 sq = sleepq_lookup(wchan); 907 if (sq == NULL) 908 return (0); 909 KASSERT(sq->sq_type == (flags & SLEEPQ_TYPE), 910 ("%s: mismatch between sleep/wakeup and cv_*", __func__)); 911 |
910 /* 911 * Find the highest priority thread on the queue. If there is a 912 * tie, use the thread that first appears in the queue as it has 913 * been sleeping the longest since threads are always added to 914 * the tail of sleep queues. 915 */ 916 besttd = TAILQ_FIRST(&sq->sq_blocked[queue]); 917 TAILQ_FOREACH(td, &sq->sq_blocked[queue], td_slpq) { 918 if (td->td_priority < besttd->td_priority) | 912 head = &sq->sq_blocked[queue]; 913 if (flags & SLEEPQ_UNFAIR) { 914 /* 915 * Find the most recently sleeping thread, but try to 916 * skip threads still in process of context switch to 917 * avoid spinning on the thread lock. 918 */ 919 sc = SC_LOOKUP(wchan); 920 besttd = TAILQ_LAST_FAST(head, thread, td_slpq); 921 while (besttd->td_lock != &sc->sc_lock) { 922 td = TAILQ_PREV_FAST(besttd, head, thread, td_slpq); 923 if (td == NULL) 924 break; |
919 besttd = td; | 925 besttd = td; |
926 } 927 } else { 928 /* 929 * Find the highest priority thread on the queue. If there 930 * is a tie, use the thread that first appears in the queue 931 * as it has been sleeping the longest since threads are 932 * always added to the tail of sleep queues. 933 */ 934 besttd = td = TAILQ_FIRST(head); 935 while ((td = TAILQ_NEXT(td, td_slpq)) != NULL) { 936 if (td->td_priority < besttd->td_priority) 937 besttd = td; 938 } |
|
920 } 921 MPASS(besttd != NULL); 922 thread_lock(besttd); 923 wakeup_swapper = sleepq_resume_thread(sq, besttd, pri); 924 thread_unlock(besttd); 925 return (wakeup_swapper); 926} 927 --- 539 unchanged lines hidden --- | 939 } 940 MPASS(besttd != NULL); 941 thread_lock(besttd); 942 wakeup_swapper = sleepq_resume_thread(sq, besttd, pri); 943 thread_unlock(besttd); 944 return (wakeup_swapper); 945} 946 --- 539 unchanged lines hidden --- |