Deleted Added
full compact
subr_sleepqueue.c (296320) subr_sleepqueue.c (296927)
1/*-
2 * Copyright (c) 2004 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 43 unchanged lines hidden (view full) ---

52 * must consistently use the same lock to synchronize with a wait channel,
53 * though this check is currently only a warning for sleep/wakeup due to
54 * pre-existing abuse of that API. The same lock must also be held when
55 * awakening threads, though that is currently only enforced for condition
56 * variables.
57 */
58
59#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2004 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 43 unchanged lines hidden (view full) ---

52 * must consistently use the same lock to synchronize with a wait channel,
53 * though this check is currently only a warning for sleep/wakeup due to
54 * pre-existing abuse of that API. The same lock must also be held when
55 * awakening threads, though that is currently only enforced for condition
56 * variables.
57 */
58
59#include <sys/cdefs.h>
60__FBSDID("$FreeBSD: head/sys/kern/subr_sleepqueue.c 296320 2016-03-02 18:46:17Z kib $");
60__FBSDID("$FreeBSD: head/sys/kern/subr_sleepqueue.c 296927 2016-03-16 04:22:32Z cem $");
61
62#include "opt_sleepqueue_profiling.h"
63#include "opt_ddb.h"
64#include "opt_sched.h"
65
66#include <sys/param.h>
67#include <sys/systm.h>
68#include <sys/lock.h>
69#include <sys/kernel.h>
70#include <sys/ktr.h>
71#include <sys/mutex.h>
72#include <sys/proc.h>
73#include <sys/sbuf.h>
74#include <sys/sched.h>
75#include <sys/sdt.h>
76#include <sys/signalvar.h>
77#include <sys/sleepqueue.h>
61
62#include "opt_sleepqueue_profiling.h"
63#include "opt_ddb.h"
64#include "opt_sched.h"
65
66#include <sys/param.h>
67#include <sys/systm.h>
68#include <sys/lock.h>
69#include <sys/kernel.h>
70#include <sys/ktr.h>
71#include <sys/mutex.h>
72#include <sys/proc.h>
73#include <sys/sbuf.h>
74#include <sys/sched.h>
75#include <sys/sdt.h>
76#include <sys/signalvar.h>
77#include <sys/sleepqueue.h>
78#include <sys/stack.h>
78#include <sys/sysctl.h>
79
80#include <vm/uma.h>
81
82#ifdef DDB
83#include <ddb/ddb.h>
84#endif
85
79#include <sys/sysctl.h>
80
81#include <vm/uma.h>
82
83#ifdef DDB
84#include <ddb/ddb.h>
85#endif
86
87
86/*
87 * Constants for the hash table of sleep queue chains.
88 * SC_TABLESIZE must be a power of two for SC_MASK to work properly.
89 */
90#define SC_TABLESIZE 256 /* Must be power of 2. */
91#define SC_MASK (SC_TABLESIZE - 1)
92#define SC_SHIFT 8
93#define SC_HASH(wc) ((((uintptr_t)(wc) >> SC_SHIFT) ^ (uintptr_t)(wc)) & \

--- 935 unchanged lines hidden (view full) ---

1029 MPASS(wchan != NULL);
1030 sq = sleepq_lookup(wchan);
1031 MPASS(sq != NULL);
1032
1033 /* Thread is asleep on sleep queue sq, so wake it up. */
1034 return (sleepq_resume_thread(sq, td, 0));
1035}
1036
88/*
89 * Constants for the hash table of sleep queue chains.
90 * SC_TABLESIZE must be a power of two for SC_MASK to work properly.
91 */
92#define SC_TABLESIZE 256 /* Must be power of 2. */
93#define SC_MASK (SC_TABLESIZE - 1)
94#define SC_SHIFT 8
95#define SC_HASH(wc) ((((uintptr_t)(wc) >> SC_SHIFT) ^ (uintptr_t)(wc)) & \

--- 935 unchanged lines hidden (view full) ---

