sv.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:13k
源码类别:

嵌入式Linux

开发平台:

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