Add new documentation
[reactos.git] / reactos / doc / notes
1 *** This file contains messages I've culled off the net as well
2 as previous discussions all of which have useful info on fixes
3 that need to be added to ReactOS. messages are between five
4 dashes on a line by themselves. If you implement the fix
5 reffered to in a message, feel free to delete it from the file.
6 Rex ***
7 -----
8 Yes with DPCs, KeDrainDpcQueue should go to HIGH_LEVEL because
9 it needs to synchronize with KeInsertDpcQueue. Also the idle thread
10 should run at DISPATCH_LEVEL and regularly drain the dpc queue, that
11 way if an irq happens and the dpc can't be executed immediately it
12 will be executed as soon as the processor is idle rather than
13 waiting for the next timer tick
14 -----
15 About the console driver, I think it might be quite useful to have a simple
16 way for apps to print to the screen for debugging. But when the kernel is more
17 stable, console handling should be moved to user level because console printing
18 needs to know about windows and so on which can only be done at user level.
19 -----
20 Subject: Re: IMSAMP-how to avoid rebooting?
21 Date: 9 Nov 1998 00:40:32 -0000
22 From: Charles Bryant <n51190709.ch@chch.demon.co.uk>
23 Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
24 References: 1, 2 , 3 , 4
25
26 In article <un264wzle.fsf@xxx.yyy.zzz>, David C. <qqqq@xxx.yyy.zzz> wrote:
27 >The reason it won't unload when something is bound to it is the same
28 >reason you can't unload any other driver that has an open client. If
29 >you install any driver, and have a user program (or another driver) open
30 >a handle to it, and then give the "net stop" command to unload it,
31 >you'll find that the unload will be delayed until the user program
32 >closes its handle.
33
34 When developing a driver I found this to be a considerable nuisance.
35 Frequently a bug would leave an IRP stuck in the driver and I
36 couldn't unload and reload a fixed version. While reading NTDDK.H I
37 found a suspicious constant and discovered that the Flags field in
38 the device (the one which you OR in DO_BUFFERED_IO or DO_DIRECT_IO)
39 has a bit called DO_UNLOAD_PENDING. By experiment I confirmed that
40 this bit is set when you do 'net stop', so a driver can check it
41 periodically (e.g. from a timer DPC every ten seconds) and cancel all
42 queued IRPs if it is found to be set.
43
44 Since this is not documented anywhere that I can find, it might be
45 unwise to rely on it for production code, but it is very useful for
46 debugging. Maybe someone with internals knowledge can comment on the
47 reliability of it.
48 -----
49 Subject: Re: Kernel bugs
50 Date: Fri, 23 Oct 1998 12:08:36 -0700
51 From: rex <rex@lvcablemodem.com>
52 To: Jason Filby <jasonfilby@yahoo.com>
53 References: 1
54
55 Jason Filby wrote:
56
57 > Hi,
58 >
59 > Ok -- here's most of what I get when I press a key:
60 >
61 > Page fault detected at address 1fd4 with eip c042f794
62 > Recursive page fault detected
63 > Exception 14(2)
64 > CS:EIP 20:c042f794
65 >
66 > Rex -- do you know of anyway to find out which function in what file
67 > is causing the exception? I know that for problems in the kernel, you
68 > just look in the ntoskrnl\kernel.sym file and find the EIP value which
69 > matches the one given in the exception debug text. But what about
70 > modules? How can we track exceptions that occur in functions in modules?
71 >
72
73 I know this is a little belated, but I thought I'd take astab at answering
74 this anyway. add an option to the
75 makefile for the module to generate a listing file with
76 symbol information. Then, on a boot test, note the
77 address that the module is loaded at, and subtract
78 this from the EIP value. add any offset used in the
79 module link specification (I dont think there currently
80 is one), and look for the last symbol with a lower
81 address offset.
82
83 Brian, I have an idea on how to make this exception
84 dump information a little more useful. We should
85 have the load information for the load modules
86 in memory somewhere. Perhaps the exception
87 dump could check offending addresses to see if
88 they lie in the kernel or in a module, and if they
89 lie in a module the proper offset could be subtracted
90 and this number could be displayed seperately. If
91 I get a chance today, I'll make this change and send
92 it to ya.
93
94 Rex.
95 -----
96 Subject: [ros-kernel] Pet peeve of the week
97 Resent-Date: Sun, 25 Oct 1998 11:57:40 -0600
98 Resent-From: ros-kernel@sid-dis.com
99 Date: Sun, 25 Oct 1998 09:53:48 -0800
100 From: rex <rex@lvcablemodem.com>
101 Reply-To: <ros-kernel@sid-dis.com>
102 To: ReactOS Kernel Forum <ros-kernel@sid-dis.com>
103
104 Hi all,
105
106 I guess it's about time to start another mailstorm
107 on the list. :)
108
109 I have a suggestion for a change to the kernel.
110 It not a very big change, and I hope everyone
111 will agree that it makes sense.
112
113 There is a structure used in many places in the
114 kernel called LARGE_INTEGER. the is also
115 a version called ULARGE_INTEGER, but it
116 is not used at all as far as I can tell. this structure
117 is equivalent to a long long int. You can literally
118 cast a pointer to a LARGE_INTEGER to a
119 long long int and all manipulation will work
120 seemlessly. My suggestion is that we replace the
121 use of this structure with long long ints. Even
122 microsoft, in their infinite wisdom, has made this
123 suggestion in the DDK documentation. If you're
124 wondering where, look at the RTL functions
125 that manipulate LARGE_INTEGER structs.
126
127 Replacing LI's with long long ints will work
128 because they are binary compatable. All software
129 compiled to use LI's will manipulate long long ints
130 correctly and vice versa. There is one problem
131 with this suggestion: the LARGE_INTEGER type
132 is a structure containing 2 members. Any code
133 that accesses the structure by members will break.
134 I think the kernel side impact is minimal, and is
135 worth the change. However, the structure is used
136 in several of the Win32 API functions, and needs
137 to remain there. I think we build a conditionally
138 compiled version of the LARGE_INTEGER type.
139 In kernel mode code (the kernel proper and drivers)
140 the LARGE INTEGER will be the following:
141
142 typedef long long int LARGE_INTEGER,
143 *PLARGE_INTEGER;
144 typedef unsigned long long int ULARGE_INTEGER,
145 *PULARGE_INTEGER;
146
147 and in user mode code it will expand out to the
148 current definition (which by the way, is not
149 strictly correct, but can't be because it uses a
150 MS compiler extension).
151
152 Brian, I would be willing to make the conversion
153 to those kernel modules that needed it, and of
154 course to the IDE driver if we want to go forward
155 with the change.
156
157 Lastly, I'll mention what made me consider this.
158 I was fixing the timer routines, and two of the
159 three problems turned out to be related to LI
160 conversion problems.
161
162 Rex.
163 -----
164 Subject: Re: [ros-kernel] Pet peeve of the week
165 Date: Thu, 29 Oct 1998 19:10:37 +0100
166 From: Boudewijn <ariadne@xs4all.nl>
167 To: rex@lvcablemodem.com
168 References: 1
169
170 Hai Rex
171
172 I think it is a good idea to wrap a makro around the member access
173 to large integers.
174 I haven't tested this, but do you think this is a good sugestion ?
175
176 #ifdef COMPILER_LARGE_INTEGERS
177 #define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( ( LargeInteger >>
178 32) )
179 #define GET_LARGE_INTEGER_LOW_PART(LargeInteger) ( (LargeInteger &
180 0xFFFFFFFF) )
181 #define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) (
182 LargeInteger |= ( ((LARGE_INTEGER)Signed_Long) << 32 ) )
183 #define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) (
184 LargeInteger |= Unsigned_Long )
185 #else
186 #define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( (
187 LargeInteger.HighPart) )
188 #define GET_LARGE_INTEGER_LOW_PART(LargeInteger) (
189 (LargeInteger.LowPart) )
190 #define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) (
191 LargeInteger.HighPart= Signed_Long )
192 #define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) (
193 LargeInteger.LowPart = Unsigned_Long )
194 #endif
195
196 Boudewijn
197 -----
198 Subject: Re: Question on "Sending buffers on the stack to asynchronous DeviceIoControl with buffered I/O"
199 Date: Mon, 16 Nov 1998 11:24:57 -0800
200 From: "-Paul" <paulsan@microsoftSPAM.com>
201 Organization: Microsoft Corp.
202 Newsgroups: microsoft.public.win32.programmer.kernel, comp.os.ms-windows.programmer.nt.kernel-mode
203 References: 1
204
205 Radu, I post the following information occassionally for questions such as
206 yours. I hope it helps.
207
208 -Paul
209
210 Here is an explanation of buffers and DeviceIoControl.
211
212 First, here are the parameters,
213
214 BOOL DeviceIoControl(
215 HANDLE hDevice, // handle to device of interest
216 DWORD dwIoControlCode, // control code of operation to perform
217 LPVOID lpInBuffer, // pointer to buffer to supply input data
218 DWORD nInBufferSize, // size of input buffer
219 LPVOID lpOutBuffer, // pointer to buffer to receive output data
220 DWORD nOutBufferSize, // size of output buffer
221 LPDWORD lpBytesReturned, // pointer to variable to receive output byte
222 count
223 LPOVERLAPPED lpOverlapped // pointer to overlapped structure for
224 asynchronous operation
225 );
226
227 METHOD_BUFFERED
228
229 user-mode perspective
230
231 lpInBuffer - optional, contains data that is written to the driver
232 lpOutBuffer - optional, contains data that is read from the driver after
233 the call has completed
234
235 lpInBuffer and lpOutBuffer can be two buffers or a single shared buffer.
236 If a shared buffer, lpInBuffer is overwritten by lpOutBuffer.
237
238
239 I/O Manager perspective
240
241 examines nInBufferSize and nOutBufferSize. Allocates memory from non-paged
242 pool and puts the address of this pool in Irp->AssociatedIrp.SystemBuffer.
243 The size of this buffer is equal to the size of the larger of the two
244 bufferes. This buffer is accessible at any IRQL.
245
246 copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
247 copies nOutBufferSize to
248 irpSp->Parameters.DeviceIoControl.OutputBufferLength
249 copies contents of lpInBuffer to SystemBuffer allocated above
250 calls your driver
251
252
253
254 Device Driver perspective
255
256 you have one buffer, Irp->AssociatedIrp.SystemBuffer. You read input data
257 from this buffer and you write output data to the same buffer, overwriting
258 the input data.
259
260 Before calling IoCompleteRequest, you must
261 - set IoStatus.Status to an approriate NtStatus
262 - if IoStatus.Status == STATUS_SUCCESS
263 set IoStatus.Information to the
264 number of bytes you want copied
265 from the SystemBuffer back into
266 lpOutBuffer.
267
268
269 I/O Manager Completion Routine perspective
270
271 looks at IoStatus block, if IoStatus.Status = STATUS_SUCCESS, copies the
272 number of bytes specified by IoStatus.Information from
273 Irp->AssociatedIrp.SystemBuffer into lpOutBuffer
274 completes the request
275
276
277
278
279
280
281 METHOD_IN_DIRECT
282
283 user-mode perspective
284
285 lpInBuffer - optional, contains data that is written to the driver. This
286 buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
287 confusion, mentally rename this buffer to lpControlBuffer. This is
288 typically a small, optional buffer that might contain a control structure
289 with useful information for the device driver. This buffer is smal and is
290 double buffered.
291
292 lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is read by
293 the driver. To avoid confusion, mentally rename this buffer to
294 lpDataTransferBuffer. This is physically the same buffer that the device
295 driver will read from. There is no double buffering. Technically, this
296 buffer is still optional, but since you are using this buffering method,
297 what would be the point???
298
299 I/O Manager perspective
300
301 If lpInBuffer exists, allocates memory from non-paged pool and puts the
302 address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
303 accessible at any IRQL.
304
305 copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
306 copies nOutBufferSize to
307 irpSp->Parameters.DeviceIoControl.OutputBufferLength
308 copies contents of lpInBuffer to SystemBuffer allocated above
309 So far this is completely identical to METHOD_BUFFERED. Most likely
310 lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
311
312 For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
313 allocated. lpOutBuffer is probed and locked into memory. Then, the user
314 buffer virtual addresses are checked to be sure they are readable in the
315 caller's access mode.
316
317 The MDL is address is stored in Irp->MdlAddress.
318 Your driver is called.
319
320
321 Device Driver perspective
322
323 The device driver can read the copy of lpOutBuffer via
324 Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
325 this buffer is lost. The I/O Manager does not copy any data back to the
326 user-mode buffers as it did in the completion routine for METHOD_BUFFERED.
327 Art Baker's book is wrong in this respect (page 168, "data going from the
328 driver back to the caller is passed through an intermediate system-space
329 buffer" and page 177, "When the IOCTL IRP is completed, the contents of the
330 system buffer will be copied back into the callers original output buffer".
331
332 The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
333 The driver uses whatever Mdl API's to read the buffer. Usually, this
334 buffer is to be written to some mass storage media or some similar
335 operation. Since this is a large data transfer, assume a completion
336 routine is required.
337
338 mark the Irp pending
339 queue it
340 return status pending
341
342
343
344
345 Device Driver Completion Routine perspective
346
347 standard completion routine operations
348 set IoStatus.Status to an approriate NtStatus
349 IoStatus.Information is not needed
350 completete the request
351
352
353
354
355 I/O Manager Completion Routine perspective
356
357 standard I/O Manager completion routine operations
358 unmap the pages
359 deallocate the Mdl
360 complete the request
361
362
363
364
365
366 METHOD_OUT_DIRECT
367
368 user-mode perspective
369
370 lpInBuffer - optional, contains data that is written to the driver. This
371 buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
372 confusion, mentally rename this buffer to lpControlBuffer. This is
373 typically a small, optional buffer that might contain a control structure
374 with useful information for the device driver. This buffer is smal and is
375 double buffered.
376
377 lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is written
378 by the driver and read by the wer-mode application when the request is
379 completed. To avoid confusion, mentally rename this buffer to
380 lpDataTransferBuffer. This is physically the same buffer that the device
381 driver will write to. There is no double buffering. Technically, this
382 buffer is still optional, but since you are using this buffering method,
383 what would be the point???
384
385 I/O Manager perspective
386
387 If lpInBuffer exists, allocates memory from non-paged pool and puts the
388 address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
389 accessible at any IRQL.
390
391 copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
392 copies nOutBufferSize to
393 irpSp->Parameters.DeviceIoControl.OutputBufferLength
394 copies contents of lpInBuffer to SystemBuffer allocated above
395 So far this is completely identical to METHOD_BUFFERED. Most likely
396 lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
397
398 For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
399 allocated. lpOutBuffer is probed and locked into memory. Then the user
400 buffer's addresses are checked to make sure the caller could write to them
401 in the caller's access mode.
402
403 The MDL is address is stored in Irp->MdlAddress.
404 Your driver is called.
405
406
407 Device Driver perspective
408
409 The device driver can read the copy of lpOutBuffer via
410 Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
411 this buffer is lost.
412
413 The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
414 The driver uses whatever Mdl API's to write data to the buffer. Usually,
415 this buffer is to be read from some mass storage media or some similar
416 operation. Since this is a large data transfer, assume a completion
417 routine is required.
418
419 mark the Irp pending
420 queue it
421 return status pending
422
423
424
425
426 Device Driver Completion Routine perspective
427
428 standard completion routine operations
429 set IoStatus.Status to an approriate NtStatus
430 IoStatus.Information is not needed
431 completete the request
432
433
434
435
436 I/O Manager Completion Routine perspective
437
438 standard I/O Manager completion routine operations
439 unmap the pages
440 deallocate the Mdl
441 complete the request
442
443
444
445
446 METHOD_NEITHER
447
448 I/O Manager perspective
449
450 Irp->UserBuffer = lpOutputBuffer;
451 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = lpInputBuffer;
452
453 No comments here. Don't use METHOD_DIRECT unless you know what you are
454 doing. Simple rule.
455
456 If your IOCtl involves no data transfer buffers, then METHOD_NEITHER is the
457 fastest path through the I/O Manager that involves an Irp.
458
459
460
461
462 Final Comment
463
464 Don't touch Irp->UserBuffer. This is a bookmark for the I/O Manager. Two
465 major problems can occur. 1 - page fault at high IRQL, or 2 - you write
466 something to Irp->UserBuffer and the I/O Manager overwrites you in its
467 completion routine. File systems access Irp->UserBuffer, but FSD writers
468 know all of the above and know when it is safe to touch Irp->UserBuffer.
469
470
471
472 Radu Woinaroski wrote in message <364F8F6E.2434B010@scitec.com.au>...
473 >Hello,
474 >
475 >I have a kernel-mode device driver that accepts a number of IoControl
476 >commands that use buffered data transfer (METHOD_BUFFERED).
477 >
478 >A user mode API provides a higher level access then the DeviceIoControl
479 >function.
480 >
481 >The function is implemented like that
482 >
483 >BOOL
484 Something(
485 > HANDLE hDevice ,
486 > int param1,
487 > int param2,
488 > DWORD * pReturn,
489 > LPOVERLAPPED pOverlapped)
490 >{
491 > // here a data buffer on the stack sent to asynchronous DeviceIoControl
492 >call
493 > int aDataIn[2];
494 > aDataIn[0] = param1;
495 > aDataIn[1] = param2;
496 >
497 > return DeviceIoControl(
498 > hDevice,
499 > DO_SOMETHING_IO,
500 > aDataIn,
501 > sizeof(int)*2,
502 > pReturn,
503 > sizeof(DWORD),
504 > pOverlapped);
505 >}
506 >
507 >The aDataIn buffer will not exist after DeviceIoControl returns (and
508 >when the I/O operation terminates). I know that for buffered IO the
509 >input data buffer is copyed by de IOManager to a nonpaged-pool area
510 >before passing the request to driver dispatch routine (DeviceControl).
511 >At the point of calling the dispatch routine (DeviceControl) the driver
512 >runs in the context of the calling thread so DeviceIoControl hasn't
513 >returned yet (?? or so I think) so aDataI
514 n will still be valid at the
515 >time IOManager copyes it to its buffer. So, this apears to work ok (at
516 >least in my opinion).
517 >
518 >Does I/O Manager use the Input buffer from the call to the Win32
519 >DeviceIoControl any where else after the first copy ?
520 >
521 >Is there any reason why this approach (passing a buffer on the stack to
522 >a asynchronous DeviceIoControl that uses buffered I/O) wouldn't work ?
523 >
524 >Allocating buffers from heap and deleting them on IO completion while
525 >managing asynchronous IO seems too much work ;-) .
526 >
527 >Thanks in advance for your opinions
528 >Radu W.
529 >
530 >--
531 >Radu Woinaroski
532 >Scitec
533 >Sydney, Australia
534 >Radu.Woinaroski@scitec.com.au
535 -----
536 Subject: Re: PCI ISR problem
537 Date: Fri, 20 Nov 1998 18:04:48 GMT
538 From: jeh@cmkrnl.com (Jamie Hanrahan)
539 Organization: Kernel Mode Systems, San Diego, CA
540 Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
541 References: 1
542
543 On Thu, 19 Nov 1998 15:46:13 -0600, Eric Gardiner
544 <eric.gardiner@natinst.com> wrote:
545
546 >I'm having problems with NT4 not hooking the interrupt line indicated by
547 >a PCI device. Here's what I'm doing:
548 >
549 >1) Enumerating the PCI buses on the system (using HalGetBusData) until
550 >I find my device.
551 >2) Once my device is found, I read the "Interrupt Line Register" in the
552 >device's PCI config space to determine what interrupt level to pass to
553 >HalGetInterruptVector.
554
555 Whups! No. Call HalAssignSlotResources and look at the returned
556 CM_RESOURCE_LIST to find the vector, level, port addresses, etc., for
557 your device. (Then pass the returned CM_RESOURCE_LIST to ExFreePool.)
558
559
560 See Knowledge Base article Q152044.
561
562 --- Jamie Hanrahan, Kernel Mode Systems, San Diego CA (jeh@cmkrnl.com)
563 Drivers, internals, networks, applications, and training for VMS and Windows NT
564 NT kernel driver FAQ, links, and other information: http://www.cmkrnl.com/
565
566 Please post replies, followups, questions, etc., in news, not via e-mail.
567 -----
568 Subject: Re: IRP canceling
569 Date: Mon, 23 Nov 1998 09:05:47 -0500
570 From: Walter Oney <waltoney@oneysoft.com>
571 Organization: Walter Oney Software
572 Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
573 References: 1
574
575 Seol,Keun Seok wrote:
576 > But, if the IRP was the CurrentIrp of the Device Object,
577 > the Driver's Start I/O routine will try to process the IRP.
578 > In the DDK help, the Start I/O routine MUST check the current IRP's
579 > Cancel bit.
580 > If set, Start I/O routine must just return.
581 >
582 > But I think that the IRP already completed should not be accessed.
583
584 You're absolutely right. I recommend the following code in a standard
585 StartIo routine to avoid the problem you point out:
586
587 VOID StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
588 {
589 KIRQL oldirql;
590 IoAcquireCancelSpinLock(&oldirql);
591 if (Irp != DeviceObject->CurrentIrp || Irp->Cancel)
592 {
593 IoReleaseCancelSpinLock(oldirql);
594 return;
595 }
596 else
597 {
598 IoSetCancelRoutine(Irp, NULL);
599 IoReleaseCancelSpinLock(oldirql);
600 }
601 . . .
602 }
603
604 This dovetails with a standard cancel routine:
605
606 VOID CancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp)
607 {
608 if (DeviceObject->CurrentIrp == Irp)
609 {
610 IoReleaseCancelSpinLock(Irp->CancelIrql);
611 IoStartNextPacket(DeviceObject, TRUE);
612 }
613 else
614 {
615 KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,
616 &Irp->Tail.Overlay.DeviceQueueEntry);
617 IoReleaseCancelSpinLock(Irp->CancelIrql);
618 }
619 Irp->IoStatus.Status = STATUS_CANCELLED;
620 Irp->IoStatus.Information = 0;
621 IoCompleteRequest(Irp, IO_NO_INCREMENT);
622 }
623
624 You need to remember that the C language specification requires that
625 evaluation of boolean operators short circuit when the result is known.
626 So, if StartIo discovers that the Irp it got as an argument is not the
627 same as CurrentIrp, it will not attempt to evaulate Irp->Cancel.
628
629 Now, as to why this works: StartIo gets called either by IoStartPacket
630 or IoStartNextPacket. Each of them will grab the cancel spin lock and
631 set CurrentIrp, then release the spin lock and call StartIo. If someone
632 should sneak in on another CPU and cancel this very same IRP, your
633 cancel routine will immediately release the spin lock and call
634 IoStartNextPacket. One of two things will then happen. IoStartNextPacket
635 may succeed in getting the cancel spin lock, whereupon it will nullify
636 the CurrentIrp pointer. If another IRP is on the queue, it will remove
637 it from the queue, set CurrentIrp to point to this *new* IRP, release
638 the spin lock, and call StartIo. [You now have two instances of StartIo
639 running on two different CPUs for two different IRPs, but it's not a
640 problem because they won't be able to interfere with each other.]
641 Meanwhile, your original instance of StartIo gets the cancel spin lock
642 and sees that CurrentIrp is not equal to the IRP pointer it got as an
643 argument, so it gives up.
644
645 The second way this could play out is that StartIo gets the cancel lock
646 before IoStartNextPacket does. In this case, CurrentIrp is still
647 pointing to the IRP that's in the process of being cancelled and that
648 StartIo got as an argument. But this IRP hasn't been completed yet (the
649 CPU that's running your cancel routine is spinning inside
650 IoStartNextPacket and therefore hasn't gotten to calling
651 IoCompleteRequest yet), so no-one will have been able to call IoFreeIrp
652 to make your pointer invalid.
653
654 People may tell you that you should be using your own queues for IRPs so
655 you can avoid bottlenecking the system on the global cancel spin lock.
656 That's true enough, but doing it correctly with Plug and Play and Power
657 management things in the way is gigantically complicated. There's a
658 sample in the NT 5 beta-2 DDK called CANCEL that shows how to manage
659 your own queue if you don't worry about PNP and POWER. I hear tell of an
660 upcoming MSJ article by a Microsoft developer that may solve the
661 complete problem.
662 -----
663 Subject: ANNOUNCE: ALINK v1.5
664 Date: 16 Nov 1998 16:36:05 GMT
665 From: anthony_w@my-dejanews.com
666 Organization: Deja News - The Leader in Internet Discussion
667 Newsgroups: comp.os.ms-windows.programmer.win32, comp.lang.asm.x86, comp.os.msdos.programmer
668
669 ALINK is a freeware linker, creating MSDOS COM and EXE files and Win32 PE EXE
670 and DLL files from OMF format OBJ and LIB files, win32-COFF format OBJ files,
671 and win32 RES files.
672
673 NEW for version 1.5:
674
675 Win32 COFF object file support.
676
677 Download it now from my home page.
678
679 Anthony
680 --
681 anthony_w@geocities.com
682 http://www.geocities.com/SiliconValley/Network/4311/index.html
683
684 -----------== Posted via Deja News, The Discussion Network ==----------
685 http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
686 -----
687