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

📄 sem_open.c

📁 unix网络编程的源码
💻 C
字号:
/* include sem_open1 */
#include	"unpipc.h"
#include	"semaphore.h"

#include	<stdarg.h>		/* for variable arg lists */
#define		MAX_TRIES	10	/* for waiting for initialization */

mysem_t	*
mysem_open(const char *pathname, int oflag, ... )
{
	int		fd, i, created, save_errno;
	mode_t	mode;
	va_list	ap;
	mysem_t	*sem, seminit;
	struct stat	statbuff;
	unsigned int	value;
	pthread_mutexattr_t	mattr;
	pthread_condattr_t	cattr;

	created = 0;
	sem = MAP_FAILED;				/* [sic] */
again:
	if (oflag & O_CREAT) {
		va_start(ap, oflag);		/* init ap to final named argument */
		mode = va_arg(ap, va_mode_t) & ~S_IXUSR;
		value = va_arg(ap, unsigned int);
		va_end(ap);

			/* 4open and specify O_EXCL and user-execute */
		fd = open(pathname, oflag | O_EXCL | O_RDWR, mode | S_IXUSR);
		if (fd < 0) {
			if (errno == EEXIST && (oflag & O_EXCL) == 0)
				goto exists;		/* already exists, OK */
			else
				return(SEM_FAILED);
		}
		created = 1;
			/* 4first one to create the file initializes it */
			/* 4set the file size */
		bzero(&seminit, sizeof(seminit));
		if (write(fd, &seminit, sizeof(seminit)) != sizeof(seminit))
			goto err;

			/* 4memory map the file */
		sem = mmap(NULL, sizeof(mysem_t), PROT_READ | PROT_WRITE,
				   MAP_SHARED, fd, 0);
		if (sem == MAP_FAILED)
			goto err;

			/* 4initialize mutex, condition variable, and value */
		if ( (i = pthread_mutexattr_init(&mattr)) != 0)
			goto pthreaderr;
		pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
		i = pthread_mutex_init(&sem->sem_mutex, &mattr);
		pthread_mutexattr_destroy(&mattr);	/* be sure to destroy */
		if (i != 0)
			goto pthreaderr;

		if ( (i = pthread_condattr_init(&cattr)) != 0)
			goto pthreaderr;
		pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
		i = pthread_cond_init(&sem->sem_cond, &cattr);
		pthread_condattr_destroy(&cattr);	/* be sure to destroy */
		if (i != 0)
			goto pthreaderr;

		if ( (sem->sem_count = value) > sysconf(_SC_SEM_VALUE_MAX)) {
			errno = EINVAL;
			goto err;
		}
			/* 4initialization complete, turn off user-execute bit */
		if (fchmod(fd, mode) == -1)
			goto err;
		close(fd);
		sem->sem_magic = SEM_MAGIC;
		return(sem);
	}
/* end sem_open1 */
/* include sem_open2 */
exists:
	if ( (fd = open(pathname, O_RDWR)) < 0) {
		if (errno == ENOENT && (oflag & O_CREAT))
			goto again;
		goto err;
	}

	sem = mmap(NULL, sizeof(mysem_t), PROT_READ | PROT_WRITE,
			   MAP_SHARED, fd, 0);
	if (sem == MAP_FAILED)
		goto err;

		/* 4make certain initialization is complete */
	for (i = 0; i < MAX_TRIES; i++) {
		if (stat(pathname, &statbuff) == -1) {
			if (errno == ENOENT && (oflag & O_CREAT)) {
				close(fd);
				goto again;
			}
			goto err;
		}
		if ((statbuff.st_mode & S_IXUSR) == 0) {
			close(fd);
			sem->sem_magic = SEM_MAGIC;
			return(sem);
		}
		sleep(1);
	}
	errno = ETIMEDOUT;
	goto err;

pthreaderr:
	errno = i;
err:
		/* 4don't let munmap() or close() change errno */
	save_errno = errno;
	if (created)
		unlink(pathname);
	if (sem != MAP_FAILED)
		munmap(sem, sizeof(mysem_t));
	close(fd);
	errno = save_errno;
	return(SEM_FAILED);
}
/* end sem_open2 */

mysem_t	*
Mysem_open(const char *pathname, int oflag, ... )
{
	va_list	ap;
	mode_t	mode;
	mysem_t	*sem;
	unsigned int	value;

	if (oflag & O_CREAT) {
		va_start(ap, oflag);		/* init ap to final named argument */
		mode = va_arg(ap, va_mode_t);
		value = va_arg(ap, unsigned int);
		va_end(ap);
		if ( (sem = mysem_open(pathname, oflag, mode, value)) == SEM_FAILED)
			err_sys("mysem_open error for %s", pathname);
	} else {
		if ( (sem = mysem_open(pathname, oflag)) == SEM_FAILED)
			err_sys("mysem_open error for %s", pathname);
	}

	return(sem);
}

⌨️ 快捷键说明

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