LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 846|回复: 0

sem.c

[复制链接]
发表于 2004-2-5 21:43:07 | 显示全部楼层 |阅读模式

  1. 1 /*
  2.   2  * linux/ipc/sem.c
  3.   3  * Copyright (C) 1992 Krishna Balasubramanian
  4.   4  * Copyright (C) 1995 Eric Schenk, Bruno Haible
  5.   5  *
  6.   6  * IMPLEMENTATION NOTES ON CODE REWRITE (Eric Schenk, January 1995):
  7.   7  * This code underwent a massive rewrite in order to solve some problems
  8.   8  * with the original code. In particular the original code failed to
  9.   9  * wake up processes that were waiting for semval to go to 0 if the
  10. 10  * value went to 0 and was then incremented rapidly enough. In solving
  11. 11  * this problem I have also modified the implementation so that it
  12. 12  * processes pending operations in a FIFO manner, thus give a guarantee
  13. 13  * that processes waiting for a lock on the semaphore won't starve
  14. 14  * unless another locking process fails to unlock.
  15. 15  * In addition the following two changes in behavior have been introduced:
  16. 16  * - The original implementation of semop returned the value
  17. 17  *   last semaphore element examined on success. This does not
  18. 18  *   match the manual page specifications, and effectively
  19. 19  *   allows the user to read the semaphore even if they do not
  20. 20  *   have read permissions. The implementation now returns 0
  21. 21  *   on success as stated in the manual page.
  22. 22  * - There is some confusion over whether the set of undo adjustments
  23. 23  *   to be performed at exit should be done in an atomic manner.
  24. 24  *   That is, if we are attempting to decrement the semval should we queue
  25. 25  *   up and wait until we can do so legally?
  26. 26  *   The original implementation attempted to do this.
  27. 27  *   The current implementation does not do so. This is because I don't
  28. 28  *   think it is the right thing (TM) to do, and because I couldn't
  29. 29  *   see a clean way to get the old behavior with the new design.
  30. 30  *   The POSIX standard and SVID should be consulted to determine
  31. 31  *   what behavior is mandated.
  32. 32  *
  33. 33  * Further notes on refinement (Christoph Rohland, December 1998):
  34. 34  * - The POSIX standard says, that the undo adjustments simply should
  35. 35  *   redo. So the current implementation is o.K.
  36. 36  * - The previous code had two flaws:
  37. 37  *   1) It actively gave the semaphore to the next waiting process
  38. 38  *      sleeping on the semaphore. Since this process did not have the
  39. 39  *      cpu this led to many unnecessary context switches and bad
  40. 40  *      performance. Now we only check which process should be able to
  41. 41  *      get the semaphore and if this process wants to reduce some
  42. 42  *      semaphore value we simply wake it up without doing the
  43. 43  *      operation. So it has to try to get it later. Thus e.g. the
  44. 44  *      running process may reacquire the semaphore during the current
  45. 45  *      time slice. If it only waits for zero or increases the semaphore,
  46. 46  *      we do the operation in advance and wake it up.
  47. 47  *   2) It did not wake up all zero waiting processes. We try to do
  48. 48  *      better but only get the semops right which only wait for zero or
  49. 49  *      increase. If there are decrement operations in the operations
  50. 50  *      array we do the same as before.
  51. 51  *
  52. 52  * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
  53. 53  *
  54. 54  * SMP-threaded, sysctl's added
  55. 55  * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  56. 56  * Enforced range limit on SEM_UNDO
  57. 57  * (c) 2001 Red Hat Inc <alan@redhat.com>
  58. 58  */
  59. 59
  60. 60 #include <linux/config.h>
  61. 61 #include <linux/slab.h>
  62. 62 #include <linux/spinlock.h>
  63. 63 #include <linux/init.h>
  64. 64 #include <linux/proc_fs.h>
  65. 65 #include <asm/uaccess.h>
  66. 66 #include "util.h"
  67. 67
  68. 68
  69. 69 #define sem_lock(id)    ((struct sem_array*)ipc_lock(&sem_ids,id))
  70. 70 #define sem_unlock(id)  ipc_unlock(&sem_ids,id)
  71. 71 #define sem_rmid(id)    ((struct sem_array*)ipc_rmid(&sem_ids,id))
  72. 72 #define sem_checkid(sma, semid) \
  73. 73         ipc_checkid(&sem_ids,&sma->sem_perm,semid)
  74. 74 #define sem_buildid(id, seq) \
  75. 75         ipc_buildid(&sem_ids, id, seq)
  76. 76 static struct ipc_ids sem_ids;
  77. 77
  78. 78 static int newary (key_t, int, int);
  79. 79 static void freeary (int id);
  80. 80 #ifdef CONFIG_PROC_FS
  81. 81 static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
  82. 82 #endif
  83. 83
  84. 84 #define SEMMSL_FAST     256 /* 512 bytes on stack */
  85. 85 #define SEMOPM_FAST     64  /* ~ 372 bytes on stack */
  86. 86
  87. 87 /*
  88. 88  * linked list protection:
  89. 89  *      sem_undo.id_next,
  90. 90  *      sem_array.sem_pending{,last},
  91. 91  *      sem_array.sem_undo: sem_lock() for read/write
  92. 92  *      sem_undo.proc_next: only "current" is allowed to read/write that field.
  93. 93  *      
  94. 94  */
  95. 95
  96. 96 int sem_ctls[4] = {SEMMSL, SEMMNS, SEMOPM, SEMMNI};
  97. 97 #define sc_semmsl       (sem_ctls[0])
  98. 98 #define sc_semmns       (sem_ctls[1])
  99. 99 #define sc_semopm       (sem_ctls[2])
  100. 100 #define sc_semmni       (sem_ctls[3])
  101. 101
  102. 102 static int used_sems;
  103. 103
  104. 104 void __init sem_init (void)
  105. 105 {
  106. 106         used_sems = 0;
  107. 107         ipc_init_ids(&sem_ids,sc_semmni);
  108. 108
  109. 109 #ifdef CONFIG_PROC_FS
  110. 110         create_proc_read_entry("sysvipc/sem", 0, 0, sysvipc_sem_read_proc, NULL);
  111. 111 #endif
  112. 112 }
  113. 113
  114. 114 static int newary (key_t key, int nsems, int semflg)
  115. 115
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表