1031 MPASS(wchan != NULL);
1032 sq = sleepq_lookup(wchan);
1033 MPASS(sq != NULL);
1034
1035 /* Thread is asleep on sleep queue sq, so wake it up. */
1036 return (sleepq_resume_thread(sq, td, 0));
1037}
1038
1039/*
1040 * Prints the stacks of all threads presently sleeping on wchan/queue to
1041 * the sbuf sb. Sets count_stacks_printed to the number of stacks actually
1042 * printed. Typically, this will equal the number of threads sleeping on the
1043 * queue, but may be less if sb overflowed before all stacks were printed.
1044 */
1045int
1046sleepq_sbuf_print_stacks(struct sbuf *sb, void *wchan, int queue,
1047 int *count_stacks_printed)
1048{
1049 struct thread *td, *td_next;
1050 struct sleepqueue *sq;
1051 struct stack **st;
1052 struct sbuf **td_infos;
1053 int i, stack_idx, error, stacks_to_allocate;
1054 bool finished, partial_print;
1055
1056 error = 0;
1057 finished = false;
1058 partial_print = false;
1059
1060 KASSERT(wchan != NULL, ("%s: invalid NULL wait channel", __func__));
1061 MPASS((queue >= 0) && (queue < NR_SLEEPQS));
1062
1063 stacks_to_allocate = 10;
1064 for (i = 0; i < 3 && !finished ; i++) {
1065 /* We cannot malloc while holding the queue's spinlock, so
1066 * we do our mallocs now, and hope it is enough. If it
1067 * isn't, we will free these, drop the lock, malloc more,
1068 * and try again, up to a point. After that point we will
1069 * give up and report ENOMEM. We also cannot write to sb
1070 * during this time since the client may have set the
1071 * SBUF_AUTOEXTEND flag on their sbuf, which could cause a
1072 * malloc as we print to it. So we defer actually printing
1073 * to sb until after we drop the spinlock.
1074 */
1075
1076 /* Where we will store the stacks. */
1077 st = malloc(sizeof(struct stack *) * stacks_to_allocate,
1078 M_TEMP, M_WAITOK);
1079 for (stack_idx = 0; stack_idx < stacks_to_allocate;
1080 stack_idx++)
1081 st[stack_idx] = stack_create();
1082
1083 /* Where we will store the td name, tid, etc. */
1084 td_infos = malloc(sizeof(struct sbuf *) * stacks_to_allocate,
1085 M_TEMP, M_WAITOK);
1086 for (stack_idx = 0; stack_idx < stacks_to_allocate;
1087 stack_idx++)
1088 td_infos[stack_idx] = sbuf_new(NULL, NULL,
1089 MAXCOMLEN + sizeof(struct thread *) * 2 + 40,
1090 SBUF_FIXEDLEN);
1091
1092 sleepq_lock(wchan);
1093 sq = sleepq_lookup(wchan);
1094 if (sq == NULL) {
1095 /* This sleepq does not exist; exit and return ENOENT. */
1096 error = ENOENT;
1097 finished = true;
1098 sleepq_release(wchan);
1099 goto loop_end;
1100 }
1101
1102 stack_idx = 0;
1103 /* Save thread info */
1104 TAILQ_FOREACH_SAFE(td, &sq->sq_blocked[queue], td_slpq,
1105 td_next) {
1106 if (stack_idx >= stacks_to_allocate)
1107 goto loop_end;
1108
1109 /* Note the td_lock is equal to the sleepq_lock here. */
1110 stack_save_td(st[stack_idx], td);
1111
1112 sbuf_printf(td_infos[stack_idx], "%d: %s %p",
1113 td->td_tid, td->td_name, td);
1114
1115 ++stack_idx;
1116 }
1117
1118 finished = true;
1119 sleepq_release(wchan);
1120
1121 /* Print the stacks */
1122 for (i = 0; i < stack_idx; i++) {
1123 sbuf_finish(td_infos[i]);
1124 sbuf_printf(sb, "--- thread %s: ---\n", sbuf_data(td_infos[i]));
1125 stack_sbuf_print(sb, st[i]);
1126 sbuf_printf(sb, "\n");
1127
1128 error = sbuf_error(sb);
1129 if (error == 0)
1130 *count_stacks_printed = stack_idx;
1131 }
1132
1133loop_end:
1134 if (!finished)
1135 sleepq_release(wchan);
1136 for (stack_idx = 0; stack_idx < stacks_to_allocate;
1137 stack_idx++)
1138 stack_destroy(st[stack_idx]);
1139 for (stack_idx = 0; stack_idx < stacks_to_allocate;
1140 stack_idx++)
1141 sbuf_delete(td_infos[stack_idx]);
1142 free(st, M_TEMP);
1143 free(td_infos, M_TEMP);
1144 stacks_to_allocate *= 10;
1145 }
1146
1147 if (!finished && error == 0)
1148 error = ENOMEM;
1149
1150 return (error);
1151}
1152
1037#ifdef SLEEPQUEUE_PROFILING
1038#define SLEEPQ_PROF_LOCATIONS 1024
1039#define SLEEPQ_SBUFSIZE 512
1040struct sleepq_prof {
1041 LIST_ENTRY(sleepq_prof) sp_link;
1042 const char *sp_wmesg;
1043 long sp_count;
1044};

--- 204 unchanged lines hidden ---
1153#ifdef SLEEPQUEUE_PROFILING
1154#define SLEEPQ_PROF_LOCATIONS 1024
1155#define SLEEPQ_SBUFSIZE 512
1156struct sleepq_prof {
1157 LIST_ENTRY(sleepq_prof) sp_link;
1158 const char *sp_wmesg;
1159 long sp_count;
1160};

--- 204 unchanged lines hidden ---