Whamcloud - gitweb
LU-2446 build: Update Whamcloud copyright messages for Intel
[fs/lustre-release.git] / libcfs / include / libcfs / winnt / winnt-lock.h
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * libcfs/include/libcfs/winnt/winnt-lock.h
37  *
38  * Basic library routines.
39  */
40
41 #ifndef __LIBCFS_WINNT_CFS_LOCK_H__
42 #define __LIBCFS_WINNT_CFS_LOCK_H__
43
44 #ifndef __LIBCFS_LIBCFS_H__
45 #error Do not #include this file directly. #include <libcfs/libcfs.h> instead
46 #endif
47
48 #ifdef __KERNEL__
49
50
51 /*
52  * IMPORTANT !!!!!!!!
53  *
54  * All locks' declaration are not guaranteed to be initialized,
55  * Althought some of they are initialized in Linux. All locks
56  * declared by CFS_DECL_* should be initialized explicitly.
57  */
58
59 /*
60  *  spinlock & event definitions
61  */
62
63 typedef struct spin_lock spinlock_t;
64
65 /* atomic */
66
67 typedef struct { volatile int counter; } cfs_atomic_t;
68
69 #define CFS_ATOMIC_INIT(i)      { i }
70
71 #define cfs_atomic_read(v)      ((v)->counter)
72 #define cfs_atomic_set(v,i)     (((v)->counter) = (i))
73
74 void FASTCALL cfs_atomic_add(int i, cfs_atomic_t *v);
75 void FASTCALL cfs_atomic_sub(int i, cfs_atomic_t *v);
76
77 int FASTCALL cfs_atomic_sub_and_test(int i, cfs_atomic_t *v);
78
79 void FASTCALL cfs_atomic_inc(cfs_atomic_t *v);
80 void FASTCALL cfs_atomic_dec(cfs_atomic_t *v);
81
82 int FASTCALL cfs_atomic_dec_and_test(cfs_atomic_t *v);
83 int FASTCALL cfs_atomic_inc_and_test(cfs_atomic_t *v);
84
85 int FASTCALL cfs_atomic_add_return(int i, cfs_atomic_t *v);
86 int FASTCALL cfs_atomic_sub_return(int i, cfs_atomic_t *v);
87
88 #define cfs_atomic_inc_return(v)  cfs_atomic_add_return(1, v)
89 #define cfs_atomic_dec_return(v)  cfs_atomic_sub_return(1, v)
90
91 int FASTCALL cfs_atomic_dec_and_lock(cfs_atomic_t *v, spinlock_t *lock);
92
93 /* event */
94
95 typedef KEVENT          event_t;
96
97 /*
98  * cfs_init_event
99  *   To initialize the event object
100  *
101  * Arguments:
102  *   event:  pointer to the event object
103  *   type:   Non Zero: SynchronizationEvent
104  *           Zero: NotificationEvent
105  *   status: the initial stats of the event
106  *           Non Zero: signaled
107  *           Zero: un-signaled
108  *
109  * Return Value:
110  *   N/A
111  *
112  * Notes:
113  *   N/A
114  */
115 static inline void
116 cfs_init_event(event_t *event, int type, int status)
117 {
118     KeInitializeEvent(
119             event,
120             (type) ? SynchronizationEvent: NotificationEvent,
121             (status) ? TRUE : FALSE
122             );
123 }
124
125 /*
126  * cfs_wait_event_internal
127  *   To wait on an event to syncrhonize the process
128  *
129  * Arguments:
130  *   event:  pointer to the event object
131  *   timeout: the timeout for waitting or 0 means infinite time.
132  *
133  * Return Value:
134  *   Zero:   waiting timeouts
135  *   Non Zero: event signaled ...
136  *
137  * Notes:
138  *   N/A
139  */
140
141 static inline int64_t
142 cfs_wait_event_internal(event_t * event, int64_t timeout)
143 {
144     NTSTATUS        Status;
145     LARGE_INTEGER   TimeOut;
146
147     TimeOut.QuadPart = -1 * (10000000/CFS_HZ) * timeout;
148
149     Status = KeWaitForSingleObject(
150                 event,
151                 Executive,
152                 KernelMode,
153                 FALSE,
154                 (timeout != 0) ? (&TimeOut) : (NULL)
155                 );
156
157     if (Status == STATUS_TIMEOUT)  {
158         return 0;
159     }
160
161     return TRUE; // signaled case
162 }
163
164 /*
165  * cfs_wake_event
166  *   To signal the event object
167  *
168  * Arguments:
169  *   event:  pointer to the event object
170  *
171  * Return Value:
172  *   N/A
173  *
174  * Notes:
175  *   N/A
176  */
177
178 static inline int
179 cfs_wake_event(event_t * event)
180 {
181     return (KeSetEvent(event, 0, FALSE) != 0);
182 }
183
184 /*
185  * cfs_clear_event
186  *   To clear/reset the status of the event object
187  *
188  * Arguments:
189  *   event:  pointer to the event object
190  *
191  * Return Value:
192  *   N/A
193  *
194  * Notes:
195  *   N/A
196  */
197
198 static inline void
199 cfs_clear_event(event_t * event)
200 {
201     KeResetEvent(event);
202 }
203
204 /*
205  * spin lock defintions / routines
206  */
207
208 /*
209  * Warning:
210  *
211  * for spinlock operations, try to grab nesting acquisition of
212  * spinlock will cause dead-lock in MP system and current irql
213  * overwritten for UP system. (UP system could allow nesting spin
214  * acqisition, because it's not spin at all just raising the irql.)
215  *
216  */
217
218 struct spin_lock {
219         KSPIN_LOCK      lock;
220         KIRQL           irql;
221 };
222
223 #define CFS_DECL_SPIN(name)             spinlock_t name;
224 #define CFS_DECL_SPIN_EXTERN(name)      extern spinlock_t name;
225
226 #define DEFINE_SPINLOCK {0}
227
228 static inline void spin_lock_init(spinlock_t *lock)
229 {
230         KeInitializeSpinLock(&(lock->lock));
231 }
232
233 static inline void spin_lock(spinlock_t *lock)
234 {
235         KeAcquireSpinLock(&(lock->lock), &(lock->irql));
236 }
237
238 static inline void spin_lock_nested(spinlock_t *lock, unsigned subclass)
239 {
240         KeAcquireSpinLock(&(lock->lock), &(lock->irql));
241 }
242
243 static inline void spin_unlock(spinlock_t *lock)
244 {
245         KIRQL   irql = lock->irql;
246         KeReleaseSpinLock(&(lock->lock), irql);
247 }
248
249
250 #define spin_lock_irqsave(lock, flags)  \
251         do { (flags) = 0; spin_lock(lock); } while (0)
252
253 #define spin_unlock_irqrestore(lock, flags) \
254         do { spin_unlock(lock); } while (0)
255
256
257 /* There's no  corresponding routine in windows kernel.
258    We must realize a light one of our own.  But there's
259    no way to identify the system is MP build or UP build
260    on the runtime. We just uses a workaround for it. */
261
262 extern int libcfs_mp_system;
263
264 static int spin_trylock(spinlock_t *lock)
265 {
266         KIRQL   Irql;
267         int     rc = 0;
268
269         ASSERT(lock != NULL);
270
271         KeRaiseIrql(DISPATCH_LEVEL, &Irql);
272
273         if (libcfs_mp_system) {
274                 if (0 == (ulong_ptr_t)lock->lock) {
275 #if _X86_
276                         __asm {
277                                 mov  edx, dword ptr [ebp + 8]
278                                 lock bts dword ptr[edx], 0
279                                 jb   lock_failed
280                                 mov  rc, TRUE
281                                 lock_failed:
282                         }
283 #else
284                         KdBreakPoint();
285 #endif
286
287                 }
288         } else {
289                 rc = TRUE;
290         }
291
292         if (rc) {
293                 lock->irql = Irql;
294         } else {
295                 KeLowerIrql(Irql);
296         }
297
298         return rc;
299 }
300
301 static int spin_is_locked(spinlock_t *lock)
302 {
303 #if _WIN32_WINNT >= 0x502
304         /* KeTestSpinLock only avalilable on 2k3 server or later */
305         return !KeTestSpinLock(&lock->lock);
306 #else
307         return (int) (lock->lock);
308 #endif
309 }
310
311 /* synchronization between cpus: it will disable all DPCs
312    kernel task scheduler on the CPU */
313 #define spin_lock_bh(x)         spin_lock(x)
314 #define spin_unlock_bh(x)       spin_unlock(x)
315 #define spin_lock_bh_init(x)    spin_lock_init(x)
316
317 /*
318  * rw_semaphore (using ERESOURCE)
319  */
320
321
322 struct rw_semaphore {
323         ERESOURCE       rwsem;
324 };
325
326
327 #define DECLARE_RWSEM(name) struct rw_semaphore name
328 #define CFS_DECLARE_RWSEM_EXTERN(name) extern struct rw_semaphore name
329
330 /*
331  * init_rwsem
332  *   To initialize the the rw_semaphore structure
333  *
334  * Arguments:
335  *   rwsem:  pointer to the rw_semaphore structure
336  *
337  * Return Value:
338  *   N/A
339  *
340  * Notes:
341  *   N/A
342  */
343
344 static inline void init_rwsem(struct rw_semaphore *s)
345 {
346         ExInitializeResourceLite(&s->rwsem);
347 }
348 #define rwsem_init init_rwsem
349
350 /*
351  * fini_rwsem
352  *   To finilize/destroy the the rw_semaphore structure
353  *
354  * Arguments:
355  *   rwsem:  pointer to the rw_semaphore structure
356  *
357  * Return Value:
358  *   N/A
359  *
360  * Notes:
361  *   For winnt system, we need this routine to delete the ERESOURCE.
362  *   Just define it NULL for other systems.
363  */
364
365 static inline void fini_rwsem(struct rw_semaphore *s)
366 {
367         ExDeleteResourceLite(&s->rwsem);
368 }
369
370 /*
371  * down_read
372  *   To acquire read-lock of the rw_semaphore
373  *
374  * Arguments:
375  *   rwsem:  pointer to the struct rw_semaphore
376  *
377  * Return Value:
378  *   N/A
379  *
380  * Notes:
381  *   N/A
382  */
383
384 static inline void down_read(struct rw_semaphore *s)
385 {
386         ExAcquireResourceSharedLite(&s->rwsem, TRUE);
387 }
388 #define down_read_nested down_read
389
390
391 /*
392  * down_read_trylock
393  *   To acquire read-lock of the rw_semaphore without blocking
394  *
395  * Arguments:
396  *   rwsem:  pointer to the struct rw_semaphore
397  *
398  * Return Value:
399  *   Zero: failed to acquire the read lock
400  *   Non-Zero: succeeded to acquire the read lock
401  *
402  * Notes:
403  *   This routine will return immediately without waiting.
404  */
405
406 static inline int down_read_trylock(struct rw_semaphore *s)
407 {
408         return ExAcquireResourceSharedLite(&s->rwsem, FALSE);
409 }
410
411
412 /*
413  * down_write
414  *   To acquire write-lock of the struct rw_semaphore
415  *
416  * Arguments:
417  *   rwsem:  pointer to the struct rw_semaphore
418  *
419  * Return Value:
420  *   N/A
421  *
422  * Notes:
423  *   N/A
424  */
425
426 static inline void down_write(struct rw_semaphore *s)
427 {
428         ExAcquireResourceExclusiveLite(&(s->rwsem), TRUE);
429 }
430 #define down_write_nested down_write
431
432 /*
433  * down_write_trylock
434  *   To acquire write-lock of the rw_semaphore without blocking
435  *
436  * Arguments:
437  *   rwsem:  pointer to the struct rw_semaphore
438  *
439  * Return Value:
440  *   Zero: failed to acquire the write lock
441  *   Non-Zero: succeeded to acquire the read lock
442  *
443  * Notes:
444  *   This routine will return immediately without waiting.
445  */
446
447 static inline int down_write_trylock(struct rw_semaphore *s)
448 {
449         return ExAcquireResourceExclusiveLite(&(s->rwsem), FALSE);
450 }
451
452
453 /*
454  * up_read
455  *   To release read-lock of the rw_semaphore
456  *
457  * Arguments:
458  *   rwsem:  pointer to the struct rw_semaphore
459  *
460  * Return Value:
461  *   N/A
462  *
463  * Notes:
464  *   N/A
465  */
466
467 static inline void up_read(struct rw_semaphore *s)
468 {
469         ExReleaseResourceForThreadLite(&(s->rwsem),
470                                        ExGetCurrentResourceThread());
471 }
472
473
474 /*
475  * up_write
476  *   To release write-lock of the rw_semaphore
477  *
478  * Arguments:
479  *   rwsem:  pointer to the struct rw_semaphore
480  *
481  * Return Value:
482  *   N/A
483  *
484  * Notes:
485  *   N/A
486  */
487
488 static inline void up_write(struct rw_semaphore *s)
489 {
490         ExReleaseResourceForThreadLite(&(s->rwsem),
491                                        ExGetCurrentResourceThread());
492 }
493
494 /*
495  * rwlock_t (using sempahore)
496  *
497  * - rwlock_init(x)
498  * - read_lock(x)
499  * - read_unlock(x)
500  * - write_lock(x)
501  * - write_unlock(x)
502  */
503
504 typedef struct {
505         spinlock_t      guard;
506         int             count;
507 } rwlock_t;
508
509 void rwlock_init(rwlock_t *rwlock);
510 void cfs_rwlock_fini(rwlock_t *rwlock);
511
512 void read_lock(rwlock_t *rwlock);
513 void read_unlock(rwlock_t *rwlock);
514 void write_lock(rwlock_t *rwlock);
515 void write_unlock(rwlock_t *rwlock);
516
517 #define write_lock_irqsave(l, f)        do { f = 0; write_lock(l); } while (0)
518 #define write_unlock_irqrestore(l, f)   do { write_unlock(l); } while (0)
519 #define read_lock_irqsave(l, f)         do { f = 0; read_lock(l); } while (0)
520 #define read_unlock_irqrestore(l, f)    do { read_unlock(l); } while (0)
521
522 #define write_lock_bh           write_lock
523 #define write_unlock_bh write_unlock
524
525 struct lock_class_key {
526         int foo;
527 };
528
529 #define lockdep_set_class(lock, class) do {} while (0)
530
531 static inline void lockdep_off(void)
532 {
533 }
534
535 static inline void lockdep_on(void)
536 {
537 }
538
539 /*
540  * Semaphore
541  *
542  * - sema_init(x, v)
543  * - __down(x)
544  * - __up(x)
545  */
546
547 struct semaphore {
548         KSEMAPHORE sem;
549 };
550
551 static inline void sema_init(struct semaphore *s, int val)
552 {
553         KeInitializeSemaphore(&s->sem, val, val);
554 }
555
556 static inline void __down(struct semaphore *s)
557 {
558         KeWaitForSingleObject(&(s->sem), Executive, KernelMode, FALSE, NULL);
559
560 }
561 static inline void __up(struct semaphore *s)
562 {
563         KeReleaseSemaphore(&s->sem, 0, 1, FALSE);
564 }
565
566 static inline int down_trylock(struct semaphore *s)
567 {
568         LARGE_INTEGER  timeout = {0};
569         NTSTATUS status = KeWaitForSingleObject(&(s->sem), Executive,
570                                                 KernelMode, FALSE, &timeout);
571
572         if (status == STATUS_SUCCESS)
573                 return 0;
574
575         return 1;
576 }
577
578 /*
579  * mutex_t:
580  *
581  * - init_mutex(x)
582  * - init_mutex_locked(x)
583  * - mutex_up(x)
584  * - mutex_down(x)
585  */
586
587 #define mutex semaphore
588
589 #define CFS_DECLARE_MUTEX(x) struct mutex x
590
591 /*
592  * init_mutex
593  *   To initialize a mutex_t structure
594  *
595  * Arguments:
596  *   mutex:  pointer to the mutex_t structure
597  *
598  * Return Value:
599  *   N/A
600  *
601  * Notes:
602  *   N/A
603  */
604 #define mutex_init cfs_init_mutex
605 static inline void cfs_init_mutex(struct mutex *mutex)
606 {
607         sema_init(mutex, 1);
608 }
609
610 /*
611  * mutex_down
612  *   To acquire the mutex lock
613  *
614  * Arguments:
615  *   mutex:  pointer to the mutex_t structure
616  *
617  * Return Value:
618  *   N/A
619  *
620  * Notes:
621  *   N/A
622  */
623
624 static inline void cfs_mutex_down(struct mutex *mutex)
625 {
626         __down(mutex);
627 }
628
629 static inline int cfs_mutex_down_interruptible(struct mutex *mutex)
630 {
631         __down(mutex);
632         return 0;
633 }
634
635 #define mutex_lock(m)           cfs_mutex_down(m)
636 #define mutex_trylock(s)        down_trylock(s)
637 #define mutex_lock_nested(m)    cfs_mutex_down(m)
638 #define down(m)                 cfs_mutex_down(m)
639 #define down_interruptible(m)   cfs_mutex_down_interruptible(m)
640
641 /*
642  * mutex_up
643  *   To release the mutex lock (acquired already)
644  *
645  * Arguments:
646  *   mutex:  pointer to the mutex_t structure
647  *
648  * Return Value:
649  *   N/A
650  *
651  * Notes:
652  *   N/A
653  */
654
655 static inline void cfs_mutex_up(struct mutex *mutex)
656 {
657         __up(mutex);
658 }
659
660 #define mutex_unlock(m)         cfs_mutex_up(m)
661 #define up(m)                   cfs_mutex_up(m)
662
663 /*
664  * init_mutex_locked
665  *   To initialize the mutex as acquired state
666  *
667  * Arguments:
668  *   mutex:  pointer to the mutex_t structure
669  *
670  * Return Value:
671  *   N/A
672  *
673  * Notes:
674  *   N/A
675  */
676
677 static inline void cfs_init_mutex_locked(struct mutex *mutex)
678 {
679         cfs_init_mutex(mutex);
680         cfs_mutex_down(mutex);
681 }
682
683 static inline void mutex_destroy(struct mutex *mutex)
684 {
685 }
686
687 /*
688  * completion
689  *
690  * - init_complition(c)
691  * - complete(c)
692  * - wait_for_completion(c)
693  */
694
695 struct completion{
696         event_t  event;
697 };
698
699
700 /*
701  * init_completion
702  *   To initialize the completion object
703  *
704  * Arguments:
705  *   c:  pointer to the completion structure
706  *
707  * Return Value:
708  *   N/A
709  *
710  * Notes:
711  *   N/A
712  */
713
714 static inline void init_completion(struct completion *c)
715 {
716         cfs_init_event(&(c->event), 1, FALSE);
717 }
718
719
720 /*
721  * complete
722  *   To complete/signal the completion object
723  *
724  * Arguments:
725  *   c:  pointer to the completion structure
726  *
727  * Return Value:
728  *   N/A
729  *
730  * Notes:
731  *   N/A
732  */
733
734 static inline void complete(struct completion *c)
735 {
736         cfs_wake_event(&(c->event));
737 }
738
739 /*
740  * wait_for_completion
741  *   To wait on the completion object. If the event is signaled,
742  *   this function will return to the call with the event un-singled.
743  *
744  * Arguments:
745  *   c:  pointer to the completion structure
746  *
747  * Return Value:
748  *   N/A
749  *
750  * Notes:
751  *   N/A
752  */
753
754 static inline void wait_for_completion(struct completion *c)
755 {
756         cfs_wait_event_internal(&(c->event), 0);
757 }
758
759 static inline int wait_for_completion_interruptible(struct completion *c)
760 {
761         cfs_wait_event_internal(&(c->event), 0);
762         return 0;
763 }
764
765 #endif /* !__KERNEL__ */
766 #endif