sv.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:13k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 2000-2001 Silicon Graphics, Inc.  All rights reserved
  7.  *
  8.  * This implemenation of synchronization variables is heavily based on
  9.  * one done by Steve Lord <lord@sgi.com>
  10.  *
  11.  * Paul Cassella <pwc@sgi.com>
  12.  */
  13. #include <linux/kernel.h>
  14. #include <linux/sched.h>
  15. #include <linux/init.h>
  16. #include <linux/interrupt.h>
  17. #include <asm/semaphore.h>
  18. #include <asm/hardirq.h>
  19. #include <asm/softirq.h>
  20. #include <asm/current.h>
  21. #include <asm/sn/sv.h>
  22. /* Define this to have sv_test() run some simple tests.
  23.    kernel_thread() must behave as expected when this is called.  */
  24. #undef RUN_SV_TEST
  25. #define DEBUG
  26. /* Set up some macros so sv_wait(), sv_signal(), and sv_broadcast()
  27.    can sanity check interrupt state on architectures where we know
  28.    how. */
  29. #ifdef DEBUG
  30.  #define SV_DEBUG_INTERRUPT_STATE
  31.  #ifdef __mips64
  32.   #define SV_TEST_INTERRUPTS_ENABLED(flags) ((flags & 0x1) != 0)
  33.   #define SV_TEST_INTERRUPTS_DISABLED(flags) ((flags & 0x1) == 0)
  34.   #define SV_INTERRUPT_TEST_WORKERS 31
  35.  #elif defined(__ia64)
  36.   #define SV_TEST_INTERRUPTS_ENABLED(flags) ((flags & 0x4000) != 0)
  37.   #define SV_TEST_INTERRUPTS_DISABLED(flags) ((flags & 0x4000) == 0)
  38.   #define SV_INTERRUPT_TEST_WORKERS 4 /* simulator's slow */
  39.  #else
  40.   #undef  SV_DEBUG_INTERRUPT_STATE
  41.   #define SV_INTERRUPT_TEST_WORKERS 4 /* reasonable? default. */
  42.  #endif /* __mips64 */
  43. #endif /* DEBUG */
  44. /* XXX FIXME hack hack hack.  Our mips64 tree is from before the
  45.    switch to WQ_FLAG_EXCLUSIVE, and our ia64 tree is from after it. */
  46. #ifdef TASK_EXCLUSIVE
  47.   #undef EXCLUSIVE_IN_QUEUE
  48. #else
  49.   #define EXCLUSIVE_IN_QUEUE
  50.   #define TASK_EXCLUSIVE 0 /* for the set_current_state() in sv_wait() */
  51. #endif
  52. static inline void sv_lock(sv_t *sv) {
  53. spin_lock(&sv->sv_lock);
  54. }
  55. static inline void sv_unlock(sv_t *sv) {
  56. spin_unlock(&sv->sv_lock);
  57. }
  58. /* up() is "extern inline", so we can't pass its address to sv_wait.
  59.    Use this function's address instead. */
  60. static void up_wrapper(struct semaphore *sem) {
  61. up(sem);
  62. }
  63. /* spin_unlock() is sometimes a macro. */
  64. static void spin_unlock_wrapper(spinlock_t *s) {
  65. spin_unlock(s);
  66. }
  67. /* XXX Perhaps sv_wait() should do the switch() each time and avoid
  68.    the extra indirection and the need for the _wrapper functions? */
  69. static inline void sv_set_mon_type(sv_t *sv, int type) {
  70. switch (type) {
  71. case SV_MON_SPIN:
  72. sv->sv_mon_unlock_func =
  73.   (sv_mon_unlock_func_t)spin_unlock_wrapper;
  74. break;
  75. case SV_MON_SEMA:
  76. sv->sv_mon_unlock_func =
  77.   (sv_mon_unlock_func_t)up_wrapper;
  78. if(sv->sv_flags & SV_INTS) {
  79. printk(KERN_ERR "sv_set_mon_type: The monitor lock "
  80.        "cannot be shared with interrupts if it is a "
  81.        "semaphore!n");
  82. BUG();
  83. }
  84. if(sv->sv_flags & SV_BHS) {
  85. printk(KERN_ERR "sv_set_mon_type: The monitor lock "
  86.        "cannot be shared with bottom-halves if it is "
  87.        "a semaphore!n");
  88. BUG();
  89. }
  90. break;
  91. #if 0 
  92. /*
  93.  * If needed, and will need to think about interrupts.  This
  94.  * may be needed, for example, if someone wants to use sv's
  95.  * with something like dev_base; writers need to hold two
  96.  * locks. 
  97.  */
  98. case SV_MON_CUSTOM: 
  99. {
  100. struct sv_mon_custom *c = lock;
  101. sv->sv_mon_unlock_func = c->sv_mon_unlock_func;
  102. sv->sv_mon_lock        = c->sv_mon_lock;
  103. break;
  104. }
  105. #endif
  106. default:
  107. printk(KERN_ERR "sv_set_mon_type: unknown type %d (0x%x)! "
  108.        "(flags 0x%x)n", type, type, sv->sv_flags);
  109. BUG();
  110. break;
  111. }
  112. sv->sv_flags |= type;
  113. }
  114. static inline void sv_set_ord(sv_t *sv, int ord) {
  115. if (!ord)
  116. ord = SV_ORDER_DEFAULT;
  117. if (ord != SV_ORDER_FIFO && ord != SV_ORDER_LIFO) {
  118. printk(KERN_EMERG "sv_set_ord: unknown order %d (0x%x)! ",
  119.        ord, ord);
  120. BUG();
  121. }
  122. sv->sv_flags |= ord;
  123. }
  124. void sv_init(sv_t *sv, sv_mon_lock_t *lock, int flags) 
  125. {
  126. int ord = flags & SV_ORDER_MASK;
  127. int type = flags & SV_MON_MASK;
  128. /* Copy all non-order, non-type flags */
  129. sv->sv_flags = (flags & ~(SV_ORDER_MASK | SV_MON_MASK));
  130. if((sv->sv_flags & (SV_INTS | SV_BHS)) == (SV_INTS | SV_BHS)) {
  131.   printk(KERN_ERR "sv_init: do not set both SV_INTS and SV_BHS, only SV_INTS.n");
  132.   BUG();
  133. }
  134. sv_set_ord(sv, ord);
  135. sv_set_mon_type(sv, type);
  136. /* If lock is NULL, we'll get it from sv_wait_compat() (and
  137.            ignore it in sv_signal() and sv_broadcast()). */
  138. sv->sv_mon_lock = lock;
  139. spin_lock_init(&sv->sv_lock);
  140. init_waitqueue_head(&sv->sv_waiters);
  141. }
  142. /*
  143.  * The associated lock must be locked on entry.  It is unlocked on return.
  144.  *
  145.  * Return values:
  146.  *
  147.  * n < 0 : interrupted,  -n jiffies remaining on timeout, or -1 if timeout == 0
  148.  * n = 0 : timeout expired
  149.  * n > 0 : sv_signal()'d, n jiffies remaining on timeout, or 1 if timeout == 0
  150.  */
  151. signed long sv_wait(sv_t *sv, int sv_wait_flags, unsigned long timeout) 
  152. {
  153. DECLARE_WAITQUEUE( wait, current );
  154. unsigned long flags;
  155. signed long ret = 0;
  156. #ifdef SV_DEBUG_INTERRUPT_STATE
  157. {
  158. unsigned long flags;
  159. __save_flags(flags);
  160. if(sv->sv_flags & SV_INTS) {
  161. if(SV_TEST_INTERRUPTS_ENABLED(flags)) {
  162. printk(KERN_ERR "sv_wait: SV_INTS and interrupts "
  163.        "enabled (flags: 0x%lx)n", flags);
  164. BUG();
  165. }
  166. } else {
  167. if (SV_TEST_INTERRUPTS_DISABLED(flags)) {
  168. printk(KERN_WARNING "sv_wait: !SV_INTS and interrupts "
  169.        "disabled! (flags: 0x%lx)n", flags);
  170. }
  171. }
  172. }
  173. #endif  /* SV_DEBUG_INTERRUPT_STATE */
  174. sv_lock(sv);
  175. sv->sv_mon_unlock_func(sv->sv_mon_lock);
  176. /* Add ourselves to the wait queue and set the state before
  177.  * releasing the sv_lock so as to avoid racing with the
  178.  * wake_up() in sv_signal() and sv_broadcast(). 
  179.  */
  180. /* don't need the _irqsave part, but there is no wq_write_lock() */
  181. wq_write_lock_irqsave(&sv->sv_waiters.lock, flags);
  182. #ifdef EXCLUSIVE_IN_QUEUE
  183. wait.flags |= WQ_FLAG_EXCLUSIVE;
  184. #endif
  185. switch(sv->sv_flags & SV_ORDER_MASK) {
  186. case SV_ORDER_FIFO:
  187. __add_wait_queue_tail(&sv->sv_waiters, &wait);
  188. break;
  189. case SV_ORDER_FILO:
  190. __add_wait_queue(&sv->sv_waiters, &wait);
  191. break;
  192. default:
  193. printk(KERN_ERR "sv_wait: unknown order!  (sv: 0x%p, flags: 0x%x)n",
  194. (void *)sv, sv->sv_flags);
  195. BUG();
  196. }
  197. wq_write_unlock_irqrestore(&sv->sv_waiters.lock, flags);
  198. if(sv_wait_flags & SV_WAIT_SIG)
  199. set_current_state(TASK_EXCLUSIVE | TASK_INTERRUPTIBLE  );
  200. else
  201. set_current_state(TASK_EXCLUSIVE | TASK_UNINTERRUPTIBLE);
  202. spin_unlock(&sv->sv_lock);
  203. if(sv->sv_flags & SV_INTS)
  204. local_irq_enable();
  205. else if(sv->sv_flags & SV_BHS)
  206. local_bh_enable();
  207. if (timeout)
  208. ret = schedule_timeout(timeout);
  209. else
  210. schedule();
  211. if(current->state != TASK_RUNNING) /* XXX Is this possible? */ {
  212. printk(KERN_ERR "sv_wait: state not TASK_RUNNING after "
  213.        "schedule().n");
  214. set_current_state(TASK_RUNNING);
  215. }
  216. remove_wait_queue(&sv->sv_waiters, &wait);
  217. /* Return cases:
  218.    - woken by a sv_signal/sv_broadcast
  219.    - woken by a signal
  220.    - woken by timeout expiring
  221. */
  222. /* XXX This isn't really accurate; we may have been woken
  223.            before the signal anyway.... */
  224. if(signal_pending(current))
  225. return timeout ? -ret : -1;
  226. return timeout ? ret : 1;
  227. }
  228. void sv_signal(sv_t *sv) 
  229. {
  230. /* If interrupts can acquire this lock, they can also acquire the
  231.    sv_mon_lock, which we must already have to have called this, so
  232.    interrupts must be disabled already.  If interrupts cannot
  233.    contend for this lock, we don't have to worry about it. */
  234. #ifdef SV_DEBUG_INTERRUPT_STATE
  235. if(sv->sv_flags & SV_INTS) {
  236. unsigned long flags;
  237. __save_flags(flags);
  238. if(SV_TEST_INTERRUPTS_ENABLED(flags))
  239. printk(KERN_ERR "sv_signal: SV_INTS and "
  240. "interrupts enabled! (flags: 0x%lx)n", flags);
  241. }
  242. #endif /* SV_DEBUG_INTERRUPT_STATE */
  243. sv_lock(sv);
  244. wake_up(&sv->sv_waiters);
  245. sv_unlock(sv);
  246. }
  247. void sv_broadcast(sv_t *sv) 
  248. {
  249. #ifdef SV_DEBUG_INTERRUPT_STATE
  250. if(sv->sv_flags & SV_INTS) {
  251. unsigned long flags;
  252. __save_flags(flags);
  253. if(SV_TEST_INTERRUPTS_ENABLED(flags))
  254. printk(KERN_ERR "sv_broadcast: SV_INTS and "
  255.        "interrupts enabled! (flags: 0x%lx)n", flags);
  256. }
  257. #endif /* SV_DEBUG_INTERRUPT_STATE */
  258. sv_lock(sv);
  259. wake_up_all(&sv->sv_waiters);
  260. sv_unlock(sv);
  261. }
  262. void sv_destroy(sv_t *sv) 
  263. {
  264. if(!spin_trylock(&sv->sv_lock)) {
  265. printk(KERN_ERR "sv_destroy: someone else has sv 0x%p locked!n", (void *)sv);
  266. BUG();
  267. }
  268. /* XXX Check that the waitqueue is empty? 
  269.        Mark the sv destroyed?
  270. */
  271. }
  272. #ifdef RUN_SV_TEST
  273. static DECLARE_MUTEX_LOCKED(talkback);
  274. static DECLARE_MUTEX_LOCKED(sem);
  275. sv_t sv;
  276. sv_t sv_filo;
  277. static int sv_test_1_w(void *arg) 
  278. {
  279. printk("sv_test_1_w: acquiring spinlock 0x%p...n", arg);
  280. spin_lock((spinlock_t*)arg);
  281. printk("sv_test_1_w: spinlock acquired, waking sv_test_1_s.n");
  282. up(&sem);
  283. printk("sv_test_1_w: sv_spin_wait()'ing.n");
  284. sv_spin_wait(&sv, arg);
  285. printk("sv_test_1_w: talkback.n");
  286. up(&talkback);
  287. printk("sv_test_1_w: exiting.n");
  288. return 0;
  289. }
  290. static int sv_test_1_s(void *arg) 
  291. {
  292. printk("sv_test_1_s: waiting for semaphore.n");
  293. down(&sem);
  294. printk("sv_test_1_s: semaphore acquired.  Acquiring spinlock.n");
  295. spin_lock((spinlock_t*)arg);
  296. printk("sv_test_1_s: spinlock acquired.  sv_signaling.n");
  297. sv_signal(&sv);
  298. printk("sv_test_1_s: talkback.n");
  299. up(&talkback);
  300. printk("sv_test_1_s: exiting.n");
  301. return 0;
  302. }
  303. static int count;
  304. static DECLARE_MUTEX(monitor);
  305. static int sv_test_2_w(void *arg) 
  306. {
  307. int dummy = count++;
  308. sv_t *sv = (sv_t *)arg;
  309. down(&monitor);
  310. up(&talkback);
  311. printk("sv_test_2_w: thread %d started, sv_waiting.n", dummy);
  312. sv_sema_wait(sv, &monitor);
  313. printk("sv_test_2_w: thread %d woken, exiting.n", dummy);
  314. up(&sem);
  315. return 0;
  316. }
  317. static int sv_test_2_s_1(void *arg) 
  318. {
  319. int i;
  320. sv_t *sv = (sv_t *)arg;
  321. down(&monitor);
  322. for(i = 0; i < 3; i++) {
  323. printk("sv_test_2_s_1: waking one thread.n");
  324. sv_signal(sv);
  325. down(&sem);
  326. }
  327. printk("sv_test_2_s_1: signaling and broadcasting again.  Nothing should happen.n");
  328. sv_signal(sv);
  329. sv_broadcast(sv);
  330. sv_signal(sv);
  331. sv_broadcast(sv);
  332. printk("sv_test_2_s_1: talkbacking.n");
  333. up(&talkback);
  334. up(&monitor);
  335. return 0;
  336. }
  337. static int sv_test_2_s(void *arg) 
  338. {
  339. int i;
  340. sv_t *sv = (sv_t *)arg;
  341. down(&monitor);
  342. for(i = 0; i < 3; i++) {
  343. printk("sv_test_2_s: waking one thread (should be %d.)n", i);
  344. sv_signal(sv);
  345. down(&sem);
  346. }
  347. printk("sv_test_3_s: waking remaining threads with broadcast.n");
  348. sv_broadcast(sv);
  349. for(; i < 10; i++)
  350. down(&sem);
  351. printk("sv_test_3_s: sending talkback.n");
  352. up(&talkback);
  353. printk("sv_test_3_s: exiting.n");
  354. up(&monitor);
  355. return 0;
  356. }
  357. static void big_test(sv_t *sv) 
  358. {
  359. int i;
  360. count = 0;
  361. for(i = 0; i < 3; i++) {
  362. printk("big_test: spawning thread %d.n", i);
  363. kernel_thread(sv_test_2_w, sv, 0);
  364. down(&talkback);
  365. }
  366. printk("big_test: spawning first wake-up thread.n");
  367. kernel_thread(sv_test_2_s_1, sv, 0);
  368. down(&talkback);
  369. printk("big_test: talkback happened.n");
  370. for(i = 3; i < 13; i++) {
  371. printk("big_test: spawning thread %d.n", i);
  372. kernel_thread(sv_test_2_w, sv, 0);
  373. down(&talkback);
  374. }
  375. printk("big_test: spawning wake-up thread.n");
  376. kernel_thread(sv_test_2_s, sv, 0);
  377. down(&talkback);
  378. }
  379. sv_t int_test_sv;
  380. spinlock_t int_test_spin = SPIN_LOCK_UNLOCKED;
  381. int int_test_ready;
  382. static int irqtestcount;
  383. static int interrupt_test_worker(void *unused) 
  384. {
  385. int id = ++irqtestcount;
  386. int it = 0;
  387. unsigned long flags, flags2;
  388. printk("ITW: thread %d started.n", id);
  389. while(1) {
  390. __save_flags(flags2);
  391. if(jiffies % 3) {
  392. printk("ITW %2d %5d: irqsaving          (%lx)n", id, it, flags2);
  393. spin_lock_irqsave(&int_test_spin, flags);
  394. } else {
  395. printk("ITW %2d %5d: spin_lock_irqing   (%lx)n", id, it, flags2);
  396. spin_lock_irq(&int_test_spin);
  397. }
  398. __save_flags(flags2);
  399. printk("ITW %2d %5d: locked, sv_waiting (%lx).n", id, it, flags2);
  400. sv_wait(&int_test_sv, 0, 0);
  401. __save_flags(flags2);
  402. printk("ITW %2d %5d: wait finished      (%lx), pausingn", id, it, flags2);
  403. set_current_state(TASK_INTERRUPTIBLE);
  404. schedule_timeout(jiffies & 0xf);
  405. if(current->state != TASK_RUNNING)
  406.   printk("ITW:  current->state isn't RUNNING after schedule!n");
  407. it++;
  408. }
  409. }
  410. static void interrupt_test(void) 
  411. {
  412. int i;
  413. printk("interrupt_test: initing sv.n");
  414. sv_init(&int_test_sv, &int_test_spin, SV_MON_SPIN | SV_INTS);
  415. for(i = 0; i < SV_INTERRUPT_TEST_WORKERS; i++) {
  416. printk("interrupt_test: starting test thread %d.n", i);
  417. kernel_thread(interrupt_test_worker, 0, 0);
  418. }
  419. printk("interrupt_test: done with init part.n");
  420. int_test_ready = 1;
  421. }
  422. int sv_test(void) 
  423. {
  424. spinlock_t s = SPIN_LOCK_UNLOCKED;
  425. sv_init(&sv, &s, SV_MON_SPIN);
  426. printk("sv_test: starting sv_test_1_w.n");
  427. kernel_thread(sv_test_1_w, &s, 0);
  428. printk("sv_test: starting sv_test_1_s.n");
  429. kernel_thread(sv_test_1_s, &s, 0);
  430. printk("sv_test: waiting for talkback.n");
  431. down(&talkback); down(&talkback);
  432. printk("sv_test: talkback happened, sv_destroying.n");
  433. sv_destroy(&sv);
  434. count = 0;
  435. printk("sv_test: beginning big_test on sv.n");
  436. sv_init(&sv, &monitor, SV_MON_SEMA);
  437. big_test(&sv);
  438. sv_destroy(&sv);
  439. printk("sv_test: beginning big_test on sv_filo.n");
  440. sv_init(&sv_filo, &monitor, SV_MON_SEMA | SV_ORDER_FILO);
  441. big_test(&sv_filo);
  442. sv_destroy(&sv_filo);
  443. interrupt_test();
  444. printk("sv_test: done.n");
  445. return 0;
  446. }
  447. __initcall(sv_test);
  448. #endif /* RUN_SV_TEST */