⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 semaphore.c

📁 linux 内核源代码
💻 C
字号:
/* semaphore.c: FR-V semaphores * * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * - Derived from lib/rwsem-spinlock.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#include <linux/sched.h>#include <linux/module.h>#include <asm/semaphore.h>struct sem_waiter {	struct list_head	list;	struct task_struct	*task;};#ifdef CONFIG_DEBUG_SEMAPHOREvoid semtrace(struct semaphore *sem, const char *str){	if (sem->debug)		printk("[%d] %s({%d,%d})\n",		       current->pid,		       str,		       sem->counter,		       list_empty(&sem->wait_list) ? 0 : 1);}#else#define semtrace(SEM,STR) do { } while(0)#endif/* * wait for a token to be granted from a semaphore * - entered with lock held and interrupts disabled */void __down(struct semaphore *sem, unsigned long flags){	struct task_struct *tsk = current;	struct sem_waiter waiter;	semtrace(sem, "Entering __down");	/* set up my own style of waitqueue */	waiter.task = tsk;	get_task_struct(tsk);	list_add_tail(&waiter.list, &sem->wait_list);	/* we don't need to touch the semaphore struct anymore */	spin_unlock_irqrestore(&sem->wait_lock, flags);	/* wait to be given the semaphore */	set_task_state(tsk, TASK_UNINTERRUPTIBLE);	for (;;) {		if (list_empty(&waiter.list))			break;		schedule();		set_task_state(tsk, TASK_UNINTERRUPTIBLE);	}	tsk->state = TASK_RUNNING;	semtrace(sem, "Leaving __down");}EXPORT_SYMBOL(__down);/* * interruptibly wait for a token to be granted from a semaphore * - entered with lock held and interrupts disabled */int __down_interruptible(struct semaphore *sem, unsigned long flags){	struct task_struct *tsk = current;	struct sem_waiter waiter;	int ret;	semtrace(sem,"Entering __down_interruptible");	/* set up my own style of waitqueue */	waiter.task = tsk;	get_task_struct(tsk);	list_add_tail(&waiter.list, &sem->wait_list);	/* we don't need to touch the semaphore struct anymore */	set_task_state(tsk, TASK_INTERRUPTIBLE);	spin_unlock_irqrestore(&sem->wait_lock, flags);	/* wait to be given the semaphore */	ret = 0;	for (;;) {		if (list_empty(&waiter.list))			break;		if (unlikely(signal_pending(current)))			goto interrupted;		schedule();		set_task_state(tsk, TASK_INTERRUPTIBLE);	} out:	tsk->state = TASK_RUNNING;	semtrace(sem, "Leaving __down_interruptible");	return ret; interrupted:	spin_lock_irqsave(&sem->wait_lock, flags);	if (!list_empty(&waiter.list)) {		list_del(&waiter.list);		ret = -EINTR;	}	spin_unlock_irqrestore(&sem->wait_lock, flags);	if (ret == -EINTR)		put_task_struct(current);	goto out;}EXPORT_SYMBOL(__down_interruptible);/* * release a single token back to a semaphore * - entered with lock held and interrupts disabled */void __up(struct semaphore *sem){	struct task_struct *tsk;	struct sem_waiter *waiter;	semtrace(sem,"Entering __up");	/* grant the token to the process at the front of the queue */	waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);	/* We must be careful not to touch 'waiter' after we set ->task = NULL.	 * It is allocated on the waiter's stack and may become invalid at	 * any time after that point (due to a wakeup from another source).	 */	list_del_init(&waiter->list);	tsk = waiter->task;	mb();	waiter->task = NULL;	wake_up_process(tsk);	put_task_struct(tsk);	semtrace(sem,"Leaving __up");}EXPORT_SYMBOL(__up);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -