1 /*
2 * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2024, Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8 #include "IOSchedulerRoster.h"
9
10 #include <util/AutoLock.h>
11
12
13 /*static*/ IOSchedulerRoster IOSchedulerRoster::sDefaultInstance;
14
15
IOSchedulerRoster()16 IOSchedulerRoster::IOSchedulerRoster()
17 :
18 fNextID(1),
19 fNotificationService("I/O")
20 {
21 mutex_init(&fLock, "IOSchedulerRoster");
22 fNotificationService.Register();
23 }
24
25
~IOSchedulerRoster()26 IOSchedulerRoster::~IOSchedulerRoster()
27 {
28 mutex_destroy(&fLock);
29 fNotificationService.Unregister();
30 }
31
32
33 void
AddScheduler(IOScheduler * scheduler)34 IOSchedulerRoster::AddScheduler(IOScheduler* scheduler)
35 {
36 AutoLocker<IOSchedulerRoster> locker(this);
37 fSchedulers.Add(scheduler);
38 locker.Unlock();
39
40 Notify(IO_SCHEDULER_ADDED, scheduler);
41 }
42
43
44 void
RemoveScheduler(IOScheduler * scheduler)45 IOSchedulerRoster::RemoveScheduler(IOScheduler* scheduler)
46 {
47 AutoLocker<IOSchedulerRoster> locker(this);
48 fSchedulers.Remove(scheduler);
49 locker.Unlock();
50
51 Notify(IO_SCHEDULER_REMOVED, scheduler);
52 }
53
54
55 void
Notify(uint32 eventCode,const IOScheduler * scheduler,IORequest * request,IOOperation * operation)56 IOSchedulerRoster::Notify(uint32 eventCode, const IOScheduler* scheduler,
57 IORequest* request, IOOperation* operation)
58 {
59 AutoLocker<DefaultNotificationService> locker(fNotificationService);
60
61 if (!fNotificationService.HasListeners())
62 return;
63
64 KMessage event;
65 event.SetTo(fEventBuffer, sizeof(fEventBuffer), IO_SCHEDULER_MONITOR);
66 event.AddInt32("event", eventCode);
67 event.AddPointer("scheduler", scheduler);
68 if (request != NULL) {
69 event.AddPointer("request", request);
70 if (operation != NULL)
71 event.AddPointer("operation", operation);
72 }
73
74 fNotificationService.NotifyLocked(event, eventCode);
75 }
76
77
78 int32
NextID()79 IOSchedulerRoster::NextID()
80 {
81 AutoLocker<IOSchedulerRoster> locker(this);
82 return fNextID++;
83 }
84
85
86 // #pragma mark - debug methods and initialization
87
88
89 void
Dump() const90 IOSchedulerRoster::Dump() const
91 {
92 kprintf("IOSchedulerRoster at %p\n", this);
93 kprintf(" mutex: %p\n", &fLock);
94 kprintf(" next ID: %" B_PRId32 "\n", fNextID);
95
96 kprintf(" schedulers:");
97 for (IOSchedulerList::ConstIterator it
98 = fSchedulers.GetIterator();
99 IOScheduler* scheduler = it.Next();) {
100 kprintf(" %p", scheduler);
101 }
102 kprintf("\n");
103 }
104
105
106 static int
dump_io_scheduler_roster(int argc,char ** argv)107 dump_io_scheduler_roster(int argc, char** argv)
108 {
109 IOSchedulerRoster* roster;
110 if (argc == 1) {
111 roster = IOSchedulerRoster::Default();
112 } else if (argc == 2) {
113 roster = (IOSchedulerRoster*)parse_expression(argv[1]);
114 if (roster == NULL)
115 return -1;
116 } else {
117 print_debugger_command_usage(argv[0]);
118 return 0;
119 }
120
121 roster->Dump();
122 return 0;
123 }
124
125
126 static int
dump_io_scheduler(int argc,char ** argv)127 dump_io_scheduler(int argc, char** argv)
128 {
129 if (argc != 2) {
130 print_debugger_command_usage(argv[0]);
131 return 0;
132 }
133
134 IOScheduler* scheduler = (IOScheduler*)parse_expression(argv[1]);
135 scheduler->Dump();
136 return 0;
137 }
138
139
140 static int
dump_io_request_owner(int argc,char ** argv)141 dump_io_request_owner(int argc, char** argv)
142 {
143 if (argc != 2) {
144 print_debugger_command_usage(argv[0]);
145 return 0;
146 }
147
148 IORequestOwner* owner = (IORequestOwner*)parse_expression(argv[1]);
149 owner->Dump();
150 return 0;
151 }
152
153
154 static int
dump_io_request(int argc,char ** argv)155 dump_io_request(int argc, char** argv)
156 {
157 if (argc != 2 || !strcmp(argv[1], "--help")) {
158 kprintf("usage: %s <ptr-to-io-request>\n", argv[0]);
159 return 0;
160 }
161
162 IORequest* request = (IORequest*)parse_expression(argv[1]);
163 request->Dump();
164 return 0;
165 }
166
167
168 static int
dump_io_operation(int argc,char ** argv)169 dump_io_operation(int argc, char** argv)
170 {
171 if (argc != 2 || !strcmp(argv[1], "--help")) {
172 kprintf("usage: %s <ptr-to-io-operation>\n", argv[0]);
173 return 0;
174 }
175
176 IOOperation* operation = (IOOperation*)parse_expression(argv[1]);
177 operation->Dump();
178 return 0;
179 }
180
181
182 static int
dump_io_buffer(int argc,char ** argv)183 dump_io_buffer(int argc, char** argv)
184 {
185 if (argc != 2 || !strcmp(argv[1], "--help")) {
186 kprintf("usage: %s <ptr-to-io-buffer>\n", argv[0]);
187 return 0;
188 }
189
190 IOBuffer* buffer = (IOBuffer*)parse_expression(argv[1]);
191 buffer->Dump();
192 return 0;
193 }
194
195
196 static int
dump_dma_buffer(int argc,char ** argv)197 dump_dma_buffer(int argc, char** argv)
198 {
199 if (argc != 2 || !strcmp(argv[1], "--help")) {
200 kprintf("usage: %s <ptr-to-dma-buffer>\n", argv[0]);
201 return 0;
202 }
203
204 DMABuffer* buffer = (DMABuffer*)parse_expression(argv[1]);
205 buffer->Dump();
206 return 0;
207 }
208
209
210 /*static*/ void
Init()211 IOSchedulerRoster::Init()
212 {
213 new(&sDefaultInstance) IOSchedulerRoster;
214
215 add_debugger_command_etc("io_scheduler_roster", &dump_io_scheduler_roster,
216 "Dump an I/O scheduler roster",
217 "<scheduler-roster>\n"
218 "Dumps I/O scheduler roster at address <scheduler-roster>.\n"
219 "If unspecified, dump the default roster.\n", 0);
220 add_debugger_command_etc("io_scheduler", &dump_io_scheduler,
221 "Dump an I/O scheduler",
222 "<scheduler>\n"
223 "Dumps I/O scheduler at address <scheduler>.\n", 0);
224 add_debugger_command_etc("io_request_owner", &dump_io_request_owner,
225 "Dump an I/O request owner",
226 "<owner>\n"
227 "Dumps I/O request owner at address <owner>.\n", 0);
228 add_debugger_command("io_request", &dump_io_request, "dump an I/O request");
229 add_debugger_command("io_operation", &dump_io_operation,
230 "dump an I/O operation");
231 add_debugger_command("io_buffer", &dump_io_buffer, "dump an I/O buffer");
232 add_debugger_command("dma_buffer", &dump_dma_buffer, "dump a DMA buffer");
233 }
234