Ядро Linux в комментариях

       

Include/asm-i386/semaphore.h


11579 #ifndef _I386_SEMAPHORE_H 11580 #define _I386_SEMAPHORE_H 11581 11582 #include <linux/linkage.h> 11583 11584 /* 11585 * SMP- and interrupt-safe semaphores.. 11586 * 11587 * (C) Copyright 1996 Linus Torvalds 11588 * 11589 * Modified 1996-12-23 by Dave Grothe <dave@gcom.com> to 11590 * fix bugs in the original code and to make semaphore 11591 * waits interruptible so that processes waiting on 11592 * semaphores can be killed. 11593 * Modified 1999-02-14 by Andrea Arcangeli, split the 11594 * sched.c helper functions in asm/sempahore-helper.h 11595 * while fixing a potential and subtle race discovered by 11596 * Ulrich Schmid in down_interruptible(). Since I started 11597 * to play here I also implemented the `trylock' 11598 * semaphore operation. 11599 * 11600 * If you would like to see an analysis of this 11601 * implementation, please ftp to gcom.com and download 11602 * the file 11603 * /pub/linux/src/semaphore/semaphore-2.0.24.tar.gz. */ 11604 11605 #include <asm/system.h> 11606 #include <asm/atomic.h> 11607 #include <asm/spinlock.h> 11608 11609 struct semaphore { 11610 atomic_t count; 11611 int waking; 11612 struct wait_queue * wait; 11613 }; 11614 11615 #define MUTEX \ 11616 ((struct semaphore) { ATOMIC_INIT(1), 0, NULL }) 11617 #define MUTEX_LOCKED \ 11618 ((struct semaphore) { ATOMIC_INIT(0), 0, NULL }) 11619 11620 asmlinkage void 11621 __down_failed(void /* special reg calling convention */); 11622 asmlinkage int 11623 __down_failed_interruptible(void /* params in regs */); 11624 asmlinkage int 11625 __down_failed_trylock(void /* params in registers */); 11626 asmlinkage void 11627 __up_wakeup(void /* special reg calling convention */); 11628 11629 asmlinkage void __down(struct semaphore * sem); 11630 asmlinkage int __down_interruptible( 11631 struct semaphore * sem); 11632 asmlinkage int __down_trylock(struct semaphore * sem); 11633 asmlinkage void __up(struct semaphore * sem); 11634 11635 extern spinlock_t semaphore_wake_lock; 11636 11637 #define sema_init(sem, val) \ 11638 atomic_set(&((sem)->count), (val)) 11639 11640 /* This is ugly, but we want the default case to fall 11641 * through. "down_failed" is a special asm handler that 11642 * calls the C routine that actually waits. See 11643 * arch/i386/lib/semaphore.S */


11644 extern inline void down(struct semaphore * sem) 11645 { 11646 __asm__ __volatile__( 11647 "# atomic down operation\n\t" 11648 #ifdef __SMP__ 11649 "lock ; " 11650 #endif 11651 "decl 0(%0)\n\t" 11652 "js 2f\n" 11653 "1:\n" 11654 ".section .text.lock,\"ax\"\n" 11655 "2:\tpushl $1b\n\t" 11656 "jmp __down_failed\n" 11657 ".previous" 11658 :/* no outputs */ 11659 :"c" (sem) 11660 :"memory"); 11661 } 11662 11663 extern inline int

11664 down_interruptible(struct semaphore * sem) 11665 { 11666 int result; 11667 11668 __asm__ __volatile__( 11669 "# atomic interruptible down operation\n\t" 11670 #ifdef __SMP__ 11671 "lock ; " 11672 #endif 11673 "decl 0(%1)\n\t" 11674 "js 2f\n\t" 11675 "xorl %0,%0\n" 11676 "1:\n" 11677 ".section .text.lock,\"ax\"\n" 11678 "2:\tpushl $1b\n\t" 11679 "jmp __down_failed_interruptible\n" 11680 ".previous" 11681 :"=a" (result) 11682 :"c" (sem) 11683 :"memory"); 11684 return result; 11685 } 11686

11687 extern inline int down_trylock(struct semaphore * sem) 11688 { 11689 int result; 11690 11691 __asm__ __volatile__( 11692 "# atomic interruptible down operation\n\t" 11693 #ifdef __SMP__ 11694 "lock ; " 11695 #endif 11696 "decl 0(%1)\n\t" 11697 "js 2f\n\t" 11698 "xorl %0,%0\n" 11699 "1:\n" 11700 ".section .text.lock,\"ax\"\n" 11701 "2:\tpushl $1b\n\t" 11702 "jmp __down_failed_trylock\n" 11703 ".previous" 11704 :"=a" (result) 11705 :"c" (sem) 11706 :"memory"); 11707 return result; 11708 } 11709 11710 /* Note! This is subtle. We jump to wake people up only 11711 * if the semaphore was negative (== somebody was waiting 11712 * on it). The default case (no contention) will result 11713 * in NO jumps for both down() and up(). */

11714 extern inline void up(struct semaphore * sem) 11715 { 11716 __asm__ __volatile__( 11717 "# atomic up operation\n\t" 11718 #ifdef __SMP__ 11719 "lock ; " 11720 #endif 11721 "incl 0(%0)\n\t" 11722 "jle 2f\n" 11723 "1:\n" 11724 ".section .text.lock,\"ax\"\n" 11725 "2:\tpushl $1b\n\t" 11726 "jmp __up_wakeup\n" 11727 ".previous" 11728 :/* no outputs */ 11729 :"c" (sem) 11730 :"memory"); 11731 } 11732 11733 #endif


Содержание раздела