linux编辑信号量,信号量在Linux中的实现





在Linux 3.13中,普通信号量的定义如下

count<0, 其绝对值表示在等待队列中的进程个数;count>0,表示可以同时进入临界区域的进程个数。down操作对count减1,如果count<0,则进程进入等待队列;up操作对count加1,如果count>=0,这唤醒一个等待队列上的进程。

sleepers 对当前临界资源的进程个数的辅助计数。

在linux中对信号量的操作有up(),down()和down_interuptible()。down()和down_interuptible唯一的区别,在等待过程中,down_interuptible()可以被其他信号中断,而down()不可以。

up函数的调用次序是:先调用up_wakeup(),在调用__up()。而down()函数的次序是:先调用down_failed(),再调用__down().

函数实现

/**

43 * down - acquire the semaphore

44 * @sem: the semaphore to be acquired

45 *

46 * Acquires the semaphore. If no more tasks are allowed to acquire the

47 * semaphore, calling this function will put the task to sleep until the

48 * semaphore is released.

49 *

50 * Use of this function is deprecated, please use down_interruptible() or

51 * down_killable() instead.

52 */

53 void down(struct semaphore *sem)

54 {

55 unsigned long flags;

56

57 raw_spin_lock_irqsave(&sem->lock, flags);

58 if (likely(sem->count > 0))

59 sem->count--;

60 else

61 __down(sem);

62 raw_spin_unlock_irqrestore(&sem->lock, flags);

63 }

64 EXPORT_SYMBOL(down);

65

66 /**

67 * down_interruptible - acquire the semaphore unless interrupted

68 * @sem: the semaphore to be acquired

69 *

70 * Attempts to acquire the semaphore. If no more tasks are allowed to

71 * acquire the semaphore, calling this function will put the task to sleep.

72 * If the sleep is interrupted by a signal, this function will return -EINTR.

73 * If the semaphore is successfully acquired, this function returns 0.

74 */

75 int down_interruptible(struct semaphore *sem)

76 {

77 unsigned long flags;

78 int result = 0;

79

80 raw_spin_lock_irqsave(&sem->lock, flags);

81 if (likely(sem->count > 0))

82 sem->count--;

83 else

84 result = __down_interruptible(sem);

85 raw_spin_unlock_irqrestore(&sem->lock, flags);

86

87 return result;

88 }

89 EXPORT_SYMBOL(down_interruptible);

90

91 /**

92 * down_killable - acquire the semaphore unless killed

93 * @sem: the semaphore to be acquired

94 *

95 * Attempts to acquire the semaphore. If no more tasks are allowed to

96 * acquire the semaphore, calling this function will put the task to sleep.

97 * If the sleep is interrupted by a fatal signal, this function will return

98 * -EINTR. If the semaphore is successfully acquired, this function returns

99 * 0.

100 */

101 int down_killable(struct semaphore *sem)

102 {

103 unsigned long flags;

104 int result = 0;

105

106 raw_spin_lock_irqsave(&sem->lock, flags);

107 if (likely(sem->count > 0))

108 sem->count--;

109 else

110 result = __down_killable(sem);

111 raw_spin_unlock_irqrestore(&sem->lock, flags);

112

113 return result;

114 }

115 EXPORT_SYMBOL(down_killable);

116

117 /**

118 * down_trylock - try to acquire the semaphore, without waiting

119 * @sem: the semaphore to be acquired

120 *

121 * Try to acquire the semaphore atomically. Returns 0 if the semaphore has

122 * been acquired successfully or 1 if it it cannot be acquired.

123 *

124 * NOTE: This return value is inverted from both spin_trylock and

125 * mutex_trylock! Be careful about this when converting code.

126 *

127 * Unlike mutex_trylock, this function can be used from interrupt context,

128 * and the semaphore can be released by any task or interrupt.

129 */

130 int down_trylock(struct semaphore *sem)

