diff options
| author | Mattias Andrée <maandree@operamail.com> | 2015-04-14 05:43:31 +0200 | 
|---|---|---|
| committer | Mattias Andrée <maandree@operamail.com> | 2015-04-14 05:43:31 +0200 | 
| commit | 22f70acde48aa4c67ce96982c7ae4213907b23ea (patch) | |
| tree | 33f9df3b5682bb812ad5cde47ee0795dbe998efe | |
| parent | create semaphore array with random key (diff) | |
| download | bus-22f70acde48aa4c67ce96982c7ae4213907b23ea.tar.gz bus-22f70acde48aa4c67ce96982c7ae4213907b23ea.tar.bz2 bus-22f70acde48aa4c67ce96982c7ae4213907b23ea.tar.xz | |
first sync draft
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to '')
| -rw-r--r-- | src/semaphore.c | 183 | 
1 files changed, 174 insertions, 9 deletions
| diff --git a/src/semaphore.c b/src/semaphore.c index 5447c82..8c9f099 100644 --- a/src/semaphore.c +++ b/src/semaphore.c @@ -2,6 +2,7 @@  #include <stdio.h>  #include <time.h>  #include <errno.h> +#include <string.h>  #include <sys/ipc.h>  #include <sys/sem.h> @@ -16,17 +17,26 @@ union semun {  #endif +#define P 0 +#define Q 1 +#define N 2 + +#define SEMAPHORES 3 + +  char *argv0; -int main(int argc, char *argv[]) +static int +create_semaphores(void)  {  	key_t key; -	int id = -1; +	int id = -1, saved_errno; +	union semun values; -	(void) argc; -	argv0 = *argv; +	values.array = NULL; +	/* Create semaphore array. */  	srand(time(NULL));  	for (;;) {  		double r = (double)rand(); @@ -35,24 +45,179 @@ int main(int argc, char *argv[])  		key = (key_t)r + 1;  		if (key == IPC_PRIVATE)  			continue; -		id = semget(key, 3, IPC_CREAT | IPC_EXCL | 0600); +		id = semget(key, SEMAPHORES, IPC_CREAT | IPC_EXCL | 0600);  		if (id != -1)  			break;  		if ((errno != EEXIST) && (errno != EINTR))  			goto fail;  	} -	printf("key:%zx, id:%i\n", (size_t)key, id); - -	if (semctl(id, 0, IPC_RMID) == -1) +	/* Initialise the array. */ +	values.array = calloc(SEMAPHORES, sizeof(unsigned short)); +	if (values.array == NULL)  		goto fail; +	if (semctl(id, 0, SETALL, values.array) == -1) +		goto fail; +	free(values.array); +	values.array = NULL; +	printf("key:%zi(x%zx), id:%i\n", (ssize_t)key, (size_t)key, id);  	return 0;  fail: -	perror(argv0); +	saved_errno = errno;  	if ((id != -1) && (semctl(id, 0, IPC_RMID) == -1))  		perror(argv0); +	free(values.array); +	errno = saved_errno; +	return -1; +} + + +static int +remove_semaphores(key_t key) +{ +	int id = semget(key, SEMAPHORES, 0600); + +	if (id == -1) +		return -1; + +	if (semctl(id, 0, IPC_RMID) == -1) +		return -1; + +	return 0; +} + + +static int +acquire_semaphore(key_t key, int semaphore, int delta) +{ +	struct sembuf op; +	int id; + +	id = semget(key, SEMAPHORES, 0600); +	if (id == -1) +		return -1; + +	op.sem_op = -delta; +	op.sem_num = semaphore; +	op.sem_flg = 0; + +	return semop(id, &op, 1); +} + + +static int +release_semaphore(key_t key, int semaphore, int delta) +{ +	struct sembuf op; +	int id; + +	id = semget(key, SEMAPHORES, 0600); +	if (id == -1) +		return -1; + +	op.sem_op = delta; +	op.sem_num = semaphore; +	op.sem_flg = 0; + +	return semop(id, &op, 1); +} + + +static int +zero_semaphore(key_t key, int semaphore) +{ +	struct sembuf op; +	int id; + +	id = semget(key, SEMAPHORES, 0600); +	if (id == -1) +		return -1; + +	op.sem_op = 0; +	op.sem_num = semaphore; +	op.sem_flg = 0; + +	return semop(id, &op, 1); +} + + +static int +read_semaphore(key_t key, int semaphore, int *z, int *n, int *v) +{ +	struct sembuf op; +	int id, r; + +	id = semget(key, SEMAPHORES, 0600); +	if (id == -1) +		return -1; + +	if (r = semctl(id, semaphore, GETZCNT), r == -1) +		return -1; +	if (z) +		*z = r; + +	if (r = semctl(id, semaphore, GETNCNT), r == -1) +		return -1; +	if (n) +		*n = r; + +	if (r = semctl(id, semaphore, GETVAL), r == -1) +		return -1; +	if (v) +		*v = r; + +	return 0; +} + + +int +main(int argc, char *argv[]) +{ +	int r = -1, saved_errno, value; +	key_t key = argc > 2 ? (key_t)atoll(argv[2]) : 0; + +	argv0 = *argv; + +	if (!strcmp(argv[1], "create")) { +		r = create_semaphores(); +	} else if (!strcmp(argv[1], "remove")) { +		r = remove_semaphores(key); +	} else if (!strcmp(argv[1], "pick-up")) { +		r = release_semaphore(key, N, 1); +	} else if (!strcmp(argv[1], "hang-up")) { +		r = acquire_semaphore(key, N, 1); +	} else if (!strcmp(argv[1], "listen")) { +		r = acquire_semaphore(key, Q, 1); +		if (r) { +			saved_errno = errno; +			r = release_semaphore(key, P, 1); +			if (r) +				perror(argv0); +			errno = saved_errno; +			goto fail; +		} +		printf("read here\n"); +		r = release_semaphore(key, P, 1); +	} else if (!strcmp(argv[1], "speak")) { +		printf("write here\n"); +		r = read_semaphore(key, N, NULL, NULL, &value); +		if (r) +			goto fail; +		r = release_semaphore(key, Q, value); +		if (r) +			goto fail; +		r = acquire_semaphore(key, P, value); +	} else +		return 2; + +	if (r) +		goto fail; +	return 0; + +fail: +	perror(argv0);  	return 1;  } | 