131 {

132 unsigned long flags;

133 int count;

134

135 raw_spin_lock_irqsave(&sem->lock, flags);

136 count = sem->count - 1;

137 if (likely(count >= 0))

138 sem->count = count;

139 raw_spin_unlock_irqrestore(&sem->lock, flags);

140

141 return (count < 0);

142 }

143 EXPORT_SYMBOL(down_trylock);

144

145 /**

146 * down_timeout - acquire the semaphore within a specified time

147 * @sem: the semaphore to be acquired

148 * @jiffies: how long to wait before failing

149 *

150 * Attempts to acquire the semaphore. If no more tasks are allowed to

151 * acquire the semaphore, calling this function will put the task to sleep.

152 * If the semaphore is not released within the specified number of jiffies,

153 * this function returns -ETIME. It returns 0 if the semaphore was acquired.

154 */

155 int down_timeout(struct semaphore *sem, long jiffies)

156 {

157 unsigned long flags;

158 int result = 0;

159

160 raw_spin_lock_irqsave(&sem->lock, flags);

161 if (likely(sem->count > 0))

162 sem->count--;

163 else

164 result = __down_timeout(sem, jiffies);

165 raw_spin_unlock_irqrestore(&sem->lock, flags);

166

167 return result;

168 }

169 EXPORT_SYMBOL(down_timeout);

170

171 /**

172 * up - release the semaphore

173 * @sem: the semaphore to release

174 *

175 * Release the semaphore. Unlike mutexes, up() may be called from any

176 * context and even by tasks which have never called down().

177 */

178 void up(struct semaphore *sem)

179 {

180 unsigned long flags;

181

182 raw_spin_lock_irqsave(&sem->lock, flags);

183 if (likely(list_empty(&sem->wait_list)))

184 sem->count++;

185 else

186 __up(sem);

187 raw_spin_unlock_irqrestore(&sem->lock, flags);

188 }

189 EXPORT_SYMBOL(up);

190

191 /* Functions for the contended case */

192

193 struct semaphore_waiter {

194 struct list_head list;

195 struct task_struct *task;

196 bool up;

197 };

198

199 /*

200 * Because this function is inlined, the 'state' parameter will be

201 * constant, and thus optimised away by the compiler. Likewise the

202 * 'timeout' parameter for the cases without timeouts.

203 */

204 static inline int __sched __down_common(struct semaphore *sem, long state,

205 long timeout)

206 {

207 struct task_struct *task = current;

208 struct semaphore_waiter waiter;

209

210 list_add_tail(&waiter.list, &sem->wait_list);

211 waiter.task = task;

212 waiter.up = false;

213

214 for (;;) {

215 if (signal_pending_state(state, task))

216 goto interrupted;

217 if (unlikely(timeout <= 0))

218 goto timed_out;

219 __set_task_state(task, state);

220 raw_spin_unlock_irq(&sem->lock);

221 timeout = schedule_timeout(timeout);

222 raw_spin_lock_irq(&sem->lock);

223 if (waiter.up)

224 return 0;

225 }

226

227 timed_out:

228 list_del(&waiter.list);

229 return -ETIME;

230

231 interrupted:

232 list_del(&waiter.list);

233 return -EINTR;

234 }

235

236 static noinline void __sched __down(struct semaphore *sem)

237 {

238 __down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);

239 }

240

241 static noinline int __sched __down_interruptible(struct semaphore *sem)

242 {

243 return __down_common(sem, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);

244 }

245

246 static noinline int __sched __down_killable(struct semaphore *sem)

247 {

248 return __down_common(sem, TASK_KILLABLE, MAX_SCHEDULE_TIMEOUT);

249 }

250

251 static noinline int __sched __down_timeout(struct semaphore *sem, long jiffies)

252 {

253 return __down_common(sem, TASK_UNINTERRUPTIBLE, jiffies);

254 }

255

256 static noinline void __sched __up(struct semaphore *sem)

257 {

258 struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,

259 struct semaphore_waiter, list);

260 list_del(&waiter->list);

261 waiter->up = true;

262 wake_up_process(waiter->task);



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值